diff --git a/bibutils/adsout.c b/bibutils/adsout.c
--- a/bibutils/adsout.c
+++ b/bibutils/adsout.c
@@ -1,14 +1,15 @@
 /*
  * adsout.c
  *
- * Copyright (c) Richard Mathar 2007-2010
- * Copyright (c) Chris Putnam 2007-2010
+ * Copyright (c) Richard Mathar 2007-2012
+ * Copyright (c) Chris Putnam 2007-2012
  *
  * Program and source code released under the GPL
  *
  */
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
 #include <ctype.h>
 #include "utf8.h"
@@ -33,6 +34,10 @@
 	p->addcount         = 0;
 	p->singlerefperfile = 0;
 
+	if ( p->charsetout == BIBL_CHARSET_UNICODE ) {
+		p->utf8out = p->utf8bom = 1;
+	}
+
 	p->headerf = adsout_writeheader;
 	p->footerf = NULL;
 	p->writef  = adsout_write;
@@ -95,7 +100,7 @@
 	char *tag, *data;
 	int i, j, type = TYPE_UNKNOWN;
 
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		tag = info->tag[i].data;
 		if ( strcasecmp( tag, "GENRE" )!=0 &&
 		     strcasecmp( tag, "NGENRE" )!=0 ) continue;
@@ -123,7 +128,7 @@
 		}
 	}
 	if ( type==TYPE_UNKNOWN ) {
-		for ( i=0; i<info->nfields; ++i ) {
+		for ( i=0; i<info->n; ++i ) {
 			if ( strcasecmp( info->tag[i].data, "RESOURCE" ) )
 				continue;
 			data = info->data[i].data;
@@ -142,44 +147,44 @@
 }
 
 static void
-output_title( FILE *fp, fields *info, char * full, char *sub, char *endtag, int level )
+output_title( FILE *fp, fields *f, char *full, char *sub, char *adstag, int level )
 {
-	int n1 = fields_find( info, full, level );
-	int n2 = fields_find( info, sub, level );
-	int sn = fields_find( info, "PAGESTART", -1 );
-	int en = fields_find( info, "PAGEEND", -1 );
-	int ar = fields_find( info, "ARTICLENUMBER", -1 );
-	if ( n1!=-1 ) {
-		fprintf( fp, "%s %s", endtag, info->data[n1].data );
-		fields_setused( info, n1 );
-		if ( n2!=-1 ) {
-			if ( info->data[n1].data[info->data[n1].len]!='?' )
+	newstr *fulltitle, *subtitle, *vol, *iss, *sn, *en, *ar;
+
+	fulltitle = fields_findv( f, level, FIELDS_STRP, full );
+	subtitle  = fields_findv( f, level, FIELDS_STRP, sub );
+
+	if ( fulltitle && fulltitle->len ) {
+
+		fprintf( fp, "%s %s", adstag, fulltitle->data );
+		if ( subtitle && subtitle->len ) {
+			if ( fulltitle->data[ fulltitle->len - 1 ] != '?' )
 				fprintf( fp, ": " );
 			else fprintf( fp, " " );
-			fprintf( fp, "%s", info->data[n2].data );
-			fields_setused( info, n2 );
+			fprintf( fp, "%s", subtitle->data );
 		}
 
-		n1 = fields_find( info, "VOLUME", -1 );
-		if ( n1!=-1 )
-			fprintf( fp, ", vol. %s", info->data[n1].data );
-		n1 = fields_find( info, "ISSUE", -1 );
-		if ( n1 == -1 )
-			n1 = fields_find( info, "NUMBER", -1 );
-		if ( n1!=-1 )
-			fprintf( fp, ", no. %s", info->data[n1].data );
+		vol = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "VOLUME" );
+		if ( vol && vol->len ) fprintf( fp, ", vol. %s", vol->data );
 
-		if ( sn!=-1 ) {
-			if ( en != -1)
-				fprintf( fp, ", pp.");
+		iss = fields_findv_firstof( f, LEVEL_ANY, FIELDS_STRP, "ISSUE",
+			"NUMBER", NULL );
+		if ( iss && iss->len ) fprintf( fp, ", no. %s", iss->data );
+
+		sn = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGESTART" );
+		en = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGEEND" );
+		ar = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );
+		if ( sn && sn->len ) {
+			if ( en && en->len )
+				fprintf( fp, ", pp." );
 			else
-				fprintf( fp, ", p.");
-			fprintf( fp, " %s", info->data[sn].data);
-		} else if ( ar!=-1 ) {
-			fprintf( fp, " p. %s", info->data[ar].data );
+				fprintf( fp, ", p." );
+			fprintf( fp, " %s", sn->data );
+		} else if ( ar && ar->len ) {
+			fprintf( fp, ", p. %s", ar->data );
 		}
-		if ( en!=-1 ) {
-			fprintf( fp, "-%s", info->data[en].data );
+		if ( en && en->len ) {
+			fprintf( fp, "-%s", en->data );
 		}
 
 		fprintf( fp, "\n" );
@@ -205,44 +210,31 @@
 }
 
 static void
-output_people( FILE *fp, fields *info, char *tag, char *entag, int level )
+output_people( FILE *fp, fields *f, char *tag1, char *tag2, char *tag3, char *adstag, int level )
 {
-	int i, cnt=0;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( level!=-1 && info->level[i]!=level ) continue;
-		if ( !strcasecmp( info->tag[i].data, tag ) ) {
-			if ( cnt ) fprintf( fp, "; " );
-			else fprintf( fp, "%s ", entag );
-			output_person( fp, info->data[i].data );
-			cnt++;
-		}
+	vplist a;
+	int i;
+	vplist_init( &a );
+	fields_findv_eachof( f, level, FIELDS_CHRP, &a, tag1, tag2, tag3, NULL );
+	extern void  fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... );
+	for ( i=0; i<a.n; ++i ) {
+		if ( i==0 ) fprintf( fp, "%s ", adstag );
+		else fprintf( fp, "; " );
+		output_person( fp, (char *) vplist_get( &a, i) );
 	}
-	if ( cnt ) fprintf( fp, "\n" );
+	if ( a.n ) fprintf( fp, "\n" );
+	vplist_free( &a );
 }
 
 static void
-output_pages( FILE *fp, fields *info )
-{
-	int sn = fields_find( info, "PAGESTART", -1 );
-	int en = fields_find( info, "PAGEEND", -1 );
-	int ar = fields_find( info, "ARTICLENUMBER", -1 );
-	if ( sn!=-1 ) {
-		fprintf( fp, "%%P %s\n", info->data[sn].data);
-	} else if ( ar!=-1 ) {
-		fprintf( fp, "%%P %s\n", info->data[ar].data );
-	}
-	if ( en!=-1 ) {
-		fprintf( fp, "%%L %s\n", info->data[en].data );
-	}
-}
-
-static int
-get_year( fields *info, int level )
+output_pages( FILE *fp, fields *f )
 {
-	int year = fields_find( info, "YEAR", level );
-	if ( year==-1 )
-		year = fields_find( info, "PARTYEAR", level );
-	return year;
+	newstr *sn = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGESTART" );
+	newstr *en = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "PAGEEND" );
+	newstr *ar = fields_findv( f, LEVEL_ANY, FIELDS_STRP, "ARTICLENUMBER" );
+	if ( sn && sn->len!=0 ) fprintf( fp, "%%P %s\n", sn->data );
+	else if ( ar && ar->len!=0 ) fprintf( fp, "%%P %s\n", ar->data );
+	if ( en && en->len!=0 ) fprintf( fp, "%%L %s\n", en->data );
 }
 
 static int
@@ -261,24 +253,23 @@
 }
 
 static int
-get_month( fields *info, int level )
+get_month( fields *f, int level )
 {
-	int n;
-	n = fields_find( info, "MONTH", level );
-	if ( n==-1 ) n = fields_find( info, "PARTMONTH", level );
-	if ( n==-1 ) return 0;
-	else return mont2mont( info->data[n].data ); 
+	newstr *month = fields_findv_firstof( f, level, FIELDS_STRP,
+			"MONTH", "PARTMONTH", NULL );
+	if ( month && month->len ) return mont2mont( month->data );
+	else return 0;
 }
 
 static void
-output_date( FILE *fp, fields *info, char *entag, int level )
+output_date( FILE *fp, fields *f, char *adstag, int level )
 {
-	int year, month;
-	year = get_year( info, level );
-	if ( year!=-1 ) {
-		month = get_month( info, level );
-		fprintf( fp, "%s %02d/%s\n", entag, month, 
-			info->data[year].data );
+	newstr *year = fields_findv_firstof( f, level, FIELDS_STRP,
+		"YEAR", "PARTYEAR", NULL );
+	int month;
+	if ( year && year->len ) {
+		month = get_month( f, level );
+		fprintf( fp, "%s %02d/%s\n", adstag, month, year->data );
 	}
 }
 
@@ -297,12 +288,18 @@
 }
 
 static char
-get_firstinitial( fields *info )
+get_firstinitial( fields *f )
 {
-	int n = fields_find( info, "AUTHOR", 0 );
-	if ( n==-1 ) n = fields_find( info, "AUTHOR", -1 );
-	if ( n!=-1 ) return info->data[n].data[0];
-	else return '\0';
+	char *name;
+	int n;
+
+	n = fields_find( f, "AUTHOR", LEVEL_MAIN );
+	if ( n==-1 ) n = fields_find( f, "AUTHOR", LEVEL_ANY );
+
+	if ( n!=-1 ) {
+		name = fields_value( f, n, FIELDS_CHRP );
+		return name[0];
+	} else return '\0';
 }
 
 static int
@@ -313,14 +310,14 @@
 }
 
 static int
-get_journalabbr( fields *info )
+get_journalabbr( fields *f )
 {
 	char *jrnl;
 	int ljrnl, ltmp, len, n, j;
 
-	n = fields_find( info, "TITLE", LEVEL_HOST );
+	n = fields_find( f, "TITLE", LEVEL_HOST );
 	if ( n!=-1 ) {
-		jrnl = info->data[n].data;
+		jrnl = fields_value( f, n, FIELDS_CHRP );
 		ljrnl = strlen( jrnl );
 		for ( j=0; j<njournals; j++ ) {
 			ltmp = strlen( journals[j]+6 );
@@ -333,7 +330,7 @@
 }
 
 static void
-output_Rtag( FILE *fp, fields *info, char * entag, int type )
+output_Rtag( FILE *fp, fields *f, char *adstag, int type )
 {
 	char out[20], ch;
 	int n;
@@ -342,23 +339,23 @@
 	strcpy( out, "..................." );
 
 	/** YYYY */
-	n = fields_find( info, "YEAR", -1 );
-	if ( n==-1 ) n = fields_find( info, "PARTYEAR", -1 );
-	if ( n!=-1 ) output_4digit_value( out, atoi( info->data[n].data ) );
+	n = fields_find( f, "YEAR", LEVEL_ANY );
+	if ( n==-1 ) n = fields_find( f, "PARTYEAR", LEVEL_ANY );
+	if ( n!=-1 ) output_4digit_value( out, atoi( fields_value( f, n, FIELDS_CHRP ) ) );
 
 	/** JJJJ */
-	n = get_journalabbr( info );
+	n = get_journalabbr( f );
 	if ( n!=-1 ) strncpy( out+4, journals[n], 5 );
 
 	/** VVVV */
-	n = fields_find( info, "VOLUME", -1 );
-	if ( n!=-1 ) output_4digit_value( out+9, atoi( info->data[n].data ) );
+	n = fields_find( f, "VOLUME", LEVEL_ANY );
+	if ( n!=-1 ) output_4digit_value( out+9, atoi( fields_value( f, n, FIELDS_CHRP ) ) );
 
 	/** MPPPP */
-	n = fields_find( info, "PAGESTART", -1 );
-	if ( n==-1 ) n = fields_find( info, "ARTICLENUMBER", -1 );
+	n = fields_find( f, "PAGESTART", LEVEL_ANY );
+	if ( n==-1 ) n = fields_find( f, "ARTICLENUMBER", LEVEL_ANY );
 	if ( n!=-1 ) {
-		page = atoll( info->data[n].data );
+		page = atoll( fields_value( f, n, FIELDS_CHRP ) );
 		output_4digit_value( out+14, page );
 		if ( page>=10000 ) {
 			ch = 'a' + (page/10000);
@@ -367,82 +364,76 @@
 	}
 
 	/** A */
-        ch = toupper( get_firstinitial( info ) );
+        ch = toupper( get_firstinitial( f ) );
 	if ( ch!='\0' ) out[18] = ch;
 
-	fprintf( fp, "%s %s\n", entag, out );
+	fprintf( fp, "%s %s\n", adstag, out );
 }
 
 static void
-output_easyall( FILE *fp, fields *info, char *tag, char *entag, int level )
+output_easyall( FILE *fp, fields *f, char *tag, char *adstag, int level )
 {
+	vplist a;
 	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( level!=-1 && info->level[i]!=level ) continue;
-		if ( !strcmp( info->tag[i].data, tag ) )
-			fprintf( fp, "%s %s\n", entag, info->data[i].data );
-	}
+	vplist_init( &a );
+	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
+	for ( i=0; i<a.n; ++i )
+		fprintf( fp, "%s %s\n", adstag, (char *) vplist_get( &a, i ) );
+	vplist_free( &a );
 }
 
 static void
-output_easy( FILE *fp, fields *info, char *tag, char *entag, int level )
+output_easy( FILE *fp, fields *f, char *tag, char *adstag, int level )
 {
-	int n = fields_find( info, tag, level );
-	if ( n!=-1 )
-		fprintf( fp, "%s %s\n", entag, info->data[n].data );
+	char *value = fields_findv( f, level, FIELDS_CHRP, tag );
+	if ( value && value[0]!='\0' ) fprintf( fp, "%s %s\n", adstag, value );
 }
 
 static void
-output_keys( FILE *fp, fields *info, char *tag, char *entag, int level )
+output_keys( FILE *fp, fields *f, char *tag, char *adstag, int level )
 {
-	int i, n, nkeys = 0;
-	n = fields_find( info, tag, level );
-	if ( n!=-1 ) {
-		fprintf( fp, "%s ", entag );
-		for ( i=0; i<info->nfields; ++i ) {
-			if ( level!=-1 && info->level[i]!=level ) continue;
-			if ( !strcmp( info->tag[i].data, tag ) ) {
-				if ( nkeys ) fprintf( fp, ", " );
-				fprintf( fp, "%s", info->data[i].data );
-				nkeys++;
-			}
-		}
-		fprintf( fp, "\n" );
+	vplist a;
+	int i;
+	vplist_init( &a );
+	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
+	for ( i=0; i<a.n; ++i ) {
+		if ( i==0 ) fprintf( fp, "%s ", adstag );
+		else fprintf( fp, ", " );
+		fprintf( fp, "%s", (char *) vplist_get( &a, i ) );
 	}
+	if ( a.n ) fprintf( fp, "\n" );
+	vplist_free( &a );
 }
 
 void
-adsout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
+adsout_write( fields *f, FILE *fp, param *p, unsigned long refnum )
 {
 	int type;
-	fields_clearused( info );
-	type = get_type( info );
+	fields_clearused( f );
+	type = get_type( f );
 
-	output_people( fp, info, "AUTHOR", "%A", 0 );
-	output_easyall( fp, info, "AUTHOR:ASIS", "%A", 0 );
-	output_easyall( fp, info, "AUTHOR:CORP", "%A", 0 );
-	output_people( fp, info, "EDITOR", "%E", -1 );
-	output_easyall( fp, info, "EDITOR:ASIS", "%E", -1 );
-	output_easyall( fp, info, "EDITOR:CORP", "%E", -1 );
-	output_easy( fp, info, "TITLE", "%T", -1 );
+	output_people(  fp, f, "AUTHOR", "AUTHOR:ASIS", "AUTHOR:CORP", "%A", LEVEL_MAIN );
+	output_people(  fp, f, "EDITOR", "EDITOR:ASIS", "EDITOR:CORP", "%E", LEVEL_ANY );
+	output_easy(    fp, f, "TITLE",       "%T", LEVEL_ANY );
 
 	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE )
-		output_title( fp, info, "TITLE", "SUBTITLE", "%J", 1 );
+		output_title( fp, f, "TITLE", "SUBTITLE", "%J", LEVEL_HOST );
 
-	output_date( fp, info, "%D", -1 );
-	output_easy( fp, info, "VOLUME", "%V", -1 );
-	output_easy( fp, info, "ISSUE", "%N", -1 );
-	output_easy( fp, info, "NUMBER", "%N", -1 );
-	output_easy( fp, info, "LANGUAGE", "%M", -1 );
-	output_easyall( fp, info, "NOTES", "%X", -1 );
-	output_easy( fp, info, "ABSTRACT", "%B", -1 );
-	output_keys( fp, info, "KEYWORD", "%K", -1 );
-	output_easyall( fp, info, "URL", "%U", -1 ); 
-	output_easyall( fp, info, "FILEATTACH", "%U", -1 ); 
-	output_pages( fp, info );
-	output_easyall( fp, info, "DOI", "%Y", -1 );
+	output_date(    fp, f,               "%D", LEVEL_ANY );
+	output_easy(    fp, f, "VOLUME",     "%V", LEVEL_ANY );
+	output_easy(    fp, f, "ISSUE",      "%N", LEVEL_ANY );
+	output_easy(    fp, f, "NUMBER",     "%N", LEVEL_ANY );
+	output_easy(    fp, f, "LANGUAGE",   "%M", LEVEL_ANY );
+	output_easyall( fp, f, "NOTES",      "%X", LEVEL_ANY );
+	output_easy(    fp, f, "ABSTRACT",   "%B", LEVEL_ANY );
+	output_keys(    fp, f, "KEYWORD",    "%K", LEVEL_ANY );
+	output_easyall( fp, f, "URL",        "%U", LEVEL_ANY ); 
+	output_easyall( fp, f, "FILEATTACH", "%U", LEVEL_ANY ); 
+	output_easyall( fp, f, "FIGATTACH",  "%U", LEVEL_ANY ); 
+	output_pages( fp, f );
+	output_easyall( fp, f, "DOI",        "%Y", LEVEL_ANY );
         fprintf( fp, "%%W PHY\n%%G AUTHOR\n" );
-	output_Rtag( fp, info, "%R", type );
+	output_Rtag( fp, f, "%R", type );
 	fprintf( fp, "\n" );
 	fflush( fp );
 }
diff --git a/bibutils/adsout.h b/bibutils/adsout.h
--- a/bibutils/adsout.h
+++ b/bibutils/adsout.h
@@ -1,8 +1,8 @@
 /*
  * adsout.h
  *
- * Copyright (c) Richard Mathar 2007-10
- * Copyright (c) Chris Putnam 2007-10
+ * Copyright (c) Richard Mathar 2007-2012
+ * Copyright (c) Chris Putnam 2007-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/bibcore.c b/bibutils/bibcore.c
--- a/bibutils/bibcore.c
+++ b/bibutils/bibcore.c
@@ -1,7 +1,7 @@
 /*
  * bibcore.c
  *
- * Copyright (c) Chris Putnam 2005-2010
+ * Copyright (c) Chris Putnam 2005-2012
  *
  * Source code released under the GPL
  *
@@ -12,10 +12,81 @@
 
 /* internal includes */
 #include "reftypes.h"
+#include "charsets.h"
 #include "newstr_conv.h"
 #include "is_ws.h"
 
+/* illegal modes to pass in, but use internally for consistency */
+#define BIBL_INTERNALIN   (BIBL_LASTIN+1)
+#define BIBL_INTERNALOUT  (BIBL_LASTOUT+1)
+
+#define debug_set( p ) ( p->verbose > 1 )
+#define verbose_set( p ) ( p->verbose )
+
 static void
+report_params( FILE *fp, const char *f, param *p )
+{
+	fprintf( fp, "-------------------params start for %s\n", f );
+	fprintf( fp, "\tprogname='%s'\n\n", p->progname );
+
+	fprintf( fp, "\treadformat=%d", p->readformat );
+	switch ( p->readformat ) {
+		case BIBL_INTERNALIN:   fprintf( fp, " (BIBL_INTERNALIN)\n" );   break;
+		case BIBL_MODSIN:       fprintf( fp, " (BIBL_MODSIN)\n" );       break;
+		case BIBL_BIBTEXIN:     fprintf( fp, " (BIBL_BIBTEXIN)\n" );     break;
+		case BIBL_RISIN:        fprintf( fp, " (BIBL_RISIN)\n" );        break;
+		case BIBL_ENDNOTEIN:    fprintf( fp, " (BIBL_ENDNOTEIN)\n" );    break;
+		case BIBL_COPACIN:      fprintf( fp, " (BIBL_COPACIN)\n" );      break;
+		case BIBL_ISIIN:        fprintf( fp, " (BIBL_ISIIN)\n" );        break;
+		case BIBL_MEDLINEIN:    fprintf( fp, " (BIBL_MEDLINEIN)\n" );    break;
+		case BIBL_ENDNOTEXMLIN: fprintf( fp, " (BIBL_ENDNOTEXMLIN)\n" ); break;
+		case BIBL_BIBLATEXIN:   fprintf( fp, " (BIBL_BIBLATEXIN)\n" );   break;
+		case BIBL_EBIIN:        fprintf( fp, " (BIBL_EBIIN)\n" );        break;
+		case BIBL_WORDIN:       fprintf( fp, " (BIBL_WORDIN)\n" );       break;
+		default:                fprintf( fp, " (Illegal)\n" );           break;
+	}
+	fprintf( fp, "\tcharsetin=%d\n", p->charsetin );
+/*	fprintf( fp, "\tcharsetin=%d (%s)\n", p->charsetin, get_charsetname( p->charsetin ) );*/
+	fprintf( fp, "\tcharsetin_src=%d", p->charsetin_src );
+	switch ( p->charsetin_src ) {
+		case 0:  fprintf( fp, " (BIBL_SRC_DEFAULT)\n" ); break;
+		case 1:  fprintf( fp, " (BIBL_SRC_FILE)\n" );    break;
+		case 2:  fprintf( fp, " (BIBL_SRC_USER)\n" );    break;
+		default: fprintf( fp, " (Illegal value!)\n" );   break;
+	}
+	fprintf( fp, "\tutf8in=%d\n", p->utf8in );
+	fprintf( fp, "\tlatexin=%d\n", p->latexin );
+	fprintf( fp, "\txmlin=%d\n\n", p->xmlin );
+
+	fprintf( fp, "\twriteformat=%d", p->writeformat );
+	switch ( p->writeformat ) {
+		case BIBL_INTERNALOUT:  fprintf( fp, " (BIBL_INTERNALOUT)\n" );  break;
+		case BIBL_MODSOUT:      fprintf( fp, " (BIBL_MODSOUT)\n" );      break;
+		case BIBL_BIBTEXOUT:    fprintf( fp, " (BIBL_BIBTEXOUT)\n" );    break;
+		case BIBL_RISOUT:       fprintf( fp, " (BIBL_RISOUT)\n" );       break;
+		case BIBL_ENDNOTEOUT:   fprintf( fp, " (BIBL_ENDNOTEOUT)\n" );   break;
+		case BIBL_ISIOUT:       fprintf( fp, " (BIBL_ISIOUT)\n" );       break;
+		case BIBL_WORD2007OUT:  fprintf( fp, " (BIBL_WORD2007OUT)\n" );  break;
+		case BIBL_ADSABSOUT:    fprintf( fp, " (BIBL_ADSABSOUT)\n" );    break;
+		default:                fprintf( fp, " (Illegal)\n" );           break;
+	}
+/*	fprintf( fp, "\tcharsetout=%d (%s)\n", p->charsetout, get_charsetname( p->charsetout ) );*/
+	fprintf( fp, "\tcharsetout=%d\n", p->charsetout );
+	fprintf( fp, "\tcharsetout_src=%d", p->charsetout_src );
+	switch ( p->charsetout_src ) {
+		case 0:  fprintf( fp, " (BIBL_SRC_DEFAULT)\n" ); break;
+		case 1:  fprintf( fp, " (BIBL_SRC_FILE)\n" );    break;
+		case 2:  fprintf( fp, " (BIBL_SRC_USER)\n" );    break;
+		default: fprintf( fp, " (Illegal value!)\n" );   break;
+	}
+	fprintf( fp, "\tutf8out=%d\n", p->utf8out );
+	fprintf( fp, "\tutf8bom=%d\n", p->utf8bom );
+	fprintf( fp, "\tlatexout=%d\n", p->latexout );
+	fprintf( fp, "\txmlout=%d\n", p->xmlout );
+	fprintf( fp, "-------------------params end for %s\n", f );
+}
+
+static void
 bibl_duplicateparams( param *np, param *op )
 {
 	list_init( &(np->asis) );
@@ -71,6 +142,7 @@
 	np->charsetout_src = BIBL_SRC_DEFAULT;
 	np->xmlout = 0;
 	np->latexout = 0;
+	np->writeformat = BIBL_INTERNALOUT;
 }
 
 static void
@@ -82,6 +154,7 @@
 	np->utf8in = 1;
 	np->charsetin = BIBL_CHARSET_UNICODE;
 	np->charsetin_src = BIBL_SRC_DEFAULT;
+	np->readformat = BIBL_INTERNALIN;
 }
 
 void
@@ -166,28 +239,34 @@
 }
 
 void
-bibl_verbose2( fields *info, char *filename, long nrefs )
+bibl_verbose2( fields *f, char *filename, long nrefs )
 {
-	int i;
+	int i, n;
+	n = fields_num( f );
 	fprintf( stderr, "======== %s %ld : converted\n", filename, nrefs );
-	for ( i=0; i<info->nfields; ++i ) {
-		fprintf( stderr, "'%s'='%s' level=%d\n", info->tag[i].data,
-				info->data[i].data , info->level[i]);
+	for ( i=0; i<n; ++i ) {
+		fprintf( stderr, "'%s'='%s' level=%d\n",
+			(char*) fields_tag( f, i, FIELDS_CHRP_NOUSE ),
+			(char*) fields_value( f, i, FIELDS_CHRP_NOUSE ),
+			fields_level( f, i ) );
 	}
 	fprintf( stderr, "\n" );
 	fflush( stderr );
 }
 
 void
-bibl_verbose1( fields *info, fields *orig, char *filename, long nrefs )
+bibl_verbose1( fields *f, fields *orig, char *filename, long nrefs )
 {
-	int i;
+	int i, n;
+	n = fields_num( orig );
 	fprintf( stderr, "======== %s %ld : processed\n", filename, nrefs );
-	for ( i=0; i<orig->nfields; ++i ) {
-		fprintf( stderr, "'%s'='%s' level=%d\n", orig->tag[i].data,
-				orig->data[i].data , orig->level[i]);
+	for ( i=0; i<n; ++i ) {
+		fprintf( stderr, "'%s'='%s' level=%d\n",
+			(char*) fields_tag( orig, i, FIELDS_CHRP_NOUSE ),
+			(char*) fields_value( orig, i, FIELDS_CHRP_NOUSE ),
+			fields_level( orig, i ) );
 	}
-	if ( info ) bibl_verbose2( info, filename, nrefs );
+	if ( f ) bibl_verbose2( f, filename, nrefs );
 }
 
 void
@@ -199,7 +278,7 @@
 }
 
 static void
-process_alwaysadd( fields *info, int reftype, param *r )
+process_alwaysadd( fields *f, int reftype, param *r )
 {
         char tag[512], data[512], *p, *q;
         int i, process, level;
@@ -223,7 +302,7 @@
                         p++;
                 }
                 *q = '\0';
-                fields_add( info, tag, data, level );
+                fields_add( f, tag, data, level );
         }
 }
 
@@ -267,24 +346,27 @@
 bibl_fixcharsets( bibl *b, param *p )
 {
 	fields *ref;
+	char *tag;
 	long i, j;
-	int swap = 0;
+	int swap = 0, n;
 	int latexout = p->latexout;
 	int latexin  = p->latexin;
 	for ( i=0; i<b->nrefs; ++i ) {
 		ref = b->ref[i];
-		for ( j=0; j<ref->nfields; ++j ) {
+		n = fields_num( ref );
+		for ( j=0; j<n; ++j ) {
 			if ( latexin || latexout ) {
+				tag = fields_tag( ref, j, FIELDS_CHRP_NOUSE );
 				/* don't texify/detexify URL's and the like */
-				if ( !strcasecmp( ref->tag[j].data, "DOI" ) ||
-				     !strcasecmp( ref->tag[j].data, "URL" ) ||
-				     !strcasecmp( ref->tag[j].data, "REFNUM" )){
+				if ( !strcasecmp( tag, "DOI" ) ||
+				     !strcasecmp( tag, "URL" ) ||
+				     !strcasecmp( tag, "REFNUM" ) ) {
 					latexin  = 0;
 					latexout = 0;
 					swap = 1;
 				}
 			}
-			newstr_convert( &(ref->data[j]),
+			newstr_convert( fields_value( ref, j, FIELDS_STRP_NOUSE ),
 				p->charsetin,  latexin,  p->utf8in,  
 				p->xmlin,
 				p->charsetout, latexout, p->utf8out, 
@@ -299,34 +381,39 @@
 }
 
 static int
-build_refnum( fields *info, long nrefs )
+build_refnum( fields *f, long nrefs )
 {
+	char *year, *author, *p, num[512];
 	newstr refnum;
-	char *p, num[512];
-	int y, a;
+
 	newstr_init( &refnum );
-	y = fields_find( info, "YEAR", 0 );
-	if ( y==-1 ) y = fields_find( info, "YEAR", -1 );
-	if ( y==-1 ) y = fields_find( info, "PARTYEAR", -1 );
-	a = fields_find( info, "AUTHOR", 0 );
-	if ( a==-1 ) a = fields_find( info, "AUTHOR", -1 );
-	if ( a==-1 ) a = fields_find( info, "AUTHOR:CORP", -1 );
-	if ( a==-1 ) a = fields_find( info, "AUTHOR:ASIS", -1 );
-	if ( a!=-1 && y!=-1 ) {
-		p = info->data[a].data;
-		while ( p && *p && *p!='|' )
+
+	year = fields_findv( f, LEVEL_MAIN, FIELDS_CHRP_NOUSE, "YEAR" );
+	if ( !year )
+		year = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP_NOUSE,
+			"YEAR", "PARTYEAR", NULL );
+
+	author = fields_findv( f, LEVEL_MAIN, FIELDS_CHRP_NOUSE, "AUTHOR" );
+	if ( !author )
+		author = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP_NOUSE,
+			"AUTHOR", "AUTHOR:CORP", "AUTHOR:ASIS", NULL );
+
+	if ( year && author ) {
+		p = author;
+		while ( *p && *p!='|' )
 			newstr_addchar( &refnum, *p++ );
-		p = info->data[y].data;
-		while ( p && *p && *p!=' ' && *p!='\t' )
+		p = year;
+		while ( *p && *p!=' ' && *p!='\t' )
 			newstr_addchar( &refnum, *p++ );
 	} else {
 		sprintf( num, "%ld", nrefs );
-		newstr_strcpy( &refnum, "ref" );
-		newstr_strcat( &refnum, num );
+		newstr_mergestrs( &refnum, "ref", num, NULL );
 	}
-	fields_add( info, "REFNUM", refnum.data, 0 );
+
+	fields_add( f, "REFNUM", refnum.data, 0 );
 	newstr_free( &refnum );
-	return fields_find( info, "REFNUM", 0 );
+
+	return fields_find( f, "REFNUM", 0 );
 }
 
 static void
@@ -348,36 +435,36 @@
 }
 
 static int
-generate_citekey( fields *info, int nref )
+generate_citekey( fields *f, int nref )
 {
 	newstr citekey;
 	int n1, n2;
 	char *p, buf[100];
 	newstr_init( &citekey );
-	n1 = fields_find( info, "AUTHOR", 0 );
-	if ( n1==-1 ) n1 = fields_find( info, "AUTHOR", -1 );
-	n2 = fields_find( info, "YEAR", 0 );
-	if ( n2==-1 ) n2 = fields_find( info, "YEAR", -1 );
-	if ( n2==-1 ) n2 = fields_find( info, "PARTYEAR", 0 );
-	if ( n2==-1 ) n2 = fields_find( info, "PARTYEAR", -1 );
+	n1 = fields_find( f, "AUTHOR", 0 );
+	if ( n1==-1 ) n1 = fields_find( f, "AUTHOR", -1 );
+	n2 = fields_find( f, "YEAR", 0 );
+	if ( n2==-1 ) n2 = fields_find( f, "YEAR", -1 );
+	if ( n2==-1 ) n2 = fields_find( f, "PARTYEAR", 0 );
+	if ( n2==-1 ) n2 = fields_find( f, "PARTYEAR", -1 );
 	if ( n1!=-1 && n2!=-1 ) {
-		p = info->data[n1].data;
+		p = f->data[n1].data;
 		while ( p && *p && *p!='|' ) {
 			if ( !is_ws( *p ) ) newstr_addchar( &citekey, *p ); 
 			p++;
 		}
-		p = info->data[n2].data;
+		p = f->data[n2].data;
 		while ( p && *p ) {
 			if ( !is_ws( *p ) ) newstr_addchar( &citekey, *p );
 			p++;
 		}
-		fields_add( info, "REFNUM", citekey.data, 0 );
+		fields_add( f, "REFNUM", citekey.data, 0 );
 	} else {
 		sprintf( buf, "ref%d\n", nref );
 		newstr_strcpy( &citekey, buf );
 	}
 	newstr_free( &citekey );
-	return fields_find( info, "REFNUM", -1 );
+	return fields_find( f, "REFNUM", -1 );
 }
 
 static void
@@ -415,14 +502,14 @@
 static void
 get_citekeys( bibl *b, list *citekeys )
 {
-	fields *info;
+	fields *f;
 	int i, n;
 	for ( i=0; i<b->nrefs; ++i ) {
-		info = b->ref[i];
-		n = fields_find( info, "REFNUM", -1 );
-		if ( n==-1 ) n = generate_citekey( info, i );
-		if ( n!=-1 && info->data[n].data )
-			list_add( citekeys, info->data[n].data );
+		f = b->ref[i];
+		n = fields_find( f, "REFNUM", -1 );
+		if ( n==-1 ) n = generate_citekey( f, i );
+		if ( n!=-1 && f->data[n].data )
+			list_add( citekeys, f->data[n].data );
 		else
 			list_add( citekeys, "" );
 	}
@@ -465,8 +552,9 @@
 convert_ref( bibl *bin, char *fname, bibl *bout, param *p )
 {
 	fields *rin, *rout;
+	int reftype = 0;
 	long i;
-	int reftype;
+
 	if ( p->cleanf ) p->cleanf( bin, p );
 	for ( i=0; i<bin->nrefs; ++i ) {
 		rin = bin->ref[i];
@@ -474,10 +562,9 @@
 		if ( !rout ) return BIBL_ERR_MEMERR;
 		if ( p->typef ) 
 			reftype = p->typef( rin, fname, i+1, p, p->all, p->nall );
-		else reftype = 0;
 		if ( p->all ) process_alwaysadd( rout, reftype, p );
 		p->convertf( rin, rout, reftype, p, p->all, p->nall );
-		if ( p->verbose ) 
+		if ( verbose_set( p ) ) 
 			bibl_verbose1( rout, rin, fname, i+1 );
 		bibl_addref( bout, rout );
 	}
@@ -499,12 +586,15 @@
 	bibl_setreadparams( &lp, p );
 	bibl_init( &bin );
 	read_ref( fp, &bin, filename, &lp );
+
+	if ( debug_set( p ) ) report_params( stderr, "bibl_read", &lp );
+
 	if ( !lp.output_raw || ( lp.output_raw & BIBL_RAW_WITHCHARCONVERT ) )
 		bibl_fixcharsets( &bin, &lp );
 	if ( !lp.output_raw )
 		convert_ref( &bin, filename, b, &lp );
 	else {
-		if ( p->verbose > 1 ) bibl_verbose0( &bin );
+		if ( debug_set( p ) ) bibl_verbose0( &bin );
 		bibl_copy( b, &bin );
 	}
 	if ( !lp.output_raw || ( lp.output_raw & BIBL_RAW_WITHMAKEREFID ) )
@@ -522,10 +612,13 @@
 	FILE *fp;
 	long count;
 	int  found;
-	if ( mode==BIBL_BIBTEXOUT ) strcpy( suffix, "bib" );
-	else if ( mode==BIBL_RISOUT ) strcpy( suffix, "ris" );
-	else if ( mode==BIBL_ENDNOTEOUT ) strcpy( suffix, "end" );
-	else if ( mode==BIBL_ADSABSOUT ) strcpy( suffix, "ads" );
+	if      ( mode==BIBL_ADSABSOUT )     strcpy( suffix, "ads" );
+	else if ( mode==BIBL_BIBTEXOUT )     strcpy( suffix, "bib" );
+	else if ( mode==BIBL_ENDNOTEOUT )    strcpy( suffix, "end" );
+	else if ( mode==BIBL_ISIOUT )        strcpy( suffix, "isi" );
+	else if ( mode==BIBL_MODSOUT )       strcpy( suffix, "xml" );
+	else if ( mode==BIBL_RISOUT )        strcpy( suffix, "ris" );
+	else if ( mode==BIBL_WORD2007OUT )   strcpy( suffix, "xml" );
 	found = fields_find( reffields, "REFNUM", 0 );
 	/* find new filename based on reference */
 	if ( found!=-1 ) {
@@ -580,6 +673,7 @@
 
 	bibl_setwriteparams( &lp, p );
 	bibl_fixcharsets( b, &lp );
+	if ( debug_set( p ) ) report_params( stderr, "bibl_write", &lp );
 	output_bibl( fp, b, &lp );
 
 	return BIBL_OK;
diff --git a/bibutils/bibl.c b/bibutils/bibl.c
--- a/bibutils/bibl.c
+++ b/bibutils/bibl.c
@@ -1,7 +1,7 @@
 /*
  * bibl.c
  *
- * Copyright (c) Chris Putnam 2005-2010
+ * Copyright (c) Chris Putnam 2005-2012
  *
  * Source code released under the GPL
  *
@@ -69,16 +69,20 @@
 void
 bibl_copy( bibl *bout, bibl *bin )
 {
-	fields *refin;
-	fields *refout;
-	int i, j;
+	fields *refin, *refout;
+	char *tag, *value;
+	int level;
+	int i, j, n;
 	for ( i=0; i<bin->nrefs; ++i ) {
 		refin = bin->ref[i];
 		refout = fields_new();
-		for ( j=0; j<refin->nfields; ++j ) {
-			if ( refin->tag[j].data && refin->data[j].data )
-				fields_add( refout, refin->tag[j].data, 
-					refin->data[j].data, refin->level[j] );
+		n = fields_num( refin );
+		for ( j=0; j<n; ++j ) {
+			tag = fields_tag( refin, j, FIELDS_CHRP );
+			value = fields_value( refin, j, FIELDS_CHRP );
+			level = fields_level( refin, j );
+			if ( tag && value )
+				fields_add( refout, tag, value, level );
 		}
 		bibl_addref( bout, refout );
 	}
diff --git a/bibutils/bibl.h b/bibutils/bibl.h
--- a/bibutils/bibl.h
+++ b/bibutils/bibl.h
@@ -1,7 +1,7 @@
 /*
  * bibl.h
  *
- * Copyright (c) Chris Putnam 2005-10
+ * Copyright (c) Chris Putnam 2005-12
  *
  */
 #ifndef BIBL_H
diff --git a/bibutils/biblatexin.c b/bibutils/biblatexin.c
--- a/bibutils/biblatexin.c
+++ b/bibutils/biblatexin.c
@@ -1,8 +1,8 @@
 /*
  * biblatexin.c
  *
- * Copyright (c) Chris Putnam 2008-2010
- * Copyright (c) Johannes Wilm 2010
+ * Copyright (c) Chris Putnam 2008-2012
+ * Copyright (c) Johannes Wilm 2010-2012
  *
  * Program and source code released under the GPL
  *
@@ -409,7 +409,7 @@
 		type = bin->ref[i]->data[ntype].data;
 		fields_setused( bin->ref[i], n );
 /*		bin->ref[i]->used[n] = 1; */
-		for ( j=0; j<bin->ref[ncross]->nfields; ++j ) {
+		for ( j=0; j<bin->ref[ncross]->n; ++j ) {
 			nt = bin->ref[ncross]->tag[j].data;
 			if ( !strcasecmp( nt, "INTERNAL_TYPE" ) ) continue;
 			if ( !strcasecmp( nt, "REFNUM" ) ) continue;
@@ -430,10 +430,11 @@
 biblatexin_cleanref( fields *bibin, param *p )
 {
 	newstr *t, *d;
-	int i;
-	for ( i=0; i<bibin->nfields; ++i ) {
-		t = &( bibin->tag[i] );
-		d = &( bibin->data[i] );
+	int i, n;
+	n = fields_num( bibin );
+	for ( i=0; i<n; ++i ) {
+		t = fields_tag( bibin, i, FIELDS_STRP_NOUSE );
+		d = fields_value( bibin, i, FIELDS_STRP_NOUSE );
 		biblatex_cleandata( d, bibin, p );
 		if ( !strsearch( t->data, "AUTHORS" ) ) {
 			newstr_findreplace( d, "\n", " " );
@@ -600,12 +601,15 @@
 }
 
 static void
-report( fields *info )
+report( fields *f )
 {
-	int i;
-	for ( i=0; i<info->nfields; ++i )
-		fprintf(stderr, "'%s' %d = '%s'\n",info->tag[i].data,info->level[i],
-			info->data[i].data);
+	int i, n;
+	n = fields_num( f );
+	for ( i=0; i<n; ++i )
+		fprintf(stderr, "'%s' %d = '%s'\n",
+			(char*)fields_tag( f, i, FIELDS_CHRP_NOUSE ),
+			fields_level( f, i ),
+			(char*)fields_value( f, i, FIELDS_CHRP_NOUSE ) );
 }
 
 static void
@@ -622,9 +626,11 @@
 		variants *all, int nall )
 {
 	newstr *t, *d;
-	int process, level, i, n;
+	int process, level, i, n, nfields;
 	char *newtag;
-	for ( i=0; i<bibin->nfields; ++i ) {
+
+	nfields = fields_num( bibin );
+	for ( i=0; i<nfields; ++i ) {
 
                /* skip ones already "used" such as successful crossref */
                 if ( bibin->used[i] ) continue;
diff --git a/bibutils/biblatexin.h b/bibutils/biblatexin.h
--- a/bibutils/biblatexin.h
+++ b/bibutils/biblatexin.h
@@ -1,7 +1,7 @@
 /*
  * biblatexin.h
  *
- * Copyright (c) Chris Putnam 2008-2010
+ * Copyright (c) Chris Putnam 2008-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/bibtexin.c b/bibutils/bibtexin.c
--- a/bibutils/bibtexin.c
+++ b/bibutils/bibtexin.c
@@ -1,7 +1,7 @@
 /*
  * bibtexin.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
@@ -182,6 +182,7 @@
 	newstr_findreplace( s, "\\textsuperscript", "" );
 	newstr_findreplace( s, "\\emph", "" );
 	newstr_findreplace( s, "\\url", "" );
+	newstr_findreplace( s, "\\mbox", "" );
 
 	/* Other text annotations */
 	newstr_findreplace( s, "\\it ", "" );
@@ -294,7 +295,8 @@
 	newstr_empty( data );
 
 	if ( *p=='@' ) p++; /* skip '@' character */
-	while ( *p && *p!='{' && *p!='(' ) newstr_addchar( &tmp, *p++ );
+	while ( *p && *p!='{' && *p!='(' && !is_ws( *p ) ) newstr_addchar( &tmp, *p++ );
+	p = skip_ws( p );
 	if ( *p=='{' || *p=='(' ) p++;
 	p = skip_ws( p );
 
@@ -471,8 +473,7 @@
 		ntype = fields_find( bin->ref[i], "INTERNAL_TYPE", -1 );
 		type = bin->ref[i]->data[ntype].data;
 		fields_setused( bin->ref[i], n );
-/*		bin->ref[i]->used[n] = 1; */
-		for ( j=0; j<bin->ref[ncross]->nfields; ++j ) {
+		for ( j=0; j<bin->ref[ncross]->n; ++j ) {
 			nt = bin->ref[ncross]->tag[j].data;
 			if ( !strcasecmp( nt, "INTERNAL_TYPE" ) ) continue;
 			if ( !strcasecmp( nt, "REFNUM" ) ) continue;
@@ -493,10 +494,11 @@
 bibtexin_cleanref( fields *bibin, param *p )
 {
 	newstr *t, *d;
-	int i;
-	for ( i=0; i<bibin->nfields; ++i ) {
-		t = &( bibin->tag[i] );
-		d = &( bibin->data[i] );
+	int i, n;
+	n = fields_num( bibin );
+	for ( i=0; i<n; ++i ) {
+		t = fields_tag( bibin, i, FIELDS_STRP_NOUSE );
+		d = fields_value( bibin, i, FIELDS_STRP_NOUSE );
 		bibtex_cleandata( d, bibin, p );
 		if ( !strsearch( t->data, "AUTHORS" ) ) {
 			newstr_findreplace( d, "\n", " " );
@@ -562,8 +564,9 @@
 }
 
 static void
-process_urlcore( fields *info, char *p, int level, char *default_tag )
+process_urlcore( fields *info, newstr *d, int level, char *default_tag )
 {
+	char *p = d->data;
 	if ( !strncasecmp( p, "\\urllink", 8 ) )
 		fields_add( info, "URL", p+8, level );
 	else if ( !strncasecmp( p, "\\url", 4 ) )
@@ -578,49 +581,124 @@
 }
 
 static void
-process_url( fields *info, char *p, int level )
+process_url( fields *info, newstr *d, int level )
 {
-	process_urlcore( info, p, level, "URL" );
+	process_urlcore( info, d, level, "URL" );
 }
 
+/* Split keywords="" with semicolons.
+ * Commas are also frequently used, but will break
+ * entries like:
+ *       keywords="Microscopy, Confocal"
+ */
 static void
-process_howpublished( fields *info, char *p, int level )
+process_keywords( fields *info, newstr *d, int level )
 {
+	newstr keyword;
+	char *p;
+
+	if ( !d || d->len==0 ) return;
+
+	p = d->data;
+	newstr_init( &keyword );
+
+	while ( *p ) {
+		p = skip_ws( p );
+		while ( *p && *p!=';' ) newstr_addchar( &keyword, *p++ );
+		newstr_trimendingws( &keyword );
+		if ( keyword.len ) {
+			fields_add( info, "KEYWORD", keyword.data, level );
+			newstr_empty( &keyword );
+		}
+		if ( *p==';' ) p++;
+	}
+	newstr_free( &keyword );
+}
+
+static void
+process_howpublished( fields *info, newstr *d, int level )
+{
+	char *p = d->data;
 	/* Some users put Diploma thesis in howpublished */
 	if ( !strncasecmp( p, "Diplom", 6 ) )
 		fields_replace_or_add( info, "GENRE", "Diploma thesis", level );
 	else if ( !strncasecmp( p, "Habilitation", 13 ) )
 		fields_replace_or_add( info, "GENRE", "Habilitation thesis", level );
 	else 
-		process_urlcore( info, p, level, "DESCRIPTION" );
+		process_urlcore( info, d, level, "DESCRIPTION" );
 }
 
 /*
  * sentelink = {file://localhost/full/path/to/file.pdf,Sente,PDF}
  */
 static void
-process_sente( fields *info, char *p, int level )
+process_sente( fields *info, newstr *d, int level )
 {
 	newstr link;
+	char *p = d->data;
 	newstr_init( &link );
 	while ( *p && *p!=',' ) newstr_addchar( &link, *p++ );
+	newstr_trimstartingws( &link );
+	newstr_trimendingws( &link );
 	if ( link.len ) fields_add( info, "FILEATTACH", link.data, level );
 	newstr_free( &link );
 }
 
+static int
+count_colons( char *p )
+{
+	int n = 0;
+	while ( *p ) {
+		if ( *p==':' ) n++;
+		p++;
+	}
+	return n;
+}
+
+static int
+first_colon( char *p )
+{
+	int n = 0;
+	while ( p[n] && p[n]!=':' ) n++;
+	return n;
+}
+
+static int
+last_colon( char *p )
+{
+	int n = strlen( p ) - 1;
+	while ( n>0 && p[n]!=':' ) n--;
+	return n;
+}
+
 /*
  * file={Description:/full/path/to/file.pdf:PDF}
  */
 static void
-process_file( fields *info, char *p, int level )
+process_file( fields *info, newstr *d, int level )
 {
+	char *p = d->data;
 	newstr link;
-	newstr_init( &link );
-	while ( *p && *p!=':' ) p++;
-	if ( *p==':' ) p++;
-	while ( *p && *p!=':' ) newstr_addchar( &link, *p++ );
-	if ( link.len ) fields_add( info, "FILEATTACH", link.data, level );
-	newstr_free( &link );
+	int i, n, n1, n2;
+
+	n = count_colons( p );
+	if ( n > 1 ) {
+		/* A DOS file can contain a colon ":C:/....pdf:PDF" */
+		/* Extract after 1st and up to last colons */
+		n1 = first_colon( p ) + 1;
+		n2 = last_colon( p );
+		newstr_init( &link );
+		for ( i=n1; i<n2; ++i ) {
+			newstr_addchar( &link, p[i] );
+		}
+		newstr_trimstartingws( &link );
+		newstr_trimendingws( &link );
+		if ( link.len ) fields_add( info, "FILEATTACH", link.data, level );
+		newstr_free( &link );
+	} else {
+		/* This field isn't formatted properly, so just copy directly */
+		fields_add( info, "FILEATTACH", p, level );
+	}
 }
 
 int
@@ -643,12 +721,15 @@
 }
 
 static void
-report( fields *info )
+report( fields *f )
 {
-	int i;
-	for ( i=0; i<info->nfields; ++i )
-		fprintf(stderr, "'%s' %d = '%s'\n",info->tag[i].data,info->level[i],
-			info->data[i].data);
+	int i, n;
+	n = fields_num( f );
+	for ( i=0; i<n; ++i )
+		fprintf(stderr, "'%s' %d = '%s'\n",
+			(char*)fields_tag( f, i, FIELDS_CHRP ),
+			fields_level( f, i ),
+			(char*)fields_value( f, i, FIELDS_CHRP ) );
 }
 
 static void
@@ -660,54 +741,136 @@
 	}
 }
 
+/* bibtexin_titleinbook_isbooktitle()
+ *
+ * Normally, the title field of inbook refers to the book.  The
+ * section in a @inbook reference is untitled.  If it's titled,
+ * the @incollection should be used.  For example, in:
+ *
+ * @inbook{
+ *    title="xxx"
+ * }
+ *
+ * the booktitle is "xxx".
+ *
+ * However, @inbook is frequently abused (and treated like
+ * @incollection) so that title and booktitle are present
+ * and title is now 'supposed' to refer to the section.  For example:
+ *
+ * @inbook{
+ *     title="yyy",
+ *     booktitle="xxx"
+ * }
+ *
+ * Therefore report whether or not booktitle is present as well
+ * as title in @inbook references.  If not, then make 'title'
+ * correspond to the title of the book, not the section.
+ *
+ */
+static int
+bibtexin_titleinbook_isbooktitle( char *intag, fields *bibin )
+{
+	int n;
+
+	/* ...look only at 'title="xxx"' elements */
+	if ( strcasecmp( intag, "TITLE" ) ) return 0;
+
+	/* ...look only at '@inbook' references */
+	n = fields_find( bibin, "INTERNAL_TYPE", -1 );
+	if ( n==-1 ) return 0;
+	if ( strcasecmp( fields_value( bibin, n, FIELDS_CHRP ), "INBOOK" ) ) return 0;
+
+	/* ...look to see if 'booktitle="yyy"' exists */
+	n = fields_find( bibin, "BOOKTITLE", -1 );
+	if ( n==-1 ) return 0;
+	else return 1;
+}
+static void
+bibtexin_title_process( fields *info, char *outtag, fields *bibin, newstr *t, newstr *d, int level, int nosplittitle )
+{
+	char *intag = t->data;
+	char *indata = d->data;
+	if ( bibtexin_titleinbook_isbooktitle( intag, bibin ) ) level=LEVEL_MAIN;
+	title_process( info, outtag, indata, level, nosplittitle );
+}
+static void
+bibtex_simple( fields *info, char *outtag, newstr *d, int level )
+{
+	fields_add( info, outtag, d->data, level );
+}
+
 void
 bibtexin_convertf( fields *bibin, fields *info, int reftype, param *p,
 		variants *all, int nall )
 {
+	int process, level, i, n, nfields;
 	newstr *t, *d;
-	int process, level, i, n;
-	char *newtag;
-	for ( i=0; i<bibin->nfields; ++i ) {
+	char *outtag;
 
-		/* skip ones already "used" such as successful crossref */
-		if ( bibin->used[i] ) continue;
+	nfields = fields_num( bibin );
+	for ( i=0; i<nfields; ++i ) {
 
-		/* skip ones with no data */
-		d = &( bibin->data[i] );
-		if ( d->len == 0 ) continue;
+		if ( fields_used( bibin, i ) ) continue; /* e.g. successful crossref */
+		if ( fields_nodata( bibin, i ) ) continue;
 
-		t = &( bibin->tag[i] );
+		t = fields_tag( bibin, i, FIELDS_STRP );
 		n = process_findoldtag( t->data, reftype, all, nall );
 		if ( n==-1 ) {
 			bibtexin_notag( p, t->data );
 			continue;
 		}
 
-		/* skip ones of type ALWAYS (previously added) */
-		process = ((all[reftype]).tags[n]).processingtype;
-		if ( process == ALWAYS ) continue;
+		d = fields_value( bibin, i, FIELDS_STRP );
 
+		process = ((all[reftype]).tags[n]).processingtype;
 		level   = ((all[reftype]).tags[n]).level;
-		newtag  = ((all[reftype]).tags[n]).newstr;
+		outtag  = ((all[reftype]).tags[n]).newstr;
 
-		if ( process==SIMPLE )
-			fields_add( info, newtag, d->data, level );
-		else if ( process==TITLE )
-			title_process( info, "TITLE", d->data, level, 
-					p->nosplittitle );
-		else if ( process==PERSON )
-			process_names( info, newtag, d, level, &(p->asis), 
-					&(p->corps) );
-		else if ( process==PAGES )
-			process_pages( info, d, level);
-		else if ( process==BIBTEX_URL )
-			process_url( info, d->data, level );
-		else if ( process==HOWPUBLISHED )
-			process_howpublished( info, d->data, level );
-		else if ( process==BIBTEX_SENTE )
-			process_sente( info, d->data, level );
-		else if ( process==BIBTEX_FILE )
-			process_file( info, d->data, level );
+		switch( process ) {
+
+		case SIMPLE:
+			bibtex_simple( info, outtag, d, level );
+			break;
+
+		case TITLE:
+			bibtexin_title_process( info, "TITLE", bibin, t, d, level, p->nosplittitle );
+			break;
+
+		case PERSON:
+			process_names( info, outtag, d, level, &(p->asis), &(p->corps) );
+			break;
+
+		case PAGES:
+			process_pages( info, d, level );
+			break;
+
+		case KEYWORD:
+			process_keywords( info, d, level );
+			break;
+
+		case HOWPUBLISHED:
+			process_howpublished( info, d, level );
+			break;
+
+		case BIBTEX_URL:
+			process_url( info, d, level );
+			break;
+
+		case LINKEDFILE:
+			process_file( info, d, level );
+			break;
+
+		case BIBTEX_SENTE:
+			process_sente( info, d, level );
+			break;
+
+		case ALWAYS:
+			/* added by core bibutils code */
+			break;
+
+		default:
+			break;
+		}
 	}
 	if ( p->verbose ) report( info );
 }
diff --git a/bibutils/bibtexin.h b/bibutils/bibtexin.h
--- a/bibutils/bibtexin.h
+++ b/bibutils/bibtexin.h
@@ -1,7 +1,7 @@
 /*
  * bibtexin.h
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/bibtexout.c b/bibutils/bibtexout.c
--- a/bibutils/bibtexout.c
+++ b/bibutils/bibtexout.c
@@ -1,7 +1,7 @@
 /*
  * bibtexout.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
@@ -91,7 +91,7 @@
 	int type = TYPE_UNKNOWN, i, maxlevel, n, level;
 
 	/* determine bibliography type */
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		if ( strcasecmp( info->tag[i].data, "GENRE" ) &&
 		     strcasecmp( info->tag[i].data, "NGENRE" ) ) continue;
 		genre = info->data[i].data;
@@ -127,7 +127,7 @@
 			type = TYPE_ELECTRONIC;
 	}
 	if ( type==TYPE_UNKNOWN ) {
-		for ( i=0; i<info->nfields; ++i ) {
+		for ( i=0; i<info->n; ++i ) {
 			if ( strcasecmp( info->tag[i].data, "ISSUANCE" ) ) continue;
 			if ( !strcasecmp( info->data[i].data, "monographic" ) ) {
 				if ( info->level[i]==0 ) type = TYPE_BOOK;
@@ -258,9 +258,9 @@
 		int format_opts )
 {
 	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcasecmp( info->tag[i].data, intag ) ) continue;
-		output_and_use( fp, info, i, outtag, format_opts );
+	for ( i=0; i<info->n; ++i ) {
+		if ( fields_match_tag( info, i, intag ) )
+			output_and_use( fp, info, i, outtag, format_opts );
 	}
 }
 
@@ -270,7 +270,7 @@
 	newstr data;
 	int i;
 	newstr_init( &data );
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		if ( strcasecmp( info->tag[i].data, "FILEATTACH" ) ) continue;
 		newstr_strcpy( &data, ":" );
 		newstr_newstrcat( &data, &(info->data[i]) );
@@ -314,7 +314,7 @@
 
 	/* primary citation authors */
 	npeople = 0;
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		if ( level!=-1 && info->level[i]!=level ) continue;
 		person = ( strcasecmp( info->tag[i].data, tag ) == 0 );
 		corp   = ( strcasecmp( info->tag[i].data, ctag ) == 0 );
@@ -348,7 +348,7 @@
 static void
 output_title( FILE *fp, fields *info, unsigned long refnum, char *bibtag, int level, int format_opts )
 {
-	newstr title;
+	newstr title, *mainttl, *subttl;
 	int n1 = -1, n2 = -1;
 	/* Option is for short titles of journals */
 	if ( ( format_opts & BIBOUT_SHORTTITLE ) && level==1 ) {
@@ -361,13 +361,16 @@
 	}
 	if ( n1!=-1 ) {
 		newstr_init( &title );
-		newstr_newstrcpy( &title, &(info->data[n1]) );
+		mainttl = fields_value( info, n1, FIELDS_STRP );
+		newstr_newstrcpy( &title, mainttl );
 		fields_setused( info, n1 );
 		if ( n2!=-1 ) {
-			if ( info->data[n1].data[info->data[n1].len]!='?' )
+			subttl = fields_value( info, n2, FIELDS_STRP );
+			if ( mainttl->len > 0 &&
+			     mainttl->data[mainttl->len-1]!='?' )
 				newstr_strcat( &title, ": " );
 			else newstr_addchar( &title, ' ' );
-			newstr_strcat( &title, info->data[n2].data );
+			newstr_newstrcat( &title, subttl );
 			fields_setused( info, n2 );
 		}
 		output_element( fp, bibtag, title.data, format_opts );
diff --git a/bibutils/bibtexout.h b/bibutils/bibtexout.h
--- a/bibutils/bibtexout.h
+++ b/bibutils/bibtexout.h
@@ -1,7 +1,7 @@
 /*
  * bibtexout.h
  *
- * Copyright (c) Chris Putnam 2005-2010
+ * Copyright (c) Chris Putnam 2005-2012
  *
  */
 #ifndef BIBTEXOUT_H
diff --git a/bibutils/bibtextypes.c b/bibutils/bibtextypes.c
--- a/bibutils/bibtextypes.c
+++ b/bibutils/bibtextypes.c
@@ -1,7 +1,7 @@
 /*
  * bibtypes.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
@@ -41,16 +41,17 @@
 	{ "url",          "",      BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",       HOWPUBLISHED, LEVEL_MAIN },
 	{ "doi",          "DOI",       SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",       SIMPLE, LEVEL_MAIN },
 	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",            "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },
 	{ " ",            "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
 	{ " ",            "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
+	{ " ",            "GENRE|journal article",  ALWAYS, LEVEL_MAIN },
 	{ " ",            "GENRE|periodical",       ALWAYS, LEVEL_HOST },
 	{ " ",            "GENRE|academic journal", ALWAYS, LEVEL_HOST }
 };
@@ -87,13 +88,13 @@
 	{ "url",          "",       BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "address"       "ADDRESS",   SIMPLE, LEVEL_MAIN },
 	{ "howpublished", "",       HOWPUBLISHED, LEVEL_MAIN },
 	{ "doi",          "DOI",       SIMPLE, LEVEL_MAIN },
 	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ "refnum",       "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ " ",            "INTERNAL_TYPE|BOOK",     ALWAYS, LEVEL_MAIN },
 	{ " ",            "RESOURCE|text", ALWAYS, LEVEL_MAIN },
@@ -130,12 +131,12 @@
 	{ "url",          "",          BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",          HOWPUBLISHED, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",          SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
 	{ "type",      "GENRE",            SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|REPORT",     ALWAYS, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
 	{ " ",         "GENRE|report",    ALWAYS, LEVEL_MAIN }
@@ -167,12 +168,12 @@
 	{ "url",       "",       BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "language",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|REPORT",       ALWAYS, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text",     ALWAYS, LEVEL_MAIN },
 	{ " ",         "GENRE|instruction", ALWAYS, LEVEL_MAIN }
@@ -184,7 +185,7 @@
 	{ "author",    "AUTHOR",    PERSON, LEVEL_MAIN },
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "editor",    "EDITOR",    PERSON, LEVEL_HOST },
-	{ "chapter",   "TITLE",     TITLE,  LEVEL_MAIN },
+	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },
 	{ "title",     "TITLE",     TITLE,  LEVEL_HOST },
 	{ "booktitle", "TITLE",     TITLE,  LEVEL_HOST },
 	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },
@@ -208,7 +209,7 @@
 	{ "url",       "",       BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
@@ -216,11 +217,12 @@
 	{ "note",         "NOTES",        SIMPLE, LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
-	{ " ",         "INTERNAL_TYPE|INBOOK",   ALWAYS, LEVEL_MAIN },
-	{ " ",         "RESOURCE|text", ALWAYS, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
+	{ " ",         "INTERNAL_TYPE|INBOOK", ALWAYS, LEVEL_MAIN },
+	{ " ",         "RESOURCE|text",        ALWAYS, LEVEL_MAIN },
 	{ " ",         "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },
-	{ " ",         "GENRE|book",    ALWAYS, LEVEL_HOST }
+	{ " ",         "GENRE|book chapter",   ALWAYS, LEVEL_MAIN },
+	{ " ",         "GENRE|book",           ALWAYS, LEVEL_HOST }
 };
 
 /* References of papers in conference proceedings */
@@ -232,6 +234,7 @@
 	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
 	{ "booktitle", "TITLE",     TITLE,  LEVEL_HOST },
 	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },
+	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_HOST },
 	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_HOST },
 	{ "address",   "ADDRESS",   SIMPLE, LEVEL_HOST },
@@ -253,7 +256,7 @@
 	{ "url",       "",       BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "type",      "GENRE",      SIMPLE, LEVEL_MAIN },
 	{ "note",         "NOTES",        SIMPLE, LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
@@ -261,7 +264,7 @@
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|INPROCEEDINGS",  ALWAYS, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text",       ALWAYS, LEVEL_MAIN },
 	{ " ",         "GENRE|conference publication",   ALWAYS, LEVEL_HOST }
@@ -274,7 +277,7 @@
 	{ "translator",   "TRANSLATOR",PERSON, LEVEL_MAIN },
 	{ "editor",    "EDITOR",    PERSON, LEVEL_HOST },
 	{ "title",     "TITLE",     TITLE,  LEVEL_MAIN },
-	{ "chapter",   "TITLE",     TITLE,  LEVEL_MAIN },
+	{ "chapter",   "CHAPTER",   SIMPLE, LEVEL_MAIN },
 	{ "booktitle", "TITLE",     TITLE,  LEVEL_HOST },
 	{ "series",    "TITLE",     TITLE,  LEVEL_SERIES },
 	{ "publisher", "PUBLISHER", SIMPLE, LEVEL_HOST },
@@ -300,12 +303,12 @@
 	{ "url",       "",       BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_HOST },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|INCOLLECTION",   ALWAYS, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text", ALWAYS, LEVEL_MAIN },
 	{ " ",         "ISSUANCE|monographic", ALWAYS, LEVEL_MAIN },
@@ -339,7 +342,7 @@
 	{ "url",       "",       BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
@@ -348,7 +351,7 @@
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|PROCEEDINGS",    ALWAYS, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text",       ALWAYS, LEVEL_MAIN },
 	{ " ",         "GENRE|conference publication",   ALWAYS, LEVEL_MAIN }
@@ -370,7 +373,7 @@
 	{ "url",       "",       BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "" ,   HOWPUBLISHED, LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
@@ -380,7 +383,7 @@
 	{ "type",         "GENRE",         SIMPLE, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|THESIS",   ALWAYS, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text", ALWAYS, LEVEL_MAIN },
 	{ " ",         "GENRE|thesis",  ALWAYS, LEVEL_MAIN },
@@ -403,7 +406,7 @@
 	{ "url",       "",       BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
 	{ "note",         "NOTES",        SIMPLE, LEVEL_MAIN },
@@ -413,7 +416,7 @@
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|THESIS",   ALWAYS, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text", ALWAYS, LEVEL_MAIN },
 	{ " ",         "GENRE|thesis",  ALWAYS, LEVEL_MAIN },
@@ -440,7 +443,7 @@
 	{ "url",       "",       BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "location",     "LOCATION",     SIMPLE, LEVEL_MAIN },
@@ -449,7 +452,7 @@
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|BOOK",       ALWAYS, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
 	{ " ",         "GENRE|unpublished",      ALWAYS, LEVEL_MAIN }
@@ -480,7 +483,7 @@
 	{ "url",       "",      BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "language",     "LANGUAGE",     SIMPLE, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
@@ -491,7 +494,7 @@
 	{ "note",         "NOTES",        SIMPLE, LEVEL_MAIN },
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",          "BIBKEY",          SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|STANDARD",    ALWAYS, LEVEL_MAIN }
@@ -520,7 +523,7 @@
 	{ "url",          "",        BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",         HOWPUBLISHED, LEVEL_MAIN },
 	{ "refnum",       "REFNUM",      SIMPLE, LEVEL_MAIN },
 	{ "language",     "LANGUAGE",    SIMPLE, LEVEL_MAIN },
@@ -528,7 +531,7 @@
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "organization", "AUTHOR:CORP", SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",            "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
 	{ " ",            "GENRE|periodical",ALWAYS, LEVEL_MAIN }
 };
@@ -563,12 +566,12 @@
 	{ "url",       "",      BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "type",       "GENRE",     SIMPLE, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
 	{ " ",         "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|PATENT",    ALWAYS, LEVEL_MAIN },
 	{ " ",         "GENRE|patent",    ALWAYS, LEVEL_MAIN },
@@ -597,7 +600,7 @@
 	{ "url",       "",      BIBTEX_URL, LEVEL_MAIN },
 	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
 	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "file",         "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
 	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
 	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
@@ -606,7 +609,7 @@
 	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
 	{ "key",       "BIBKEY",       SIMPLE, LEVEL_MAIN },
 	{ "language",  "LANGUAGE",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",     "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "keywords",     "KEYWORD",   KEYWORD, LEVEL_MAIN },
         { " ",  "RESOURCE|software, multimedia",    ALWAYS, LEVEL_MAIN },
 	{ " ",         "GENRE|electronic",       ALWAYS, LEVEL_MAIN },
 };
@@ -629,18 +632,18 @@
 	{ "doi",       "DOI",       SIMPLE, LEVEL_MAIN },
 	{ "ftp",       "",      BIBTEX_URL, LEVEL_MAIN },
 	{ "url",       "",      BIBTEX_URL, LEVEL_MAIN },
-	{ "pdf",          "FILEATTACH",SIMPLE, LEVEL_MAIN },
-	{ "sentelink",    "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
-	{ "file",         "FILEATTACH",BIBTEX_FILE,  LEVEL_MAIN },
+	{ "pdf",       "FILEATTACH",   SIMPLE, LEVEL_MAIN },
+	{ "sentelink", "FILEATTACH",BIBTEX_SENTE, LEVEL_MAIN },
+	{ "file",      "FILEATTACH",LINKEDFILE,   LEVEL_MAIN },
 	{ "howpublished", "",    HOWPUBLISHED, LEVEL_MAIN },
-	{ "refnum",    "REFNUM",    SIMPLE, LEVEL_MAIN },
-	{ "crossref",     "CROSSREF",  SIMPLE, LEVEL_MAIN },
-	{ "location",  "LOCATION",  SIMPLE, LEVEL_MAIN },
-	{ "note",      "NOTES",     SIMPLE, LEVEL_MAIN },
-	{ "annote",       "ANNOTE",    SIMPLE, LEVEL_MAIN },
+	{ "refnum",    "REFNUM",       SIMPLE, LEVEL_MAIN },
+	{ "crossref",  "CROSSREF",     SIMPLE, LEVEL_MAIN },
+	{ "location",  "LOCATION",     SIMPLE, LEVEL_MAIN },
+	{ "note",      "NOTES",        SIMPLE, LEVEL_MAIN },
+	{ "annote",    "ANNOTE",       SIMPLE, LEVEL_MAIN },
 	{ "key",       "BIBKEY",       SIMPLE, LEVEL_MAIN },
-	{ "language",  "LANGUAGE",  SIMPLE, LEVEL_MAIN },
-	{ "keywords",  "KEYWORD",   SIMPLE, LEVEL_MAIN },
+	{ "language",  "LANGUAGE",     SIMPLE, LEVEL_MAIN },
+	{ "keywords",  "KEYWORD",      KEYWORD, LEVEL_MAIN },
 	{ " ",         "INTERNAL_TYPE|MISC",       ALWAYS, LEVEL_MAIN },
 };
 
diff --git a/bibutils/bibutils.c b/bibutils/bibutils.c
--- a/bibutils/bibutils.c
+++ b/bibutils/bibutils.c
@@ -1,7 +1,7 @@
 /*
  * bibutils.c
  *
- * Copyright (c) Chris Putnam 2005-2010
+ * Copyright (c) Chris Putnam 2005-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/bibutils.h b/bibutils/bibutils.h
--- a/bibutils/bibutils.h
+++ b/bibutils/bibutils.h
@@ -1,7 +1,7 @@
 /*
  * bibutils.h
  *
- * Copyright (c) Chris Putnam 2005-2010
+ * Copyright (c) Chris Putnam 2005-2012
  *
  */
 #ifndef BIBUTILS_H
@@ -14,6 +14,7 @@
 #include <stdio.h>
 #include "bibl.h"
 #include "list.h"
+#include "charsets.h"
 
 #define BIBL_OK           (0)
 #define BIBL_ERR_BADINPUT (-1)
@@ -49,9 +50,9 @@
 #define BIBL_RAW_WITHCHARCONVERT (4)
 #define BIBL_RAW_WITHMAKEREFID   (8)
 
-#define BIBL_CHARSET_UNKNOWN (-1)
-#define BIBL_CHARSET_UNICODE (-2)
-#define BIBL_CHARSET_GB18030 (-3)
+#define BIBL_CHARSET_UNKNOWN CHARSET_UNKNOWN
+#define BIBL_CHARSET_UNICODE CHARSET_UNICODE
+#define BIBL_CHARSET_GB18030 CHARSET_GB18030
 #define BIBL_CHARSET_DEFAULT (66)  /* Latin-1/ISO8859-1 */
 
 #define BIBL_SRC_DEFAULT (0)  /* value from program default */
diff --git a/bibutils/bltypes.c b/bibutils/bltypes.c
--- a/bibutils/bltypes.c
+++ b/bibutils/bltypes.c
@@ -1,8 +1,8 @@
 /*
  * bltypes.c
  *
- * Copyright (c) Chris Putnam 2008-2010
- * Copyright (c) Johannes Wilm 2010
+ * Copyright (c) Chris Putnam 2008-2012
+ * Copyright (c) Johannes Wilm 2010-2012
  *
  * Program and source code released under the GPL
  *
@@ -69,6 +69,7 @@
 	{ " ",            "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },
 	{ " ",            "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
 	{ " ",            "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
+        { " ",            "GENRE|journal article",  ALWAYS, LEVEL_MAIN },
 	{ " ",            "GENRE|periodical",       ALWAYS, LEVEL_HOST }
 };
 
@@ -277,6 +278,7 @@
 	{ " ",               "INTERNAL_TYPE|INBOOK",    ALWAYS, LEVEL_MAIN },
 	{ " ",               "RESOURCE|text",ALWAYS, LEVEL_MAIN },
 	{ " ",               "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },
+        { " ",               "GENRE|book chapter",   ALWAYS, LEVEL_MAIN },
 	{ " ",               "GENRE|book",   ALWAYS, LEVEL_HOST }
 };
 
diff --git a/bibutils/charsets.c b/bibutils/charsets.c
--- a/bibutils/charsets.c
+++ b/bibutils/charsets.c
@@ -1,7 +1,7 @@
 /*
  * charsets.h
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/charsets.h b/bibutils/charsets.h
--- a/bibutils/charsets.h
+++ b/bibutils/charsets.h
@@ -1,12 +1,18 @@
 /*
  * charsets.h
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  *
  */
+#ifndef CHARSETS_H
+#define CHARSETS_H
 
+#define CHARSET_UNKNOWN (-1)
+#define CHARSET_UNICODE (-2)
+#define CHARSET_GB18030 (-3)
+
 typedef unsigned int charconvert;
 
 typedef struct allcharconvert_t {
@@ -18,4 +24,4 @@
 extern allcharconvert_t allcharconvert[];
 extern int nallcharconvert;
 
-
+#endif
diff --git a/bibutils/copacin.c b/bibutils/copacin.c
--- a/bibutils/copacin.c
+++ b/bibutils/copacin.c
@@ -1,7 +1,7 @@
 /*
  * copacin.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
@@ -32,6 +32,7 @@
 	p->nosplittitle     = 0;
 	p->verbose          = 0;
 	p->addcount         = 0;
+	p->output_raw       = 0;
 
 	p->readf    = copacin_readf;
 	p->processf = copacin_processf;
@@ -267,42 +268,61 @@
 }
 
 void
-copacin_convertf( fields *copacin, fields *info, int reftype, param *p, variants *all, int nall )
+copacin_convertf( fields *copacin, fields *out, int reftype, param *p, variants *all, int nall )
 {
-	newstr *t, *d;
-	int  process, level, i, n;
+	int  process, level, i, n, nfields;
+	newstr *tag, *data;
 	char *newtag;
-	for ( i=0; i<copacin->nfields; ++i ) {
-		t = &( copacin->tag[i] );
-		d = &( copacin->data[i] );
-		n = process_findoldtag( t->data, reftype, all, nall );
+
+	nfields = fields_num( copacin );
+	for ( i=0; i<nfields; ++i ) {
+
+		tag = fields_tag( copacin, i, FIELDS_STRP );
+
+		n = process_findoldtag( tag->data, reftype, all, nall );
 		if ( n==-1 ) {
-			copacin_report_notag( p, t->data );
+			copacin_report_notag( p, tag->data );
 			continue;
 		}
+
 		process = ((all[reftype]).tags[n]).processingtype;
 		if ( process == ALWAYS ) continue; /*add these later*/
+
+		data = fields_value( copacin, i, FIELDS_STRP );
 		level = ((all[reftype]).tags[n]).level;
 		newtag = ((all[reftype]).tags[n]).newstr;
-		if ( process==SIMPLE )
-			fields_add( info, newtag, d->data, level );
-		else if ( process==TITLE )
-			title_process( info, newtag, d->data, level, 
-					p->nosplittitle );
-		else if ( process==PERSON )
-			copacin_addname( info, newtag, d, level, &(p->asis), 
-					&(p->corps) );
-		else if ( process==DATE )
-			copacin_adddate(info,all[reftype].
-					tags[i].oldstr,newtag,d->data,level);
-		else if ( process==PAGES )
-			copacin_addpage( info, d->data, level );
-		else if ( process==SERIALNO )
-			addsn( info, d->data, level );
-/*		else {
-			fprintf(stderr,"%s: internal error -- "
-				"illegal process %d\n", r->progname, process );
-		}*/
+
+		switch ( process ) {
+
+		case SIMPLE:
+			fields_add( out, newtag, data->data, level );
+			break;
+
+		case TITLE:
+			title_process( out, newtag, data->data, level, p->nosplittitle );
+			break;
+
+		case PERSON:
+			copacin_addname( out, newtag, data, level, &(p->asis), &(p->corps) );
+			break;
+
+		case DATE:
+			copacin_adddate(out,all[reftype].  tags[i].oldstr,newtag,data->data,level);
+			break;
+
+		case PAGES:
+			copacin_addpage( out, data->data, level );
+			break;
+
+		case SERIALNO:
+			addsn( out, data->data, level );
+			break;
+
+		default:
+			fprintf(stderr,"%s: internal error -- " "illegal process value %d\n", p->progname, process );
+			break;
+		}
+
 	}
 }
 
diff --git a/bibutils/copacin.h b/bibutils/copacin.h
--- a/bibutils/copacin.h
+++ b/bibutils/copacin.h
@@ -1,7 +1,7 @@
 /*
  * copacin.h
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/copactypes.c b/bibutils/copactypes.c
--- a/bibutils/copactypes.c
+++ b/bibutils/copactypes.c
@@ -1,7 +1,7 @@
 /*
  * copactypes.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/doi.c b/bibutils/doi.c
--- a/bibutils/doi.c
+++ b/bibutils/doi.c
@@ -9,7 +9,7 @@
  * is_doi()
  * Check for DOI buried in another field.
  *
- * Copyright (c) Chris Putnam 2008-2010
+ * Copyright (c) Chris Putnam 2008-2012
  *
  * Source code released under the GPL
  */
@@ -33,56 +33,47 @@
 }
 
 static int
-url_exists( fields *info, char *urltag, newstr *doi_url )
+url_exists( fields *f, char *urltag, newstr *doi_url )
 {
-	int i, found = 0;
+	int i, n;
 	if ( urltag ) {
-		for ( i=0; i<info->nfields && !found; ++i ) {
-			if ( strcmp( info->tag[i].data, urltag ) )
-				continue;
-			if ( !strcmp( info->data[i].data, doi_url->data ) )
-				found=1;
+		n = fields_num( f );
+		for ( i=0; i<n; ++i ) {
+			if ( strcmp( fields_tag( f, i, FIELDS_CHRP ), urltag ) ) continue;
+			if ( strcmp( fields_value( f, i, FIELDS_CHRP ), doi_url->data ) ) continue;
+			return 1;
 		}
 	}
-	return found;
+	return 0;
 }
 
+static void
+xxx_to_url( fields *f, int n, char *http_prefix, char *urltag, newstr *xxx_url )
+{
+	newstr_empty( xxx_url );
+	construct_url( http_prefix, fields_value( f, n, FIELDS_STRP ), xxx_url );
+	if ( url_exists( f, urltag, xxx_url ) )
+		newstr_empty( xxx_url );
+}
 void
-doi_to_url( fields *info, int n, char *urltag, newstr *doi_url )
+doi_to_url( fields *f, int n, char *urltag, newstr *url )
 {
-	newstr_empty( doi_url );
-	construct_url( "http://dx.doi.org", &(info->data[n]), doi_url );
-	if ( url_exists( info, urltag, doi_url ) )
-		newstr_empty( doi_url );
+	xxx_to_url( f, n, "http://dx.doi.org", urltag, url );
 }
-
 void
-jstor_to_url( fields *info, int n, char *urltag, newstr *jstor_url )
+jstor_to_url( fields *f, int n, char *urltag, newstr *url )
 {
-	newstr_empty( jstor_url );
-	construct_url( "http://www.jstor.org/stable", &(info->data[n]),
-		jstor_url );
-	if ( url_exists( info, urltag, jstor_url ) )
-		newstr_empty( jstor_url );
+	xxx_to_url( f, n, "http://www.jstor.org/stable", urltag, url );
 }
-
 void
-pmid_to_url( fields *info, int n, char *urltag, newstr *pmid_url )
+pmid_to_url( fields *f, int n, char *urltag, newstr *url )
 {
-	newstr_empty( pmid_url );
-	construct_url( "http://www.ncbi.nlm.nih.gov/pubmed", &(info->data[n]),
-			pmid_url );
-	if ( url_exists( info, urltag, pmid_url ) )
-		newstr_empty( pmid_url );
+	xxx_to_url( f, n, "http://www.ncbi.nlm.nih.gov/pubmed", urltag, url );
 }
-
 void
-arxiv_to_url( fields *info, int n, char *urltag, newstr *arxiv_url )
+arxiv_to_url( fields *f, int n, char *urltag, newstr *url )
 {
-	newstr_empty( arxiv_url );
-	construct_url( "http://arxiv.org/abs", &(info->data[n]), arxiv_url );
-	if ( url_exists( info, urltag, arxiv_url ) )
-		newstr_empty( arxiv_url );
+	xxx_to_url( f, n, "http://arxiv.org/abs", urltag, url );
 }
 
 /* Rules for the pattern:
diff --git a/bibutils/doi.h b/bibutils/doi.h
--- a/bibutils/doi.h
+++ b/bibutils/doi.h
@@ -1,7 +1,7 @@
 /*
  * doi.h
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  */
diff --git a/bibutils/ebiin.c b/bibutils/ebiin.c
--- a/bibutils/ebiin.c
+++ b/bibutils/ebiin.c
@@ -1,7 +1,7 @@
 /*
  * ebiin.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
@@ -509,11 +509,17 @@
 }
 
 void
-ebiin_convertf( fields *ebiin, fields *info, int reftype, int verbose, 
+ebiin_convertf( fields *ebiin, fields *out, int reftype, int verbose, 
 	variants *all, int nall )
 {
-	int i;
-	for ( i=0; i<ebiin->nfields; ++i )
-		fields_add( info, ebiin->tag[i].data, ebiin->data[i].data,
-				ebiin->level[i] );
+	char *tag, *value;
+	int i, n, level;
+
+	n = fields_num( ebiin );
+	for ( i=0; i<n; ++i ) {
+		tag = fields_tag( ebiin, i, FIELDS_CHRP );
+		value = fields_value( ebiin, i, FIELDS_CHRP );
+		level = fields_level( ebiin, i );
+		fields_add( out, tag, value, level );
+	}
 }
diff --git a/bibutils/ebiin.h b/bibutils/ebiin.h
--- a/bibutils/ebiin.h
+++ b/bibutils/ebiin.h
@@ -1,7 +1,7 @@
 /*
  * ebiin.h
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/endin.c b/bibutils/endin.c
--- a/bibutils/endin.c
+++ b/bibutils/endin.c
@@ -1,7 +1,7 @@
 /*
  * endin.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
@@ -161,7 +161,7 @@
 		} else {
 			p = process_endline2( &tag, &data, p );
 			/* endnote puts %K only on 1st line of keywords */
-			n = endin->nfields;
+			n = fields_num( endin );
 			if ( n>0 && data.len ) {
 			if ( !strncmp( endin->tag[n-1].data, "%K", 2 ) ) {
 				fields_add( endin, "%K", data.data, 0 );
@@ -388,8 +388,9 @@
 static void
 endin_cleanref( fields *endin )
 {
-	int i;
-	for ( i=0; i<endin->nfields; ++i ) {
+	int i, n;
+	n = fields_num( endin );
+	for ( i=0; i<n; ++i ) {
 		if ( is_wiley_author( endin, i ) )
 			cleanup_wiley_author( endin, i );
 	}
@@ -426,53 +427,75 @@
 void
 endin_convertf( fields *endin, fields *info, int reftype, param *p, variants *all, int nall )
 {
-	newstr *d;
-	int  i, level, n, process;
+	int  i, level, n, process, nfields;
 	char *newtag, *t;
-	for ( i=0; i<endin->nfields; ++i ) {
+	newstr *d;
+
+	nfields = fields_num( endin );
+	for ( i=0; i<nfields; ++i ) {
 		/* Ensure that data exists */
-		d = &( endin->data[i] );
-		if ( !(d->data) || d->len==0 ) continue;
+		d = fields_value( endin, i, FIELDS_STRP );
+		if ( d->len==0 || !(d->data) ) continue;
 		/*
 		 * All refer format tags start with '%'.  If we have one
 		 * that doesn't, assume that it comes from endx2xml
 		 * and just copy and paste to output
 		 */
-		t = endin->tag[i].data;
+		t = fields_tag( endin, i, FIELDS_CHRP );
 		if ( t[0]!='%' ) {
 			fields_add( info, t, d->data, endin->level[i] );
 			continue;
 		}
+
 		n = process_findoldtag( t, reftype, all, nall );
 		if ( n==-1 ) {
 			endin_notag( p, t, d->data );
 			continue;
 		}
+
 		process = ((all[reftype]).tags[n]).processingtype;
 		if ( process == ALWAYS ) continue; /* add these later */
 		level = ((all[reftype]).tags[n]).level;
 		newtag = ((all[reftype]).tags[n]).newstr;
-		if ( process==SIMPLE )
+
+		switch ( process ) {
+
+		case SIMPLE:
 			fields_add( info, newtag, d->data, level );
-		else if ( process==TYPE )
+			break;
+
+		case TYPE:
 			addtype( info, d->data, level );
-		else if ( process==TITLE )
-			title_process( info, newtag, d->data, level, 
-					p->nosplittitle );
-		else if ( process==PERSON )
-			name_add( info, newtag, d->data, level, 
-					&(p->asis), &(p->corps) );
-		else if ( process==DATE )
+			break;
+
+		case TITLE:
+			title_process( info, newtag, d->data, level, p->nosplittitle );
+			break;
+
+		case PERSON:
+			name_add( info, newtag, d->data, level, &(p->asis), &(p->corps) );
+			break;
+
+		case DATE:
 			adddate( info, t, newtag,d->data,level);
-		else if ( process==PAGES )
+			break;
+
+		case PAGES:
 			addpage( info, d->data, level );
-		else if ( process==SERIALNO )
+			break;
+
+		case SERIALNO:
 			addsn( info, d->data, level );
-		else if ( process==NOTES )
+			break;
+
+		case NOTES:
 			addnotes( info, newtag, d->data, level );
-		else {
-/*				fprintf(stderr,"%s: internal error -- illegal process %d\n", r->progname, process );
-*/
+			break;
+
+		default:
+			fprintf(stderr,"%s: internal error -- illegal process number %d\n", p->progname, process );
+			break;
 		}
+
 	}
 }
diff --git a/bibutils/endin.h b/bibutils/endin.h
--- a/bibutils/endin.h
+++ b/bibutils/endin.h
@@ -1,7 +1,7 @@
 /*
  * endin.h
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/endout.c b/bibutils/endout.c
--- a/bibutils/endout.c
+++ b/bibutils/endout.c
@@ -1,7 +1,7 @@
 /*
  * endout.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
@@ -33,6 +33,10 @@
 	p->addcount         = 0;
 	p->singlerefperfile = 0;
 
+	if ( p->charsetout == BIBL_CHARSET_UNICODE ) {
+		p->utf8out = p->utf8bom = 1;
+	}
+
 	p->headerf = endout_writeheader;
 	p->footerf = NULL;
 	p->writef  = endout_write;
@@ -199,7 +203,7 @@
 	char *tag, *data;
 	int i, j, type = TYPE_UNKNOWN;
 
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		tag = info->tag[i].data;
 		if ( strcasecmp( tag, "GENRE" )!=0 &&
 		     strcasecmp( tag, "NGENRE" )!=0 ) continue;
@@ -231,7 +235,7 @@
 		if ( ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE || type==TYPE_NEWSARTICLE ) && info->level[i]<1 ) type=TYPE_UNKNOWN;
 	}
 	if ( type==TYPE_UNKNOWN ) {
-		for ( i=0; i<info->nfields; ++i ) {
+		for ( i=0; i<info->n; ++i ) {
 			if ( strcasecmp( info->tag[i].data, "RESOURCE" ) )
 				continue;
 			data = info->data[i].data;
@@ -316,20 +320,19 @@
 output_title( FILE *fp, fields *info, char *full, char *sub, char *endtag, 
 		int level )
 {
-	int n1 = fields_find( info, full, level );
-	int n2 = fields_find( info, sub, level );
-	if ( n1!=-1 ) {
-		fprintf( fp, "%s %s", endtag, info->data[n1].data );
-		fields_setused( info, n1 );
-		if ( n2!=-1 ) {
-			if ( info->data[n1].data[info->data[n1].len]!='?' )
-				fprintf( fp, ": " );
-			else fprintf( fp, " " );
-			fprintf( fp, "%s", info->data[n2].data );
-			fields_setused( info, n2 );
-		}
-		fprintf( fp, "\n" );
+	newstr *mainttl = fields_findv( info, level, FIELDS_STRP, full );
+	newstr *subttl  = fields_findv( info, level, FIELDS_STRP, sub );
+
+	if ( !mainttl ) return;
+
+	fprintf( fp, "%s %s", endtag, mainttl->data );
+	if ( subttl ) {
+		if ( mainttl->len > 0 &&
+		     mainttl->data[ mainttl->len-1 ]!='?' )
+				fprintf( fp, ":" );
+		fprintf( fp, " %s", subttl->data );
 	}
+	fprintf( fp, "\n" );
 }
 
 static void
@@ -353,12 +356,17 @@
 static void
 output_people( FILE *fp, fields *info, char *tag, char *entag, int level )
 {
-	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( level!=-1 && info->level[i]!=level ) continue;
-		if ( !strcasecmp( info->tag[i].data, tag ) ) {
+	int i, n, flvl;
+	char *ftag, *fval;
+	n = fields_num( info );
+	for ( i=0; i<n; ++i ) {
+		flvl = fields_level( info, i );
+		if ( level!=LEVEL_ANY && flvl!=level ) continue;
+		ftag = fields_tag( info, i, FIELDS_CHRP );
+		if ( !strcasecmp( ftag, tag ) ) {
+			fval = fields_value( info, i, FIELDS_CHRP );
 			fprintf( fp, "%s ", entag );
-			output_person( fp, info->data[i].data );
+			output_person( fp, fval );
 			fprintf( fp, "\n" );
 		}
 	}
@@ -367,87 +375,104 @@
 static void
 output_pages( FILE *fp, fields *info )
 {
-	int sn = fields_find( info, "PAGESTART", -1 );
-	int en = fields_find( info, "PAGEEND", -1 );
-	int ar = fields_find( info, "ARTICLENUMBER", -1 );
-	if ( sn!=-1 || en!=-1 ) {
+	char *sn = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGESTART" );
+	char *en = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGEEND" );
+	char *ar;
+	if ( sn || en ) {
 		fprintf( fp, "%%P ");
-		if ( sn!=-1 ) fprintf( fp, "%s", info->data[sn].data );
-		if ( sn!=-1 && en!=-1 ) fprintf( fp, "-" );
-		if ( en!=-1 ) fprintf( fp, "%s", info->data[en].data );
-		fprintf( fp, "\n");
-	} else if ( ar!=-1 ) {
-		fprintf( fp, "%%P %s\n", info->data[ar].data );
+		if ( sn ) fprintf( fp, "%s", sn );
+		if ( sn && en ) fprintf( fp, "-" );
+		if ( en ) fprintf( fp, "%s", en );
+		fprintf( fp, "\n" );
+	} else {
+		ar = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
+		if ( ar ) fprintf( fp, "%%P %s\n", ar );
 	}
 }
 
 static void
-output_doi( FILE *fp, fields *info )
+output_doi( FILE *fp, fields *f )
 {
 	newstr doi_url;
-	int i;
+	int i, n;
+
 	newstr_init( &doi_url );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcmp( info->tag[i].data, "DOI" ) ) continue;
-		doi_to_url( info, i, "URL", &doi_url );
+
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( !fields_match_tag( f, i, "DOI" ) ) continue;
+		doi_to_url( f, i, "URL", &doi_url );
 		if ( doi_url.len )
 			fprintf( fp, "%%U %s\n", doi_url.data );
 	}
+
 	newstr_free( &doi_url );
 }
 
 static void
-output_pmid( FILE *fp, fields *info )
+output_pmid( FILE *fp, fields *f )
 {
 	newstr pmid_url;
-	int i;
+	int i, n;
+
 	newstr_init( &pmid_url );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcmp( info->tag[i].data, "PMID" ) ) continue;
-		pmid_to_url( info, i, "URL", &pmid_url );
+
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( !fields_match_tag( f, i, "PMID" ) ) continue;
+		pmid_to_url( f, i, "URL", &pmid_url );
 		if ( pmid_url.len )
 			fprintf( fp, "%%U %s\n", pmid_url.data );
 	}
+
 	newstr_free( &pmid_url );
 }
 
 static void
-output_arxiv( FILE *fp, fields *info )
+output_arxiv( FILE *fp, fields *f )
 {
 	newstr arxiv_url;
-	int i;
+	int i, n;
+
 	newstr_init( &arxiv_url );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcmp( info->tag[i].data, "ARXIV" ) ) continue;
-		arxiv_to_url( info, i, "URL", &arxiv_url );
+
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( !fields_match_tag( f, i, "ARXIV" ) ) continue;
+		arxiv_to_url( f, i, "URL", &arxiv_url );
 		if ( arxiv_url.len )
 			fprintf( fp, "%%U %s\n", arxiv_url.data );
 	}
+
 	newstr_free( &arxiv_url );
 }
 
 static void
-output_jstor( FILE *fp, fields *info )
+output_jstor( FILE *fp, fields *f )
 {
 	newstr jstor_url;
-	int i;
+	int i, n;
+
 	newstr_init( &jstor_url );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcmp( info->tag[i].data, "JSTOR" ) ) continue;
-		jstor_to_url( info, i, "URL", &jstor_url );
+
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( !fields_match_tag( f, i, "JSTOR" ) ) continue;
+		jstor_to_url( f, i, "URL", &jstor_url );
 		if ( jstor_url.len )
 			fprintf( fp, "%%U %s\n", jstor_url.data );
 	}
+
 	newstr_free( &jstor_url );
 }
 
 static void
 output_year( FILE *fp, fields *info, int level )
 {
-	int year = fields_find( info, "YEAR", level );
-	if ( year==-1 ) year = fields_find( info, "PARTYEAR", level );
-	if ( year!=-1 )
-		fprintf( fp, "%%D %s\n", info->data[year].data );
+	char *year = fields_findv_firstof( info, level, FIELDS_CHRP,
+			"YEAR", "PARTYEAR", NULL );
+	if ( year )
+		fprintf( fp, "%%D %s\n", year );
 }
 
 static void
@@ -457,21 +482,19 @@
 		"May", "June", "July", "August", "September", "October",
 		"November", "December" };
 	int m;
-	int month = fields_find( info, "MONTH", level );
-	int day   = fields_find( info, "DAY", level );
-	if ( month==-1 ) month = fields_find( info, "PARTMONTH", level );
-	if ( day==-1 ) day = fields_find( info, "PARTDAY", level );
-	if ( month!=-1 || day!=-1 ) {
+	char *month = fields_findv_firstof( info, level, FIELDS_CHRP,
+			"MONTH", "PARTMONTH", NULL );
+	char *day   = fields_findv_firstof( info, level, FIELDS_CHRP,
+			"DAY", "PARTDAY", NULL );
+	if ( month || day ) {
 		fprintf( fp, "%%8 " );
-		if ( month!=-1 ) {
-			m = atoi( info->data[month].data );
-			if ( m>0 && m<13 )
-				fprintf( fp, "%s", months[m-1] );
-			else
-				fprintf( fp, "%s", info->data[month].data );
+		if ( month ) {
+			m = atoi( month );
+			if ( m>0 && m<13 ) fprintf( fp, "%s", months[m-1] );
+			else fprintf( fp, "%s", month );
 		}
-		if ( month!=-1 && day!=-1 ) fprintf( fp, " " );
-		if ( day!=-1 ) fprintf( fp, "%s", info->data[day].data );
+		if ( month && day ) fprintf( fp, " " );
+		if ( day ) fprintf( fp, "%s", day );
 		fprintf( fp, "\n" );
 	}
 }
@@ -494,75 +517,86 @@
 static void
 output_easyall( FILE *fp, fields *info, char *tag, char *entag, int level )
 {
+	vplist a;
 	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( level!=-1 && info->level[i]!=level ) continue;
-		if ( !strcmp( info->tag[i].data, tag ) )
-			fprintf( fp, "%s %s\n", entag, info->data[i].data );
-	}
+	vplist_init( &a );
+	fields_findv_each( info, level, FIELDS_CHRP, &a, tag );
+	for ( i=0; i<a.n; ++i )
+		fprintf( fp, "%s %s\n", entag, (char *) vplist_get( &a, i ) );
+	vplist_free( &a );
 }
 
 static void
 output_easy( FILE *fp, fields *info, char *tag, char *entag, int level )
 {
-	int n = fields_find( info, tag, level );
-	if ( n!=-1 )
-		fprintf( fp, "%s %s\n", entag, info->data[n].data );
+	char *value = fields_findv( info, level, FIELDS_CHRP, tag );
+	if ( value ) fprintf( fp, "%s %s\n", entag, value );
 }
 
 void
 endout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
 {
 	int type;
+
 	fields_clearused( info );
+
 	type = get_type( info );
+
 	output_type( fp, type, p );
-	output_title( fp, info, "TITLE", "SUBTITLE", "%T", 0 );
-	output_title( fp, info, "SHORTTITLE", "SHORTSUBTITLE", "%!", 0 );
-	output_people( fp, info, "AUTHOR", "%A", 0 );
-	output_people( fp, info, "EDITOR", "%E", -1 );
-	output_people( fp, info, "TRANSLATOR", "%H", -1 );
+
+	output_title( fp, info, "TITLE",      "SUBTITLE",      "%T", LEVEL_MAIN );
+	output_title( fp, info, "SHORTTITLE", "SHORTSUBTITLE", "%!", LEVEL_MAIN );
+
+	output_people( fp, info, "AUTHOR",     "%A", LEVEL_MAIN );
+	output_people( fp, info, "EDITOR",     "%E", LEVEL_ANY  );
+	output_people( fp, info, "TRANSLATOR", "%H", LEVEL_ANY  );
+
 	if ( type==TYPE_CASE )
-		output_easy( fp, info, "AUTHOR:CORP", "%I", 0 );
+		output_easy(    fp, info, "AUTHOR:CORP", "%I", LEVEL_MAIN );
 	else if ( type==TYPE_HEARING )
-		output_easyall( fp, info, "AUTHOR:CORP", "%S", 0 );
+		output_easyall( fp, info, "AUTHOR:CORP", "%S", LEVEL_MAIN );
 	else if ( type==TYPE_NEWSARTICLE )
-		output_people( fp, info, "REPORTER", "%A", 0 );
+		output_people(  fp, info, "REPORTER",    "%A", LEVEL_MAIN );
 	else if ( type==TYPE_COMMUNICATION )
-		output_people( fp, info, "RECIPIENT", "%E", -1 );
+		output_people(  fp, info, "RECIPIENT",   "%E", LEVEL_ANY  );
 	else {
-		output_easyall( fp, info, "AUTHOR:CORP", "%A", 0 );
-		output_easyall( fp, info, "AUTHOR:ASIS", "%A", 0 );
-		output_easyall( fp, info, "EDITOR:CORP", "%E", -1 );
-		output_easyall( fp, info, "EDITOR:ASIS", "%E", -1 );
+		output_easyall( fp, info, "AUTHOR:CORP",     "%A", LEVEL_MAIN );
+		output_easyall( fp, info, "AUTHOR:ASIS",     "%A", LEVEL_MAIN );
+		output_easyall( fp, info, "EDITOR:CORP",     "%E", LEVEL_ANY  );
+		output_easyall( fp, info, "EDITOR:ASIS",     "%E", LEVEL_ANY  );
+		output_easyall( fp, info, "TRANSLATOR:CORP", "%H", LEVEL_ANY  );
+		output_easyall( fp, info, "TRANSLATOR:ASIS", "%H", LEVEL_ANY  );
 	}
+
 	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE )
-		output_title( fp, info, "TITLE", "SUBTITLE", "%J", 1 );
-	else output_title( fp, info, "TITLE", "SUBTITLE", "%B", 1 );
-	output_year( fp, info, -1 );
-	output_monthday( fp, info, -1 );
-	output_easy( fp, info, "VOLUME", "%V", -1 );
-	output_easy( fp, info, "ISSUE", "%N", -1 );
-	output_easy( fp, info, "NUMBER", "%N", -1 );
-	output_easy( fp, info, "EDITION", "%7", -1 );
-	output_easy( fp, info, "PUBLISHER", "%I", -1 );
-	output_easy( fp, info, "ADDRESS", "%C", -1 );
-	output_easy( fp, info, "DEGREEGRANTOR", "%C", -1 );
-	output_easy( fp, info, "DEGREEGRANTOR:CORP", "%C", -1 );
-	output_easy( fp, info, "DEGREEGRANTOR:ASIS", "%C", -1 );
-	output_easy( fp, info, "SERIALNUMBER", "%@", -1 );
-	output_easy( fp, info, "ISSN", "%@", -1 );
-	output_easy( fp, info, "ISBN", "%@", -1 );
-	output_easy( fp, info, "LANGUAGE", "%G", -1 );
-	output_easy( fp, info, "REFNUM", "%F", -1 );
-	output_easyall( fp, info, "NOTES", "%O", -1 );
-	output_easy( fp, info, "ABSTRACT", "%X", -1 );
-	output_easy( fp, info, "CLASSIFICATION", "%L", -1 );
-	output_easyall( fp, info, "KEYWORD", "%K", -1 );
-	output_easyall( fp, info, "NGENRE", "%9", -1 );
+		output_title( fp, info, "TITLE", "SUBTITLE", "%J", LEVEL_HOST );
+	else output_title( fp, info, "TITLE", "SUBTITLE", "%B", LEVEL_HOST );
+
+	output_year( fp, info, LEVEL_ANY );
+	output_monthday( fp, info, LEVEL_ANY );
+
+	output_easy( fp, info, "VOLUME",             "%V", LEVEL_ANY );
+	output_easy( fp, info, "ISSUE",              "%N", LEVEL_ANY );
+	output_easy( fp, info, "NUMBER",             "%N", LEVEL_ANY );
+	output_easy( fp, info, "EDITION",            "%7", LEVEL_ANY );
+	output_easy( fp, info, "PUBLISHER",          "%I", LEVEL_ANY );
+	output_easy( fp, info, "ADDRESS",            "%C", LEVEL_ANY );
+	output_easy( fp, info, "DEGREEGRANTOR",      "%C", LEVEL_ANY );
+	output_easy( fp, info, "DEGREEGRANTOR:CORP", "%C", LEVEL_ANY );
+	output_easy( fp, info, "DEGREEGRANTOR:ASIS", "%C", LEVEL_ANY );
+	output_easy( fp, info, "SERIALNUMBER",       "%@", LEVEL_ANY );
+	output_easy( fp, info, "ISSN",               "%@", LEVEL_ANY );
+	output_easy( fp, info, "ISBN",               "%@", LEVEL_ANY );
+	output_easy( fp, info, "LANGUAGE",           "%G", LEVEL_ANY );
+	output_easy( fp, info, "REFNUM",             "%F", LEVEL_ANY );
+	output_easyall( fp, info, "NOTES",           "%O", LEVEL_ANY );
+	output_easy( fp, info, "ABSTRACT",           "%X", LEVEL_ANY );
+	output_easy( fp, info, "CLASSIFICATION",     "%L", LEVEL_ANY );
+	output_easyall( fp, info, "KEYWORD",         "%K", LEVEL_ANY );
+	output_easyall( fp, info, "NGENRE",          "%9", LEVEL_ANY );
 	output_thesishint( fp, type );
-	output_easyall( fp, info, "URL", "%U", -1 ); 
-	output_easyall( fp, info, "FILEATTACH", "%U", -1 ); 
+	output_easyall( fp, info, "URL",             "%U", LEVEL_ANY ); 
+	output_easyall( fp, info, "FILEATTACH",      "%U", LEVEL_ANY ); 
 	output_doi( fp, info );
 	output_pmid( fp, info );
 	output_arxiv( fp, info );
diff --git a/bibutils/endout.h b/bibutils/endout.h
--- a/bibutils/endout.h
+++ b/bibutils/endout.h
@@ -1,7 +1,7 @@
 /*
  * endout.h
  *
- * Copyright (c) Chris Putnam 2005-2010
+ * Copyright (c) Chris Putnam 2005-2012
  *
  */
 #ifndef ENDOUT_H
diff --git a/bibutils/endtypes.c b/bibutils/endtypes.c
--- a/bibutils/endtypes.c
+++ b/bibutils/endtypes.c
@@ -1,7 +1,7 @@
 /*
  * endtypes.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
@@ -111,6 +111,7 @@
 	{ "%~", "DATABASE",     SIMPLE,   LEVEL_MAIN },
 	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
 	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
+        { "  ", "GENRE|journal article",  ALWAYS, LEVEL_MAIN },
 	{ "  ", "GENRE|periodical",       ALWAYS, LEVEL_HOST },
 	{ "  ", "GENRE|academic journal", ALWAYS, LEVEL_HOST }
 };
@@ -304,9 +305,10 @@
 	{ "%[", "ACCESSDATE",   SIMPLE, LEVEL_MAIN },
 	{ "%=", "LASTMODDATE",  SIMPLE, LEVEL_MAIN },
 	{ "%~", "DATABASE",     SIMPLE, LEVEL_MAIN },
-	{ "  ", "GENRE|book", ALWAYS, LEVEL_HOST },
+        { "  ", "GENRE|book chapter",   ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|book",           ALWAYS, LEVEL_HOST },
 	{ "  ", "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },
-	{ "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN }
+	{ "  ", "RESOURCE|text",        ALWAYS, LEVEL_MAIN }
 };
 
 static lookups editedbook[] = {
diff --git a/bibutils/endxmlin.c b/bibutils/endxmlin.c
--- a/bibutils/endxmlin.c
+++ b/bibutils/endxmlin.c
@@ -1,7 +1,7 @@
 /*
  * endxmlin.c
  *
- * Copyright (c) Chris Putnam 2006-2010
+ * Copyright (c) Chris Putnam 2006-2012
  *
  * Program and source code released under the GPL
  */
diff --git a/bibutils/endxmlin.h b/bibutils/endxmlin.h
--- a/bibutils/endxmlin.h
+++ b/bibutils/endxmlin.h
@@ -1,7 +1,7 @@
 /*
  * endxmlin.h
  *
- * Copyright (c) Chris Putnam 2006-2009
+ * Copyright (c) Chris Putnam 2006-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/entities.c b/bibutils/entities.c
--- a/bibutils/entities.c
+++ b/bibutils/entities.c
@@ -1,7 +1,7 @@
 /*
  * entities.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  */
@@ -21,7 +21,7 @@
 	/* Special Entities */
 	{ "&quot;",     34 },  /* quotation mark */
 	{ "&amp;",      38 },  /* ampersand */
-	{ "&apos;",     39 },  /* apostrophe */
+	{ "&apos;",     39 },  /* apostrophe (note not defined in HTML) */
 	{ "&lpar;",     40 },  /* left parenthesis */
 	{ "&rpar;",     41 },  /* right parenthesis */
 	{ "&hyphen;",   45 },  /* hyphen */
@@ -352,13 +352,16 @@
  * decode numeric entity
  *
  *    extract a numeric entity from &#NNN; or &#xNNNN;
+ *
+ *    In XML, the "x" in hexadecimal entries should be lowercase,
+ *    but we'll be generous and accept "X" as well.
  */
 static unsigned int
 decode_numeric_entity( char *s, unsigned int *pi, int *err )
 {
 	unsigned int c;
 	*err = 0;
-	if ( s[*pi+2]!='x' ) c = decode_decimal_entity( s, pi, err );
+	if ( s[*pi+2]!='x' && s[*pi+2]!='X' ) c = decode_decimal_entity( s, pi, err );
 	else c = decode_hex_entity( s, pi, err );
 	if ( *err ) {
 		*pi = *pi + 1;
@@ -369,7 +372,12 @@
 
 /*
  * decode entity
- *    extract entity from  &xxxx; 
+ *    extract entity from  &mmmm;
+ *
+ * where &mmmm; is one of
+ * - &#nnnn; is code point in decimal form
+ * - &#xhhhh; is code point in hexadecimal form (note "x" is lowercase in XML)
+ * - &mmmm; corresponds to a pre-defined XML entity, e.g. &quote for quotations
  *
  */
 unsigned int
diff --git a/bibutils/entities.h b/bibutils/entities.h
--- a/bibutils/entities.h
+++ b/bibutils/entities.h
@@ -1,7 +1,7 @@
 /*
  * entities.h
  *
- * Copyright (c) Chris Putnam 2003-2009
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  */
diff --git a/bibutils/fields.c b/bibutils/fields.c
--- a/bibutils/fields.c
+++ b/bibutils/fields.c
@@ -1,194 +1,548 @@
 /*
  * fields.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  *
  */
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdint.h>
 #include <string.h>
+#include <assert.h>
 #include "strsearch.h"
 #include "fields.h"
 
-int
-fields_add( fields *info, char *tag, char *data, int level )
+fields*
+fields_new( void )
 {
+	fields *f = ( fields * ) malloc( sizeof( fields ) );
+	if ( f ) fields_init( f );
+	return f;
+}
+
+void
+fields_init( fields *f )
+{
+	assert( f );
+
+	f->used  = NULL;
+	f->level = NULL;
+	f->tag   = NULL;
+	f->data  = NULL;
+	f->max   = f->n = 0;
+}
+
+void
+fields_free( fields *f )
+{
+	int i;
+
+	assert( f );
+
+	for ( i=0; i<f->max; ++i ) {
+		newstr_free( &(f->tag[i]) );
+		newstr_free( &(f->data[i]) );
+	}
+	if ( f->tag )   free( f->tag );
+	if ( f->data )  free( f->data );
+	if ( f->used )  free( f->used );
+	if ( f->level ) free( f->level );
+
+	fields_init( f );
+}
+
+static int
+fields_alloc( fields *f )
+{
+	int i, alloc = 20;
+
+	f->tag   = (newstr *) malloc( sizeof(newstr) * alloc );
+	f->data  = (newstr *) malloc( sizeof(newstr) * alloc );
+	f->used  = (int *)    calloc( alloc, sizeof(int) );
+	f->level = (int *)    calloc( alloc, sizeof(int) );
+	if ( !f->tag || !f->data || !f->used || !f->level ){
+		if ( f->tag )   free( f->tag );
+		if ( f->data )  free( f->data );
+		if ( f->used )  free( f->used );
+		if ( f->level ) free( f->level );
+		fields_init( f );
+		return 0;
+	}
+
+	f->max = alloc;
+	f->n = 0;
+	for ( i=0; i<alloc; ++i ) {
+		newstr_init( &(f->tag[i]) );
+		newstr_init( &(f->data[i]) );
+	}
+	return 1;
+}
+
+static int
+fields_realloc( fields *f )
+{
 	newstr *newtags, *newdata;
 	int *newused, *newlevel;
-	int min_alloc = 20, i, found;
+	int i, alloc = f->max * 2;
+
+	newtags = (newstr*) realloc( f->tag, sizeof(newstr) * alloc );
+	newdata = (newstr*) realloc( f->data, sizeof(newstr) * alloc );
+	newused = (int*)    realloc( f->used, sizeof(int) * alloc );
+	newlevel= (int*)    realloc( f->level, sizeof(int) * alloc );
+
+	if ( newtags )  f->tag   = newtags;
+	if ( newdata )  f->data  = newdata;
+	if ( newused )  f->used  = newused;
+	if ( newlevel ) f->level = newlevel;
+	
+	if ( !newtags || !newdata || !newused || !newlevel )
+		return 0;
+
+	f->max = alloc;
+
+	for ( i=f->n; i<alloc; ++i ) {
+		newstr_init( &(f->tag[i]) );
+		newstr_init( &(f->data[i]) );
+	}
+
+	return 1;
+}
+
+int
+fields_add( fields *f, char *tag, char *data, int level )
+{
+	int i, found;
+
+	assert( f );
+
 	if ( !tag || !data ) return 1;
-	if ( info->maxfields==0 ){
-		info->tag = (newstr*)malloc( sizeof(newstr) * min_alloc );
-		info->data= (newstr*)malloc( sizeof(newstr) * min_alloc );
-		info->used= (int*)      malloc( sizeof(int) * min_alloc );
-		info->level=(int*)      malloc( sizeof(int) * min_alloc );
-		if ( !info->tag || !info->data || !info->used || !info->level ){
-			if ( info->tag ) free( info->tag );
-			if ( info->data ) free( info->data );
-			if ( info->used ) free( info->used );
-			if ( info->level ) free( info->level );
-			return 0;
-		}
-		info->maxfields = min_alloc;
-		info->nfields = 0;
-		for ( i=0; i<min_alloc; ++i ) {
-			newstr_init(&(info->tag[i]));
-			newstr_init(&(info->data[i]));
-		}
-	} else if ( info->nfields >= info->maxfields ){
-		min_alloc = info->maxfields * 2;
-		newtags = (newstr*) realloc( info->tag,
-			       	sizeof(newstr) * min_alloc );
-		newdata = (newstr*) realloc( info->data,
-				sizeof(newstr) * min_alloc );
-		newused = (int*)    realloc( info->used,
-				sizeof(int) * min_alloc );
-		newlevel= (int*)    realloc( info->level,
-				sizeof(int) * min_alloc );
-		if ( !newtags || !newdata || !newused || !newlevel ) {
-			if ( newtags ) info->tag=newtags;
-			if ( newdata ) info->data=newdata;
-			if ( newused ) info->used=newused;
-			if ( newlevel ) info->level=newlevel;
-			return 0;
-		}
-		info->tag = newtags;
-		info->data = newdata;
-		info->used = newused;
-		info->level = newlevel;
-		info->maxfields = min_alloc;
-		for ( i=info->nfields; i<min_alloc; ++i ) {
-			newstr_init(&(info->tag[i]));
-			newstr_init(&(info->data[i]));
-		}
+
+	if ( f->max==0 ) {
+		if ( !fields_alloc( f ) ) return 0;
+	} else if ( f->n >= f->max ) {
+		if ( !fields_realloc( f ) ) return 0;
 	}
+
+	/* Don't duplicate identical entries */
 	found = 0;
-	for ( i=0; i<info->nfields && !found; ++i ) {
-		if ( info->level[i]==level &&
-		     !strcasecmp( info->tag[i].data, tag ) &&
-		     !strcasecmp( info->data[i].data, data ) ) found=1;
+	for ( i=0; i<f->n && !found; ++i ) {
+		if ( f->level[i]==level &&
+		     !strcasecmp( f->tag[i].data, tag ) &&
+		     !strcasecmp( f->data[i].data, data ) ) found = 1;
 	}
 	if ( !found ) {
-		newstr_strcpy( &(info->tag[info->nfields]), tag );
-		newstr_strcpy( &(info->data[info->nfields]), data );
-		info->used[ info->nfields ] = 0;
-		info->level[ info->nfields ] = level;
-		info->nfields++;
+		newstr_strcpy( &(f->tag[f->n]), tag );
+		newstr_strcpy( &(f->data[f->n]), data );
+		f->used[ f->n ] = 0;
+		f->level[ f->n ] = level;
+		f->n++;
 	}
 	return 1;
 }
 
 int
-fields_add_tagsuffix( fields *info, char *tag, char *suffix, char *data, 
-	int level )
+fields_add_tagsuffix( fields *f, char *tag, char *suffix,
+		char *data, int level )
 {
-	char *buf;
-	int len, ret;
-	len = strlen( tag ) + strlen( suffix ) + 1;
-	buf = ( char * ) malloc( sizeof(char)*len );
-	if ( !buf ) return 0;
-	strcpy( buf, tag );
-	strcat( buf, suffix );
-	ret = fields_add( info, buf, data, level );
-	free( buf );
+	newstr newtag;
+	int ret;
+
+	assert( f );
+	assert( tag );
+	assert( suffix );
+
+	newstr_init( &newtag );
+	newstr_mergestrs( &newtag, tag, suffix, NULL );
+	ret = fields_add( f, newtag.data, data, level );
+	newstr_free( &newtag );
+
 	return ret;
 }
 
+/* fields_get_level()
+ *
+ */
+inline int
+fields_get_level( fields *f, int n )
+{
+	assert( f );
+	assert( n>=0 );
+	assert( n<f->n );
 
-fields*
-fields_new( void )
+	return f->level[n];
+}
+
+/* fields_match_level()
+ *
+ * returns 1 if level matched, 0 if not
+ *
+ * level==-1 is a special flag meaning any level can match
+ */
+inline int
+fields_match_level( fields *f, int n, int level )
 {
-	fields *info = ( fields * ) malloc( sizeof( fields ) );
-	if ( info ) fields_init( info );
-	return info;
+	assert( f );
+
+	if ( level==LEVEL_ANY ) return 1;
+	if ( fields_get_level( f, n )==level ) return 1;
+	return 0;
 }
 
-void
-fields_init( fields *info )
+/* fields_match_tag()
+ *
+ * returns 1 if tag matches, 0 if not
+ *
+ */
+inline int
+fields_match_tag( fields *info, int n, char *tag )
 {
-	info->used  = NULL;
-	info->level = NULL;
-	info->tag   = NULL;
-	info->data  = NULL;
-	info->maxfields = info->nfields = 0;
+	if ( !strcmp( fields_tag( info, n, FIELDS_CHRP ), tag ) ) return 1;
+	return 0;
 }
 
-void
-fields_free( fields *info )
+inline int
+fields_match_casetag( fields *info, int n, char *tag )
 {
-	int i;
-	for (i=0; i<info->maxfields; ++i) {
-		newstr_free( &(info->tag[i]) );
-		newstr_free( &(info->data[i]) );
-	}
-	if ( info->tag )  free( info->tag );
-	if ( info->data ) free( info->data );
-	if ( info->used ) free( info->used );
-	if ( info->level ) free( info->level );
-	fields_init( info );
+	if ( !strcasecmp( fields_tag( info, n, FIELDS_CHRP ), tag ) ) return 1;
+	return 0;
 }
 
-int
-fields_find( fields *info, char *searchtag, int level )
+inline int
+fields_match_tag_level( fields *info, int n, char *tag, int level )
 {
-	int i, found = -1;
-	for ( i=0; i<info->nfields && found==-1; ++i ) {
-		if ( (level==-1 || level==info->level[i]) &&
-		     !strcasecmp( info->tag[i].data, searchtag ) ) {
-			found = i;
-			/* if there is no data for the tag, mark as unfound */
-			/* but set "used" so noise is suppressed */
-			if ( info->data[i].len==0 ) {
-				found=-1;
-				info->used[i] = 1;
-			}
-		}
-	}
-	return found;
+	if ( !fields_match_level( info, n, level ) ) return 0;
+	return fields_match_tag( info, n, tag );
 }
 
-int
-fields_find_firstof( fields *info, char *tags[], int ntags, int level )
+inline int
+fields_match_casetag_level( fields *info, int n, char *tag, int level )
 {
-	int i=0, found = -1;
-	while ( i<ntags && found==-1 )
-		found = fields_find( info, tags[i], level );
-	return found;
+	if ( !fields_match_level( info, n, level ) ) return 0;
+	return fields_match_casetag( info, n, tag );
 }
 
+/* fields_find()
+ *
+ * Return position [0,f->n) for match of the tag.
+ * Return -1 if tag isn't found.
+ */
+int
+fields_find( fields *f, char *tag, int level )
+{
+	int i;
 
+	assert( f );
+	assert( tag );
+
+	for ( i=0; i<f->n; ++i ) {
+		if ( !fields_match_casetag_level( f, i, tag, level ) )
+			continue;
+		if ( f->data[i].len ) return i;
+		else {
+			/* if there is no data for the tag, don't "find" it */
+			/* and set "used" so noise is suppressed */
+			f->used[i] = 1;
+		}
+	}
+
+	return -1;
+}
+
 int
-fields_maxlevel( fields *info )
+fields_maxlevel( fields *f )
 {
 	int i, max = 0;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( info->level[i]>max ) max = info->level[i];
+
+	assert( f );
+
+	for ( i=0; i<f->n; ++i ) {
+		if ( f->level[i] > max )
+			max = f->level[i];
 	}
+
 	return max;
 }
 
 void
-fields_clearused( fields *info )
+fields_clearused( fields *f )
 {
 	int i;
-	for ( i=0; i<info->nfields; ++i )
-		info->used[i] = 0;
+
+	assert( f );
+
+	for ( i=0; i<f->n; ++i )
+		f->used[i] = 0;
 }
 
 void
-fields_setused( fields *info, int n )
+fields_setused( fields *f, int n )
 {
-	if ( n < info->nfields )
-		info->used[n] = 1;
+	assert( f );
+
+	if ( n < f->n )
+		f->used[n] = 1;
 }
 
 void
-fields_replace_or_add( fields *info, char *tag, char *data, int level )
+fields_replace_or_add( fields *f, char *tag, char *data, int level )
 {
-	int n = fields_find( info, tag, level );
-	if ( n==-1 ) fields_add( info, tag, data, level );
-	else newstr_strcpy( &(info->data[n]), data );
+	int n = fields_find( f, tag, level );
+	if ( n==-1 ) fields_add( f, tag, data, level );
+	else newstr_strcpy( &(f->data[n]), data );
 }
 
+char *fields_null_value = "\0";
+
+inline int
+fields_used( fields *f, int n )
+{
+	if ( n < f->n ) return f->used[n];
+	else return 0;
+}
+
+inline int
+fields_nodata( fields *f, int n )
+{
+	newstr *d;
+	if ( n < f->n ) {
+		d = &( f->data[n] );
+		if ( d->len > 0 ) return 0;
+		return 1;
+	} else {
+		return 1;
+	}
+}
+
+inline int
+fields_num( fields *f )
+{
+	assert( f );
+	return f->n;
+}
+
+/*
+ * #define FIELDS_CHRP       
+ * #define FIELDS_STRP       
+ * #define FIELDS_CHRP_NOLEN
+ * #define FIELDS_STRP_NOLEN
+ * 
+ * If the length of the tagged value is zero and the mode is
+ * FIELDS_STRP_NOLEN or FIELDS_CHRP_NOLEN, return a pointer to
+ * a static null string as the data field could be new due to
+ * the way newstr handles initialized strings with no data.
+ *
+ */
+
+void *
+fields_value( fields *f, int n, int mode )
+{
+	intptr_t retn;
+
+	assert( f );
+	assert( n >= 0 );
+	assert( n < f->n );
+
+	if ( mode & FIELDS_SETUSE_FLAG )
+		fields_setused( f, n );
+
+	if ( mode & FIELDS_STRP_FLAG )
+		return &(f->data[n]);
+	else if ( mode & FIELDS_POSP_FLAG ) {
+		retn = n;
+		return ( void * ) retn; /* Rather pointless */
+	} else {
+		if ( f->data[n].len )
+			return f->data[n].data;
+		else
+			return fields_null_value;
+	}
+}
+
+void *
+fields_tag( fields *f, int n, int mode )
+{
+	intptr_t retn;
+
+	assert( f );
+	assert( n >= 0 );
+	assert( n < f->n );
+
+	if ( mode & FIELDS_STRP_FLAG )
+		return &(f->tag[n]);
+	else if ( mode & FIELDS_POSP_FLAG ) {
+		retn = n;
+		return ( void * ) retn; /* Rather pointless */
+	} else {
+		if ( f->tag[n].len )
+			return f->tag[n].data;
+		else
+			return fields_null_value;
+	}
+}
+
+int
+fields_level( fields *f, int n )
+{
+	assert( f );
+	assert( n >= 0 );
+	assert( n < f->n );
+
+	return f->level[n];
+}
+
+void *
+fields_findv( fields *f, int level, int mode, char *tag )
+{
+	int i, found = -1;
+	intptr_t retn;
+
+	assert( f );
+	assert( tag );
+
+	for ( i=0; i<f->n && found==-1; ++i ) {
+
+		if ( !fields_match_level( f, i, level ) ) continue;
+		if ( !fields_match_casetag( f, i, tag ) ) continue;
+
+		if ( f->data[i].len!=0 ) found = i;
+		else {
+			if ( mode & FIELDS_NOLENOK_FLAG ) {
+				return (void *) fields_null_value;
+			} else if ( mode & FIELDS_SETUSE_FLAG ) {
+				f->used[i] = 1; /* Suppress "noise" of unused */
+			}
+		}
+	}
+
+	if ( found==-1 ) return NULL;
+
+	if ( mode & FIELDS_SETUSE_FLAG )
+		fields_setused( f, found );
+
+	if ( mode & FIELDS_STRP_FLAG )
+		return (void *) &(f->data[found]);
+	else if ( mode & FIELDS_POSP_FLAG ) {
+		retn = found;
+		return (void *) retn;
+	} else
+		return (void *) f->data[found].data;
+}
+
+void *
+fields_findv_firstof( fields *f, int level, int mode, ... )
+{
+	char *tag, *value;
+	va_list argp;
+
+	assert( f );
+
+	va_start( argp, mode );
+	while ( ( tag = ( char * ) va_arg( argp, char * ) ) ) {
+		value = fields_findv( f, level, mode, tag );
+		if ( value ) {
+			va_end( argp );
+			return value;
+		}
+	}
+	va_end( argp );
+
+	return NULL;
+}
+
+static void
+fields_findv_each_add( fields *f, int mode, int n, vplist *a )
+{
+	intptr_t retn;
+
+	assert( a );
+	assert( f );
+	assert( n >= 0 );
+	assert( n < f->n );
+
+	if ( mode & FIELDS_SETUSE_FLAG )
+		fields_setused( f, n );
+
+	if ( mode & FIELDS_STRP_FLAG ) {
+		vplist_add( a, (void *) &(f->data[n]) );
+	} else if ( mode & FIELDS_POSP_FLAG ) {
+		retn = n;
+		vplist_add( a, (void *) retn );
+	} else {
+		vplist_add( a, (void *) f->data[n].data );
+	}
+}
+
+void
+fields_findv_each( fields *f, int level, int mode, vplist *a, char *tag )
+{
+	int i;
+
+	assert( a );
+	assert( tag );
+	assert( f );
+
+	for ( i=0; i<f->n; ++i ) {
+
+		if ( !fields_match_level( f, i, level ) ) continue;
+		if ( !fields_match_casetag( f, i, tag ) ) continue;
+
+		if ( f->data[i].len!=0 ) {
+			fields_findv_each_add( f, mode, i, a );
+		} else {
+			if ( mode & FIELDS_NOLENOK_FLAG ) {
+				fields_findv_each_add( f, mode, i, a );
+			} else {
+				f->used[i] = 1; /* Suppress "noise" of unused */
+			}
+		}
+
+	}
+}
+
+void
+fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... )
+{
+	va_list argp;
+	vplist tags;
+	char *tag;
+	int i, j, found;
+
+	assert( f );
+	assert( a );
+
+	vplist_init( &tags );
+
+	/* build list of tags to search for */
+	va_start( argp, a );
+	while ( ( tag = ( char * ) va_arg( argp, char * ) ) )
+		vplist_add( &tags, tag );
+	va_end( argp );
+
+	/* search list */
+	for ( i=0; i<f->n; ++i ) {
+
+		if ( !fields_match_level( f, i, level ) ) continue;
+
+		found = 0;
+		for ( j=0; j<tags.n && !found; ++j ) {
+			if ( fields_match_casetag( f, i, vplist_get( &tags, j ) ) )
+				found = 1;
+		}
+		if ( !found ) continue;
+
+		if ( f->data[i].len!=0 ) {
+			fields_findv_each_add( f, mode, i, a );
+		} else {
+			if ( mode & FIELDS_NOLENOK_FLAG ) {
+				fields_findv_each_add( f, mode, i, a );
+			} else {
+				f->used[i] = 1; /* Suppress "noise" of unused */
+			}
+		}
+
+	}
+
+	vplist_free( &tags );
+}
diff --git a/bibutils/fields.h b/bibutils/fields.h
--- a/bibutils/fields.h
+++ b/bibutils/fields.h
@@ -1,7 +1,7 @@
 /*
  * fields.h
  *
- * Copyright (c) Chris Putnam 2003-2009
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  *
@@ -9,36 +9,74 @@
 #ifndef FIELDS_H
 #define FIELDS_H
 
-#define LEVEL_MAIN (0)
-#define LEVEL_HOST (1)
-#define LEVEL_SERIES (2)
+#define LEVEL_ANY    (-1)
+#define LEVEL_MAIN    (0)
+#define LEVEL_HOST    (1)
+#define LEVEL_SERIES  (2)
 
 #define LEVEL_ORIG (-2)
 
+#include <stdarg.h>
 #include "newstr.h"
+#include "vplist.h"
 
 typedef struct {
 	newstr    *tag;
 	newstr    *data;
 	int       *used;
 	int       *level;
-	int       nfields;
-	int       maxfields;
+	int       n;
+	int       max;
 } fields;
 
-extern int  fields_add( fields *info, char *tag, char *data, int level );
-extern int  fields_add_tagsuffix( fields *info, char *tag, char *suffix,
-		char *data, int level );
-extern void fields_free( fields *info );
-extern void fields_init( fields *info );
+extern void fields_init( fields *f );
 extern fields *fields_new( void );
-extern int  fields_find( fields *info, char *searchtag, int level );
-extern int  fields_find_firstof( fields *info, char *tags[], int ntags, 
-		int level );
-extern int  fields_maxlevel( fields *info );
-extern void fields_clearused( fields *info );
-extern void fields_setused( fields *info, int n );
-extern void fields_replace_or_add( fields *info, char *tag, char *data, int level );
+extern void fields_free( fields *f );
 
+extern int  fields_add( fields *f, char *tag, char *data, int level );
+extern int  fields_add_tagsuffix( fields *f, char *tag, char *suffix,
+		char *data, int level );
+
+extern int  fields_maxlevel( fields *f );
+extern void fields_clearused( fields *f );
+extern void fields_setused( fields *f, int n );
+extern void fields_replace_or_add( fields *f, char *tag, char *data, int level );
+
+extern inline int fields_num( fields *f );
+extern inline int fields_used( fields *f, int n );
+extern inline int fields_nodata( fields *f, int n );
+extern inline int fields_get_level( fields *f, int n );
+
+extern inline int fields_match_level( fields *f, int n, int level );
+extern inline int fields_match_tag( fields *f, int n, char *tag );
+extern inline int fields_match_casetag( fields *f, int n, char *tag );
+extern inline int fields_match_tag_level( fields *f, int n, char *tag, int level );
+extern inline int fields_match_casetag_level( fields *f, int n, char *tag, int level );
+
+#define FIELDS_STRP_FLAG     (2)
+#define FIELDS_POSP_FLAG     (4)
+#define FIELDS_NOLENOK_FLAG  (8)
+#define FIELDS_SETUSE_FLAG  (16)
+
+#define FIELDS_CHRP        (FIELDS_SETUSE_FLAG                                         )
+#define FIELDS_STRP        (FIELDS_SETUSE_FLAG | FIELDS_STRP_FLAG                      )
+#define FIELDS_POSP        (FIELDS_SETUSE_FLAG | FIELDS_POSP_FLAG                      )
+#define FIELDS_CHRP_NOLEN  (FIELDS_SETUSE_FLAG |                    FIELDS_NOLENOK_FLAG)
+#define FIELDS_STRP_NOLEN  (FIELDS_SETUSE_FLAG | FIELDS_STRP_FLAG | FIELDS_NOLENOK_FLAG)
+#define FIELDS_POSP_NOLEN  (FIELDS_SETUSE_FLAG | FIELDS_POSP_FLAG | FIELDS_NOLENOK_FLAG)
+#define FIELDS_CHRP_NOUSE  (                            0                              )
+#define FIELDS_STRP_NOUSE  (                     FIELDS_STRP_FLAG                      )
+
+extern void *fields_tag( fields *f, int n, int mode );
+extern void *fields_value( fields *f, int n, int mode );
+extern int   fields_level( fields *f, int n );
+ 
+extern int   fields_find( fields *f, char *searchtag, int level );
+
+extern void *fields_findv( fields *f, int level, int mode, char *tag );
+extern void *fields_findv_firstof( fields *f, int level, int mode, ... );
+
+extern void  fields_findv_each( fields *f, int level, int mode, vplist *a, char *tag );
+extern void  fields_findv_eachof( fields *f, int level, int mode, vplist *a, ... );
 
 #endif
diff --git a/bibutils/gb18030.h b/bibutils/gb18030.h
--- a/bibutils/gb18030.h
+++ b/bibutils/gb18030.h
@@ -1,7 +1,7 @@
 /*
  * gb18030.h
  *
- * Copyright (c) Chris Putnam 2008-2009
+ * Copyright (c) Chris Putnam 2008-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/is_ws.c b/bibutils/is_ws.c
--- a/bibutils/is_ws.c
+++ b/bibutils/is_ws.c
@@ -1,7 +1,7 @@
 /*
  * is_ws.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/is_ws.h b/bibutils/is_ws.h
--- a/bibutils/is_ws.h
+++ b/bibutils/is_ws.h
@@ -1,7 +1,7 @@
 /*
  * is_ws.h
  *
- * Copyright (c) Chris Putnam 2003-2009
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/isiin.c b/bibutils/isiin.c
--- a/bibutils/isiin.c
+++ b/bibutils/isiin.c
@@ -1,7 +1,7 @@
 /*
  * isiin.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
@@ -148,7 +148,7 @@
 		if ( (tag.len>1) && isiin_istag( tag.data ) ) {
 			fields_add( isiin, tag.data, data.data, 0 );
 		} else {
-			n = isiin->nfields;
+			n = fields_num( isiin );
 			if ( n>0 ) {
 				/* only one AU or AF for list of authors */
 				if ( !strcmp( isiin->tag[n-1].data,"AU") ){
@@ -204,21 +204,23 @@
 static void
 isiin_addauthors( fields *isiin, fields *info, int reftype, variants *all, int nall, list *asis, list *corps )
 {
-	newstr *t, *d;
 	char *newtag, *authortype, use_af[]="AF", use_au[]="AU";
-	int level, i, n, has_af=0, has_au=0;
-	for ( i=0; i<isiin->nfields && has_af==0; ++i ) {
-		t = &( isiin->tag[i] );
+	int level, i, n, has_af=0, has_au=0, nfields;
+	newstr *t, *d;
+
+	nfields = fields_num( isiin );
+	for ( i=0; i<nfields && has_af==0; ++i ) {
+		t = fields_tag( isiin, i, FIELDS_STRP );
 		if ( !strcasecmp( t->data, "AU" ) ) has_au++;
 		if ( !strcasecmp( t->data, "AF" ) ) has_af++;
 	}
 	if ( has_af ) authortype = use_af;
 	else authortype = use_au;
-	for ( i=0; i<isiin->nfields; ++i ) {
-		t = &( isiin->tag[i] );
+	for ( i=0; i<nfields; ++i ) {
+		t = fields_tag( isiin, i, FIELDS_STRP );
 		if ( !strcasecmp( t->data, "AU" ) ) has_au++;
 		if ( strcasecmp( t->data, authortype ) ) continue;
-		d = &( isiin->data[i] );
+		d = fields_value( isiin, i, FIELDS_STRP );
 		n = process_findoldtag( authortype, reftype, all, nall );
 		level = ((all[reftype]).tags[n]).level;
 		newtag = all[reftype].tags[n].newstr;
@@ -238,38 +240,58 @@
 void
 isiin_convertf( fields *isiin, fields *info, int reftype, param *p, variants *all, int nall )
 {
+	int process, level, i, n, nfields;
 	newstr *t, *d;
-	int process, level, i, n;
 	char *newtag;
 
-	isiin_addauthors( isiin, info, reftype, all, nall, &(p->asis), 
-			&(p->corps) );
+	isiin_addauthors( isiin, info, reftype, all, nall, &(p->asis), &(p->corps) );
 
-	for ( i=0; i<isiin->nfields; ++i ) {
-		t = &( isiin->tag[i] );
+	nfields = fields_num( isiin );
+	for ( i=0; i<nfields; ++i ) {
+
+		t = fields_tag( isiin, i, FIELDS_STRP );
 		if ( !strcasecmp( t->data, "AU" ) || !strcasecmp( t->data, "AF" ) )
 			continue;
-		d = &( isiin->data[i] );
+
 		n = process_findoldtag( t->data, reftype, all, nall );
 		if ( n==-1 ) {
 			isiin_report_notag( p, t->data );
 			continue;
 		}
+
+		d = fields_value( isiin, i, FIELDS_STRP );
 		process = ((all[reftype]).tags[n]).processingtype;
 		level = ((all[reftype]).tags[n]).level;
 		newtag = all[reftype].tags[n].newstr;
-		if ( process == SIMPLE || process == DATE )
+
+		switch ( process ) {
+
+		case SIMPLE:
 			fields_add( info, newtag, d->data, level );
-		else if ( process == PERSON )
-			name_add( info, newtag, d->data, level, &(p->asis), 
-					&(p->corps) );
-		else if ( process == TITLE )
-			title_process( info, newtag, d->data, level, 
-					p->nosplittitle );
-		else if ( process == ISI_KEYWORD )
+			break;
+
+		case DATE:
+			fields_add( info, newtag, d->data, level );
+			break;
+
+		case PERSON:
+			name_add( info, newtag, d->data, level, &(p->asis), &(p->corps) );
+			break;
+
+		case TITLE:
+			title_process( info, newtag, d->data, level, p->nosplittitle );
+			break;
+
+		case KEYWORD:
 			keyword_process( info, newtag, d->data, level );
-		else if ( process == SERIALNO )
+			break;
+
+		case SERIALNO:
 			addsn( info, d->data, level );
+			break;
+
+		}
+
 		/* do nothing if process==TYPE || process==ALWAYS */
 	}
 }
diff --git a/bibutils/isiin.h b/bibutils/isiin.h
--- a/bibutils/isiin.h
+++ b/bibutils/isiin.h
@@ -1,7 +1,7 @@
 /*
  * isiin.h
  * 
- * Copyright (c) Chris Putnam 2004-2009
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/isiout.c b/bibutils/isiout.c
--- a/bibutils/isiout.c
+++ b/bibutils/isiout.c
@@ -1,7 +1,7 @@
 /*
  * isiout.c
  *
- * Copyright (c) Chris Putnam 2008-2010
+ * Copyright (c) Chris Putnam 2008-2012
  *
  * Source code released under the GPL
  */
@@ -32,6 +32,10 @@
 	p->addcount         = 0;
 	p->singlerefperfile = 0;
 
+	if ( p->charsetout == BIBL_CHARSET_UNICODE ) {
+		p->utf8out = p->utf8bom = 1;
+	}
+
 	p->headerf = isiout_writeheader;
 	p->footerf = NULL;
 	p->writef  = isiout_write;
@@ -56,61 +60,81 @@
 }
 
 static int 
-get_type( fields *info )
+get_type( fields *f )
 {
-	char *tag, *data;
-        int type = TYPE_UNKNOWN, i;
-        for ( i=0; i<info->nfields; ++i ) {
-		tag = info->tag[i].data;
+        int type = TYPE_UNKNOWN, i, n, level;
+	char *tag, *value;
+	n = fields_num( f );
+        for ( i=0; i<n; ++i ) {
+		tag = fields_tag( f, i, FIELDS_CHRP );
                 if ( strcasecmp( tag, "GENRE" ) &&
                      strcasecmp( tag, "NGENRE") ) continue;
-		data = info->data[i].data;
-                if ( !strcasecmp( data, "periodical" ) ||
-                     !strcasecmp( data, "academic journal" ) )
+		value = fields_value( f, i, FIELDS_CHRP );
+		level = fields_level( f, i );
+                if ( !strcasecmp( value, "periodical" ) ||
+                     !strcasecmp( value, "academic journal" ) ||
+		     !strcasecmp( value, "journal article" ) ) {
                         type = TYPE_ARTICLE;
-                else if ( !strcasecmp( data, "book" ) ) {
-                        if ( info->level[i]==0 ) type=TYPE_BOOK;
+                } else if ( !strcasecmp( value, "book" ) ) {
+                        if ( level==0 ) type=TYPE_BOOK;
                         else type=TYPE_INBOOK;
+		} else if ( !strcasecmp( value, "book chapter" ) ) {
+			type = TYPE_INBOOK;
                 }
         }
         return type;
 }
 
 static void
-output_title( FILE *fp, fields *info, char *isitag, int level )
+output_titlecore( FILE *fp, fields *f, char *isitag, int level,
+	char *maintag, char *subtag )
 {
-        int n1 = fields_find( info, "TITLE", level );
-        int n2 = fields_find( info, "SUBTITLE", level );
-        if ( n1!=-1 ) {
-                fprintf( fp, "%s %s", isitag, info->data[n1].data );
-                if ( n2!=-1 ) {
-                        if ( info->data[n1].data[info->data[n1].len]!='?' )
-                                fprintf( fp, ": " );
-                        else fprintf( fp, " " );
-                        fprintf( fp, "%s", info->data[n2].data );
-                }
-                fprintf( fp, "\n" );
-        }
+	newstr *mainttl = fields_findv( f, level, FIELDS_STRP, maintag );
+	newstr *subttl  = fields_findv( f, level, FIELDS_STRP, subtag );
+
+	if ( !mainttl ) return;
+
+	fprintf( fp, "%s %s", isitag, mainttl->data );
+	if ( subttl ) {
+		if ( mainttl->len > 0 &&
+		     mainttl->data[ mainttl->len - 1 ]!='?' )
+				fprintf( fp, ":" );
+		fprintf( fp, " %s", subttl->data );
+	}
+	fprintf( fp, "\n" );
 }
 
 static void
-output_abbrtitle( FILE *fp, fields *info, char *isitag, int level )
+output_title( FILE *fp, fields *f, char *isitag, int level )
 {
-        int n1 = fields_find( info, "SHORTTITLE", level );
-        int n2 = fields_find( info, "SHORTSUBTITLE", level );
-        if ( n1!=-1 ) {
-                fprintf( fp, "%s %s", isitag, info->data[n1].data );
-                if ( n2!=-1 ){
-                        if ( info->data[n1].data[info->data[n1].len]!='?' )
-                                fprintf( fp, ": " );
-                        else fprintf( fp, " " );
-                        fprintf( fp, "%s", info->data[n2].data );
-                }
-                fprintf( fp, "\n" );
-        }
+	output_titlecore( fp, f, isitag, level, "TITLE", "SUBTITLE" );
 }
 
 static void
+output_abbrtitle( FILE *fp, fields *f, char *isitag, int level )
+{
+	output_titlecore( fp, f, isitag, level, "SHORTTITLE", "SHORTSUBTITLE" );
+}
+
+static void
+output_keywords( FILE *fp, fields *f )
+{
+	vplist kw;
+	int i;
+	vplist_init( &kw );
+	fields_findv_each( f, LEVEL_ANY, FIELDS_CHRP, &kw, "KEYWORD" );
+	if ( kw.n ) {
+		fprintf( fp, "DE " );
+		for ( i=0; i<kw.n; ++i ) {
+			if ( i>0 ) fprintf( fp, "; " );
+			fprintf( fp, "%s", (char *)vplist_get( &kw, i ) );
+		}
+		fprintf( fp, "\n" );
+	}
+	vplist_free( &kw );
+}
+
+static void
 output_person( FILE *fp, char *name )
 {
 	int n = 0, nchars = 0;
@@ -129,151 +153,134 @@
 }
 
 static void
-output_keywords( FILE *fp, fields *info )
-{
-	int n = 0, i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcasecmp( info->tag[i].data, "KEYWORD" ) ) continue;
-		if ( n==0 )
-			fprintf( fp, "DE " );
-		if ( n>0 )
-			fprintf( fp, "; " );
-		fprintf( fp, "%s", info->data[i].data );
-		n++;
-	}
-	if ( n ) fprintf( fp, "\n" );
-}
-
-static void
-output_people( FILE *fp, fields *info, char *tag, char *isitag, int level )
+output_people( FILE *fp, fields *f, char *tag, char *isitag, int level )
 {
-	int n = 0, i;
-        for ( i=0; i<info->nfields; ++i ) {
-                if ( strcasecmp( info->tag[i].data, tag ) ) continue;
-		if ( level!=-1 && info->level[i]!=level ) continue;
-		if ( n==0 ) {
-			fprintf( fp, "%s ", isitag );
-		} else {
-			fprintf( fp, "   " );
+	vplist people;
+	int i;
+	vplist_init( &people );
+	fields_findv_each( f, level, FIELDS_CHRP, &people, tag );
+	if ( people.n ) {
+		fprintf( fp, "%s ", isitag );
+		for ( i=0; i<people.n; ++i ) {
+			if ( i!=0 ) fprintf( fp, "   " );
+			output_person( fp, (char *)vplist_get( &people, i ) );
+			fprintf( fp, "\n" );
 		}
-		output_person( fp, info->data[i].data );
-		fprintf( fp, "\n" );
-		n++;
 	}
+	vplist_free( &people );
 }
 
 static void
-output_easy( FILE *fp, fields *info, char *tag, char *isitag, int level )
+output_easy( FILE *fp, fields *f, char *tag, char *isitag, int level )
 {
-        int n = fields_find( info, tag, level );
-        if ( n!=-1 )
-                fprintf( fp, "%s %s\n", isitag, info->data[n].data );
+	char *value = fields_findv( f, level, FIELDS_CHRP, tag );
+	if ( value ) fprintf( fp, "%s %s\n", isitag, value );
 }
 
 static void
-output_easyall( FILE *fp, fields *info, char *tag, char *isitag, int level )
+output_easyall( FILE *fp, fields *f, char *tag, char *isitag, int level )
 {
+	vplist a;
 	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( level!=-1 && info->level[i]!=level ) continue;
-		if ( strcasecmp( info->tag[i].data, tag ) ) continue;
-		fprintf( fp, "%s %s\n", isitag, info->data[i].data );
-	}
+	vplist_init( &a );
+	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
+	for ( i=0; i<a.n; ++i )
+		fprintf( fp, "%s %s\n", isitag, (char *) vplist_get( &a, i ) );
+	vplist_free( &a );
 }
 
-
 static void
-output_date( FILE *fp, fields *info )
+output_date( FILE *fp, fields *f )
 {
-	int n;
-
-	n = fields_find( info, "PARTMONTH", -1 );
-	if ( n==-1 ) n = fields_find( info, "MONTH", -1 );
-	if ( n!=-1 ) fprintf( fp, "%s %s\n", "PD", info->data[n].data );
-
-	n = fields_find( info, "PARTYEAR", -1 );
-	if ( n==-1 ) n = fields_find( info, "YEAR", -1 );
-	if ( n!=-1 ) fprintf( fp, "%s %s\n", "PY", info->data[n].data );
+	char *month = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
+		"PARTMONTH", "MONTH", NULL );
+	char *year  = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
+		"PARTYEAR", "YEAR", NULL );
+	if ( month ) fprintf( fp, "PD %s\n", month );
+	if ( year )  fprintf( fp, "PY %s\n", year );
 }
 
 static void
-output_verbose( fields *info, unsigned long refnum )
+output_verbose( fields *f, unsigned long refnum )
 {
-	int i;
+	char *tag, *value;
+	int i, n, level;
 	fprintf( stderr, "REF #%lu----\n", refnum+1 );
-	for ( i=0; i<info->nfields; ++i ) {
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		tag   = fields_tag( f, i, FIELDS_CHRP_NOUSE );
+		value = fields_value( f, i, FIELDS_CHRP_NOUSE );
+		level = fields_level( f, i );
 		fprintf( stderr, "\t'%s'\t'%s'\t%d\n",
-			info->tag[i].data,
-			info->data[i].data,
-			info->level[i]);
+			tag, value, level );
 	}
 }
 
 void
-isiout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
+isiout_write( fields *f, FILE *fp, param *p, unsigned long refnum )
 {
-        int type = get_type( info );
+        int type = get_type( f );
 
 	if ( p->format_opts & BIBL_FORMAT_VERBOSE )
-		output_verbose( info, refnum );
+		output_verbose( f, refnum );
 
         output_type( fp, type );
-	output_people( fp, info, "AUTHOR", "AU", 0 );
-	output_easyall( fp, info, "AUTHOR:CORP", "AU", 0 );
-	output_easyall( fp, info, "AUTHOR:ASIS", "AU", 0 );
-/*      output_people( fp, info, "AUTHOR", "A2", 1 );
-        output_people( fp, info, "AUTHOR:CORP", "A2", 1 );
-        output_people( fp, info, "AUTHOR:ASIS", "A2", 1 );
-        output_people( fp, info, "AUTHOR", "A3", 2 );
-        output_people( fp, info, "AUTHOR:CORP", "A3", 2 );
-        output_people( fp, info, "AUTHOR:ASIS", "A3", 2 );
-        output_people( fp, info, "EDITOR", "ED", -1 );
-	output_people( fp, info, "EDITOR:CORP", "ED", -1 );
-        output_people( fp, info, "EDITOR:ASIS", "ED", -1 );*/
-/*        output_date( fp, info, refnum );*/
+	output_people( fp, f, "AUTHOR", "AU", 0 );
+	output_easyall( fp, f, "AUTHOR:CORP", "AU", 0 );
+	output_easyall( fp, f, "AUTHOR:ASIS", "AU", 0 );
+/*      output_people( fp, f, "AUTHOR", "A2", 1 );
+        output_people( fp, f, "AUTHOR:CORP", "A2", 1 );
+        output_people( fp, f, "AUTHOR:ASIS", "A2", 1 );
+        output_people( fp, f, "AUTHOR", "A3", 2 );
+        output_people( fp, f, "AUTHOR:CORP", "A3", 2 );
+        output_people( fp, f, "AUTHOR:ASIS", "A3", 2 );
+        output_people( fp, f, "EDITOR", "ED", -1 );
+	output_people( fp, f, "EDITOR:CORP", "ED", -1 );
+        output_people( fp, f, "EDITOR:ASIS", "ED", -1 );*/
+/*        output_date( fp, f, refnum );*/
 
-        output_title( fp, info, "TI", 0 );
+        output_title( fp, f, "TI", 0 );
         if ( type==TYPE_ARTICLE ) {
-                output_title( fp, info, "SO", 1 );
-		output_abbrtitle( fp, info, "JI", 1 );
+                output_title( fp, f, "SO", 1 );
+		output_abbrtitle( fp, f, "JI", 1 );
 	}
-        else output_title( fp, info, "BT", 1 );
+        else output_title( fp, f, "BT", 1 );
 
-	output_date( fp, info );
-/*	output_easy( fp, info, "PARTMONTH", "PD", -1 );
-	output_easy( fp, info, "PARTYEAR", "PY", -1 );*/
+	output_date( fp, f );
+/*	output_easy( fp, f, "PARTMONTH", "PD", -1 );
+	output_easy( fp, f, "PARTYEAR", "PY", -1 );*/
 
-	output_easy( fp, info, "PAGESTART", "BP", -1 );
-	output_easy( fp, info, "PAGEEND",   "EP", -1 );
-        output_easy( fp, info, "ARTICLENUMBER", "AR", -1 );
+	output_easy( fp, f, "PAGESTART", "BP", -1 );
+	output_easy( fp, f, "PAGEEND",   "EP", -1 );
+        output_easy( fp, f, "ARTICLENUMBER", "AR", -1 );
         /* output article number as pages */
-	output_easy( fp, info, "TOTALPAGES","PG", -1 );
+	output_easy( fp, f, "TOTALPAGES","PG", -1 );
 
-        output_easy( fp, info, "VOLUME",    "VL", -1 );
-        output_easy( fp, info, "ISSUE",     "IS", -1 );
-        output_easy( fp, info, "NUMBER",    "IS", -1 );
-	output_easy( fp, info, "DOI",       "DI", -1 );
-	output_easy( fp, info, "ISIREFNUM", "UT", -1 );
-	output_easy( fp, info, "LANGUAGE",  "LA", -1 );
-	output_easy( fp, info, "ISIDELIVERNUM", "GA", -1 );
-	output_keywords( fp, info );
-	output_easy( fp, info, "ABSTRACT",  "AB", -1 );
-	output_easy( fp, info, "TIMESCITED", "TC", -1 );
-	output_easy( fp, info, "NUMBERREFS", "NR", -1 );
-	output_easy( fp, info, "CITEDREFS",  "CR", -1 );
-	output_easy( fp, info, "ADDRESS",    "PI", -1 );
+        output_easy( fp, f, "VOLUME",    "VL", -1 );
+        output_easy( fp, f, "ISSUE",     "IS", -1 );
+        output_easy( fp, f, "NUMBER",    "IS", -1 );
+	output_easy( fp, f, "DOI",       "DI", -1 );
+	output_easy( fp, f, "ISIREFNUM", "UT", -1 );
+	output_easy( fp, f, "LANGUAGE",  "LA", -1 );
+	output_easy( fp, f, "ISIDELIVERNUM", "GA", -1 );
+	output_keywords( fp, f );
+	output_easy( fp, f, "ABSTRACT",  "AB", -1 );
+	output_easy( fp, f, "TIMESCITED", "TC", -1 );
+	output_easy( fp, f, "NUMBERREFS", "NR", -1 );
+	output_easy( fp, f, "CITEDREFS",  "CR", -1 );
+	output_easy( fp, f, "ADDRESS",    "PI", -1 );
 
-/*        output_easy( fp, info, "PUBLISHER", "PB", -1 );
-        output_easy( fp, info, "DEGREEGRANTOR", "PB", -1 );
-        output_easy( fp, info, "ADDRESS", "CY", -1 );
-        output_easy( fp, info, "ABSTRACT", "AB", -1 );
-        output_easy( fp, info, "ISSN", "SN", -1 );
-        output_easy( fp, info, "ISBN", "SN", -1 );
-        output_easyall( fp, info, "URL", "UR", -1 );
-        output_easyall( fp, info, "FILEATTACH", "UR", -1 );
-        output_pubmed( fp, info, refnum );
-        output_easyall( fp, info, "NOTES", "N1", -1 );
-        output_easyall( fp, info, "REFNUM", "ID", -1 );*/
+/*        output_easy( fp, f, "PUBLISHER", "PB", -1 );
+        output_easy( fp, f, "DEGREEGRANTOR", "PB", -1 );
+        output_easy( fp, f, "ADDRESS", "CY", -1 );
+        output_easy( fp, f, "ABSTRACT", "AB", -1 );
+        output_easy( fp, f, "ISSN", "SN", -1 );
+        output_easy( fp, f, "ISBN", "SN", -1 );
+        output_easyall( fp, f, "URL", "UR", -1 );
+        output_easyall( fp, f, "FILEATTACH", "UR", -1 );
+        output_pubmed( fp, f, refnum );
+        output_easyall( fp, f, "NOTES", "N1", -1 );
+        output_easyall( fp, f, "REFNUM", "ID", -1 );*/
         fprintf( fp, "ER\n\n" );
         fflush( fp );
 }
diff --git a/bibutils/isiout.h b/bibutils/isiout.h
--- a/bibutils/isiout.h
+++ b/bibutils/isiout.h
@@ -1,7 +1,7 @@
 /*
  * isiout.h
  *
- * Copyright (c) Chris Putnam 2007-2009
+ * Copyright (c) Chris Putnam 2007-2012
  *
  */
 #ifndef ISIOUT_H
diff --git a/bibutils/isitypes.c b/bibutils/isitypes.c
--- a/bibutils/isitypes.c
+++ b/bibutils/isitypes.c
@@ -1,7 +1,7 @@
 /*
  * isitypes.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
@@ -36,8 +36,8 @@
 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST },
 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },
-	{ "DE",     "KEYWORD",   ISI_KEYWORD, LEVEL_MAIN }, /* author keywords */
-	{ "ID",     "KEYWORD",   ISI_KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
+	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */
+	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
 	{ "TC",     "TIMESCITED", SIMPLE, LEVEL_MAIN },
 	{ "NR",     "NUMBERREFS", SIMPLE, LEVEL_MAIN },
@@ -51,6 +51,7 @@
 	{ " ",      "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },
 	{ " ",      "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
 	{ " ",      "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
+	{ " ",      "GENRE|journal article",  ALWAYS, LEVEL_MAIN },
 	{ " ",      "GENRE|periodical",       ALWAYS, LEVEL_HOST },
 	{ " ",      "GENRE|academic journal", ALWAYS, LEVEL_HOST }
 };
@@ -77,8 +78,8 @@
 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST },
 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },
-	{ "DE",     "KEYWORD",   ISI_KEYWORD, LEVEL_MAIN }, /* author keywords */
-	{ "ID",     "KEYWORD",   ISI_KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
+	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */
+	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
 	{ "TC",     "TIMESCITED", SIMPLE, LEVEL_MAIN },
 	{ "NR",     "NUMBERREFS", SIMPLE, LEVEL_MAIN },
@@ -118,8 +119,8 @@
 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST },
 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },
-	{ "DE",     "KEYWORD",   ISI_KEYWORD, LEVEL_MAIN }, /* author keywords */
-	{ "ID",     "KEYWORD",   ISI_KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
+	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */
+	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
 	{ "TC",     "TIMESCITED", SIMPLE, LEVEL_MAIN },
 	{ "NR",     "NUMBERREFS", SIMPLE, LEVEL_MAIN },
@@ -129,10 +130,11 @@
 	{ "GA",     "ISIDELIVERNUM", SIMPLE, LEVEL_MAIN}, /*ISI document delivery number */
 	{ "UT",     "ISIREFNUM", SIMPLE, LEVEL_MAIN }, /* ISI unique article identifer */
 	{ "DI",     "DOI",       SIMPLE, LEVEL_MAIN },
-	{ " ",      "INTERNAL_TYPE|INBOOK",   ALWAYS, LEVEL_MAIN },
-	{ " ",      "RESOURCE|text", ALWAYS, LEVEL_MAIN },
-	{ " ",      "ISSUANCE|monographic",    ALWAYS, LEVEL_HOST },
-	{ " ",      "GENRE|book",    ALWAYS, LEVEL_HOST }
+	{ " ",      "INTERNAL_TYPE|INBOOK", ALWAYS, LEVEL_MAIN },
+	{ " ",      "RESOURCE|text",        ALWAYS, LEVEL_MAIN },
+	{ " ",      "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },
+        { " ",      "GENRE|book chapter",   ALWAYS, LEVEL_MAIN },
+	{ " ",      "GENRE|book",           ALWAYS, LEVEL_HOST }
 };
 
 static lookups bookinseries[] = {
@@ -159,8 +161,8 @@
 	{ "SN",     "SERIALNUMBER", SERIALNO, LEVEL_HOST },
 	{ "AB",     "ABSTRACT",  SIMPLE, LEVEL_MAIN },
 	{ "NF",     "NOTES",     SIMPLE, LEVEL_MAIN },
-	{ "DE",     "KEYWORD",   ISI_KEYWORD, LEVEL_MAIN }, /* author keywords */
-	{ "ID",     "KEYWORD",   ISI_KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
+	{ "DE",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* author keywords */
+	{ "ID",     "KEYWORD",   KEYWORD, LEVEL_MAIN }, /* new ISI keywords */
 	{ "LA",     "LANGUAGE",  SIMPLE, LEVEL_MAIN },
 	{ "TC",     "TIMESCITED", SIMPLE, LEVEL_MAIN },
 	{ "NR",     "NUMBERREFS", SIMPLE, LEVEL_MAIN },
diff --git a/bibutils/latex.c b/bibutils/latex.c
--- a/bibutils/latex.c
+++ b/bibutils/latex.c
@@ -3,7 +3,7 @@
  *
  * convert between latex special chars and unicode
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
@@ -19,17 +19,17 @@
 
 static struct latex_chars latex_chars[] = { 
 
-   {  35, "\\#",     "",   ""        }, /* Number/pound/hash sign */
-   {  36, "\\$",     "",   ""        }, /* Dollar Sign */
-   {  37, "\\%",     "",   ""        }, /* Percent Sign */
-   {  38, "\\&",     "",   ""        }, /* Ampersand */
+   {  35, "\\#",     "",   ""        },    /* Number/pound/hash sign */
+   {  36, "\\$",     "",   ""        },    /* Dollar Sign */
+   {  37, "\\%",     "",   ""        },    /* Percent Sign */
+   {  38, "\\&",     "",   ""        },    /* Ampersand */
    {  92, "{\\backslash}", "\\backslash", ""   }, /* Backslash */
    { 123, "\\{", "{\\textbraceleft}", "\\textbraceleft" }, /* Left Curly Bracket */
    { 125, "\\}", "{\\textbraceright}", "\\textbraceright" }, /* Right Curly Bracket */
-   {  95, "\\_",     "", ""        }, /* Underscore alone indicates subscript */
+   {  95, "\\_",     "", ""        },      /* Underscore alone indicates subscript */
    { 176, "{\\textdegree}", "\\textdegree", "^\\circ" }, /* Degree sign */
-   {  32, "~",       "\\ ", ""        }, /* Tilde is a sticky space */
-   { 126, "{\\textasciitilde}", "\\textasciitilde", "\\~{}" }, /* How to get a tilde in latex */
+   {  32, "~",       "\\ ", ""        },   /* "sticky" space */
+   { 126, "{\\textasciitilde}", "\\textasciitilde", "\\~{}" }, /* Tilde in latex */
                                  /* This is a cheat, should use "\verb" */
                                  /* Need same for ^ character */
 
@@ -39,7 +39,11 @@
    { 194, "{\\^A}",  "\\^{A}",  "\\^A"  }, /*               with circumflex */
    { 195, "{\\~A}",  "\\~{A}",  "\\~A"  }, /*               with tilde */
    { 196, "{\\\"A}", "\\\"{A}", "\\\"A" }, /*               with diuresis */
-   { 197, "{\\AA}",  "",        ""      }, /*               with ring above */
+   { 197, "{\\AA}",  "{\\r{A}}","\\r{A}"}, /*               with ring above */
+   { 256, "{\\={A}}","\\={A}",  "\\=A"  }, /*               with macron */
+   { 258, "{\\u{A}}","\\u{A}",  "\\u A" }, /*               with breve */
+   { 260, "{\\k{A}}","\\k{A}",  "\\k A" }, /*               with ogonek */
+   { 461, "{\\v{A}}","\\v{A}",  "\\v A" }, /*               with caron */
 
                                            /* Latin Small a */
    { 224, "{\\`a}",  "\\`{a}",  "\\`a"  }, /*               with grave */
@@ -47,49 +51,149 @@
    { 226, "{\\^a}",  "\\^{a}",  "\\^a"  }, /*               with circumflex */
    { 227, "{\\~a}",  "\\~{a}",  "\\~a"  }, /*               with tilde */
    { 228, "{\\\"a}", "\\\"{a}", "\\\"a" }, /*               with diuresis */
-   { 229, "{\\aa}",  "",        ""      }, /*               with ring above */
+   { 229, "{\\aa}",  "{\\r{a}}","\\r{a}"}, /*               with ring above */
+   { 257, "{\\={a}}","\\={a}",  "\\=a"  }, /*               with macron */
+   { 259, "{\\u{a}}","\\u{a}",  "\\u a" }, /*               with breve */
+   { 261, "{\\k{a}}","\\k{a}",  "\\k a" }, /*               with ogonek */
+   { 462, "{\\v{a}}","\\v{a}",  "\\v a" }, /*               with caron */
 
    { 198, "{\\AE}",  "\\AE",    ""      }, /* Latin Capital AE */
    { 230, "{\\ae}",  "\\ae",    ""      }, /* Latin Small ae */
 
-   { 199, "{\\c{C}}","\\c{C}",  ""      }, /* Latin Capital C with cedilla */
-   { 231, "{\\c{c}}","\\c{c}",  ""      }, /* Latin small c with cedilla*/
-   { 262, "{\\'C}",  "\\'{C}",  "\\'C"  }, /* Latin Capital C with acute */
-   { 263, "{\\'c}",  "\\'{c}",  "\\'c"  }, /* Latin small c with acute */
+                                           /* Latin Capital C */
+   { 199, "{\\c{C}}","\\c{C}",  ""      }, /*               with cedilla */
+   { 262, "{\\'{C}}","\\'{C}",  "\\'C"  }, /*               with acute */
+   { 264, "{\\^{C}}","\\^{C}",  "\\^C"  }, /*               with circumflex */
+   { 266, "{\\.{C}}","\\.{C}",  "\\.C"  }, /*               with dot above */
+   { 268, "{\\v{C}}","\\v{C}",  "\\v C" }, /*               with caron (hacek) */
 
+                                           /* Latin Small c */
+   { 231, "{\\c{c}}","\\c{c}",  ""      }, /*               with cedilla*/
+   { 263, "{\\'{c}}","\\'{c}",  "\\'c"  }, /*               with acute */
+   { 265, "{\\^{c}}","\\^{c}",  "\\^c"  }, /*               with circumflex */
+   { 265, "{\\.{c}}","\\.{c}",  "\\.c"  }, /*               with dot above */
+   { 269, "{\\v{c}}","\\v{c}",  "\\v c" }, /*               with caron (hacek) */
+
+                                           /* Latin Capital D */
+   { 270, "{\\v{D}}","\\v{D}",  "\\v D" }, /*               with caron */
+
+                                           /* Latin Small d */
+   { 270, "{\\v{d}}","\\v{d}",  "\\v d" }, /*               with caron */
+
                                            /* Latin Capital E */
    { 200, "{\\`E}",  "\\`{E}",  "\\`E"  }, /*               with grave */
    { 201, "{\\'E}",  "\\'{E}",  "\\'E"  }, /*               with acute */
    { 202, "{\\^E}",  "\\^{E}",  "\\^E"  }, /*               with circumflex */
    { 203, "{\\\"E}", "\\\"{E}", "\\\"E" }, /*               with diuresis */
+   { 274, "{\\={E}}","\\={E}",  "\\=E"  }, /*               with macron */
+   { 276, "{\\u{E}}","\\u{E}",  "\\u E" }, /*               with breve */
+   { 278, "{\\.{E}}","\\.{E}",  "\\.E"  }, /*               with dot above */
+   { 280, "{\\k{E}}","\\k{E}",  "\\k E" }, /*               with ogonek */
+   { 282, "{\\v{E}}","\\v{E}",  "\\v E" }, /*               with caron */
  
                                            /* Latin Small e */
    { 232, "{\\`e}",  "\\`{e}",  "\\`e"  }, /*               with grave */
    { 233, "{\\'e}",  "\\'{e}",  "\\'e"  }, /*               with acute */
    { 234, "{\\^e}",  "\\^{e}",  "\\^e"  }, /*               with circumflex */
    { 235, "{\\\"e}", "\\\"{e}", "\\\"e" }, /*               with diuresis */
+   { 275, "{\\={e}}","\\={e}",  "\\=e"  }, /*               with macron */
+   { 277, "{\\u{e}}","\\u{e}",  "\\u e" }, /*               with breve */
+   { 279, "{\\.{e}}","\\.{e}",  "\\.e"  }, /*               with dot above */
+   { 281, "{\\k{e}}","\\k{e}",  "\\k e" }, /*               with ogonek */
+   { 283, "{\\v{e}}","\\v{e}",  "\\v e" }, /*               with caron */
+
+                                           /* Latin Capital G */
+   { 284, "{\\^{G}}","\\^{G}",  "\\^G"  }, /*               with circumflex */
+   { 286, "{\\u{G}}","\\u{G}",  "\\u G" }, /*               with breve */
+   { 288, "{\\.{G}}","\\.{G}",  "\\.G"  }, /*               with dot above */
+   { 290, "{\\c{G}}","\\c{G}",  "\\c G" }, /*               with cedilla */
+   { 486, "{\\v{G}}","\\v{G}",  "\\v G" }, /*               with caron */
+   { 500, "{\\'{G}}","\\'{G}",  "\\'G"  }, /*               with acute */
+
+                                           /* Latin Small g */
+   { 285, "{\\^{g}}","\\^{g}",  "\\^g"  }, /*               with circumflex */
+   { 287, "{\\u{g}}","\\u{g}",  "\\u g" }, /*               with breve */
+   { 289, "{\\.{g}}","\\.{g}",  "\\.g"  }, /*               with dot above */
+   { 291, "{\\c{g}}","\\c{g}",  "\\c g" }, /*               with cedilla */
+   { 487, "{\\v{g}}","\\v{g}",  "\\v g" }, /*               with caron */
+   { 501, "{\\'{g}}","\\'{g}",  "\\'g"  }, /*               with acute */
+
+                                           /* Latin Capital H */
+   { 292, "{\\^{H}}","\\^{H}",  "\\^H"  }, /*               with circumflex */
+
+                                           /* Latin Capital h */
+   { 293, "{\\^{h}}","\\^{h}",  "\\^h"  }, /*               with circumflex */
  
-                                           /* Latin Capital i */
+                                           /* Latin Capital I */
    { 204, "{\\`I}",  "\\`{I}",  "\\`I"  }, /*               with grave */
    { 205, "{\\'I}",  "\\'{I}",  "\\'I"  }, /*               with acute */
    { 206, "{\\^I}",  "\\^{I}",  "\\^I"  }, /*               with circumflex */
    { 207, "{\\\"I}", "\\\"{I}", "\\\"I" }, /*               with diuresis */
+   { 296, "{\\~{I}}","\\~{I}",  "\\~I"  }, /*               with tilde */
+   { 298, "{\\={I}}","\\={I}",  "\\=I"  }, /*               with macron */
+   { 300, "{\\u{I}}","\\u{I}",  "\\u I" }, /*               with breve */
+   { 302, "{\\k{I}}","\\k{I}",  "\\k I" }, /*               with ogonek */
+   { 302, "{\\.{I}}","\\.{I}",  "\\. I" }, /*               with dot above */
+   { 302, "{\\v{I}}","\\v{I}",  "\\v I" }, /*               with caron */
 
                                            /* Latin Small i */
+   { 299, "{\\={\\i}}", "\\={\\i}", "\\=\\i{}"}, /*         with macron */
    { 236, "{\\`i}",  "\\`{i}",  "\\`i"  }, /*               with grave */
    { 237, "{\\'i}",  "\\'{i}",  "\\'i"  }, /*               with acute */
    { 238, "{\\^i}",  "\\^{i}",  "\\^i"  }, /*               with circumflex */
    { 239, "{\\\"i}", "\\\"{i}", "\\\"i" }, /*               with diuresis */
+   { 303, "{\\k{i}}","\\k{i}",  "\\k i" }, /*               with ogonek */
                                            /* Latex \i has no dot on "i"*/
    { 236, "{\\`\\i}",  "\\`{\\i}",  "\\`\\i"  }, /*         with grave */
    { 237, "{\\'\\i}",  "\\'{\\i}",  "\\'\\i"  }, /*         with acute */
    { 238, "{\\^\\i}",  "\\^{\\i}",  "\\^\\i"  }, /*         with circumflex */
    { 239, "{\\\"\\i}", "\\\"{\\i}", "\\\"\\i" }, /*         with diuresis */
+   { 297, "{\\~{\\i}}","\\~{\\i}",  "\\~\\i{}"}, /*         with tilde */
+   { 299, "{\\={\\i}}","\\={\\i}",  "\\=\\i{}"}, /*         with tilde */
+   { 301, "{\\u{\\i}}","\\u{\\i}",  "\\u\\i{}"}, /*         with breve */
+   { 305, "{\\i}",     "\\i{}",     ""        }, /*         without dot above */
+   { 464, "{\\v \\i{}}", "\\v \\i{}", ""      }, /*         with caron */
 
-   { 209, "{\\~N}",  "\\~{N}",  "\\~N"  }, /* Latin Capital N with tilde */
-   { 327, "{\\vN}",  "\\v{N}",  "\\vN"  }, /* Latin Capital N with caron */
-   { 241, "{\\~n}",  "\\~{n}",  "\\~n"  }, /* Latin Small n with tilde */
-   { 328, "{\\vn}",  "\\v{n}",  "\\vn"  }, /* Latin Small n with caron */
+                                           /* Latin Capital J */
+   { 308, "{\\^{J}}","\\^{J}",  "\\^J"  }, /*                with circumflex */
+
+                                           /* Latin Small j */
+   { 309, "{\\^{j}}","\\^{j}",  "\\^j"  }, /*                with circumflex */
+
+                                           /* Latin Capital K */
+   { 310, "{\\c{K}}","\\c{K}",  "\\c K" }, /*               with cedilla */
+   { 488, "{\\v{K}}","\\v{K}",  "\\v K" }, /*               with caron */
+
+                                           /* Latin Small k */
+   { 311, "{\\c{k}}","\\c{k}",  "\\c k" }, /*               with cedilla */
+   { 489, "{\\v{k}}","\\v{k}",  "\\v k" }, /*               with caron */
+
+                                           /* Latin Capital L */
+   { 313, "{\\'{L}}","\\'{L}",  "\\'L"  }, /*               with acute */
+   { 315, "{\\c{L}}","\\c{L}",  "\\c L" }, /*               with cedilla */
+   { 317, "{\\v{L}}","\\v{l}",  "\\v L" }, /*               with caron */
+   { 319, "{L\\hspace{-0.35em}$\\cdot$}","L\\hspace{-0.35em}$\\cdot$", "" }, /*               with middle dot */
+   { 321, "{\\L{}}", "\\L{}",   ""      }, /*               with stroke */
+
+                                           /* Latin Small l */
+   { 314, "{\\'{l}}","\\'{l}",  "\\'l"  }, /*               with acute */
+   { 316, "{\\c{l}}","\\c{l}",  "\\c l" }, /*               with cedilla */
+   { 318, "{\\v{l}}","\\v{l}",  "\\v l" }, /*               with caron */
+   { 318, "{l$\\cdot$}","l$\\cdot$", "" }, /*               with middle dot */
+   { 322, "{\\l{}}", "\\l{}",   ""      }, /*               with stroke */
+
+                                           /* Latin Capital N */
+   { 209, "{\\~{N}}","\\~{N}",  "\\~N"  }, /*               with tilde */
+   { 323, "{\\'{N}}","\\'{N}",  "\\'N"  }, /*               with acute */
+   { 325, "{\\c{N}}","\\c{N}",  "\\c N" }, /*               with cedilla */
+   { 327, "{\\v{N}}","\\v{N}",  "\\v N" }, /*               with caron */
+
+                                           /* Latin Small n */
+   { 241, "{\\~{n}}","\\~{n}",  "\\~n"  }, /*               with tilde */
+   { 324, "{\\'{n}}","\\'{n}",  "\\'n"  }, /*               with acute */
+   { 326, "{\\c{n}}","\\c{n}",  "\\c N" }, /*               with cedilla */
+   { 328, "{\\v{n}}","\\v{n}",  "\\v n" }, /*               with caron */
+   { 329, "\n",      "",        ""      }, /*               preceeded by apostrophe */
  
                                            /* Latin Capital O */
    { 210, "{\\`O}",  "\\`{O}",  "\\`O"  }, /*               with grave */
@@ -98,6 +202,11 @@
    { 213, "{\\~O}",  "\\~{O}",  "\\~O"  }, /*               with tilde */
    { 214, "{\\\"O}", "\\\"{O}", "\\\"O" }, /*               with diaeresis */
    { 216, "{\\O}",   "\\O",     ""      }, /*               with stroke */
+   { 332, "{\\={O}}", "\\={O}", "\\=O"  }, /*               with macron */
+   { 334, "{\\u{O}}", "\\u{O}", "\\u O" }, /*               with breve */
+   { 336, "{\\H{O}}", "\\H{O}", "\\H O" }, /*               with double acute */
+   { 465, "{\\v{O}}", "\\v{O}", "\\v O" }, /*               with caron */
+   { 490, "{\\k{O}}", "\\k{O}", "\\k O" }, /*               with ogonek */
 
                                            /* Latin Small o */
    { 242, "{\\`o}",  "\\`{o}",  "\\`o"  }, /*               with grave */
@@ -106,16 +215,45 @@
    { 245, "{\\~o}",  "\\~{o}",  "\\~o"  }, /*               with tilde */
    { 246, "{\\\"o}", "\\\"{o}", "\\\"o" }, /*               with diaeresis */
    { 248, "{\\o}",   "\\o",     ""      }, /*               with stroke */
+   { 333, "{\\={o}}", "\\={o}", "\\=o"  }, /*               with macron */
+   { 335, "{\\u{o}}", "\\u{o}", "\\u o" }, /*               with breve */
+   { 337, "{\\H{o}}", "\\H{o}", "\\H o" }, /*               with double acute */
+   { 466, "{\\v{o}}", "\\v{o}", "\\v o" }, /*               with caron */
+   { 491, "{\\k{o}}", "\\k{o}", "\\k o" }, /*               with ogonek */
 
    { 338, "{\\OE}",  "\\OE",    ""      }, /* Latin Capital OE */
    { 339, "{\\oe}",  "\\oe",    ""      }, /* Latin Small oe */
 
-   { 341, "{\\vR}",  "\\v{R}",  "\\vR"  }, /* Latin Capital R with caron */
-   { 342, "{\\vr}",  "\\v{r}",  "\\vr"  }, /* Latin Small r with caron */
+                                           /* Latin Capital R */
+   { 340, "{\\'{R}}", "\\'{R}", "\\'R"  }, /*                 with acute */
+   { 342, "{\\c{R}}", "\\c{R}", "\\c R" }, /*                 with cedilla */
+   { 344, "{\\v{R}}", "\\v{R}", "\\v R" }, /*                 with caron */
+ 
+                                           /* Latin Small r */
+   { 341, "{\\'{r}}", "\\'{r}", "\\'r"  }, /*               with acute */
+   { 343, "{\\c{r}}", "\\c{r}", "\\c r" }, /*               with cedilla */
+   { 345, "{\\v{r}}", "\\v{r}", "\\v r" }, /*               with caron */
 
-   { 352, "{\\vS}",  "\\v{S}",  "\\vS"  }, /* Latin Capital S with caron */
-   { 353, "{\\vs}",  "\\v{s}",  "\\vs"  }, /* Latin Small s with caron */
+                                           /* Latin Capital S */
+   { 346, "{\\'{S}}", "\\'{S}", "\\'S"  }, /*               with acute */
+   { 348, "{\\^{S}}", "\\^{S}", "\\^S"  }, /*               with circumflex */
+   { 350, "{\\c{S}}", "\\c{S}", "\\c S" }, /*               with cedilla */
+   { 352, "{\\v{S}}", "\\v{S}", "\\v S" }, /*               with caron */
 
+                                           /* Latin Small s */
+   { 347, "{\\'{s}}","\\'{s}",  "\\'s"  }, /*               with acute */
+   { 349, "{\\^{s}}","\\^{s}",  "\\^s"  }, /*               with circumflex */
+   { 351, "{\\c{s}}","\\c{s}",  "\\c s" }, /*               with cedilla */
+   { 353, "{\\v{s}}","\\v{s}",  "\\v s" }, /*               with caron */
+
+                                           /* Latin Capital T */
+   { 354, "{\\c{T}}", "\\c{T}", ""      }, /*               with cedilla */
+   { 356, "{\\v{T}}", "\\v{T}", ""      }, /*               with caron */
+
+                                           /* Latin Small t */
+   { 355, "{\\c{t}}", "\\c{t}", ""      }, /*               with cedilla */
+   { 357, "{\\v{t}}", "\\v{t}", ""      }, /*               with caron */
+
    { 223, "{\\ss}",  "\\ss",    ""      }, /* German sz ligature, "sharp s" */
 
                                            /* Latin Capital U */
@@ -123,25 +261,54 @@
    { 218, "{\\'U}",  "\\'{U}",  "\\'U"  }, /*               with acute */
    { 219, "{\\^U}",  "\\^{U}",  "\\^U"  }, /*               with circumflex */
    { 220, "{\\\"U}", "\\\"{U}", "\\\"U" }, /*               with diaeresis */
+   { 360, "{\\~{U}}","\\~{U}",  "\\~U"  }, /*               with tilde */
+   { 362, "{\\={U}}","\\={U}",  "\\=U"  }, /*               with macron */
+   { 364, "{\\u{U}}","\\u{U}",  "\\u U" }, /*               with breve */
+   { 366, "{\\r{U}}","\\r{U}",  "\\r U" }, /*               with ring above */
+   { 368, "{\\H{U}}","\\H{U}",  "\\H U" }, /*               with double acute */
+   { 370, "{\\k{U}}","\\k{U}",  "\\k U" }, /*               with ogonek */
+   { 467, "{\\v{U}}","\\v{U}",  "\\v U" }, /*               with caron */
 
                                            /* Latin Small u */
-   { 249, "{\\`u}",  "\\`{u}", "\\`u"   }, /*               with grave */
-   { 250, "{\\'u}",  "\\'{u}", "\\'u"   }, /*               with acute */
-   { 251, "{\\^u}",  "\\^{u}", "\\^u"   }, /*               with circumflex */
+   { 249, "{\\`u}",  "\\`{u}",  "\\`u"  }, /*               with grave */
+   { 250, "{\\'u}",  "\\'{u}",  "\\'u"  }, /*               with acute */
+   { 251, "{\\^u}",  "\\^{u}",  "\\^u"  }, /*               with circumflex */
    { 252, "{\\\"u}", "\\\"{u}", "\\\"u" }, /*               with diaeresis */
+   { 361, "{\\~{u}}","\\~{u}",  ""      }, /*               with tilde */
+   { 363, "{\\={u}}","\\={u}",  "\\=u"  }, /*               with macron */
+   { 365, "{\\u{u}}","\\u{u}",  "\\u u" }, /*               with breve */
+   { 367, "{\\r{u}}","\\r{u}",  "\\r u" }, /*               with ring above */
+   { 369, "{\\H{u}}","\\H{u}",  "\\H u" }, /*               with double acute */
+   { 371, "{\\k{u}}","\\k{u}",  "\\k u" }, /*               with ogonek */
+   { 468, "{\\v{u}}","\\v{u}",  "\\v u" }, /*               with caron */
 
-				/* Latin Capital Y */
-   { 221, "{\\'Y}",  "\\'{Y}", "\\'Y"   }, /*               with acute */
-   { 376, "{\\\"Y}", "\\\"{Y}", "\\\"Y" }, /*               with diaeresis */
+                                           /* Latin Capital W */
+   { 372, "{\\^{W}}", "\\^{W}", "\\^W"  }, /*               with circumflex */
 
-				/* Latin Small y */
+                                           /* Latin Small w */
+   { 373, "{\\^{w}}", "\\^{w}", "\\^w"  }, /*               with circumflex */
+
+                                           /* Latin Capital Y */
+   { 221, "{\\'{Y}}","\\'{Y}", "\\'Y"   }, /*               with acute */
+   { 374, "{\\^{Y}}","\\^{Y}", "\\^Y"   }, /*               with circumflex */
+   { 376, "{\\\"{Y}}","\\\"{Y}","\\\"Y" }, /*               with diaeresis */
+
+                                           /* Latin Small y */
    { 253, "{\\'y}",  "\\'{y}", "\\'y"   }, /*               with acute */
-   { 255, "{\\\"y}", "\\\"{y}", "\\\"y" }, /*               with diaeresis */
+   { 255, "{\\\"y}", "\\\"{y}","\\\"y"  }, /*               with diaeresis */
+   { 375, "{\\^{y}}","\\^{y}", "\\^y"   }, /*               with circumflex */
 
+                                           /* Latin Capital Z */
+   { 377, "{\\'{Z}}","\\'{Z}", "\\'Z"   }, /*               with acute */
+   { 379, "{\\.{Z}}","\\.{Z}", "\\.Z"   }, /*               with dot above */
+   { 381, "{\\v{Z}}","\\v{Z}", "\\v Z"  }, /*               with caron */
 
-                                /* Hacek-containing */
-   { 269, "{\\v c}", "{\\v{c}}", "\\v{c}" }, /* c with a hacek */
+                                           /* Latin Small z */
+   { 378, "{\\'{z}}","\\'{z}", "\\'z"   }, /*               with acute */
+   { 380, "{\\.{z}}","\\.{z}", "\\.z"   }, /*               with dot above */
+   { 382, "{\\v{z}}","\\v{z}", "\\v z"  }, /*               with caron */
 
+
 				/* Needs to be before \nu */
    { 8203, "$\\null$", "\\null", "" },           /* No space &#x200B; */
 
@@ -240,8 +407,8 @@
    { 12297, "{\\textrangle}", "\\textrangle", "" } ,   /* L-angle &#x3009; */
 
    { 166, "{\\textbrokenbar}", "\\textbrokenbar", "" }, /* Broken vertical bar &#xA6; */
-   { 167, "{\\textsection}", "\\textsection", "" },   /* Section sign, &#xA7; */
-   { 170, "{\\textordfeminine}", "\\textordfeminine", "" }, /* &#xAA; */
+   { 167, "{\\textsection}", "\\textsection", "\\S{}" },   /* Section sign, &#xA7; */
+   { 170, "{\\textordfeminine}", "\\textordfeminine", "$^a$" }, /* &#xAA; */
    { 172, "{\\textlnot}", "\\textlnot", "" },      /* Lnot &#xAC; */
    { 182, "{\\textparagraph}", "\\textparagraph", "" }, /* Paragraph sign &#xB6; */
    { 183, "{\\textperiodcentered}", "\\textperiodcentered", "" }, /* Period-centered &#xB7; */
diff --git a/bibutils/latex.h b/bibutils/latex.h
--- a/bibutils/latex.h
+++ b/bibutils/latex.h
@@ -1,7 +1,7 @@
 /*
  * latex.h
  *
- * Copyright (c) Chris Putnam 2004-2009
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/list.c b/bibutils/list.c
--- a/bibutils/list.c
+++ b/bibutils/list.c
@@ -1,8 +1,10 @@
 /*
  * list.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * version: 2012-03-06
  *
+ * Copyright (c) Chris Putnam 2004-2012
+ *
  * Source code released under the GPL
  *
  * Implements a simple managed array of newstrs.
@@ -10,17 +12,89 @@
  */
 #include "list.h"
 
+void
+list_init( list *a  )
+{
+	a->str = NULL;
+	a->max = 0;
+	a->n = 0;
+	a->sorted = 0;
+}
+
+void
+list_empty( list *a )
+{
+	int i;
+	for ( i=0; i<a->max; ++i )
+		newstr_empty( &(a->str[i]) );
+	a->n = 0;
+	a->sorted = 1;
+}
+
+void
+list_free( list *a )
+{
+	int i;
+	for ( i=0; i<a->max; ++i )
+		newstr_free( &(a->str[i]) );
+	free( a->str );
+	list_init( a );
+}
+
+list *
+list_new( void )
+{
+	list *a = ( list * ) malloc( sizeof ( list ) );
+	if ( a ) list_init( a );
+	return a;
+}
+
+void
+list_delete( list *a )
+{
+	list_free( a );
+	free( a );
+}
+
+/*
+ * returns 1 if n is valid string in list
+ */
+static inline int
+list_valid_num( list *a, int n )
+{
+	if ( n < 0 || n > a->n ) return 0;
+	return 1;
+}
+
+/*
+ * return pointer to newstr 'n', list_getstr() is deprecated
+ */
 newstr *
+list_get( list *a, int n )
+{
+	if ( !list_valid_num( a, n ) ) return NULL;
+	else return &(a->str[n]);
+}
+newstr *
 list_getstr( list *a, int n )
 {
-	if ( n<0 || n>a->n ) return NULL;
+	if ( !list_valid_num( a, n ) ) return NULL;
 	else return &(a->str[n]);
 }
 
+/*
+ * return pointer to C string 'n', list_getstr_char() is deprecated
+ */
 char *
+list_getc( list *a, int n )
+{
+	if ( !list_valid_num( a, n ) ) return NULL;
+	else return a->str[n].data;
+}
+char *
 list_getstr_char( list *a, int n )
 {
-	if ( n<0 || n>a->n ) return NULL;
+	if ( !list_valid_num( a, n ) ) return NULL;
 	else return a->str[n].data;
 }
 
@@ -51,59 +125,80 @@
 	return 1;
 }
 
-int
-list_add( list *a, char *value )
+static int
+list_ensure_space( list *a )
 {
 	int ok = 1;
-
-	/* ensure sufficient space */
 	if ( a->max==0 ) ok = list_alloc( a );
 	else if ( a->n >= a->max ) ok = list_realloc( a );
+	return ok;
+}
 
+int
+list_add( list *a, char *s )
+{
+	int ok = list_ensure_space( a );
 	if ( ok ) {
-		newstr_strcpy( &(a->str[a->n]), value );
+		newstr_strcpy( &(a->str[a->n]), s );
 		a->sorted = 0;
 		a->n++;
 	}
+	return ok;
+}
 
+int
+list_add_unique( list *a, char *s )
+{
+	if ( list_find( a, s )==-1 ) return list_add( a, s );
+	else return 1;
+}
+
+int
+list_add_newstr( list *a, newstr *s )
+{
+	int ok = list_ensure_space( a );
+	if ( ok ) {
+		newstr_newstrcpy( &(a->str[a->n]), s );
+		a->sorted = 0;
+		a->n++;
+	}
 	return ok;
 }
 
-void
-list_empty( list *a )
+int
+list_add_newstr_unique( list *a, newstr *s )
 {
-	int i;
-	for ( i=0; i<a->max; ++i )
-		newstr_empty( &(a->str[i]) );
-	a->n = 0;
-	a->sorted = 1;
+	if ( list_find( a, s->data )==-1 ) return list_add_newstr( a, s );
+	else return 1;
 }
 
 void
-list_free( list *a )
+list_append( list *a, list *toadd )
 {
 	int i;
-	for ( i=0; i<a->max; ++i )
-		newstr_free( &(a->str[i]) );
-	free( a->str );
-	list_init( a );
+	for ( i=0; i<toadd->n; ++i ) {
+		list_add_newstr( a, &(toadd->str[i]) );
+	}
 }
 
 void
-list_init( list *a  )
+list_append_unique( list *a, list *toadd )
 {
-	a->str = NULL;
-	a->max = 0;
-	a->n = 0;
-	a->sorted = 0;
+	int i;
+	for ( i=0; i<toadd->n; ++i ) {
+		list_add_newstr_unique( a, &(toadd->str[i]) );
+	}
 }
 
 static int
 list_comp( const void *v1, const void *v2 )
 {
-	newstr *s1 = ( newstr* ) v1;
+	newstr *s1 = ( newstr *) v1;
 	newstr *s2 = ( newstr *) v2;
-	return strcmp( s1->data, s2->data );
+	if ( !s1->len && !s2->len ) return 0;
+	else if ( !s1->len ) return -1;
+	else if ( !s2->len ) return 1;
+	else return strcmp( s1->data, s2->data );
 }
 
 void
@@ -117,17 +212,21 @@
 list_find_sorted( list *a, char *searchstr )
 {
 	int min, max, mid, comp;
+	newstr s, *cs;
 	if ( a->n==0 ) return -1;
+	newstr_init( &s );
+	newstr_strcpy( &s, searchstr );
 	min = 0;
 	max = a->n - 1;
 	while ( min <= max ) {
 		mid = ( min + max ) / 2;
-		comp = list_comp( (void*)list_getstr_char( a, mid ),
-			(void*) searchstr );
+		cs = list_get( a, mid );
+		comp = list_comp( (void*)cs, (void*) (&s) );
 		if ( comp==0 ) return mid;
 		else if ( comp > 0 ) max = mid - 1;
 		else if ( comp < 0 ) min = mid + 1;
 	}
+	newstr_free( &s );
 	return -1;
 }
 
@@ -175,27 +274,29 @@
 	return n;
 }
 
-int
-list_fill( list *a, char *filename )
+void
+list_fillfp( list *a, FILE *fp )
 {
 	newstr line;
-	FILE *fp;
-	char *p;
-	char buf[512]="";
+	char *p, buf[512]="";
 	int  bufpos = 0;
 
-	fp = fopen( filename, "r" );
-	if ( !fp ) return 0;
-
 	list_init( a );
-
 	newstr_init( &line );
 	while ( newstr_fget( fp, buf, sizeof(buf), &bufpos, &line ) ) {
 		p = &(line.data[0]);
 		if ( *p=='\0' ) continue;
-		if ( !list_add( a, line.data ) ) return 0;
+		if ( !list_add( a, line.data ) ) return;
 	}
 	newstr_free( &line );
+}
+
+int
+list_fill( list *a, char *filename )
+{
+	FILE *fp = fopen( filename, "r" );
+	if ( !fp ) return 0;
+	list_fillfp( a, fp );
 	fclose( fp );
 	return 1;
 }
@@ -233,5 +334,108 @@
 	free( anew );
 err0:
 	return NULL;
+}
+
+int
+list_match_entry( list *a, int n, char *s )
+{
+	if ( n < 0 || n >= a->n ) return 0;
+	if ( strcmp( a->str[n].data, s ) ) return 0;
+	return 1;
+}
+
+void
+list_trimend( list *a, int n )
+{
+	int i;
+	if ( a->n - n < 1 ) {
+		list_empty( a );
+	} else {
+		for ( i=a->n -n; i<a->n; ++i ) {
+			newstr_empty( &(a->str[i]) );
+		}
+		a->n -= n;
+	}
+}
+
+void
+list_tokenize( list *tokens, newstr *in, char delim )
+{
+	newstr s;
+	char *p;
+	list_empty( tokens );
+	p = in->data;
+	newstr_init( &s );
+	while ( p && *p ) {
+		while ( *p && *p!=delim ) newstr_addchar( &s, *p++ );
+		if ( s.len ) list_add( tokens, s.data );
+		newstr_empty( &s );
+		if ( *p==delim ) p++;
+	}
+	newstr_free( &s );
+}
+
+void
+list_newstrtok( list *t, newstr *s, char *sep )
+{
+	newstr tmp;
+	char *p;
+	list_empty( t );
+	if ( !s->len ) return;
+	newstr_init( &tmp );
+	p = s->data;
+	while ( *p ) {
+		if ( strchr( sep, *p ) ) {
+			if ( tmp.len ) {
+				list_add( t, tmp.data );
+				newstr_empty( &tmp );
+			}
+		} else newstr_addchar( &tmp, *p );
+		p++;
+	}
+	if ( tmp.len ) list_add( t, tmp.data );
+	newstr_free( &tmp );
+}
+
+void
+lists_init( list *a, ... )
+{
+	list *a2;
+	va_list ap;
+	list_init( a );
+	va_start( ap, a );
+	do {
+		a2 = va_arg( ap, list * );
+		if ( a2 ) list_init( a2 );
+	} while ( a2 );
+	va_end( ap );
+}
+
+void
+lists_free( list *a, ... )
+{
+	list *a2;
+	va_list ap;
+	list_free( a );
+	va_start( ap, a );
+	do {
+		a2 = va_arg( ap, list * );
+		if ( a2 ) list_free( a2 );
+	} while ( a2 );
+	va_end( ap );
+}
+
+void
+lists_empty( list *a, ... )
+{
+	list *a2;
+	va_list ap;
+	list_empty( a );
+	va_start( ap, a );
+	do {
+		a2 = va_arg( ap, list * );
+		if ( a2 ) list_empty( a2 );
+	} while ( a2 );
+	va_end( ap );
 }
 
diff --git a/bibutils/list.h b/bibutils/list.h
--- a/bibutils/list.h
+++ b/bibutils/list.h
@@ -1,8 +1,10 @@
 /*
  * list.h
  *
- * Copyright (c) Chris Putnam 2004-2009
+ * version: 2012-03-06
  *
+ * Copyright (c) Chris Putnam 2004-2012
+ *
  * Source code released under the GPL
  *
  */
@@ -12,6 +14,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 #include "newstr.h"
 
@@ -21,17 +24,46 @@
 	newstr *str;
 } list;
 
+
+extern void    lists_init( list *a, ... );
+extern void    lists_free( list *a, ... );
+extern void    lists_empty( list *a, ... );
+
+
 extern void    list_init( list *a );
+extern void    list_free( list *a );
+extern void    list_empty( list *a );
+
+extern list *  list_new( void );
+extern void    list_delete( list * );
+
+extern list*   list_dup( list *a );
+extern void    list_copy( list *to, list *from );
+
 extern int     list_add( list *a, char *value );
+extern int     list_add_unique( list *a, char *value );
+extern int     list_add_newstr( list *a, newstr *value );
+extern int     list_add_newstr_unique( list *a, newstr *value );
+extern void    list_append( list *a, list *toadd );
+extern void    list_append_unique( list *a, list *toadd );
+
+extern newstr* list_get( list *a, int n );
+extern newstr* list_getstr( list *a, int n );
+extern char*   list_getc( list *a, int n );
+extern char*   list_getstr_char( list *a, int n );
+
 extern void    list_sort( list *a );
+
 extern int     list_find( list *a, char *searchstr );
 extern int     list_findnocase( list *a, char *searchstr );
 extern int     list_find_or_add( list *a, char *searchstr );
-extern void    list_free( list *a );
+extern int     list_match_entry( list *a, int n, char *s );
+extern void    list_trimend( list *a, int n );
+
 extern int     list_fill( list *a, char *filename );
-extern newstr* list_getstr( list *a, int n );
-extern char*   list_getstr_char( list *a, int n );
-extern list*   list_dup( list *a );
-extern void    list_copy( list *to, list *from );
+extern void    list_fillfp( list *a, FILE *fp );
+extern void    list_tokenize( list *tokens, newstr *in, char delim );
+extern void    list_newstrtok( list *t, newstr *s, char *sep );
+
 
 #endif
diff --git a/bibutils/marc.h b/bibutils/marc.h
--- a/bibutils/marc.h
+++ b/bibutils/marc.h
@@ -1,7 +1,7 @@
 /*
  * marc.h
  *
- * Copyright (c) Chris Putnam 2008-9
+ * Copyright (c) Chris Putnam 2008-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/medin.c b/bibutils/medin.c
--- a/bibutils/medin.c
+++ b/bibutils/medin.c
@@ -1,7 +1,7 @@
 /*
  * medin.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
@@ -510,7 +510,7 @@
 
 	if ( node->next ) medin_assembleref( node->next, info );
 	/* assume everything is a journal article */
-	if ( info->nfields ) {
+	if ( fields_num( info ) ) {
 		fields_add( info, "RESOURCE", "text", 0 );
 		fields_add( info, "ISSUANCE", "continuing", 1 );
 		fields_add( info, "GENRE", "periodical", 1 );
@@ -533,8 +533,13 @@
 medin_convertf( fields *medin, fields *info, int reftype, int verbose, 
 	variants *all, int nall )
 {
-	int i;
-	for ( i=0; i<medin->nfields; ++i )
-		fields_add( info, medin->tag[i].data, medin->data[i].data,
-				medin->level[i] );
+	char *tag, *value;
+	int i, n, level;
+	n = fields_num( medin );
+	for ( i=0; i<n; ++i ) {
+		tag = fields_tag( medin, i, FIELDS_CHRP );
+		value = fields_value( medin, i, FIELDS_CHRP );
+		level = fields_level( medin, i );
+		fields_add( info, tag, value, level );
+	}
 }
diff --git a/bibutils/medin.h b/bibutils/medin.h
--- a/bibutils/medin.h
+++ b/bibutils/medin.h
@@ -1,7 +1,7 @@
 /*
  * medin.h
  *
- * Copyright (c) Chris Putnam 2004-2009
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/modsin.c b/bibutils/modsin.c
--- a/bibutils/modsin.c
+++ b/bibutils/modsin.c
@@ -1,7 +1,7 @@
 /*
  * modsin.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
@@ -84,10 +84,6 @@
 			fields_add( info, "PAGESTART", value.data, level );
 		} else fields_add( info, type.data, value.data, level );
 		newstrs_free( &type, &value, NULL );
-/*
-		newstr_free( &type );
-		newstr_free( &value );
-*/
 	}
 }
 
@@ -554,8 +550,10 @@
 static void
 modsin_descriptionr( xml *node, newstr *s )
 {
-	if ( xml_tagexact( node, "extent" ) ) 
+	if ( xml_tagexact( node, "extent" ) ||
+	     xml_tagexact( node, "note" ) ) {
 		newstr_newstrcpy( s, node->value );
+	}
 	if ( node->down ) modsin_descriptionr( node->down, s );
 	if ( node->next ) modsin_descriptionr( node->next, s );
 }
@@ -717,10 +715,15 @@
 modsin_convertf( fields *modsin, fields *info, int reftype, int verbose, 
 	variants *all, int nall )
 {
-	int i;
-	for ( i=0; i<modsin->nfields; ++i )
-		fields_add( info, modsin->tag[i].data, modsin->data[i].data,
-				modsin->level[i] );
+	char *tag, *value;
+	int i, n, level;
+	n = fields_num( modsin );
+	for ( i=0; i<n; ++i ) {
+		tag = fields_tag( modsin, i, FIELDS_CHRP );
+		value = fields_value( modsin, i, FIELDS_CHRP );
+		level = fields_level( modsin, i );
+		fields_add( info, tag, value, level );
+	}
 }
 
 int
diff --git a/bibutils/modsin.h b/bibutils/modsin.h
--- a/bibutils/modsin.h
+++ b/bibutils/modsin.h
@@ -1,7 +1,7 @@
 /*
  * modsin.h
  *
- * Copyright (c) Chris Putnam 2004-2009
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/modsout.c b/bibutils/modsout.c
--- a/bibutils/modsout.c
+++ b/bibutils/modsout.c
@@ -1,7 +1,7 @@
 /*
  * modsout.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  *
@@ -82,23 +82,27 @@
 }
 
 static void
-output_fill2( FILE *outptr, int level, char *tag, fields *info, int n, int cr )
+output_fill2( FILE *outptr, int level, char *tag, fields *f, int n, int cr )
 {
+	char *value;
 	if ( n!=-1 ) {
-		output_tab2_attrib( outptr, level, tag, info->data[n].data, 
+		value = fields_value( f, n, FIELDS_CHRP );
+		output_tab2_attrib( outptr, level, tag, value, 
 			NULL, NULL, cr );
-		fields_setused( info, n );
+		fields_setused( f, n );
 	}
 }
 
 static void
 output_fill4( FILE *outptr, int level, char *tag, char *aname, char *avalue,
-		fields *info, int n, int cr )
+		fields *f, int n, int cr )
 {
+	char *value;
 	if ( n!=-1 ) {
+		value = fields_value( f, n, FIELDS_CHRP );
 		output_tab4( outptr, level, tag, aname, avalue,
-				info->data[n].data, cr );
-		fields_setused( info, n );
+				value, cr );
+		fields_setused( f, n );
 	}
 }
 
@@ -109,26 +113,26 @@
  * Return number of the tags found
  */
 static int
-find_alltags( fields *info, convert *parts, int nparts, int level )
+find_alltags( fields *f, convert *parts, int nparts, int level )
 {
 	int i, n=0;
 	for ( i=0; i<nparts; ++i ) {
-		parts[i].code = fields_find( info, parts[i].internal, level );
+		parts[i].code = fields_find( f, parts[i].internal, level );
 		n += ( parts[i].code!=-1 );
 	}
 	return n;
 }
 
 static void
-output_title( fields *info, FILE *outptr, int level )
+output_title( fields *f, FILE *outptr, int level )
 {
-	int ttl = fields_find( info, "TITLE", level );
-	int subttl = fields_find( info, "SUBTITLE", level );
-	int shrttl = fields_find( info, "SHORTTITLE", level );
+	int ttl = fields_find( f, "TITLE", level );
+	int subttl = fields_find( f, "SUBTITLE", level );
+	int shrttl = fields_find( f, "SHORTTITLE", level );
 
 	output_tab1( outptr, level, "<titleInfo>\n" );
-	output_fill2( outptr, increment_level(level,1), "title", info, ttl, 1);
-	output_fill2( outptr, increment_level(level,1), "subTitle", info, subttl, 1 );
+	output_fill2( outptr, increment_level(level,1), "title", f, ttl, 1);
+	output_fill2( outptr, increment_level(level,1), "subTitle", f, subttl, 1 );
 	if ( ttl==-1 && subttl==-1 ) 
 		output_tab1( outptr, increment_level(level,1), "<title/>\n" );
 	output_tab1( outptr, level, "</titleInfo>\n" );
@@ -136,13 +140,13 @@
 	/* output shorttitle if it's different from normal title */
 	if ( shrttl!=-1 ) {
 		if ( ttl==-1 || subttl!=-1 ||
-			strcmp(info->data[ttl].data,info->data[shrttl].data) ) {
+			strcmp(f->data[ttl].data,f->data[shrttl].data) ) {
 			output_tab1( outptr, level, 
 					"<titleInfo type=\"abbreviated\">\n" );
-			output_fill2( outptr, level+1, "title", info, shrttl,1);
+			output_fill2( outptr, level+1, "title", f, shrttl,1);
 			output_tab1( outptr, level, "</titleInfo>\n" );
 		}
-		fields_setused( info, shrttl );
+		fields_setused( f, shrttl );
 	}
 }
 
@@ -194,11 +198,24 @@
 }
 
 
+/* MODS v 3.4
+ *
+ * <name [type="corporation"/type="conference"]>
+ *    <namePart></namePart>
+ *    <displayForm></displayForm>
+ *    <affiliation></affiliation>
+ *    <role>
+ *        <roleTerm [authority="marcrealtor"] type="text"></roleTerm>
+ *    </role>
+ *    <description></description>
+ * </name>
+ */
+
 #define NO_AUTHORITY (0)
 #define MARC_AUTHORITY (1)
 
 static void
-output_names( fields *info, FILE *outptr, int level )
+output_names( fields *f, FILE *outptr, int level )
 {
 	convert   names[] = {
 	  { "author",        "AUTHOR",             MARC_AUTHORITY },
@@ -225,16 +242,18 @@
 	  { "author",        "COURT",              MARC_AUTHORITY },
 	  { "author",        "LEGISLATIVEBODY",    MARC_AUTHORITY }
 	};
-	int       i, n, ntypes = sizeof( names ) / sizeof( convert );
-	newstr role;
+	int i, n, nfields, ntypes = sizeof( names ) / sizeof( convert );
 	int f_asis, f_corp, f_conf;
+	newstr role;
 
 	newstr_init( &role );
+	nfields = fields_num( f );
 	for ( n=0; n<ntypes; ++n ) {
-		for ( i=0; i<info->nfields; ++i ) {
-			if ( info->level[i]!=level ) continue;
+		for ( i=0; i<nfields; ++i ) {
+			if ( fields_level( f, i )!=level ) continue;
+			if ( f->data[i].len==0 ) continue;
 			f_asis = f_corp = f_conf = 0;
-			newstr_strcpy( &role, info->tag[i].data );
+			newstr_strcpy( &role, f->tag[i].data );
 			if ( newstr_findreplace( &role, ":ASIS", "" )) f_asis=1;
 			if ( newstr_findreplace( &role, ":CORP", "" )) f_corp=1;
 			if ( newstr_findreplace( &role, ":CONF", "" )) f_conf=1;
@@ -243,17 +262,17 @@
 			if ( f_asis ) {
 				output_tab0( outptr, level );
 				fprintf( outptr, "<name>\n" );
-				output_fill2( outptr, increment_level(level,1), "namePart", info, i, 1 );
+				output_fill2( outptr, increment_level(level,1), "namePart", f, i, 1 );
 			} else if ( f_corp ) {
 				output_tab0( outptr, level );
 				fprintf( outptr, "<name type=\"corporate\">\n" );
-				output_fill2( outptr, increment_level(level,1), "namePart", info, i, 1 );
+				output_fill2( outptr, increment_level(level,1), "namePart", f, i, 1 );
 			} else if ( f_conf ) {
 				output_tab0( outptr, level );
 				fprintf( outptr, "<name type=\"conference\">\n" );
-				output_fill2( outptr, increment_level(level,1), "namePart", info, i, 1 );
+				output_fill2( outptr, increment_level(level,1), "namePart", f, i, 1 );
 			} else {
-				output_name(outptr, info->data[i].data, level);
+				output_name(outptr, f->data[i].data, level);
 			}
 			output_tab1( outptr, increment_level(level,1), "<role>\n" );
 			output_tab1( outptr, increment_level(level,2), "<roleTerm" );
@@ -264,33 +283,33 @@
 			fprintf( outptr, "</roleTerm>\n");
 			output_tab1( outptr, increment_level(level,1), "</role>\n" );
 			output_tab1( outptr, level, "</name>\n" );
-			fields_setused( info, i );
+			fields_setused( f, i );
 		}
 	}
 	newstr_free( &role );
 }
 
 static int
-output_finddateissued( fields *info, int level, int pos[3] )
+output_finddateissued( fields *f, int level, int pos[3] )
 {
 	char      *src_names[] = { "YEAR", "MONTH", "DAY", "DATE" };
 	char      *alt_names[] = { "PARTYEAR", "PARTMONTH", "PARTDAY", "PARTDATE" };
 	int       i, found = -1, ntypes = 4;
 
 	for ( i=0; i<ntypes; ++i ) {
-		pos[i] = fields_find( info, src_names[i], level );
+		pos[i] = fields_find( f, src_names[i], level );
 		if ( pos[i]!=-1 ) found = pos[i];
 	}
 	/* for LEVEL_MAIN, do what it takes to find a date */
 	if ( found==-1 && level==0 ) {
 		for ( i=0; i<ntypes; ++i ) {
-			pos[i] = fields_find( info, src_names[i], -1 );
+			pos[i] = fields_find( f, src_names[i], -1 );
 			if ( pos[i]!=-1 ) found = pos[i];
 		}
 	}
 	if ( found==-1 && level==0 ) {
 		for ( i=0; i<ntypes; ++i ) {
-			pos[i] = fields_find( info, alt_names[i], -1 );
+			pos[i] = fields_find( f, alt_names[i], -1 );
 			if ( pos[i]!=-1 ) found = pos[i];
 		}
 	}
@@ -298,40 +317,40 @@
 }
 
 static void
-output_datepieces( fields *info, FILE *outptr, int pos[4] )
+output_datepieces( fields *f, FILE *outptr, int pos[4] )
 {
 	int nprinted = 0, i;
 	for ( i=0; i<3 && pos[i]!=-1; ++i ) {
 		if ( nprinted>0 ) fprintf( outptr, "-" );
-		if ( i>0 && info->data[pos[i]].len==1 )
+		if ( i>0 && f->data[pos[i]].len==1 )
 			fprintf( outptr, "0" ); /*zero pad Jan,Feb,etc*/
-		fprintf( outptr,"%s",info->data[pos[i]].data );
+		fprintf( outptr,"%s",f->data[pos[i]].data );
 		nprinted++;
-		fields_setused( info, pos[i] );
+		fields_setused( f, pos[i] );
 	}
 }
 
 static void
-output_dateall( fields *info, FILE *outptr, int pos )
+output_dateall( fields *f, FILE *outptr, int pos )
 {
-	fprintf( outptr, "%s", info->data[pos].data );
-	fields_setused( info, pos );
+	fprintf( outptr, "%s", f->data[pos].data );
+	fields_setused( f, pos );
 }
 
 static void
-output_dateissued( fields *info, FILE *outptr, int level, int pos[4] )
+output_dateissued( fields *f, FILE *outptr, int level, int pos[4] )
 {
 	output_tab1( outptr, increment_level(level,1), "<dateIssued>" );
 	if ( pos[0]!=-1 || pos[1]!=-1 || pos[2]!=-1 ) {
-		output_datepieces( info, outptr, pos );
+		output_datepieces( f, outptr, pos );
 	} else {
-		output_dateall( info, outptr, pos[3] );
+		output_dateall( f, outptr, pos[3] );
 	}
 	fprintf( outptr, "</dateIssued>\n" );
 }
 
 static void
-output_origin( fields *info, FILE *outptr, int level )
+output_origin( fields *f, FILE *outptr, int level )
 {
 	convert origin[] = {
 		{ "issuance",	  "ISSUANCE",	0 },
@@ -346,15 +365,15 @@
 	/* find all information to be outputted */
 	found = -1;
 	for ( n=0; n<ntypes; ++n ) {
-		pos[n] = fields_find( info, origin[n].internal, level );
+		pos[n] = fields_find( f, origin[n].internal, level );
 		if ( pos[n]!=-1 ) found = pos[n];
 	}
-	datefound = output_finddateissued( info, level, date );
+	datefound = output_finddateissued( f, level, date );
 	if ( found==-1 && datefound==-1 ) return;
 
 	output_tab1( outptr, level, "<originInfo>\n" );
-	output_fill2( outptr, increment_level(level,1), "issuance", info, pos[0], 1 );
-	if ( datefound!=-1 ) output_dateissued( info, outptr, level, date );
+	output_fill2( outptr, increment_level(level,1), "issuance", f, pos[0], 1 );
+	if ( datefound!=-1 ) output_dateissued( f, outptr, level, date );
 
 	for ( n=1; n<ntypes; n++ ) {
 		if ( pos[n]==-1 ) continue;
@@ -364,11 +383,11 @@
 		if ( origin[n].code ) {
 			fprintf( outptr, "\n" );
 			output_fill4( outptr, increment_level(level,2), 
-				"placeTerm", "type", "text", info, pos[n], 1 );
+				"placeTerm", "type", "text", f, pos[n], 1 );
 			output_tab0( outptr, increment_level(level,1) );
 		} else {
-			fprintf( outptr, "%s", info->data[pos[n]].data );
-			fields_setused( info, pos[n] );
+			fprintf( outptr, "%s", f->data[pos[n]].data );
+			fields_setused( f, pos[n] );
 		}
 		fprintf( outptr, "</%s>\n", origin[n].mods );
 	}
@@ -376,28 +395,28 @@
 }
 
 static void
-output_language( fields *info, FILE *outptr, int level )
+output_language( fields *f, FILE *outptr, int level )
 {
-	int n = fields_find( info, "LANGUAGE", level );
-	output_fill2( outptr, level, "language", info, n, 1 );
+	int n = fields_find( f, "LANGUAGE", level );
+	output_fill2( outptr, level, "language", f, n, 1 );
 }
 
 static void
-output_description( fields *info, FILE *outptr, int level )
+output_description( fields *f, FILE *outptr, int level )
 {
-	int n = fields_find( info, "DESCRIPTION", level );
+	int n = fields_find( f, "DESCRIPTION", level );
 	if (n != -1) {
 		output_tab1( outptr, level, "<physicalDescription>\n" );
-		output_fill2( outptr, increment_level(level,1), "note", info, n, 1 );
+		output_fill2( outptr, increment_level(level,1), "note", f, n, 1 );
 		output_tab1( outptr, level, "</physicalDescription>\n" );
 	}
 }
 
 static void
-output_toc( fields *info, FILE *outptr, int level )
+output_toc( fields *f, FILE *outptr, int level )
 {
-	int n = fields_find( info, "CONTENTS", level );
-	output_fill2( outptr, level, "tableOfContents", info, n, 1 );
+	int n = fields_find( f, "CONTENTS", level );
+	output_fill2( outptr, level, "tableOfContents", f, n, 1 );
 }
 
 /* detail output
@@ -407,14 +426,14 @@
  * <detail type="volume"><number>xxx</number></detail
  */
 static void
-mods_output_detail( fields *info, FILE *outptr, int item, char *item_name,
+mods_output_detail( fields *f, FILE *outptr, int item, char *item_name,
 		int level )
 {
 	if ( item==-1 ) return;
 	output_tab0( outptr, increment_level( level, 1 ) );
 	fprintf( outptr, "<detail type=\"%s\"><number>%s</number></detail>\n", 
-			item_name, info->data[item].data );
-	fields_setused( info, item );
+			item_name, f->data[item].data );
+	fields_setused( f, item );
 }
 
 
@@ -426,14 +445,14 @@
  * </extent>
  */
 static void
-mods_output_extents( fields *info, FILE *outptr, int start, int end,
+mods_output_extents( fields *f, FILE *outptr, int start, int end,
 		int total, char *extype, int level )
 {
 	output_tab0( outptr, increment_level(level,1) );
 	fprintf( outptr, "<extent unit=\"%s\">\n", extype);
-	output_fill2( outptr, increment_level(level,2), "start", info, start, 1 );
-	output_fill2( outptr, increment_level(level,2), "end", info, end, 1 );
-	output_fill2( outptr, increment_level(level,2), "total", info, total, 1 );
+	output_fill2( outptr, increment_level(level,2), "start", f, start, 1 );
+	output_fill2( outptr, increment_level(level,2), "end", f, end, 1 );
+	output_fill2( outptr, increment_level(level,2), "total", f, total, 1 );
 	output_tab1 ( outptr, increment_level(level,1), "</extent>\n" );
 }
 
@@ -455,7 +474,7 @@
  *
  */
 static int
-output_partdate( fields *info, FILE *outptr, int level, int wrote_header )
+output_partdate( fields *f, FILE *outptr, int level, int wrote_header )
 {
 	convert parts[3] = {
 		{ "",	"PARTYEAR",                -1 },
@@ -464,26 +483,26 @@
 	};
 	int nparts = sizeof(parts)/sizeof(parts[0]);
 
-	if ( !find_alltags( info, parts, nparts, level ) ) return 0;
+	if ( !find_alltags( f, parts, nparts, level ) ) return 0;
 
 	try_output_partheader( outptr, wrote_header, level );
 	output_tab1( outptr, increment_level(level,1), "<date>" );
 
 	if ( parts[0].code!=-1 ) {
-		fprintf( outptr, "%s", info->data[ parts[0].code ].data);
-		fields_setused( info, parts[0].code );
+		fprintf( outptr, "%s", f->data[ parts[0].code ].data);
+		fields_setused( f, parts[0].code );
 	} else fprintf( outptr, "XXXX" );
 
 	if ( parts[1].code!=-1 ) {
-		fprintf( outptr, "-%s", info->data[parts[1].code].data );
-		fields_setused( info, parts[1].code );
+		fprintf( outptr, "-%s", f->data[parts[1].code].data );
+		fields_setused( f, parts[1].code );
 	}
 
 	if ( parts[2].code!=-1 ) {
 		if ( parts[1].code!=-1 ) fprintf( outptr, "-" );
 		else fprintf( outptr, "-XX-" );
-		fprintf( outptr, "%s", info->data[parts[2].code].data );
-		fields_setused( info, parts[2].code );
+		fprintf( outptr, "%s", f->data[parts[2].code].data );
+		fields_setused( f, parts[2].code );
 	}
 
 	fprintf( outptr,"</date>\n");
@@ -492,7 +511,7 @@
 }
 
 static int
-output_partpages( fields *info, FILE *outptr, int level, int wrote_header )
+output_partpages( fields *f, FILE *outptr, int level, int wrote_header )
 {
 	convert parts[3] = {
 		{ "",  "PAGESTART",                -1 },
@@ -501,25 +520,25 @@
 	};
 	int nparts = sizeof(parts)/sizeof(parts[0]);
 
-	if ( !find_alltags( info, parts, nparts, level ) ) return 0;
+	if ( !find_alltags( f, parts, nparts, level ) ) return 0;
 
 	try_output_partheader( outptr, wrote_header, level );
 
 	/* If PAGESTART or PAGEEND are  undefined */
 	if ( parts[0].code==-1 || parts[1].code==-1 ) {
 		if ( parts[0].code!=-1 )
-			mods_output_detail( info, outptr, parts[0].code,
+			mods_output_detail( f, outptr, parts[0].code,
 				"page", level );
 		if ( parts[1].code!=-1 )
-			mods_output_detail( info, outptr, parts[1].code,
+			mods_output_detail( f, outptr, parts[1].code,
 				"page", level );
 		if ( parts[2].code!=-1 )
-			mods_output_extents( info, outptr, -1, -1,
+			mods_output_extents( f, outptr, -1, -1,
 					parts[2].code, "page", level ); 
 	}
 	/* If both PAGESTART and PAGEEND are defined */
 	else {
-		mods_output_extents( info, outptr, parts[0].code, 
+		mods_output_extents( f, outptr, parts[0].code, 
 			parts[1].code, parts[2].code, "page", level ); 
 	}
 
@@ -527,7 +546,7 @@
 }
 
 static int
-output_partelement( fields *info, FILE *outptr, int level, int wrote_header )
+output_partelement( fields *f, FILE *outptr, int level, int wrote_header )
 {
 	convert parts[] = {
 		{ "volume",          "VOLUME",          -1 },
@@ -542,19 +561,19 @@
 	};
 	int i, nparts = sizeof( parts ) / sizeof( convert ), n;
 
-	n = fields_find( info, "NUMVOLUMES", level );
-	if ( !find_alltags( info, parts, nparts, level ) && n==-1 ) return 0;
+	n = fields_find( f, "NUMVOLUMES", level );
+	if ( !find_alltags( f, parts, nparts, level ) && n==-1 ) return 0;
 	try_output_partheader( outptr, wrote_header, level );
 
 	for ( i=0; i<nparts; ++i ) {
 		if ( parts[i].code==-1 ) continue;
-		mods_output_detail( info, outptr, parts[i].code, parts[i].mods,
+		mods_output_detail( f, outptr, parts[i].code, parts[i].mods,
 				level );
 	}
 
 	if ( n!=-1 ) {
 		output_tab1( outptr, level, "<extent unit=\"volumes\">\n" );
-		output_fill2( outptr, increment_level(level,1), "total", info, n, 1 );
+		output_fill2( outptr, increment_level(level,1), "total", f, n, 1 );
 		output_tab1( outptr, level, "</extent>\n" );
 	}
 
@@ -562,114 +581,123 @@
 }
 
 static void
-output_part( fields *info, FILE *outptr, int level )
+output_part( fields *f, FILE *outptr, int level )
 {
 	int wrote_hdr;
-	wrote_hdr  = output_partdate( info, outptr, level, 0 );
-	wrote_hdr += output_partelement( info, outptr, level, wrote_hdr );
-	wrote_hdr += output_partpages( info, outptr, level, wrote_hdr );
+	wrote_hdr  = output_partdate( f, outptr, level, 0 );
+	wrote_hdr += output_partelement( f, outptr, level, wrote_hdr );
+	wrote_hdr += output_partpages( f, outptr, level, wrote_hdr );
 	try_output_partfooter( outptr, wrote_hdr, level );
 }
 
 static void
-output_genre( fields *info, FILE *outptr, int level )
+output_genre( fields *f, FILE *outptr, int level )
 {
-	int i, ismarc;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( info->level[i]!=level ) continue;
-		if ( strcasecmp( info->tag[i].data, "GENRE" ) ) continue;
-		if ( marc_findgenre( info->data[i].data )!=-1 ) ismarc = 1;
+	int i, ismarc, n;
+	char *value;
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( fields_level( f, i ) != level ) continue;
+		if ( !fields_match_tag( f, i, "GENRE" ) &&
+		     !fields_match_tag( f, i, "NGENRE" ) )
+			continue;
+		value = fields_value( f, i, FIELDS_CHRP );
+		if ( marc_findgenre( value )!=-1 ) ismarc = 1;
 		else ismarc = 0;
 		output_tab1( outptr, level, "<genre" );
 		if ( ismarc ) 
 			fprintf( outptr, " authority=\"marcgt\"" );
-		fprintf( outptr, ">%s</genre>\n", info->data[i].data );
-		fields_setused( info, i );
+		fprintf( outptr, ">%s</genre>\n", value );
+		fields_setused( f, i );
 	}
 }
 
 static void
-output_typeresource( fields *info, FILE *outptr, int level )
+output_typeresource( fields *f, FILE *outptr, int level )
 {
 	int n, ismarc = 0;
-	n = fields_find( info, "RESOURCE", level );
+	char *value;
+	n = fields_find( f, "RESOURCE", level );
 	if ( n!=-1 ) {
-		if ( marc_findresource( info->data[n].data )!=-1 ) ismarc = 1;
+		value = fields_value( f, n, FIELDS_CHRP );
+		if ( marc_findresource( value )!=-1 ) ismarc = 1;
 		if ( !ismarc ) {
-			fprintf( stderr, "Illegal typeofResource = '%s'\n",
-					info->data[n].data );
+			fprintf( stderr, "Illegal typeofResource = '%s'\n", value );
 		} else {
-			output_fill2( outptr, level, "typeOfResource", info, 
-				n, 1 );
+			output_fill2( outptr, level, "typeOfResource", f, n, 1 );
 		}
-		fields_setused( info, n );
+		fields_setused( f, n );
 	}
 }
 
 static void
-output_type( fields *info, FILE *outptr, int level )
+output_type( fields *f, FILE *outptr, int level )
 {
-	int n = fields_find( info, "INTERNAL_TYPE", 0 );
-	if ( n!=-1 ) fields_setused( info, n );
-	output_typeresource( info, outptr, level );
-	output_genre( info, outptr, level );
+	int n = fields_find( f, "INTERNAL_TYPE", 0 );
+	if ( n!=-1 ) fields_setused( f, n );
+	output_typeresource( f, outptr, level );
+	output_genre( f, outptr, level );
 }
 
 static void
-output_abs( fields *info, FILE *outptr, int level )
+output_abs( fields *f, FILE *outptr, int level )
 {
-	int i;
-	int nabs = fields_find( info, "ABSTRACT", level );
-	output_fill2( outptr, level, "abstract", info, nabs, 1 );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( info->level[i]!=level ) continue;
-		if ( !strcasecmp( info->tag[i].data, "NOTES" ) )
-			output_fill2( outptr, level, "note", info, i, 1 );
-		if ( !strcasecmp( info->tag[i].data, "ANNOTE" ) )
-			output_fill2( outptr, level, "bibtex-annote", info, i, 1 );
+	int i, n;
+	int nabs = fields_find( f, "ABSTRACT", level );
+	output_fill2( outptr, level, "abstract", f, nabs, 1 );
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( fields_level( f, i ) != level ) continue;
+		if ( !strcasecmp( f->tag[i].data, "NOTES" ) )
+			output_fill2( outptr, level, "note", f, i, 1 );
+		if ( !strcasecmp( f->tag[i].data, "ANNOTE" ) )
+			output_fill2( outptr, level, "bibtex-annote", f, i, 1 );
 	}
 }
 
 static void
-output_timescited( fields *info, FILE *outptr, int level )
+output_timescited( fields *f, FILE *outptr, int level )
 {
-	int n = fields_find( info, "TIMESCITED", level );
+	int n = fields_find( f, "TIMESCITED", level );
+	char *value;
 	if ( n!=-1 ) {
+		value = fields_value( f, n, FIELDS_CHRP );
 		output_tab0( outptr, level );
-		fprintf( outptr, "<note>Times Cited: %s</note>\n",
-				info->data[n].data );
-		fields_setused( info, n );
+		fprintf( outptr, "<note>Times Cited: %s</note>\n", value );
+		fields_setused( f, n );
 	}
 }
 
 static void
-output_indexkey( fields *info, FILE *outptr, int level )
+output_indexkey( fields *f, FILE *outptr, int level )
 {
-	int n = fields_find( info, "BIBKEY", level );
+	int n = fields_find( f, "BIBKEY", level );
+	char *value;
 	if ( n!=-1 ) {
+		value = fields_value( f, n, FIELDS_CHRP );
 		output_tab0( outptr, level );
-		fprintf( outptr, "<note>Key: %s</note>\n",
-				info->data[n].data );
-		fields_setused( info, n );
+		fprintf( outptr, "<note>Key: %s</note>\n", value );
+		fields_setused( f, n );
 	}
 }
 
 static void
-output_key( fields *info, FILE *outptr, int level )
+output_key( fields *f, FILE *outptr, int level )
 {
-	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( info->level[i]!=level ) continue;
-		if ( !strcasecmp( info->tag[i].data, "KEYWORD" ) ) {
+	int i, n;
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( fields_level( f, i ) != level ) continue;
+		if ( !strcasecmp( f->tag[i].data, "KEYWORD" ) ) {
 			output_tab1( outptr, level, "<subject>\n" );
-			output_fill2( outptr, increment_level(level,1), "topic", info, i, 1 );
+			output_fill2( outptr, increment_level(level,1), "topic", f, i, 1 );
 			output_tab1( outptr, level, "</subject>\n" );
 		}
 	}
 }
 
 static void
-output_sn( fields *info, FILE *outptr, int level )
+output_sn( fields *f, FILE *outptr, int level )
 {
 	convert sn_types[] = {
 		{ "isbn",      "ISBN",      0 },
@@ -689,69 +717,79 @@
 		{ "jstor",     "JSTOR",     0 },
 	};
 	int n, ntypes = sizeof( sn_types ) / sizeof( sn_types[0] );
-	int       found, i;
+	int found, i, nfields;
 
-	found = fields_find ( info, "CALLNUMBER", level );
-	output_fill2( outptr, level, "classification", info, found, 1 );
+	found = fields_find ( f, "CALLNUMBER", level );
+	output_fill2( outptr, level, "classification", f, found, 1 );
 
 	for ( n=0; n<ntypes; ++n ) {
-		found = fields_find( info, sn_types[n].internal, level );
+		found = fields_find( f, sn_types[n].internal, level );
 		if ( found==-1 ) continue;
 		output_tab0( outptr, level );
 		fprintf( outptr, "<identifier type=\"%s\">%s</identifier>\n",
 				sn_types[n].mods,
-				info->data[found].data
+				f->data[found].data
 		       );
-		fields_setused( info, found );
+		fields_setused( f, found );
 	}
-	for ( i=0; i<info->nfields;++i ) {
-		if ( info->level[i]!=level ) continue;
-		if ( !strcasecmp( info->tag[i].data, "SERIALNUMBER" ) ) {
+	nfields = fields_num( f );
+	for ( i=0; i<nfields; ++i ) {
+		if ( f->level[i]!=level ) continue;
+		if ( !strcasecmp( f->tag[i].data, "SERIALNUMBER" ) ) {
 			output_tab0( outptr, level );
 			fprintf( outptr, "<identifier type=\"%s\">%s</identifier>\n",
-				"serial number", info->data[i].data );
-			fields_setused( info, i );
+				"serial number", f->data[i].data );
+			fields_setused( f, i );
 		}
 	}
 }
 
 static void
-output_url( fields *info, FILE *outptr, int level )
+output_url( fields *f, FILE *outptr, int level )
 {
-	int location = fields_find( info, "LOCATION", level );
-	int url = fields_find( info, "URL", level );
-	int fileattach = fields_find( info, "FILEATTACH", level );
-	int pdflink = fields_find( info, "PDFLINK", level );
-	int i;
-	if ( url==-1 && location==-1 && pdflink==-1 && fileattach==-1) return;
+	int location = fields_find( f, "LOCATION", level );
+	int url = fields_find( f, "URL", level );
+	int fileattach = fields_find( f, "FILEATTACH", level );
+	int pdflink = fields_find( f, "PDFLINK", level );
+	int i, n;
+	if ( url==-1 && location==-1 && pdflink==-1 && fileattach==-1 ) return;
 	output_tab1( outptr, level, "<location>\n" );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( info->level[i]!=level ) continue;
-		if ( !strcasecmp( info->tag[i].data, "URL" ) ) {
-			output_fill2( outptr, increment_level(level,1), "url", info, i, 1 );
-		} else if ( !strcasecmp( info->tag[i].data, "PDFLINK" ) ) {
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( f->level[i]!=level ) continue;
+		if ( !strcasecmp( f->tag[i].data, "URL" ) ) {
+			output_fill2( outptr, increment_level(level,1), "url", f, i, 1 );
+		}
+	}
+	for ( i=0; i<n; ++i ) {
+		if ( f->level[i]!=level ) continue;
+		if ( !strcasecmp( f->tag[i].data, "PDFLINK" ) ) {
 			output_fill2( outptr, increment_level(level,1), "url",
-				/*"urlType", "pdf",*/ info, i, 1 );
-		} else if ( !strcasecmp( info->tag[i].data, "FILEATTACH" ) ){
+				/*"urlType", "pdf",*/ f, i, 1 );
+		}
+	}
+	for ( i=0; i<n; ++i ) {
+		if ( f->level[i]!=level ) continue;
+		if ( !strcasecmp( f->tag[i].data, "FILEATTACH" ) ){
 			output_tab0( outptr, increment_level(level,1) );
 			fprintf( outptr, "<url displayLabel=\"Electronic full text\" access=\"raw object\">" );
-			fprintf( outptr, " %s</url>\n", info->data[i].data );
-			fields_setused( info, i );
+			fprintf( outptr, "%s</url>\n", f->data[i].data );
+			fields_setused( f, i );
 		}
 	}
 	if ( location!=-1 )
-		output_fill2( outptr, increment_level(level,1), "physicalLocation", info, 
+		output_fill2( outptr, increment_level(level,1), "physicalLocation", f, 
 				location, 1 );
 	output_tab1( outptr, level, "</location>\n" );
 }
 
-/* refnum should start with a non-number and not include spaces */
+/* refnum should start with a non-number and not include spaces -- ignore this */
 static void
-output_refnum( fields *info, int n, FILE *outptr )
+output_refnum( fields *f, int n, FILE *outptr )
 {
-	char *p = info->data[n].data;
-	if ( p && ((*p>='0' && *p<='9') || *p=='-' || *p=='_' ))
-		fprintf( outptr, "ref" );
+	char *p = fields_value( f, n, FIELDS_CHRP_NOUSE );
+/*	if ( p && ((*p>='0' && *p<='9') || *p=='-' || *p=='_' ))
+		fprintf( outptr, "ref" );*/
 	while ( p && *p ) {
 		if ( !is_ws(*p) ) fprintf( outptr, "%c", *p );
 /*		if ( (*p>='A' && *p<='Z') ||
@@ -764,15 +802,15 @@
 }
 
 static void
-output_head( fields *info, FILE *outptr, int dropkey, unsigned long numrefs )
+output_head( fields *f, FILE *outptr, int dropkey, unsigned long numrefs )
 {
 	int n;
 	fprintf( outptr, "<mods");
 	if ( !dropkey ) {
-		n = fields_find( info, "REFNUM", 0 );
+		n = fields_find( f, "REFNUM", 0 );
 		if ( n!=-1 ) {
 			fprintf( outptr, " ID=\"");
-			output_refnum( info, n, outptr );
+			output_refnum( f, n, outptr );
 			fprintf( outptr, "\"");
 		}
 	}
@@ -780,83 +818,124 @@
 }
 
 static int
-original_items( fields *info, int level )
+original_items( fields *f, int level )
 {
-	int i, targetlevel;
+	int i, targetlevel, n;
 	if ( level < 0 ) return 0;
 	targetlevel = -( level + 2 );
-	for ( i=0; i<info->nfields; ++i )
-		if ( info->level[i]==targetlevel ) return targetlevel;
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( fields_level( f, i ) == targetlevel )
+			return targetlevel;
+	}
 	return 0;
 }
 
 static void
-output_citeparts( fields *info, FILE *outptr, int level, int max )
+output_citeparts( fields *f, FILE *outptr, int level, int max )
 {
 	int orig_level;
-	output_title( info, outptr, level );
-	output_names( info, outptr, level);
-	output_origin( info, outptr, level );
-	output_type( info, outptr, level );
-	output_language( info, outptr, level );
-	output_description( info, outptr, level );
-	if ( level>=0 && level < max ) {
+
+	output_title(       f, outptr, level );
+	output_names(       f, outptr, level );
+	output_origin(      f, outptr, level );
+	output_type(        f, outptr, level );
+	output_language(    f, outptr, level );
+	output_description( f, outptr, level );
+
+	if ( level >= 0 && level < max ) {
 		output_tab0( outptr, level );
 		fprintf( outptr, "<relatedItem type=\"host\">\n" );
-		output_citeparts(info, outptr, increment_level(level,1), max );
+		output_citeparts( f, outptr, increment_level(level,1), max );
 		output_tab0( outptr, level );
 		fprintf( outptr, "</relatedItem>\n");
 	}
 	/* Look for original item things */
-	orig_level = original_items( info, level );
+	orig_level = original_items( f, level );
 	if ( orig_level ) {
 		output_tab0( outptr, level );
 		fprintf( outptr, "<relatedItem type=\"original\">\n" );
-		output_citeparts( info, outptr, orig_level, max );
+		output_citeparts( f, outptr, orig_level, max );
 		output_tab0( outptr, level );
 		fprintf( outptr, "</relatedItem>\n" );
 	}
-	output_abs( info, outptr, level );
-	output_timescited( info, outptr, level );
-	output_indexkey( info, outptr, level );
-	output_toc( info, outptr, level );
-	output_key( info, outptr, level );
-	output_sn( info, outptr, level );
-	output_url( info, outptr, level );
-	/* as of MODS 3.1, <part> tags can be in the main items */
-	/*if ( level>0 ) */
-	output_part( info, outptr, level );
-}
-
-static void
-modsout_report_unused_tag( fields *info, int i, param *p, unsigned long numrefs )
-{
-	if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
-	fprintf( stderr, "Ref %lu unused tag: '%s' value: '%s' level: %d\n",
-			numrefs+1, info->tag[i].data, info->data[i].data,
-			info->level[i] );
+	output_abs(        f, outptr, level );
+	output_timescited( f, outptr, level );
+	output_indexkey(   f, outptr, level );
+	output_toc(        f, outptr, level );
+	output_key(        f, outptr, level );
+	output_sn(         f, outptr, level );
+	output_url(        f, outptr, level );
+	output_part(       f, outptr, level );
 }
 
 static void
-modsout_report_unused_tags( fields *info, param *p, unsigned long numrefs )
+modsout_report_unused_tags( fields *f, param *p, unsigned long numrefs )
 {
-	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( info->used[i] ) continue;
-		modsout_report_unused_tag( info, i, p, numrefs );
+	int i, n, nwritten, nunused = 0, level;
+	char *tag, *value;
+	n = fields_num( f );
+	for ( i=0; i<n; ++i ) {
+		if ( fields_used( f, i ) ) continue;
+		nunused++;
 	}
+	if ( nunused ) {
+		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
+		fprintf( stderr, "Reference %lu has unused tags.\n", numrefs+1 );
+		/* Find author from level 0 */
+		nwritten = 0;
+		for ( i=0; i<n; ++i ) {
+			if ( fields_level( f, i ) != 0 ) continue;
+			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );
+			if ( strncasecmp( tag, "AUTHOR", 6 ) ) continue;
+			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
+			if ( nwritten==0 ) fprintf( stderr, "\tAuthor(s) (level=0):\n" );
+			fprintf( stderr, "\t\t'%s'\n", value );
+			nwritten++;
+		}
+		nwritten = 0;
+		for ( i=0; i<n; ++i ) {
+			if ( fields_level( f, i ) != 0 ) continue;
+			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );
+			if ( strcasecmp( tag, "YEAR" ) && strcasecmp( tag, "PARTYEAR" ) ) continue;
+			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
+			if ( nwritten==0 ) fprintf( stderr, "\tYear(s) (level=0):\n" );
+			fprintf( stderr, "\t\t'%s'\n", value );
+			nwritten++;
+		}
+		nwritten = 0;
+		for ( i=0; i<n; ++i ) {
+			if ( fields_level( f, i ) != 0 ) continue;
+			tag = fields_tag( f, i, FIELDS_CHRP_NOUSE );
+			if ( strncasecmp( tag, "TITLE", 5 ) ) continue;
+			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
+			if ( nwritten==0 ) fprintf( stderr, "\tTitle(s) (level=0):\n" );
+			fprintf( stderr, "\t\t'%s'\n", value );
+			nwritten++;
+		}
+	
+		fprintf( stderr, "\tUnused tags:\n" );
+		for ( i=0; i<n; ++i ) {
+			if ( fields_used( f, i ) ) continue;
+			tag   = fields_tag(   f, i, FIELDS_CHRP_NOUSE );
+			value = fields_value( f, i, FIELDS_CHRP_NOUSE );
+			level = fields_level( f, i );
+			fprintf( stderr, "\t\ttag: '%s' value: '%s' level: %d\n",
+				tag, value, level );
+		}
+	}
 }
 
 void
-modsout_write( fields *info, FILE *outptr, param *p, unsigned long numrefs )
+modsout_write( fields *f, FILE *outptr, param *p, unsigned long numrefs )
 {
 	int max, dropkey;
-	max = fields_maxlevel( info );
+	max = fields_maxlevel( f );
 	dropkey = ( p->format_opts & MODSOUT_DROPKEY );
 
-	output_head( info, outptr, dropkey, numrefs );
-	output_citeparts( info, outptr, 0, max );
-	modsout_report_unused_tags( info, p, numrefs );
+	output_head( f, outptr, dropkey, numrefs );
+	output_citeparts( f, outptr, 0, max );
+	modsout_report_unused_tags( f, p, numrefs );
 
 	fprintf( outptr, "</mods>\n" );
 	fflush( outptr );
diff --git a/bibutils/modsout.h b/bibutils/modsout.h
--- a/bibutils/modsout.h
+++ b/bibutils/modsout.h
@@ -1,7 +1,7 @@
 /*
  * modsout.h
  *
- * Copyright (c) Chris Putnam 2003-2009
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/modstypes.h b/bibutils/modstypes.h
--- a/bibutils/modstypes.h
+++ b/bibutils/modstypes.h
@@ -1,7 +1,7 @@
 /*
  * modstypes.h
  *
- * Copyright (c) Chris Putnam 2008-9
+ * Copyright (c) Chris Putnam 2008-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/name.c b/bibutils/name.c
--- a/bibutils/name.c
+++ b/bibutils/name.c
@@ -3,7 +3,7 @@
  *
  * mangle names w/ and w/o commas
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/name.h b/bibutils/name.h
--- a/bibutils/name.h
+++ b/bibutils/name.h
@@ -3,7 +3,7 @@
  *
  * mangle names w/ and w/o commas
  *
- * Copyright (c) Chris Putnam 2004-2009
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/newstr.c b/bibutils/newstr.c
--- a/bibutils/newstr.c
+++ b/bibutils/newstr.c
@@ -1,7 +1,7 @@
 /*
  * newstr.c
  *
- * Copyright (c) Chris Putnam 1999-2010
+ * Copyright (c) Chris Putnam 1999-2012
  *
  * Source code released under the GPL
  *
@@ -104,6 +104,20 @@
 	va_end( ap );
 }
 
+void
+newstr_mergestrs( newstr *s, ... )
+{
+	va_list ap;
+	char *cp;
+	newstr_empty( s );
+	va_start( ap, s );
+	do {
+		cp = va_arg( ap, char * );
+		if ( cp ) newstr_strcat( s, cp );
+	} while ( cp );
+	va_end( ap );
+}
+
 static void 
 newstr_initalloc( newstr *s, unsigned long minsize )
 {
@@ -193,6 +207,29 @@
 	s->data[s->len] = '\0';
 }
 
+/* newstr_addutf8
+ *
+ * Add potential multibyte character to s starting at pointer p.
+ * Multibyte Unicode characters have the high bit set.
+ *
+ * Since we can progress more than one byte at p, return the
+ * properly updated pointer p.
+ */
+char *
+newstr_addutf8( newstr *s, char *p )
+{
+	if ( ! ((*p) & 128 ) ) {
+		newstr_addchar( s, *p );
+		p++;
+	} else {
+		while ( ((*p) & 128) ) {
+			newstr_addchar( s, *p );
+			p++;
+		}
+	}
+	return p;
+}
+
 void 
 newstr_fprintf( FILE *fp, newstr *s )
 {
@@ -457,6 +494,15 @@
 		s->data[i] = toupper( s->data[i] );
 }
 
+void
+newstr_tolower( newstr *s )
+{
+	unsigned long i;
+	assert( s );
+	for ( i=0; i<s->len; ++i )
+		s->data[i] = tolower( s->data[i] );
+}
+
 /* newstr_swapstrings( s1, s2 )
  * be sneaky and swap internal newstring data from one
  * string to another
@@ -486,6 +532,33 @@
 }
 
 void
+newstr_trimstartingws( newstr *s )
+{
+	unsigned char still_ws;
+	unsigned long n, m;
+
+	assert( s );
+
+	if ( s->len==0 || !is_ws( s->data[0] ) ) return;
+
+	m = n = 0;
+	still_ws = 1;
+	while ( m <= s->len ) {
+		if ( still_ws && !is_ws( s->data[ m ] ) ) {
+			still_ws = 0;
+		}
+		if ( !still_ws ) {
+			s->data[ n ] = s->data[ m ];
+			n++;
+		}
+		m++;
+	}
+
+	s->len = n;
+}
+	
+
+void
 newstr_trimendingws( newstr *s )
 {
 	assert( s );
@@ -495,3 +568,103 @@
 	}
 }
 
+int
+newstr_match_first( newstr *s, char ch )
+{
+	if ( !s->len ) return 0;
+	if ( s->data[0] == ch ) return 1;
+	return 0;
+}
+
+int
+newstr_match_end( newstr *s, char ch )
+{
+	if ( !s->len ) return 0;
+	if ( s->data[ s->len - 1 ] == ch ) return 1;
+	return 0;
+}
+
+void
+newstr_trimbegin( newstr *s, int n )
+{
+	int i;
+	assert( s );
+	if ( s->len - n < 1 ) newstr_empty( s );
+	for ( i=1; i<=s->len; ++i ) /* pick up '\0' with '<=' */
+		s->data[i-1] = s->data[i];
+	s->len -= n;
+}
+
+void
+newstr_trimend( newstr *s, int n )
+{
+	assert( s );
+	if ( s->len - n < 1 ) newstr_empty( s );
+	else {
+		s->len -= n;
+		s->data[ s->len ] = '\0';
+	}
+}
+
+static void
+newstr_check_case( newstr *s, int *lowercase, int *uppercase )
+{
+	int i;
+	*lowercase = 0;
+	*uppercase = 0;
+	if ( s->len < 1 ) return;
+	for ( i=0; i<s->len && !( *lowercase && *uppercase ); ++i ) {
+		if ( isalpha( s->data[i] ) ) {
+			if ( isupper( s->data[i] ) ) *uppercase += 1;
+			else if ( islower( s->data[i] ) ) *lowercase += 1;
+		}
+	}
+}
+
+int
+newstr_is_mixedcase( newstr *s )
+{
+	int lowercase, uppercase;
+	newstr_check_case( s, &lowercase, &uppercase );
+	if ( lowercase > 0 && uppercase > 0 ) return 1;
+	return 0;
+}
+
+int
+newstr_is_lowercase( newstr *s )
+{
+	int lowercase, uppercase;
+	newstr_check_case( s, &lowercase, &uppercase );
+	if ( lowercase > 0 && uppercase == 0 ) return 1;
+	return 0;
+}
+
+int
+newstr_is_uppercase( newstr *s )
+{
+	int lowercase, uppercase;
+	newstr_check_case( s, &lowercase, &uppercase );
+	if ( lowercase == 0 && uppercase > 0 ) return 1;
+	return 0;
+}
+
+void
+newstr_stripws( newstr *s )
+{
+	unsigned long len = 0;
+	char *p, *q;
+	assert( s );
+	if ( s->len ) {
+		p = q = s->data;
+		while ( *p ) {
+			if ( !is_ws( *p ) ) {
+				*q = *p;
+				q++;
+				len++;
+			}
+			p++;
+		}
+		*q = '\0';
+	}
+	s->len = len;
+}
diff --git a/bibutils/newstr.h b/bibutils/newstr.h
--- a/bibutils/newstr.h
+++ b/bibutils/newstr.h
@@ -1,7 +1,7 @@
 /*
  * newstring.h
  *
- * Copyright (c) Chris Putnam 1999-2009
+ * Copyright (c) Chris Putnam 1999-2012
  *
  * Source code released under the GPL
  *
@@ -28,8 +28,10 @@
 void    newstrs_empty      ( newstr *s, ... );
 void    newstrs_free       ( newstr *s, ... );
 
+void newstr_mergestrs   ( newstr *s, ... );
 newstr *newstr_strdup   ( char *buf );
 void newstr_addchar     ( newstr *s, char newchar );
+char *newstr_addutf8    ( newstr *s, char *p );
 void newstr_strcat      ( newstr *s, char *addstr );
 void newstr_newstrcat   ( newstr *s, newstr *old );
 void newstr_segcat      ( newstr *s, char *startat, char *endat );
@@ -43,8 +45,19 @@
                           newstr *outs );
 int  newstr_findreplace ( newstr *s, char *find, char *replace );
 void newstr_toupper     ( newstr *s );
+void newstr_tolower     ( newstr *s );
+void newstr_trimstartingws( newstr *s );
 void newstr_trimendingws( newstr *s );
 void newstr_swapstrings ( newstr *s1, newstr *s2 );
+
+int  newstr_match_first ( newstr *s, char ch );
+int  newstr_match_end   ( newstr *s, char ch );
+void newstr_trimbegin   ( newstr *s, int n );
+void newstr_trimend     ( newstr *s, int n );
+
+int  newstr_is_mixedcase( newstr *s );
+int  newstr_is_lowercase( newstr *s );
+int  newstr_is_uppercase( newstr *s );
 
 /* NEWSTR_PARANOIA
  *
diff --git a/bibutils/newstr_conv.c b/bibutils/newstr_conv.c
--- a/bibutils/newstr_conv.c
+++ b/bibutils/newstr_conv.c
@@ -1,7 +1,7 @@
 /*
  * newstr_conv.c
  *
- * Copyright (c) Chris Putnam 1999-2010
+ * Copyright (c) Chris Putnam 1999-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/newstr_conv.h b/bibutils/newstr_conv.h
--- a/bibutils/newstr_conv.h
+++ b/bibutils/newstr_conv.h
@@ -1,7 +1,7 @@
 /*
  * newstring_conv.h
  *
- * Copyright (c) Chris Putnam 1999-2009
+ * Copyright (c) Chris Putnam 1999-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/reftypes.c b/bibutils/reftypes.c
--- a/bibutils/reftypes.c
+++ b/bibutils/reftypes.c
@@ -1,7 +1,7 @@
 /*
  * reftypes.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/reftypes.h b/bibutils/reftypes.h
--- a/bibutils/reftypes.h
+++ b/bibutils/reftypes.h
@@ -1,7 +1,7 @@
 /*
  * reftypes.h
  *
- * Copyright (c) Chris Putnam 2003-2009
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Source code released under the GPL
  *
@@ -22,10 +22,10 @@
 #define HOWPUBLISHED  (10)
 #define BIBTEX_URL    (11)
 #define BIBTEX_SENTE  (12)
-#define BIBTEX_FILE   (13)
+#define LINKEDFILE    (13)
 #define BIBTEX_GENRE  (14)
 #define BIBTEX_EPRINT (15)
-#define ISI_KEYWORD   (16)
+#define KEYWORD       (16)
 
 typedef struct {
 	char *oldstr;
diff --git a/bibutils/risin.c b/bibutils/risin.c
--- a/bibutils/risin.c
+++ b/bibutils/risin.c
@@ -1,7 +1,7 @@
 /*
  * risin.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
@@ -161,6 +161,8 @@
 risin_processf( fields *risin, char *p, char *filename, long nref )
 {
 	newstr tag, data;
+	int n;
+
 	newstrs_init( &tag, &data, NULL );
 
 	while ( *p ) {
@@ -171,9 +173,10 @@
 			fields_add( risin, tag.data, data.data, 0 );
 		} else {
 			p = process_line2( &tag, &data, p );
-			if ( data.len && risin->nfields>0 ) {
+			n = fields_num( risin );
+			if ( data.len && n>0 ) {
 				newstr *od;
-				od = &(risin->data[risin->nfields-1] );
+				od = fields_value( risin, n-1, FIELDS_STRP );
 				newstr_addchar( od, ' ' );
 				newstr_strcat( od, data.data );
 			}
@@ -187,27 +190,73 @@
 
 /* oxfordjournals hide the DOI in the NOTES N1 field */
 static void
-notes_add( fields *info, char *tag, newstr *s, int level )
+risin_addnotes( fields *f, char *tag, newstr *s, int level )
 {
 	int doi = is_doi( s->data );
 	if ( doi!=-1 )
-		fields_add( info, "DOI", &(s->data[doi]), level );
+		fields_add( f, "DOI", &(s->data[doi]), level );
 	else
-		fields_add( info, tag, s->data, level );
+		fields_add( f, tag, s->data, level );
 }
 
+static int
+is_uri_file_scheme( char *p )
+{
+	if ( !strncmp( p, "file:", 5 ) ) return 5;
+	return 0;
+}
+
+static int
+is_uri_remote_scheme( char *p )
+{
+	char *scheme[] = { "http:", "ftp:", "git:", "gopher:" };
+	int i, len, nschemes = sizeof( scheme ) / sizeof( scheme[0] );
+	for ( i=0; i<nschemes; ++i ) {
+		len = strlen( scheme[i] );
+		if ( !strncmp( p, scheme[i], len ) ) return len;
+	}
+	return 0;
+}
+
+static void
+risin_addfile( fields *f, char *tag, newstr *s, int level )
+{
+	char *p;
+	int n;
+
+	/* if URL is file:///path/to/xyz.pdf, only store "///path/to/xyz.pdf" */
+	n = is_uri_file_scheme( s->data );
+	if ( n ) {
+		/* skip past "file:" and store only actual path */
+		p = s->data + n;
+		fields_add( f, tag, p, level );
+		return;
+	}
+
+	/* if URL is http:, ftp:, etc. store as a URL */
+	n = is_uri_remote_scheme( s->data );
+	if ( n ) {
+		fields_add( f, "URL", s->data, level );
+		return;
+	}
+
+	/* badly formed, RIS wants URI, but store value anyway */
+	fields_add( f, tag, s->data, level );
+}
+
 /* scopus puts DOI in the DO or DI tag, but it needs cleaning */
 static void
-doi_add( fields *info, char *tag, newstr *s, int level )
+risin_adddoi( fields *f, char *tag, newstr *s, int level )
 {
 	int doi = is_doi( s->data );
 	if ( doi!=-1 )
-		fields_add( info, "DOI", &(s->data[doi]), level );
+		fields_add( f, "DOI", &(s->data[doi]), level );
 }
 
 static void
-adddate( fields *info, char *tag, char *p, int level )
+risin_adddate( fields *f, char *tag, newstr *d, int level )
 {
+	char *p = d->data;
 	newstr date;
 	int part = ( !strncasecmp( tag, "PART", 4 ) );
 
@@ -215,31 +264,31 @@
 	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );
 	if ( *p=='/' ) p++;
 	if ( date.len>0 ) {
-		if ( part ) fields_add( info, "PARTYEAR", date.data, level );
-		else        fields_add( info, "YEAR",     date.data, level );
+		if ( part ) fields_add( f, "PARTYEAR", date.data, level );
+		else        fields_add( f, "YEAR",     date.data, level );
 	}
 
 	newstr_empty( &date );
 	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );
 	if ( *p=='/' ) p++;
 	if ( date.len>0 ) {
-		if ( part ) fields_add( info, "PARTMONTH", date.data, level );
-		else        fields_add( info, "MONTH",     date.data, level );
+		if ( part ) fields_add( f, "PARTMONTH", date.data, level );
+		else        fields_add( f, "MONTH",     date.data, level );
 	}
 
 	newstr_empty( &date );
 	while ( *p && *p!='/' ) newstr_addchar( &date, *p++ );
 	if ( *p=='/' ) p++;
 	if ( date.len>0 ) {
-		if ( part ) fields_add( info, "PARTDAY", date.data, level );
-		else        fields_add( info, "DAY",     date.data, level );
+		if ( part ) fields_add( f, "PARTDAY", date.data, level );
+		else        fields_add( f, "DAY",     date.data, level );
 	}
 
 	newstr_empty( &date );
 	while ( *p ) newstr_addchar( &date, *p++ );
 	if ( date.len>0 ) {
-		if ( part ) fields_add( info, "PARTDATEOTHER", date.data,level);
-		else        fields_add( info, "DATEOTHER", date.data, level );
+		if ( part ) fields_add( f, "PARTDATEOTHER", date.data,level);
+		else        fields_add( f, "DATEOTHER", date.data, level );
 	}
 	newstr_free( &date );
 }
@@ -270,14 +319,16 @@
 }
 
 void
-risin_convertf( fields *risin, fields *info, int reftype, param *p, variants *all, int nall )
+risin_convertf( fields *risin, fields *f, int reftype, param *p, variants *all, int nall )
 {
+	int process, level, i, n, nfields;
+	char *outtag, *tag, *value;
 	newstr *t, *d;
-	int process, level, i, n;
-	char *newtag;
-	for ( i=0; i<risin->nfields; ++i ) {
-		t = &( risin->tag[i] );
-		d = &( risin->data[i] );
+
+	nfields = fields_num( risin );
+
+	for ( i=0; i<nfields; ++i ) {
+		t = fields_tag( risin, i, FIELDS_STRP );
 		n = process_findoldtag( t->data, reftype, all, nall );
 		if ( n==-1 ) {
 			risin_report_notag( p, t->data );
@@ -285,37 +336,67 @@
 		}
 		process = ((all[reftype]).tags[n]).processingtype;
 		level   = ((all[reftype]).tags[n]).level;
-		newtag  = ((all[reftype]).tags[n]).newstr;
-		if ( process==SIMPLE )
-			fields_add( info, newtag, d->data, level );
-		else if ( process==PERSON )
-			name_add( info, newtag, d->data, level, &(p->asis), 
+		outtag  = ((all[reftype]).tags[n]).newstr;
+		d = fields_value( risin, i, FIELDS_STRP );
+
+		switch ( process ) {
+
+		case SIMPLE:
+			fields_add( f, outtag, d->data, level );
+			break;
+
+		case PERSON:
+			name_add( f, outtag, d->data, level, &(p->asis), 
 					&(p->corps) );
-		else if ( process==TITLE )
-			title_process( info, newtag, d->data, level, 
+			break;
+
+		case TITLE:
+			title_process( f, outtag, d->data, level, 
 					p->nosplittitle );
-		else if ( process==DATE )
-			adddate( info, newtag, d->data, level );
-		else if ( process==SERIALNO )
-			addsn( info, d->data, level );
-		else if ( process==NOTES )
-			notes_add( info, newtag, d, level );
-		else if ( process==DOI )
-			doi_add( info, newtag, d, level );
-		else { /* do nothing */ }
+			break;
+
+		case SERIALNO:
+			addsn( f, d->data, level );
+			break;
+
+		case DATE:
+			risin_adddate( f, outtag, d, level );
+			break;
+
+		case NOTES:
+			risin_addnotes( f, outtag, d, level );
+			break;
+
+		case DOI:
+			risin_adddoi( f, outtag, d, level );
+			break;
+
+		case LINKEDFILE:
+			risin_addfile( f, outtag, d, level );
+			break;
+
+		case ALWAYS:
+			/* Handled by core code */
+			break;
+
+		default:
+			break;
+
+		}
 	}
+
 	/* look for thesis-type hint */
 	if ( !strcasecmp( all[reftype].type, "THES" ) ) {
-		for ( i=0; i<risin->nfields; ++i ) {
-			if ( strcasecmp(risin->tag[i].data, "U1") )
-				continue;
-			if ( !strcasecmp(risin->data[i].data,"Ph.D. Thesis")||
-			     !strcasecmp(risin->data[i].data,"Masters Thesis")||
-			     !strcasecmp(risin->data[i].data,"Diploma Thesis")||
-			     !strcasecmp(risin->data[i].data,"Doctoral Thesis")||
-			     !strcasecmp(risin->data[i].data,"Habilitation Thesis"))
-				fields_add( info, "GENRE", risin->data[i].data,
-					0 );
+		for ( i=0; i<nfields; ++i ) {
+			tag = fields_tag( risin, i, FIELDS_CHRP );
+			if ( strcasecmp( tag, "U1" ) ) continue;
+			value = fields_value( risin, i, FIELDS_CHRP );
+			if ( !strcasecmp(value,"Ph.D. Thesis")||
+			     !strcasecmp(value,"Masters Thesis")||
+			     !strcasecmp(value,"Diploma Thesis")||
+			     !strcasecmp(value,"Doctoral Thesis")||
+			     !strcasecmp(value,"Habilitation Thesis"))
+				fields_add( f, "GENRE", value, 0 );
 		}
 	}
 }
diff --git a/bibutils/risin.h b/bibutils/risin.h
--- a/bibutils/risin.h
+++ b/bibutils/risin.h
@@ -1,7 +1,7 @@
 /*
  * risin.h
  *
- * Copyright (c) Chris Putnam 2003-2009
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/risout.c b/bibutils/risout.c
--- a/bibutils/risout.c
+++ b/bibutils/risout.c
@@ -1,7 +1,7 @@
 /*
  * risout.c
  *
- * Copyright (c) Chris Putnam 2003-2010
+ * Copyright (c) Chris Putnam 2003-2012
  *
  * Program and source code released under the GPL
  *
@@ -33,6 +33,10 @@
 	p->addcount         = 0;
 	p->singlerefperfile = 0;
 
+	if ( p->charsetout == BIBL_CHARSET_UNICODE ) {
+		p->utf8out = p->utf8bom = 1;
+	}
+
 	p->headerf = risout_writeheader;
 	p->footerf = NULL;
 	p->writef  = risout_write;
@@ -72,14 +76,15 @@
 	int type;
 } match_type;
 
-/* Try to determine type of reference from <genre></genre> 
- * and <TypeOfResource></TypeOfResource>
+/* Try to determine type of reference from
+ * <genre></genre>
  */
 static int
-get_type_genre( fields *info )
+get_type_genre( fields *f )
 {
 	match_type match_genres[] = {
 		{ "academic journal",          TYPE_ARTICLE },
+		{ "journal article",           TYPE_ARTICLE },
 		{ "magazine",                  TYPE_MAGARTICLE },
 		{ "conference publication",    TYPE_CONF },
 		{ "newspaper",                 TYPE_NEWS },
@@ -88,6 +93,7 @@
 		{ "hearing",                   TYPE_HEAR },
 		{ "electronic",                TYPE_ELEC },
 		{ "legal case and case notes", TYPE_CASE },
+		{ "book chapter",              TYPE_INBOOK },
 		{ "Ph.D. thesis",              TYPE_PHDTHESIS },
 		{ "Masters thesis",            TYPE_MASTERSTHESIS },
 		{ "Diploma thesis",            TYPE_DIPLOMATHESIS },
@@ -99,66 +105,85 @@
 		{ "unpublished",               TYPE_UNPUBLISHED },
 	};
 	int nmatch_genres = sizeof( match_genres ) / sizeof( match_genres[0] );
-	match_type match_res[] = {
-		{ "software, multimedia",      TYPE_PROGRAM },
-	};
-	int nmatch_res = sizeof( match_res ) / sizeof( match_res[0] );
-	char *tag, *data;
-	int type = TYPE_UNKNOWN, i, j;
-	for ( i=0; i<info->nfields; ++i ) {
-		tag = info->tag[i].data;
-		if ( strcasecmp( tag, "GENRE" ) &&
-		     strcasecmp( tag, "NGENRE") ) continue;
-		data = info->data[i].data;
-		for ( j=0; j<nmatch_genres; ++j ) {
-			if ( !strcasecmp( data, match_genres[j].name ) )
+	int type, i, j;
+	char *value;
+
+	type = TYPE_UNKNOWN;
+
+	for ( i=0; i<fields_num( f ); ++i ) {
+		if ( !fields_match_tag( f, i,"GENRE" ) &&
+		     !fields_match_tag( f, i,"NGENRE" ) )
+			continue;
+		value = ( char * ) fields_value( f, i, FIELDS_CHRP );
+		for ( j=0; j<nmatch_genres; ++j )
+			if ( !strcasecmp( match_genres[j].name, value ) )
 				type = match_genres[j].type;
-		}
 		if ( type==TYPE_UNKNOWN ) {
-			if ( !strcasecmp( data, "periodical" ) )
+			if ( !strcasecmp( value, "periodical" ) )
 				type = TYPE_ARTICLE;
-			else if ( !strcasecmp( data, "thesis" ) )
+			else if ( !strcasecmp( value, "thesis" ) )
 				type = TYPE_THESIS;
-			else if ( !strcasecmp( data, "book" ) ) {
-				if ( info->level[i]==0 ) type=TYPE_BOOK;
+			else if ( !strcasecmp( value, "book" ) ) {
+				if ( fields_level( f, i )==0 ) type=TYPE_BOOK;
 				else type=TYPE_INBOOK;
 			}
-			else if ( !strcasecmp( data, "collection" ) ) {
-				if ( info->level[i]==0 ) type=TYPE_BOOK;
+			else if ( !strcasecmp( value, "collection" ) ) {
+				if ( fields_level( f, i )==0 ) type=TYPE_BOOK;
 				else type=TYPE_INBOOK;
 			}
 		}
+
 	}
-	if ( type==TYPE_UNKNOWN ) {
-		for ( i=0; i<info->nfields; ++i ) {
-			tag = info->tag[i].data;
-			if ( strcasecmp( tag, "RESOURCE" ) ) continue;
-			data = info->data[i].data;
 
-			for ( j=0; j<nmatch_res; ++j ) {
-				if ( !strcasecmp( data, match_res[j].name ) )
-					type = match_res[j].type;
-			}
+	return type;
+}
+
+/* Try to determine type of reference from
+ * <TypeOfResource></TypeOfResource>
+ */
+static int
+get_type_resource( fields *f )
+{
+	match_type match_res[] = {
+		{ "software, multimedia",      TYPE_PROGRAM },
+	};
+	int nmatch_res = sizeof( match_res ) / sizeof( match_res[0] );
+	int type, i, j;
+	char *value;
+	vplist a;
+
+	type = TYPE_UNKNOWN;
+
+	vplist_init( &a );
+	fields_findv_each( f, LEVEL_ANY, FIELDS_CHRP, &a, "RESOURCE" );
+
+	for ( i=0; i<a.n; ++i ) {
+		value = ( char * ) vplist_get( &a, i );
+		for ( j=0; j<nmatch_res; ++j ) {
+			if ( !strcasecmp( value, match_res[j].name ) )
+				type = match_res[j].type;
 		}
 	}
+
+	vplist_free( &a );
 	return type;
 }
 
 /* Try to determine type of reference from <issuance></issuance> and */
 /* <typeOfReference></typeOfReference> */
 static int
-get_type_issuance( fields *info )
+get_type_issuance( fields *f )
 {
 	int type = TYPE_UNKNOWN;
 	int i, monographic = 0, text = 0, monographic_level = 0;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( !strcasecmp( info->tag[i].data, "issuance" ) &&
-		     !strcasecmp( info->data[i].data, "MONOGRAPHIC" ) ){
+	for ( i=0; i<f->n; ++i ) {
+		if ( !strcasecmp( f->tag[i].data, "issuance" ) &&
+		     !strcasecmp( f->data[i].data, "MONOGRAPHIC" ) ){
 			monographic = 1;
-			monographic_level = info->level[i];
+			monographic_level = f->level[i];
 		}
-		if ( !strcasecmp( info->tag[i].data, "typeOfResource" ) &&
-		     !strcasecmp( info->data[i].data,"text") ) {
+		if ( !strcasecmp( f->tag[i].data, "typeOfResource" ) &&
+		     !strcasecmp( f->data[i].data,"text") ) {
 			text = 1;
 		}
 	}
@@ -170,11 +195,12 @@
 }
 
 static int
-get_type( fields *info )
+get_type( fields *f )
 {
 	int type;
-	type = get_type_genre( info );
-	if ( type==TYPE_UNKNOWN ) type = get_type_issuance( info );
+	type = get_type_genre( f );
+	if ( type==TYPE_UNKNOWN ) type = get_type_resource( f );
+	if ( type==TYPE_UNKNOWN ) type = get_type_issuance( f );
 	if ( type==TYPE_UNKNOWN ) type = TYPE_STD;
 	return type;
 }
@@ -220,10 +246,12 @@
 			found = 1;
 		}
 	}
+	/* Report internal error, default to TYPE_STD */
 	if ( !found ) {
 		if ( p->progname ) fprintf( stderr, "%s: ", p->progname );
 		fprintf( stderr, "Internal Error: Cannot identify type %d\n",
 			type );
+		fprintf( fp, "STD" );
 	}
 	fprintf( fp, "\n" );
 }
@@ -247,157 +275,144 @@
 }
 
 static void
-output_people( FILE *fp, fields *info, long refnum, char *tag, 
-		char *ristag, int level )
+output_people( FILE *fp, fields *f, char *tag, char *ristag, int level )
 {
+	vplist people;
 	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( level!=-1 && info->level[i]!=level ) continue;
-		if ( !strcasecmp( info->tag[i].data, tag ) ) {
-			fprintf( fp, "%s  - ", ristag );
-			output_person ( fp, info->data[i].data );
-			fprintf( fp, "\n" );
-		}
+	vplist_init( &people );
+	fields_findv_each( f, level, FIELDS_CHRP, &people, tag );
+	for ( i=0; i<people.n; ++i ) {
+		fprintf( fp, "%s  - ", ristag );
+		output_person( fp, ( char * ) vplist_get( &people, i ) );
+		fprintf( fp, "\n" );
 	}
+	vplist_free( &people );
 }
 
 static void
-output_date( FILE *fp, fields *info, long refnum )
+output_date( FILE *fp, fields *f )
 {
-	int year = fields_find( info, "YEAR", -1 );
-	int month = fields_find( info, "MONTH", -1 );
-	int day = fields_find( info, "DAY", -1 );
-	if ( year==-1 ) year = fields_find( info, "PARTYEAR", -1 );
-	if ( month==-1 ) month = fields_find( info, "PARTMONTH", -1 );
-	if ( day==-1 ) day = fields_find( info, "PARTDAY", -1 );
-	if ( year==-1 && month==-1 && day==-1 ) return;
-	fprintf( fp, "PY  - " );
-	if ( year!=-1 ) fprintf( fp, "%s", info->data[year].data );
-	fprintf( fp, "/" );
-	if ( month!=-1 ) fprintf( fp, "%s", info->data[month].data );
-	fprintf( fp, "/" );
-	if ( day!=-1 ) fprintf( fp, "%s", info->data[day].data );
-	fprintf( fp, "\n" );
+	char *year  = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
+			"YEAR", "PARTYEAR", NULL );
+	char *month = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
+			"MONTH", "PARTMONTH", NULL );
+	char *day   = fields_findv_firstof( f, LEVEL_ANY, FIELDS_CHRP,
+			"DAY", "PARTDAY", NULL );
+	if ( year )
+		fprintf( fp, "PY  - " );
+	if ( year || month || day ) {
+		fprintf( fp, "DA  - " );
+		if ( year ) fprintf( fp, "%s", year );
+		fprintf( fp, "/" );
+		if ( month ) fprintf( fp, "%s", month );
+		fprintf( fp, "/" );
+		if ( day ) fprintf( fp, "%s", day );
+		fprintf( fp, "\n" );
+	}
 }
 
 static void
-output_title( FILE *fp, fields *info, char *ristag, int level )
+output_titlecore( FILE *fp, fields *f, char *ristag, int level,
+	char *maintag, char *subtag )
 {
-	int n1 = fields_find( info, "TITLE", level );
-	int n2 = fields_find( info, "SUBTITLE", level );
-	if ( n1!=-1 ) {
-		fprintf( fp, "%s  - %s", ristag, info->data[n1].data );
-		if ( n2!=-1 ) {
-			if ( info->data[n1].data[info->data[n1].len]!='?' )
-				fprintf( fp, ": " );
-			else fprintf( fp, " " );
-			fprintf( fp, "%s", info->data[n2].data );
-		}
-		fprintf( fp, "\n" );
+	newstr *mainttl = fields_findv( f, level, FIELDS_STRP, maintag );
+	newstr *subttl  = fields_findv( f, level, FIELDS_STRP, subtag );
+
+	if ( !mainttl ) return;
+
+	fprintf( fp, "%s  - %s", ristag, mainttl->data );
+	if ( subttl ) {
+		if ( mainttl->len > 0 &&
+		     mainttl->data[ mainttl->len - 1 ]!='?' )
+			fprintf( fp, ":" );
+		fprintf( fp, " %s", subttl->data );
 	}
+	fprintf( fp, "\n" );
 }
 
 static void
-output_abbrtitle( FILE *fp, fields *info, char *ristag, int level )
+output_title( FILE *fp, fields *f, char *ristag, int level )
 {
-	int n1 = fields_find( info, "SHORTTITLE", level );
-	int n2 = fields_find( info, "SHORTSUBTITLE", level );
-	if ( n1!=-1 ) {
-		fprintf( fp, "%s  - %s", ristag, info->data[n1].data );
-		if ( n2!=-1 ){
-			if ( info->data[n1].data[info->data[n1].len]!='?' )
-				fprintf( fp, ": " );
-			else fprintf( fp, " " );
-			fprintf( fp, "%s", info->data[n2].data );
-		}
-		fprintf( fp, "\n" );
-	}
+	output_titlecore( fp, f, ristag, level, "TITLE", "SUBTITLE" );
 }
 
 static void
-output_pages( FILE *fp, fields *info, long refnum )
+output_abbrtitle( FILE *fp, fields *f, char *ristag, int level )
 {
-	int sn = fields_find( info, "PAGESTART", -1 );
-	int en = fields_find( info, "PAGEEND", -1 );
-	int ar = fields_find( info, "ARTICLENUMBER", -1 );
-	if ( sn!=-1 || en!=-1 ) {
-		if ( sn!=-1 ) 
-			fprintf( fp, "SP  - %s\n", info->data[sn].data );
-		if ( en!=-1 ) 
-			fprintf( fp, "EP  - %s\n", info->data[en].data );
-	} else if ( ar!=-1 ) {
-		fprintf( fp, "SP  - %s\n", info->data[ar].data );
-	}
+	output_titlecore( fp, f, ristag, level, "SHORTTITLE", "SHORTSUBTITLE" );
 }
 
 static void
-output_keywords( FILE *fp, fields *info )
+output_pages( FILE *fp, fields *f )
 {
-	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( !strcmp( info->tag[i].data, "KEYWORD" ) )
-			fprintf( fp, "KW  - %s\n", info->data[i].data );
+	char *sn = fields_findv( f, LEVEL_ANY, FIELDS_CHRP, "PAGESTART" );
+	char *en = fields_findv( f, LEVEL_ANY, FIELDS_CHRP, "PAGEEND" );
+	char *ar;
+
+	if ( sn || en ) {
+		if ( sn ) fprintf( fp, "SP  - %s\n", sn );
+		if ( en ) fprintf( fp, "EP  - %s\n", en );
+	} else {
+		ar = fields_findv( f, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
+		if ( ar ) fprintf( fp, "SP  - %s\n", ar );
 	}
 }
 
 static void
-output_doi( FILE *fp, fields *info )
+output_keywords( FILE *fp, fields *f )
 {
-	newstr doi_url;
+	vplist vpl;
 	int i;
-	newstr_init( &doi_url );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcmp( info->tag[i].data, "DOI" ) ) continue;
-		doi_to_url( info, i, "URL", &doi_url );
-		if ( doi_url.len )
-			fprintf( fp, "UR  - %s\n", doi_url.data );
-	}
-	newstr_free( &doi_url );
+	vplist_init( &vpl );
+	fields_findv_each( f, LEVEL_ANY, FIELDS_CHRP, &vpl, "KEYWORD" );
+	for ( i=0; i<vpl.n; ++i )
+		fprintf( fp, "KW  - %s\n", ( char * ) vplist_get( &vpl, i ) );
+	vplist_free( &vpl );
 }
 
 static void
-output_pmid( FILE *fp, fields *info )
+output_pmid( FILE *fp, fields *f )
 {
-	newstr pmid_url;
+	newstr s;
 	int i;
-	newstr_init( &pmid_url );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcmp( info->tag[i].data, "PMID" ) ) continue;
-		pmid_to_url( info, i, "URL", &pmid_url );
-		if ( pmid_url.len )
-			fprintf( fp, "UR  - %s\n", pmid_url.data );
+	newstr_init( &s );
+	for ( i=0; i<fields_num( f ); ++i ) {
+		if ( !fields_match_tag( f, i, "PMID" ) ) continue;
+		pmid_to_url( f, i, "URL", &s );
+		if ( s.len )
+			fprintf( fp, "UR  - %s\n", s.data );
 	}
-	newstr_free( &pmid_url );
+	newstr_free( &s );
 }
 
 static void
-output_arxiv( FILE *fp, fields *info )
+output_arxiv( FILE *fp, fields *f )
 {
-	newstr arxiv_url;
+	newstr s;
 	int i;
-	newstr_init( &arxiv_url );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcmp( info->tag[i].data, "ARXIV" ) ) continue;
-		arxiv_to_url( info, i, "URL", &arxiv_url );
-		if ( arxiv_url.len )
-			fprintf( fp, "UR  - %s\n", arxiv_url.data );
+	newstr_init( &s );
+	for ( i=0; i<fields_num( f ); ++i ) {
+		if ( !fields_match_tag( f, i, "ARXIV" ) ) continue;
+		arxiv_to_url( f, i, "URL", &s );
+		if ( s.len )
+			fprintf( fp, "UR  - %s\n", s.data );
 	}
-	newstr_free( &arxiv_url );
+	newstr_free( &s );
 }
 
 static void
-output_jstor( FILE *fp, fields *info )
+output_jstor( FILE *fp, fields *f )
 {
-	newstr jstor_url;
+	newstr s;
 	int i;
-	newstr_init( &jstor_url );
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcmp( info->tag[i].data, "JSTOR" ) ) continue;
-		jstor_to_url( info, i, "URL", &jstor_url );
-		if ( jstor_url.len )
-			fprintf( fp, "UR  - %s\n", jstor_url.data );
+	newstr_init( &s );
+	for ( i=0; i<fields_num( f ); ++i ) {
+		if ( !fields_match_tag( f, i, "JSTOR" ) ) continue;
+		jstor_to_url( f, i, "URL", &s );
+		if ( s.len )
+			fprintf( fp, "UR  - %s\n", s.data );
 	}
-	newstr_free( &jstor_url );
+	newstr_free( &s );
 }
 
 static void
@@ -415,74 +430,110 @@
 		fprintf( fp, "%s  - %s\n", "U1", "Habilitation thesis" );
 }
 
-static void
-output_easy( FILE *fp, fields *info, long refnum, char *tag, char *ristag, int level )
+static int
+is_uri_scheme( char *p )
 {
-	int n = fields_find( info, tag, level );
-	if ( n!=-1 ) {
-		fprintf( fp, "%s  - %s\n", ristag, info->data[n].data );
+	char *scheme[] = { "http:", "file:", "ftp:", "git:", "gopher:" };
+	int i, len, nschemes = sizeof( scheme ) / sizeof( scheme[0] );
+	for ( i=0; i<nschemes; ++i ) {
+		len = strlen( scheme[i] );
+		if ( !strncmp( p, scheme[i], len ) ) return len;
 	}
+	return 0;
 }
 
+
 static void
-output_easyall( FILE *fp, fields *info, long refnum, char *tag, char *ristag, int level )
+output_file( FILE *fp, fields *f, char *tag, char *ristag, int level )
 {
+	vplist a;
+	char *fl;
 	int i;
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( level!=-1 && level!=info->level[i] ) continue;
-		if ( !strcmp( info->tag[i].data, tag ) )
-			fprintf( fp, "%s  - %s\n", ristag, info->data[i].data );
+	vplist_init( &a );
+	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
+	for ( i=0; i<a.n; ++i ) {
+		fprintf( fp, "%s  - ", ristag );
+		fl = ( char * ) vplist_get( &a, i );
+		if ( !is_uri_scheme( fl ) )
+			fprintf( fp, "file:" );
+		fprintf( fp, "%s\n", fl );
 	}
+	vplist_free( &a );
 }
 
+static void
+output_easy( FILE *fp, fields *f, char *tag, char *ristag, int level )
+{
+	char *value = fields_findv( f, level, FIELDS_CHRP, tag );
+	if ( value ) fprintf( fp, "%s  - %s\n", ristag, value );
+}
+
+static void
+output_easyall( FILE *fp, fields *f, char *tag, char *ristag, int level )
+{
+	vplist a;
+	int i;
+	vplist_init( &a );
+	fields_findv_each( f, level, FIELDS_CHRP, &a, tag );
+	for ( i=0; i<a.n; ++i )
+		fprintf( fp, "%s  - %s\n", ristag, (char *) vplist_get( &a, i ) );
+	vplist_free( &a );
+}
+
 void
-risout_write( fields *info, FILE *fp, param *p, unsigned long refnum )
+risout_write( fields *f, FILE *fp, param *p, unsigned long refnum )
 {
 	int type;
-	type = get_type( info );
+	type = get_type( f );
 	output_type( fp, type, p );
-	output_people( fp, info, refnum, "AUTHOR", "AU", 0 );
-	output_easyall( fp, info, refnum, "AUTHOR:CORP", "AU", 0 );
-	output_easyall( fp, info, refnum, "AUTHOR:ASIS", "AU", 0 );
-	output_people( fp, info, refnum, "AUTHOR", "A2", 1 );
-	output_easyall( fp, info, refnum, "AUTHOR:CORP", "A2", 1 );
-	output_easyall( fp, info, refnum, "AUTHOR:ASIS", "A2", 1 );
-	output_people( fp, info, refnum, "AUTHOR", "A3", 2 );
-	output_easyall( fp, info, refnum, "AUTHOR:CORP", "A3", 2 );
-	output_easyall( fp, info, refnum, "AUTHOR:ASIS", "A3", 2 );
-	output_people( fp, info, refnum, "EDITOR", "ED", -1 );
-	output_easyall( fp, info, refnum, "EDITOR:CORP", "ED", -1 );
-	output_easyall( fp, info, refnum, "EDITOR:ASIS", "ED", -1 );
-	output_date( fp, info, refnum );
-	output_title( fp, info, "TI", 0 );
-	output_abbrtitle( fp, info, "T2", -1 );
+	output_people(  fp, f, "AUTHOR",      "AU", LEVEL_MAIN   );
+	output_easyall( fp, f, "AUTHOR:CORP", "AU", LEVEL_MAIN   );
+	output_easyall( fp, f, "AUTHOR:ASIS", "AU", LEVEL_MAIN   );
+	output_people(  fp, f, "AUTHOR",      "A2", LEVEL_HOST   );
+	output_easyall( fp, f, "AUTHOR:CORP", "A2", LEVEL_HOST   );
+	output_easyall( fp, f, "AUTHOR:ASIS", "A2", LEVEL_HOST   );
+	output_people(  fp, f, "AUTHOR",      "A3", LEVEL_SERIES );
+	output_easyall( fp, f, "AUTHOR:CORP", "A3", LEVEL_SERIES );
+	output_easyall( fp, f, "AUTHOR:ASIS", "A3", LEVEL_SERIES );
+	output_people(  fp, f, "EDITOR",      "ED", LEVEL_ANY    );
+	output_easyall( fp, f, "EDITOR:CORP", "ED", LEVEL_ANY    );
+	output_easyall( fp, f, "EDITOR:ASIS", "ED", LEVEL_ANY    );
+	output_date( fp, f );
+	output_title( fp, f, "TI", 0 );
+	output_abbrtitle( fp, f, "T2", -1 );
 	if ( type==TYPE_ARTICLE || type==TYPE_MAGARTICLE ) {
-		output_title( fp, info, "JO", 1 );
+		output_title( fp, f, "JO", 1 );
 	}
-	else output_title( fp, info, "BT", 1 );
-	output_title( fp, info, "T3", 2 );
-	output_pages( fp, info, refnum );
-	output_easy( fp, info, refnum, "VOLUME", "VL", -1 );
-	output_easy( fp, info, refnum, "ISSUE", "IS", -1 );
-	output_easy( fp, info, refnum, "NUMBER", "IS", -1 );
-	/* output article number as pages */
-	output_easy( fp, info, refnum, "PUBLISHER", "PB", -1 );
-	output_easy( fp, info, refnum, "DEGREEGRANTOR", "PB", -1 );
-	output_easy( fp, info, refnum, "DEGREEGRANTOR:ASIS", "PB", -1 );
-	output_easy( fp, info, refnum, "DEGREEGRANTOR:CORP", "PB", -1 );
-	output_easy( fp, info, refnum, "ADDRESS", "CY", -1 );
-	output_keywords( fp, info );
-	output_easy( fp, info, refnum, "ABSTRACT", "N2", -1 );
-	output_easy( fp, info, refnum, "ISSN", "SN", -1 );
-	output_easy( fp, info, refnum, "ISBN", "SN", -1 );
-	output_easyall( fp, info, refnum, "URL", "UR", -1 );
-	output_easyall( fp, info, refnum, "FILEATTACH", "L1", -1 );
-	output_doi( fp, info );
-	output_pmid( fp, info );
-	output_arxiv( fp, info );
-	output_jstor( fp, info );
-	output_easy( fp, info, refnum, "NOTES", "N1", -1 );
-	output_easy( fp, info, refnum, "REFNUM", "ID", -1 );
+	else output_title( fp, f, "BT", 1 );
+	output_title( fp, f, "T3", 2 );
+	output_pages( fp, f );
+	output_easy( fp, f, "VOLUME",             "VL", LEVEL_ANY );
+	output_easy( fp, f, "ISSUE",              "IS", LEVEL_ANY );
+	output_easy( fp, f, "NUMBER",             "IS", LEVEL_ANY );
+	output_easy( fp, f, "EDITION",            "ET", LEVEL_ANY );
+	output_easy( fp, f, "NUMVOLUMES",         "NV", LEVEL_ANY );
+	output_easy( fp, f, "AUTHORADDRESS",      "AD", LEVEL_ANY );
+	output_easy( fp, f, "PUBLISHER",          "PB", LEVEL_ANY );
+	output_easy( fp, f, "DEGREEGRANTOR",      "PB", LEVEL_ANY );
+	output_easy( fp, f, "DEGREEGRANTOR:ASIS", "PB", LEVEL_ANY );
+	output_easy( fp, f, "DEGREEGRANTOR:CORP", "PB", LEVEL_ANY );
+	output_easy( fp, f, "ADDRESS",            "CY", LEVEL_ANY );
+	output_keywords( fp, f );
+	output_easy( fp, f, "ABSTRACT",           "AB", LEVEL_ANY );
+	output_easy( fp, f, "CALLNUMBER",         "CN", LEVEL_ANY );
+	output_easy( fp, f, "ISSN",               "SN", LEVEL_ANY );
+	output_easy( fp, f, "ISBN",               "SN", LEVEL_ANY );
+	output_easyall( fp, f, "URL",             "UR", LEVEL_ANY );
+	output_easyall( fp, f, "DOI",             "DO", LEVEL_ANY );
+	output_file(    fp, f, "FILEATTACH",      "L1", LEVEL_ANY );
+	output_file(    fp, f, "FIGATTACH",       "L4", LEVEL_ANY );
+	output_easy( fp, f, "CAPTION",            "CA", LEVEL_ANY );
+	output_pmid( fp, f );
+	output_arxiv( fp, f );
+	output_jstor( fp, f );
+	output_easy( fp, f, "LANGUAGE",           "LA", LEVEL_ANY );
+	output_easy( fp, f, "NOTES",              "N1", LEVEL_ANY );
+	output_easy( fp, f, "REFNUM",             "ID", LEVEL_ANY );
 	output_thesishint( fp, type );
 	fprintf( fp, "ER  - \n" );
 	fflush( fp );
diff --git a/bibutils/risout.h b/bibutils/risout.h
--- a/bibutils/risout.h
+++ b/bibutils/risout.h
@@ -1,7 +1,7 @@
 /*
  * risout.h
  *
- * Copyright (c) Chris Putnam 2005-2009
+ * Copyright (c) Chris Putnam 2005-2012
  *
  */
 #ifndef RISOUT_H
diff --git a/bibutils/ristypes.c b/bibutils/ristypes.c
--- a/bibutils/ristypes.c
+++ b/bibutils/ristypes.c
@@ -1,974 +1,1488 @@
 /*
  * ristypes.c
  *
- * Copyright (c) Chris Putnam 2003-2010
- *
- * Program and source code released under the GPL
- *
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "fields.h"
-#include "reftypes.h"
-	
-static lookups generic[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "DO", "DOI",          DOI,     LEVEL_MAIN },
-	{ "DI", "DOI",          DOI,     LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN }, /*user defined */
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN }, /*misc */
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-};
-
-static lookups article[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },
-	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },
-	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },
-	{ "Y2", "PARTMONTH", SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "DO", "DOI",          DOI,     LEVEL_MAIN },
-	{ "DI", "DOI",          DOI,     LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },
-	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
-	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|periodical",       ALWAYS, LEVEL_HOST },
-	{ "  ", "GENRE|academic journal", ALWAYS, LEVEL_HOST }
-};
-
-/* magazine article */
-static lookups magarticle[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },
-	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },
-	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },
-	{ "Y2", "PARTMONTH", SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
-	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|periodical",       ALWAYS, LEVEL_HOST },
-	{ "  ", "GENRE|magazine",         ALWAYS, LEVEL_HOST }
-};
-
-
-
-static lookups newsarticle[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },
-	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },
-	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },
-	{ "Y2", "PARTMONTH", SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "INTERNAL_TYPE|NEWSARTICLE",       ALWAYS, LEVEL_MAIN },
-	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
-	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|newspaper",        ALWAYS, LEVEL_HOST }
-};
-
-static lookups book[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN }, 
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },  /* BOOKTITLE */
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "ISSUANCE|monographic",  ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|book",    ALWAYS, LEVEL_MAIN },
-	{ "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN }
-};
-
-static lookups inbook[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },
-	{ "PY", "YEAR",         DATE,    LEVEL_HOST },
-	{ "Y1", "YEAR",         DATE,    LEVEL_HOST },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_HOST }, 
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_HOST },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_HOST },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_HOST },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_HOST },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, /* BOOKTITLE */
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_HOST },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "GENRE|book",    ALWAYS, LEVEL_HOST },
-	{ "  ", "ISSUANCE|monographic",  ALWAYS, LEVEL_HOST },
-	{ "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN }
-};
-
-static lookups conference[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_HOST },
-	{ "Y1", "YEAR",         DATE,    LEVEL_HOST },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_HOST }, 
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_HOST },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "INTERNAL_TYPE|CONFERENCE",       ALWAYS, LEVEL_MAIN },
-	{ "  ", "RESOURCE|text",                ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|conference publication", ALWAYS, LEVEL_HOST }
-};
-
-static lookups statute[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN }, 
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST },  /* book title */
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "INTERNAL_TYPE|STATUTE",          ALWAYS, LEVEL_MAIN },
-	{ "  ", "RESOURCE|text",         ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|legislation",     ALWAYS, LEVEL_MAIN }
-};
-
-static lookups hearing[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN }, 
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* series title */
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "INTERNAL_TYPE|HEARING",          ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|hearing",         ALWAYS, LEVEL_MAIN }
-};
-
-static lookups cases[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN }, 
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "INTERNAL_TYPE|CASE",          ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|legal case and case notes", ALWAYS, LEVEL_MAIN }
-};
-
-static lookups communication[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "RECIPIENT",    PERSON,  LEVEL_MAIN },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_HOST }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "GENRE",        SIMPLE,  LEVEL_MAIN },
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },
-	{ "  ", "GENRE|communication",    ALWAYS, LEVEL_MAIN }
-};
-
-static lookups thesis[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN }, /*user defined */
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN }, /*misc */
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "INTERNAL_TYPE|THESIS",  ALWAYS,  LEVEL_MAIN },
-	{ "  ", "RESOURCE|text",ALWAYS,  LEVEL_MAIN },
-	{ "  ", "GENRE|thesis", ALWAYS,  LEVEL_MAIN },
-};
-
-static lookups report[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN }, /*user defined */
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN }, /*misc */
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "INTERNAL_TYPE|REPORT",  ALWAYS,  LEVEL_MAIN },
-	{ "  ", "RESOURCE|text",ALWAYS,  LEVEL_MAIN },
-	{ "  ", "GENRE|report", ALWAYS,  LEVEL_MAIN }
-};
-
-static lookups abstract[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN }, /*user defined */
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN }, /*misc */
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "GENRE|abstract or summary", ALWAYS,  LEVEL_MAIN }
-};
-
-static lookups program[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN }, /*user defined */
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN }, /*misc */
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "  ", "RESOURCE|software, multimedia", ALWAYS, LEVEL_MAIN }
-};
-
-static lookups patent[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN }, /*user defined */
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN }, /*misc */
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-        { "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN },
-        { "  ", "GENRE|patent", ALWAYS, LEVEL_MAIN }
-};
-
-static lookups electric[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN }, /*user defined */
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN }, /*misc */
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-        { " ",  "RESOURCE|software, multimedia",    ALWAYS, LEVEL_MAIN },
-        { " ",  "GENRE|electronic",       ALWAYS, LEVEL_MAIN },
-};
-
-static lookups pamphlet[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN }, /*user defined */
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN }, /*misc */
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-        { " ",  "RESOURCE|text",    ALWAYS, LEVEL_MAIN },
-        { " ",  "GENRE|pamphlet",       ALWAYS, LEVEL_MAIN },
-};
-
-static lookups unpublished[] = {
-	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },
-	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },
-	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, 
-	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },
-	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },
-	{ "Y2", "MONTH",     SIMPLE,  LEVEL_MAIN },
-	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },
-	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },
-	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },
-	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES },
-	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST }, /* JOURNAL */
-	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },
-	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },
-	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },
-	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },
-	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },
-	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },
-	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN }, 
-	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },
-	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },
-	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST }, 
-	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },
-	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },
-	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },
-	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },
-	{ "L1", "FILEATTACH",   SIMPLE,  LEVEL_MAIN },
-	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },
-	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN }, /*user defined */
-	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },
-	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN }, /*misc */
-	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN }, /* put in "notes" */
-	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },
-        { " ",         "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
-        { " ",         "GENRE|unpublished",      ALWAYS, LEVEL_MAIN }
+ * Copyright (c) Chris Putnam 2003-2012
+ *
+ * Program and source code released under the GPL
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "fields.h"
+#include "reftypes.h"
+	
+static lookups generic[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Name of Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE, LEVEL_MAIN },   /* File Attachments (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Resarch Notes -> Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated? */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+};
+
+static lookups article[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
+	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "PARTMONTH",    SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|ARTICLE",           ALWAYS, LEVEL_MAIN },
+	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
+	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|journal article",  ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|periodical",       ALWAYS, LEVEL_HOST },
+	{ "  ", "GENRE|academic journal", ALWAYS, LEVEL_HOST }
+};
+
+/* magazine article */
+static lookups magarticle[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
+	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "PARTMONTH",    SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
+	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|periodical",       ALWAYS, LEVEL_HOST },
+	{ "  ", "GENRE|magazine",         ALWAYS, LEVEL_HOST }
+};
+
+static lookups newsarticle[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
+	{ "PY", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "PARTYEAR",     DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "PARTMONTH",    SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|NEWSARTICLE",       ALWAYS, LEVEL_MAIN },
+	{ "  ", "ISSUANCE|continuing",    ALWAYS, LEVEL_HOST },
+	{ "  ", "RESOURCE|text",          ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|newspaper",        ALWAYS, LEVEL_HOST }
+};
+
+static lookups book[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "ISSUANCE|monographic",  ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|book",    ALWAYS, LEVEL_MAIN },
+	{ "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN }
+};
+
+static lookups inbook[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_HOST },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_HOST },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_HOST },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_HOST },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_HOST },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_HOST },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_HOST },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_HOST },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_HOST },   /* Access Date */
+	{ "  ", "GENRE|book chapter",   ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|book",           ALWAYS, LEVEL_HOST },
+	{ "  ", "ISSUANCE|monographic", ALWAYS, LEVEL_HOST },
+	{ "  ", "RESOURCE|text",        ALWAYS, LEVEL_MAIN }
+};
+
+static lookups conference[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_HOST },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_HOST },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_HOST },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_HOST },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|CONFERENCE",       ALWAYS, LEVEL_MAIN },
+	{ "  ", "RESOURCE|text",                ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|conference publication", ALWAYS, LEVEL_HOST }
+};
+
+static lookups statute[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|STATUTE",          ALWAYS, LEVEL_MAIN },
+	{ "  ", "RESOURCE|text",         ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|legislation",     ALWAYS, LEVEL_MAIN }
+};
+
+static lookups hearing[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|HEARING", ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|hearing",         ALWAYS, LEVEL_MAIN }
+};
+
+static lookups cases[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|CASE",              ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|legal case and case notes", ALWAYS, LEVEL_MAIN }
+};
+
+static lookups communication[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "RECIPIENT",    PERSON,  LEVEL_MAIN },   /* SPECIAL */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "GENRE",        SIMPLE,  LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|ARTICLE", ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|communication",   ALWAYS, LEVEL_MAIN }
+};
+
+static lookups thesis[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|THESIS",  ALWAYS,  LEVEL_MAIN },
+	{ "  ", "RESOURCE|text",         ALWAYS,  LEVEL_MAIN },
+	{ "  ", "GENRE|thesis",          ALWAYS,  LEVEL_MAIN },
+};
+
+static lookups report[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "INTERNAL_TYPE|REPORT",  ALWAYS,  LEVEL_MAIN },
+	{ "  ", "RESOURCE|text",         ALWAYS,  LEVEL_MAIN },
+	{ "  ", "GENRE|report",          ALWAYS,  LEVEL_MAIN }
+};
+
+static lookups abstract[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "GENRE|abstract or summary", ALWAYS,  LEVEL_MAIN }
+};
+
+static lookups program[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Misc or Number? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "RESOURCE|software, multimedia", ALWAYS, LEVEL_MAIN }
+};
+
+static lookups patent[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ "  ", "RESOURCE|text", ALWAYS, LEVEL_MAIN },
+	{ "  ", "GENRE|patent",  ALWAYS, LEVEL_MAIN }
+};
+
+static lookups electric[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ " ",  "RESOURCE|software, multimedia", ALWAYS, LEVEL_MAIN },
+	{ " ",  "GENRE|electronic",              ALWAYS, LEVEL_MAIN },
+};
+
+static lookups pamphlet[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ " ",  "RESOURCE|text",  ALWAYS, LEVEL_MAIN },
+	{ " ",  "GENRE|pamphlet", ALWAYS, LEVEL_MAIN },
+};
+
+static lookups unpublished[] = {
+	{ "A1", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "A2", "AUTHOR",       PERSON,  LEVEL_HOST },   /* 'Secondary' Author */
+	{ "A3", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Tertiary' Author */
+	{ "A4", "AUTHOR",       PERSON,  LEVEL_SERIES }, /* 'Subsidiary' Author */
+	{ "AB", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Abstract */
+	{ "AD", "AUTHORADDRESS",SIMPLE,  LEVEL_MAIN },   /* Author Address */
+	{ "AU", "AUTHOR",       PERSON,  LEVEL_MAIN },   /* Author */
+	{ "BT", "TITLE",        SIMPLE,  LEVEL_MAIN },   /* Book Title - Deprecated? */
+	{ "C1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C6", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C7", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "C8", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'Custom' - put in "notes" */
+	{ "CA", "CAPTION",      SIMPLE,  LEVEL_MAIN },   /* Caption */
+	{ "CN", "CALLNUMBER",   SIMPLE,  LEVEL_MAIN },   /* Call Number */
+	{ "CP", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CT", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "CY", "ADDRESS",      SIMPLE,  LEVEL_MAIN },   /* Place Published */
+	{ "DA", "YEAR",         DATE,    LEVEL_MAIN },   /* Date */
+	{ "DB", "DATABASE",     SIMPLE,  LEVEL_MAIN },   /* Database */
+	{ "DI", "DOI",          DOI,     LEVEL_MAIN },   /* Deprecated? */
+	{ "DO", "DOI",          DOI,     LEVEL_MAIN },   /* DOI */
+	{ "DP", "DATABASEPROV", SIMPLE,  LEVEL_MAIN },   /* Database Provider */
+	{ "ED", "EDITOR",       PERSON,  LEVEL_MAIN },   /* Deprecated? */
+	{ "EP", "PAGEEND",      SIMPLE,  LEVEL_MAIN },   /* End Page */
+	{ "ET", "EDITION",      SIMPLE,  LEVEL_MAIN },   /* Edition */
+	{ "ID", "REFNUM",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "IS", "ISSUE",        SIMPLE,  LEVEL_MAIN },   /* Number */
+	{ "J1", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "J2", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Alternate Title, abbreviated book or journal */
+	{ "JA", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JF", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "JO", "TITLE",        SIMPLE,  LEVEL_HOST },   /* Deprecated? */
+	{ "KW", "KEYWORD",      SIMPLE,  LEVEL_MAIN },   /* Keywords */
+	{ "L1", "FILEATTACH",   LINKEDFILE,  LEVEL_MAIN },   /* File Attachment (local, not URL) */
+	{ "L4", "FIGATTACH",    LINKEDFILE,  LEVEL_MAIN },   /* Figure Attachment (local, not URL) */
+	{ "LA", "LANGUAGE",     SIMPLE,  LEVEL_MAIN },   /* Language */
+	{ "LB", "LABEL",        SIMPLE,  LEVEL_MAIN },   /* Label */
+	{ "M1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M2", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Deprecated? */
+	{ "M3", "NOTES",        NOTES,   LEVEL_MAIN },   /* Misc or Type of Work? */
+	{ "N1", "NOTES",        NOTES,   LEVEL_MAIN },   /* Notes */
+	{ "N2", "ABSTRACT",     SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "NV", "NUMVOLUMES",   SIMPLE,  LEVEL_MAIN },   /* Number of Volumes */
+	{ "OP", "ORIGPUB",      SIMPLE,  LEVEL_MAIN },   /* Original Publication */
+	{ "PB", "PUBLISHER",    SIMPLE,  LEVEL_MAIN },   /* Publisher */
+	{ "PY", "YEAR",         DATE,    LEVEL_MAIN },   /* Year */
+	{ "RI", "REVIEWEDITEM", SIMPLE,  LEVEL_MAIN },   /* Reviewed Item */
+	{ "RN", "NOTES",        SIMPLE,  LEVEL_MAIN },   /* Research Notes */
+	{ "RP", "REPRINTSTATUS",SIMPLE,  LEVEL_MAIN },   /* Reprint Edition */
+	{ "SE", "SECTION",      SIMPLE,  LEVEL_MAIN },   /* Section */
+	{ "SN", "SERIALNUMBER", SERIALNO,LEVEL_MAIN },   /* ISBN/ISSN */
+	{ "SP", "PAGESTART",    SIMPLE,  LEVEL_MAIN },   /* Start Page */
+	{ "ST", "SHORTTITLE",   SIMPLE,  LEVEL_MAIN },   /* Short Title */
+	{ "T1", "TITLE",        TITLE,   LEVEL_MAIN },   /* Deprecated? */
+	{ "T2", "SHORTTITLE",   SIMPLE,  LEVEL_HOST },   /* 'Secondary' Title */
+	{ "T3", "TITLE",        SIMPLE,  LEVEL_SERIES }, /* 'Tertiary' Title */
+	{ "TI", "TITLE",        TITLE,   LEVEL_MAIN },   /* Title */
+	{ "TT", "TRANSTITLE",   TITLE,   LEVEL_MAIN },   /* Translated Title */
+	{ "U1", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U2", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U3", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U4", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "U5", "NOTES",        NOTES,   LEVEL_MAIN },   /* 'User' - Deprecated? */
+	{ "UR", "URL",          SIMPLE,  LEVEL_MAIN },   /* URL */
+	{ "VL", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Volume */
+	{ "VO", "VOLUME",       SIMPLE,  LEVEL_MAIN },   /* Deprecated? */
+	{ "Y1", "YEAR",         DATE,    LEVEL_MAIN },   /* Deprecated */
+	{ "Y2", "MONTH",        SIMPLE,  LEVEL_MAIN },   /* Access Date */
+	{ " ",         "RESOURCE|text",   ALWAYS, LEVEL_MAIN },
+	{ " ",         "GENRE|unpublished",      ALWAYS, LEVEL_MAIN }
 };
 
 #define ORIG(a) ( &(a[0]) )
diff --git a/bibutils/rules.h b/bibutils/rules.h
deleted file mode 100644
--- a/bibutils/rules.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * rules.h
- *
- * Copyright (c) Chris Putnam 2005-2010
- *
- * Source code released under the GPL
- *
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include "bibutils.h"
-
-/* internal includes */
-#include "reftypes.h"
-#include "bibtexin.h"
-#include "biblatexin.h"
-#include "bibtexout.h"
-#include "copacin.h"
-#include "endin.h"
-#include "endxmlin.h"
-#include "endout.h"
-#include "isiin.h"
-#include "isiout.h"
-#include "medin.h"
-#include "modsin.h"
-#include "risin.h"
-#include "wordin.h"
-#include "risout.h"
-#include "modsout.h"
-#include "wordout.h"
-#include "adsout.h"
-#include "newstr_conv.h"
-#include "is_ws.h"
-
-#include "ebiin.h"
-
-typedef struct convert_rules {
-	int  (*readf)(FILE*,char*,int,int*,newstr*,newstr*,int*);
-	int  (*processf)(fields*,char*,char*,long);
-	void (*cleanf)(bibl*,param*);
-	int  (*typef) (fields*,char*,int,param*,variants*,int);
-	void (*convertf)(fields*,fields*,int,param*,variants*,int);
-	void (*headerf)(FILE*,param*);
-	void (*footerf)(FILE*);
-	void (*writef)(fields*,FILE*,param*,unsigned long);
-	variants *all;
-	int  nall;
-} convert_rules;
-
diff --git a/bibutils/serialno.c b/bibutils/serialno.c
--- a/bibutils/serialno.c
+++ b/bibutils/serialno.c
@@ -1,7 +1,7 @@
 /*
  * serialno.c
  *
- * Copyright (c) Chris Putnam 2005-2010
+ * Copyright (c) Chris Putnam 2005-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/serialno.h b/bibutils/serialno.h
--- a/bibutils/serialno.h
+++ b/bibutils/serialno.h
@@ -1,7 +1,7 @@
 /*
  * serialno.h
  *
- * Copyright (c) Chris Putnam 2005-2009
+ * Copyright (c) Chris Putnam 2005-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/strsearch.c b/bibutils/strsearch.c
--- a/bibutils/strsearch.c
+++ b/bibutils/strsearch.c
@@ -1,6 +1,6 @@
 /* strsearch.c
  *
- * Copyright (c) Chris Putnam 1995-2010
+ * Copyright (c) Chris Putnam 1995-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/strsearch.h b/bibutils/strsearch.h
--- a/bibutils/strsearch.h
+++ b/bibutils/strsearch.h
@@ -1,7 +1,7 @@
 /*
  * strsearch.h
  *
- * Copyright (c) Chris Putnam 1995-2009
+ * Copyright (c) Chris Putnam 1995-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/title.c b/bibutils/title.c
--- a/bibutils/title.c
+++ b/bibutils/title.c
@@ -3,7 +3,7 @@
  *
  * process titles into title/subtitle pairs for MODS
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/title.h b/bibutils/title.h
--- a/bibutils/title.h
+++ b/bibutils/title.h
@@ -3,7 +3,7 @@
  *
  * process titles into title/subtitle pairs for MODS
  *
- * Copyright (c) Chris Putnam 2004-2009
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/utf8.c b/bibutils/utf8.c
--- a/bibutils/utf8.c
+++ b/bibutils/utf8.c
@@ -1,7 +1,7 @@
 /*
  * utf8.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/utf8.h b/bibutils/utf8.h
--- a/bibutils/utf8.h
+++ b/bibutils/utf8.h
@@ -1,7 +1,7 @@
 /*
  * utf8.h
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/vplist.c b/bibutils/vplist.c
new file mode 100644
--- /dev/null
+++ b/bibutils/vplist.c
@@ -0,0 +1,80 @@
+/*
+ * vplist.c
+ *
+ * Copyright (c) Chris Putnam 2011-2012
+ *
+ * Source code released under the GPL
+ *
+ * Implements a simple managed array of newstrs.
+ *
+ */
+#include "vplist.h"
+
+void *
+vplist_get( vplist *a, int n )
+{
+	if ( n<0 || n>a->n ) return NULL;
+	else return a->data[n];
+}
+
+static int
+vplist_alloc( vplist *a )
+{
+	int alloc = 20;
+	a->data = malloc( sizeof( void * ) * alloc );
+	if ( !(a->data) ) return 0;
+	a->max = alloc;
+	a->n = 0;
+	return 1;
+}
+
+static int
+vplist_realloc( vplist *a )
+{
+	void **more;
+	int alloc = a->max * 2;
+	more = ( void** ) realloc( a->data, sizeof( void * ) * alloc );
+	if ( !more ) return 0;
+	a->data = more;
+	a->max = alloc;
+	return 1;
+}
+
+int
+vplist_add( vplist *a, void *value )
+{
+	int ok = 1;
+
+	/* ensure sufficient space */
+	if ( a->max==0 ) ok = vplist_alloc( a );
+	else if ( a->n >= a->max ) ok = vplist_realloc( a );
+
+	if ( ok ) {
+		a->data[a->n] = value;
+		a->n++;
+	}
+
+	return ok;
+}
+
+void
+vplist_empty( vplist *a )
+{
+	a->n = 0;
+}
+
+void
+vplist_free( vplist *a )
+{
+	free( a->data );
+	vplist_init( a );
+}
+
+void
+vplist_init( vplist *a  )
+{
+	a->data = NULL;
+	a->max = 0;
+	a->n = 0;
+}
+
diff --git a/bibutils/vplist.h b/bibutils/vplist.h
new file mode 100644
--- /dev/null
+++ b/bibutils/vplist.h
@@ -0,0 +1,29 @@
+/*
+ * vplist.h
+ *
+ * Copyright (c) Chris Putnam 2011-2012
+ *
+ * Source code released under the GPL
+ *
+ */
+
+#ifndef VPLISTS_H
+#define VPLISTS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+typedef struct vplist {
+	int n, max;
+	void **data;
+} vplist;
+
+extern void    vplist_init( vplist *a );
+extern int     vplist_add( vplist *a, void *value );
+extern void    vplist_free( vplist *a );
+extern void*   vplist_get( vplist *a, int n );
+extern void    vplist_empty( vplist *a );
+
+
+#endif
diff --git a/bibutils/wordin.c b/bibutils/wordin.c
--- a/bibutils/wordin.c
+++ b/bibutils/wordin.c
@@ -1,7 +1,7 @@
 /*
  * wordin.c
  *
- * Copyright (c) Chris Putnam 2010
+ * Copyright (c) Chris Putnam 2010-2012
  *
  * Program and source code released under the GPL
  *
@@ -590,8 +590,14 @@
 wordin_convertf( fields *wordin, fields *info, int reftype, int verbose, 
 	variants *all, int nall )
 {
-	int i;
-	for ( i=0; i<wordin->nfields; ++i )
-		fields_add( info, wordin->tag[i].data, wordin->data[i].data,
-				wordin->level[i] );
+	char *tag, *value;
+	int i, n, level;
+
+	n = fields_num( wordin );
+	for ( i=0; i<n; ++i ) {
+		tag = fields_tag( wordin, i, FIELDS_CHRP );
+		value = fields_value( wordin, i, FIELDS_CHRP );
+		level = fields_level( wordin, i );
+		fields_add( info, tag, value, level );
+	}
 }
diff --git a/bibutils/wordin.h b/bibutils/wordin.h
--- a/bibutils/wordin.h
+++ b/bibutils/wordin.h
@@ -1,7 +1,7 @@
 /*
  * wordin.h
  *
- * Copyright (c) Chris Putnam 2009
+ * Copyright (c) Chris Putnam 2009-2012
  *
  * Program and source code released under the GPL
  *
diff --git a/bibutils/wordout.c b/bibutils/wordout.c
--- a/bibutils/wordout.c
+++ b/bibutils/wordout.c
@@ -3,7 +3,7 @@
  * 
  * (Word 2007 format)
  *
- * Copyright (c) Chris Putnam 2007-2010
+ * Copyright (c) Chris Putnam 2007-2012
  *
  * Source code released under the GPL
  *
@@ -44,11 +44,6 @@
 	int  code;
 } convert;
 
-typedef struct outtype {
-	int value;
-	char *out;
-} outtype;
-
 /*
 At the moment 17 unique types of sources are defined:
 
@@ -125,28 +120,32 @@
 	fields_setused( info, item );
 }
 
+static void
+output_itemv( FILE *outptr, char *tag, char *item, int level )
+{
+	int i;
+	for ( i=0; i<level; ++i ) fprintf( outptr, " " );
+	fprintf( outptr, "<%s>%s</%s>\n", tag, item, tag );
+}
+
 /* range output
  *
  * <TAG>start-end</TAG>
  *
  */
 static void
-output_range( fields *info, FILE *outptr, char *tag, int start, int end,
-		int level )
+output_range( FILE *outptr, char *tag, char *start, char *end, int level )
 {
 	int i;
-	if ( start==-1 && end==-1 ) return;
-	if ( start==-1 )
-		output_item( info, outptr, tag, end, 0 );
-	else if ( end==-1 )
-		output_item( info, outptr, tag, start, 0 );
+	if ( start==NULL && end==NULL ) return;
+	if ( start==NULL )
+		output_itemv( outptr, tag, end, 0 );
+	else if ( end==NULL )
+		output_itemv( outptr, tag, start, 0 );
 	else {
 		for ( i=0; i<level; ++i )
 			fprintf( outptr, " " );
-		fprintf( outptr, "<%s>%s-%s</%s>\n", tag, 
-			info->data[start].data, info->data[end].data, tag );
-		fields_setused( info, start );
-		fields_setused( info, end );
+		fprintf( outptr, "<%s>%s-%s</%s>\n", tag, start, end, tag );
 	}
 }
 
@@ -161,6 +160,11 @@
 
 }
 
+typedef struct outtype {
+	int value;
+	char *out;
+} outtype;
+
 static
 outtype genres[] = {
 	{ TYPE_PATENT, "patent" },
@@ -190,7 +194,7 @@
 {
 	int type = TYPE_UNKNOWN, i, j, level;
 	char *genre;
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		if ( strcasecmp( info->tag[i].data, "GENRE" ) &&
 			strcasecmp( info->tag[i].data, "NGENRE" ) ) continue;
 		genre = info->data[i].data;
@@ -235,7 +239,7 @@
 {
 	int type = TYPE_UNKNOWN, i;
 	char *resource;
-	for ( i=0; i<info->nfields; ++i ) {
+	for ( i=0; i<info->n; ++i ) {
 		if ( strcasecmp( info->tag[i].data, "GENRE" )!=0 &&
 			strcasecmp( info->tag[i].data, "NGENRE" )!=0 ) continue;
 		resource = info->data[i].data;
@@ -258,25 +262,19 @@
 static void
 output_titleinfo( fields *info, FILE *outptr, char *tag, int level )
 {
-	char *p;
-	int ttl, subttl;
-	ttl = fields_find( info, "TITLE", level );
-	subttl = fields_find( info, "SUBTITLE", level );
-	if ( ttl!=-1 || subttl!=-1 ) {
+	newstr *mainttl = fields_findv( info, level, FIELDS_STRP, "TITLE" );
+	newstr *subttl  = fields_findv( info, level, FIELDS_STRP, "SUBTITLE" );
+	if ( mainttl || subttl ) {
 		fprintf( outptr, "<%s>", tag );
-		if ( ttl!=-1 ) {
-			fprintf( outptr, "%s", info->data[ttl].data );
-			fields_setused( info, ttl );
-		}
-		if ( subttl!=-1 ) {
-			if ( ttl!=-1 ) {
-				p = info->data[ttl].data;
-				if ( p[info->data[ttl].len-1]!='?' )
-					fprintf( outptr, ":" );
-				fprintf( outptr, " " );
+		if ( mainttl ) fprintf( outptr, "%s", mainttl->data );
+		if ( subttl ) {
+			if ( mainttl ) {
+				if ( mainttl->len > 0 &&
+				     mainttl->data[mainttl->len-1]!='?' )
+					fprintf( outptr, ": " );
+				else fprintf( outptr, " " );
 			}
-			fprintf( outptr, "%s", info->data[subttl].data );
-			fields_setused( info, subttl );
+			fprintf( outptr, "%s", subttl->data );
 		}
 		fprintf( outptr, "</%s>\n", tag );
 	}
@@ -285,21 +283,19 @@
 static void
 output_title( fields *info, FILE *outptr, int level )
 {
-	int ttl = fields_find( info, "TITLE", level );
-	int subttl = fields_find( info, "SUBTITLE", level );
-	int shrttl = fields_find( info, "SHORTTITLE", level );
+	char *ttl    = fields_findv( info, level, FIELDS_CHRP, "TITLE" );
+	char *subttl = fields_findv( info, level, FIELDS_CHRP, "SUBTITLE" );
+	char *shrttl = fields_findv( info, level, FIELDS_CHRP, "SHORTTITLE" );
 
-	output_titleinfo( info, outptr, "b:Title", 0 );
+	output_titleinfo( info, outptr, "b:Title", level );
 
 	/* output shorttitle if it's different from normal title */
-	if ( shrttl!=-1 ) {
-		if ( ttl==-1 || subttl!=-1 ||
-			strcmp(info->data[ttl].data,info->data[shrttl].data) ) {
+	if ( shrttl ) {
+		if ( !ttl || ( strcmp( shrttl, ttl ) || subttl ) ) {
 			fprintf( outptr,  " <b:ShortTitle>" );
-			fprintf( outptr, "%s", info->data[shrttl].data );
+			fprintf( outptr, "%s", shrttl );
 			fprintf( outptr, "</b:ShortTitle>\n" );
 		}
-		fields_setused( info, shrttl );
 	}
 }
 
@@ -370,10 +366,11 @@
 			char *map[], int nmap, char *tag )
 {
 	newstr ntag;
-	int i, j, n=0, code;
+	int i, j, n=0, code, nfields;
 	newstr_init( &ntag );
+	nfields = fields_num( info );
 	for ( j=0; j<nmap; ++j ) {
-		for ( i=0; i<info->nfields; ++i ) {
+		for ( i=0; i<nfields; ++i ) {
 			code = extract_name_and_info( &ntag, &(info->tag[i]) );
 			if ( strcasecmp( ntag.data, map[j] ) ) continue;
 			if ( n==0 )
@@ -418,39 +415,27 @@
 static void
 output_date( fields *info, FILE *outptr, int level )
 {
-	convert parts[3] = {
-		{ "PARTYEAR",  "b:Year",  -1 },
-		{ "PARTMONTH", "b:Month", -1 },
-		{ "PARTDAY",   "b:Day",   -1 }
-	};
-
-	convert fulls[3] = {
-		{ "YEAR",  "", -1 },
-		{ "MONTH", "", -1 },
-		{ "DAY",   "", -1 }
-	};
-
-	int i, np, nf;
-	for ( i=0; i<3; ++i ) {
-		np = fields_find( info, parts[i].oldtag, level );
-		nf = fields_find( info, fulls[i].oldtag, level );
-		if ( np!=-1 )
-			output_item( info, outptr, parts[i].newtag, np, 0 );
-		else if ( nf!=-1 )
-			output_item( info, outptr, parts[i].newtag, nf, 0 );
-	}
+	char *year  = fields_findv_firstof( info, level, FIELDS_CHRP,
+			"PARTYEAR", "YEAR", NULL );
+	char *month = fields_findv_firstof( info, level, FIELDS_CHRP,
+			"PARTMONTH", "MONTH", NULL );
+	char *day   = fields_findv_firstof( info, level, FIELDS_CHRP,
+			"PARTDAY", "DAY", NULL );
+	if ( year )  output_itemv( outptr, "b:Year", year, 0 );
+	if ( month ) output_itemv( outptr, "b:Month", month, 0 );
+	if ( day )   output_itemv( outptr, "b:Day", day, 0 );
 }
 
 static void
 output_pages( fields *info, FILE *outptr, int level )
 {
-	int start = fields_find( info, "PAGESTART", -1 );
-	int end = fields_find( info, "PAGEEND", -1 );
-	int ar = fields_find( info, "ARTICLENUMBER", -1 );
-	if ( start!=-1 || end!=-1 )
-		output_range( info, outptr, "b:Pages", start, end, level );
-	else if ( ar!=-1 )
-		output_range( info, outptr, "b:Pages", ar, -1, level );
+	char *sn = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGESTART" );
+	char *en = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "PAGEEND" );
+	char *ar = fields_findv( info, LEVEL_ANY, FIELDS_CHRP, "ARTICLENUMBER" );
+	if ( sn || en )
+		output_range( outptr, "b:Pages", sn, en, level );
+	else if ( ar )
+		output_range( outptr, "b:Pages", ar, NULL, level );
 }
 
 static void
@@ -459,7 +444,7 @@
 	if ( type==TYPE_JOURNALARTICLE ) {
 		output_titleinfo( info, outptr, "b:JournalName", 1 );
 	} else if ( type==TYPE_ARTICLEINAPERIODICAL ) {
-		output_titleinfo( info, outptr, "b:PeriodicalName", 1 );
+		output_titleinfo( info, outptr, "b:PeriodicalTitle", 1 );
 	} else if ( type==TYPE_BOOKSECTION ) {
 		output_titleinfo( info, outptr, "b:ConferenceName", 1 ); /*??*/
 	} else if ( type==TYPE_PROCEEDINGS ) {
@@ -470,26 +455,31 @@
 static int
 type_is_thesis( int type )
 {
-	if ( type==TYPE_THESIS || type==TYPE_PHDTHESIS || 
-			type==TYPE_MASTERSTHESIS )
+	if ( type==TYPE_THESIS ||
+	     type==TYPE_PHDTHESIS ||
+	     type==TYPE_MASTERSTHESIS )
 		return 1;
-	else return 0;
+	else
+		return 0;
 }
 
 static void
 output_thesisdetails( fields *info, FILE *outptr, int type )
 {
-	int i;
+	char *tag;
+	int i, n;
 
 	if ( type==TYPE_PHDTHESIS )
 		output_fixed( outptr, "b:ThesisType", "Ph.D. Thesis", 0 );
 	else if ( type==TYPE_MASTERSTHESIS ) 
 		output_fixed( outptr, "b:ThesisType", "Masters Thesis", 0 );
 
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( strcasecmp( info->tag[i].data, "DEGREEGRANTOR" ) &&
-			strcasecmp( info->tag[i].data, "DEGREEGRANTOR:ASIS") &&
-			strcasecmp( info->tag[i].data, "DEGREEGRANTOR:CORP"))
+	n = fields_num( info );
+	for ( i=0; i<n; ++i ) {
+		tag = fields_tag( info, i, FIELDS_CHRP );
+		if ( strcasecmp( tag, "DEGREEGRANTOR" ) &&
+			strcasecmp( tag, "DEGREEGRANTOR:ASIS") &
+			strcasecmp( tag, "DEGREEGRANTOR:CORP"))
 				continue;
 		output_item( info, outptr, "b:Institution", i, 0 );
 	}
@@ -542,50 +532,49 @@
 static void
 output_comments( fields *info, FILE *outptr, int level )
 {
-	int i, written=0;
-	int nabs = fields_find( info, "ABSTRACT", level );
-	if ( nabs!=-1 ) {
-		fprintf( outptr, "<b:Comments>" );
-		fprintf( outptr, "%s", info->data[nabs].data );
-		written = 1;
-	}
-	for ( i=0; i<info->nfields; ++i ) {
-		if ( info->level[i]!=level ) continue;
-		if ( strcasecmp( info->tag[i].data, "NOTES" ) ) continue;
-		if ( !written ) {
-			fprintf( outptr, "<b:Comments>" );
-			written = 1;
-		}
-		fprintf( outptr, "%s", info->data[i].data );
-	}
-	if ( written ) fprintf( outptr, "</b:Comments>\n" );
+	vplist notes;
+	char *abs;
+	int i;
+
+	vplist_init( &notes );
+
+	abs = fields_findv( info, level, FIELDS_CHRP, "ABSTRACT" );
+	fields_findv_each( info, level, FIELDS_CHRP, &notes, "NOTES" );
+
+	if ( abs || notes.n ) fprintf( outptr, "<b:Comments>" );
+	if ( abs ) fprintf( outptr, "%s", abs );
+	for ( i=0; i<notes.n; ++i )
+		fprintf( outptr, "%s", (char*)vplist_get( &notes, i ) );
+	if ( abs || notes.n ) fprintf( outptr, "</b:Comments>\n" );
+
+	vplist_free( &notes );
 }
 
 static void
 output_bibkey( fields *info, FILE *outptr )
 {
-	int  n = fields_find( info, "REFNUM", -1 );
-	if ( n==-1 ) n = fields_find( info, "BIBKEY", -1 );
-	output_item( info, outptr, "b:Tag", n, 0 );
+	char *bibkey = fields_findv_firstof( info, LEVEL_ANY, FIELDS_CHRP,
+			"REFNUM", "BIBKEY", NULL );
+	if ( bibkey ) output_itemv( outptr, "b:Tag", bibkey, 0 );
 }
 
 static void
 output_citeparts( fields *info, FILE *outptr, int level, int max, int type )
 {
 	convert origin[] = {
-		{ "ADDRESS",	"b:City",	-1 },
-		{ "PUBLISHER",	"b:Publisher",	-1 },
-		{ "EDITION",	"b:Edition",	-1 }
+		{ "ADDRESS",	"b:City",	LEVEL_ANY },
+		{ "PUBLISHER",	"b:Publisher",	LEVEL_ANY },
+		{ "EDITION",	"b:Edition",	LEVEL_ANY }
 	};
 	int norigin = sizeof( origin ) / sizeof ( convert );
 	
 	convert parts[] = {
-		{ "VOLUME",          "b:Volume",  -1 },
-		{ "SECTION",         "b:Section", -1 },
-		{ "ISSUE",           "b:Issue",   -1 },
-		{ "NUMBER",          "b:Issue",   -1 },
-		{ "PUBLICLAWNUMBER", "b:Volume",  -1 },
-		{ "SESSION",         "b:Issue",   -1 },
+		{ "VOLUME",          "b:Volume",  LEVEL_ANY },
+		{ "SECTION",         "b:Section", LEVEL_ANY },
+		{ "ISSUE",           "b:Issue",   LEVEL_ANY },
+		{ "NUMBER",          "b:Issue",   LEVEL_ANY },
+		{ "PUBLICLAWNUMBER", "b:Volume",  LEVEL_ANY },
+		{ "SESSION",         "b:Issue",   LEVEL_ANY },
 	};
 	int nparts=sizeof(parts)/sizeof(convert);
 	
@@ -597,7 +586,7 @@
 	output_list( info, outptr, parts, nparts );
 	output_pages( info, outptr, level );
 	output_names( info, outptr, level, type );
-	output_title( info, outptr, level );
+	output_title( info, outptr, 0 );
 	output_comments( info, outptr, level );
 }
 
diff --git a/bibutils/wordout.h b/bibutils/wordout.h
--- a/bibutils/wordout.h
+++ b/bibutils/wordout.h
@@ -1,7 +1,7 @@
 /*
  * wordout.h
  *
- * Copyright (c) Chris Putnam 2008-2009
+ * Copyright (c) Chris Putnam 2008-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/xml.c b/bibutils/xml.c
--- a/bibutils/xml.c
+++ b/bibutils/xml.c
@@ -1,7 +1,7 @@
 /*
  * xml.c
  *
- * Copyright (c) Chris Putnam 2004-2010
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/xml.h b/bibutils/xml.h
--- a/bibutils/xml.h
+++ b/bibutils/xml.h
@@ -1,7 +1,7 @@
 /*
  * xml.h
  *
- * Copyright (c) Chris Putnam 2004-2009
+ * Copyright (c) Chris Putnam 2004-2012
  *
  * Source code released under the GPL
  *
diff --git a/bibutils/xml_encoding.h b/bibutils/xml_encoding.h
--- a/bibutils/xml_encoding.h
+++ b/bibutils/xml_encoding.h
@@ -1,7 +1,7 @@
 /*
  * xml_getencoding.h
  *
- * Copyright (c) Chris Putnam 2007-2009
+ * Copyright (c) Chris Putnam 2007-2012
  *
  * Source code released under the GPL
  *
diff --git a/hs-bibutils.cabal b/hs-bibutils.cabal
--- a/hs-bibutils.cabal
+++ b/hs-bibutils.cabal
@@ -1,6 +1,6 @@
 name:               hs-bibutils
-version:            4.12
-homepage:           http://code.haskell.org/hs-bibutils
+version:            4.14
+homepage:           http://gorgias.mine.nu/repos/hs-bibutils/
 
 synopsis:           Haskell bindings to bibutils, the bibliography
                     conversion utilities.
@@ -30,28 +30,36 @@
 cabal-version:      >= 1.4
 build-type:         Simple
 extra-source-files:
-    bibutils/adsout.c bibutils/adsout.h bibutils/adsout_journals.c bibutils/bibcore.c bibutils/bibl.c
-    bibutils/bibl.h bibutils/biblatexin.c bibutils/biblatexin.h bibutils/bibtexin.c
-    bibutils/bibtexin.h bibutils/bibtexout.c bibutils/bibtexout.h bibutils/bibtextypes.c
-    bibutils/bibutils.c bibutils/bibutils.h bibutils/bltypes.c bibutils/charsets.c
-    bibutils/charsets.h bibutils/copacin.c bibutils/copacin.h bibutils/copactypes.c
+    bibutils/adsout.c bibutils/adsout.h bibutils/adsout_journals.c
+    bibutils/bibcore.c bibutils/bibl.c bibutils/bibl.h
+    bibutils/biblatexin.c bibutils/biblatexin.h bibutils/bibtexin.c
+    bibutils/bibtexin.h bibutils/bibtexout.c bibutils/bibtexout.h
+    bibutils/bibtextypes.c bibutils/bibutils.c bibutils/bibutils.h
+    bibutils/bltypes.c bibutils/charsets.c bibutils/charsets.h
+    bibutils/copacin.c bibutils/copacin.h bibutils/copactypes.c
     bibutils/doi.c bibutils/doi.h bibutils/ebiin.c bibutils/ebiin.h
-    bibutils/endin.c bibutils/endin.h bibutils/endout.c bibutils/endout.h
-    bibutils/endtypes.c bibutils/endxmlin.c bibutils/endxmlin.h bibutils/entities.c
-    bibutils/entities.h bibutils/fields.c bibutils/fields.h bibutils/gb18030.c
-    bibutils/gb18030.h bibutils/gb18030_enumeration.c bibutils/is_ws.c bibutils/is_ws.h
-    bibutils/isiin.c bibutils/isiin.h bibutils/isiout.c bibutils/isiout.h
-    bibutils/isitypes.c bibutils/latex.c bibutils/latex.h bibutils/list.c
-    bibutils/list.h bibutils/marc.c bibutils/marc.h bibutils/medin.c
-    bibutils/medin.h bibutils/modsin.c bibutils/modsin.h bibutils/modsout.c
-    bibutils/modsout.h bibutils/modstypes.c bibutils/modstypes.h bibutils/name.c
-    bibutils/name.h bibutils/newstr.c bibutils/newstr.h bibutils/newstr_conv.c
-    bibutils/newstr_conv.h bibutils/reftypes.c bibutils/reftypes.h bibutils/risin.c
-    bibutils/risin.h bibutils/risout.c bibutils/risout.h bibutils/ristypes.c bibutils/rules.h
-    bibutils/serialno.c bibutils/serialno.h bibutils/strsearch.c bibutils/strsearch.h
-    bibutils/title.c bibutils/title.h bibutils/utf8.c bibutils/utf8.h bibutils/wordin.c
-    bibutils/wordin.h bibutils/wordout.c bibutils/wordout.h bibutils/xml.c
-    bibutils/xml.h bibutils/xml_encoding.c bibutils/xml_encoding.h
+    bibutils/endin.c bibutils/endin.h bibutils/endout.c
+    bibutils/endout.h bibutils/endtypes.c bibutils/endxmlin.c
+    bibutils/endxmlin.h bibutils/entities.c bibutils/entities.h
+    bibutils/fields.c bibutils/fields.h bibutils/gb18030.c
+    bibutils/gb18030.h bibutils/gb18030_enumeration.c bibutils/is_ws.c
+    bibutils/is_ws.h bibutils/isiin.c bibutils/isiin.h
+    bibutils/isiout.c bibutils/isiout.h bibutils/isitypes.c
+    bibutils/latex.c bibutils/latex.h bibutils/list.c bibutils/list.h
+    bibutils/marc.c bibutils/marc.h bibutils/medin.c bibutils/medin.h
+    bibutils/modsin.c bibutils/modsin.h bibutils/modsout.c
+    bibutils/modsout.h bibutils/modstypes.c bibutils/modstypes.h
+    bibutils/mycvout.c bibutils/name.c bibutils/name.h
+    bibutils/newstr.c bibutils/newstr.h bibutils/newstr_conv.c
+    bibutils/newstr_conv.h bibutils/reftypes.c bibutils/reftypes.h
+    bibutils/risin.c bibutils/risin.h bibutils/risout.c
+    bibutils/risout.h bibutils/ristypes.c bibutils/vplist.c
+    bibutils/vplist.h bibutils/serialno.c bibutils/serialno.h
+    bibutils/strsearch.c bibutils/strsearch.h bibutils/title.c
+    bibutils/title.h bibutils/utf8.c bibutils/utf8.h bibutils/wordin.c
+    bibutils/wordin.h bibutils/wordout.c bibutils/wordout.h
+    bibutils/xml.c bibutils/xml.h bibutils/xml_encoding.c
+    bibutils/xml_encoding.h
 
 library
     exposed-modules:  Text.Bibutils
@@ -64,18 +72,23 @@
     includes:         bibutils.h
     c-sources:
         cbits/stub.c
-        bibutils/adsout.c bibutils/bibcore.c bibutils/bibl.c bibutils/biblatexin.c bibutils/bibtexin.c
-        bibutils/bibtexout.c bibutils/bibtextypes.c bibutils/bibutils.c bibutils/bltypes.c
-        bibutils/charsets.c bibutils/copacin.c bibutils/copactypes.c bibutils/doi.c
-        bibutils/ebiin.c bibutils/endin.c bibutils/endout.c bibutils/endtypes.c
-        bibutils/endxmlin.c bibutils/entities.c bibutils/fields.c bibutils/gb18030.c
-        bibutils/is_ws.c bibutils/isiin.c bibutils/isiout.c bibutils/isitypes.c
-        bibutils/latex.c bibutils/list.c bibutils/marc.c bibutils/medin.c
-        bibutils/modsin.c bibutils/modsout.c bibutils/modstypes.c bibutils/name.c
-        bibutils/newstr.c bibutils/newstr_conv.c bibutils/reftypes.c bibutils/risin.c
-        bibutils/risout.c bibutils/ristypes.c bibutils/serialno.c bibutils/strsearch.c
-        bibutils/title.c bibutils/utf8.c bibutils/wordin.c bibutils/wordout.c
-        bibutils/xml.c bibutils/xml_encoding.c
+        bibutils/adsout.c bibutils/adsout_journals.c
+        bibutils/bibcore.c bibutils/bibl.c bibutils/biblatexin.c
+        bibutils/bibtexin.c bibutils/bibtexout.c
+        bibutils/bibtextypes.c bibutils/bibutils.c bibutils/bltypes.c
+        bibutils/charsets.c bibutils/copacin.c bibutils/copactypes.c
+        bibutils/doi.c bibutils/ebiin.c bibutils/endin.c
+        bibutils/endout.c bibutils/endtypes.c bibutils/endxmlin.c
+        bibutils/entities.c bibutils/fields.c bibutils/gb18030.c
+        bibutils/is_ws.c bibutils/isiin.c bibutils/isiout.c
+        bibutils/isitypes.c bibutils/latex.c bibutils/list.c
+        bibutils/marc.c bibutils/medin.c bibutils/modsin.c
+        bibutils/modsout.c bibutils/modstypes.c bibutils/name.c
+        bibutils/newstr.c bibutils/newstr_conv.c bibutils/reftypes.c
+        bibutils/risin.c bibutils/risout.c bibutils/ristypes.c
+        bibutils/vplist.c bibutils/serialno.c bibutils/strsearch.c
+        bibutils/title.c bibutils/utf8.c bibutils/wordin.c
+        bibutils/wordout.c bibutils/xml.c bibutils/xml_encoding.c
 
     if impl(ghc >= 6.10)
        build-depends: base >= 4, syb
