[SCM] Extract bibliographic references from various sources branch, debian, updated. debian/1.3.3-1

Filippo Rusconi (Debian Maintainer) rusconi-debian at laposte.net
Fri Sep 18 20:35:58 UTC 2009


The following commit has been merged in the debian branch:
commit 4ad6cca5239eaa386dfc762a10626f8a2b70ea14
Author: Filippo Rusconi (Debian Maintainer) <rusconi-debian at laposte.net>
Date:   Fri Sep 11 15:00:48 2009 +0200

    Imported cb2bib-1.3.3
    
    Summary: Imported cb2bib-1.3.3
    Keywords:
    
    Imported cb2bib-1.3.3
    into Git repository

diff --git a/CHANGELOG b/CHANGELOG
index 6c05b7f..2d534d6 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,13 @@
+2009-09-10   REALEASE OF VERSION 1.3.3
+2009-09-06   Added 'fix string: context' search type
+2009-08-26   Optimized search in files, and implemented fast matching for approximate strings
+2009-08-26   Fixed compiler -Werror=format-security errors in qDebug calls
+2009-08-18   Added --sloppy switch for --doc2bib and --txt2bib actions
+2009-08-11   Fixed export entries from search browser
+2009-08-06   Added relevant Prism metadata recognition
+2009-08-03   Fixed possible separator duplication in keywords
+2009-08-03   Wrote a more clarifying documentation for automatic extractions
+2009-08-01   Fixed a regression not converting '2nd' and '3rd' PubMed author suffixes
 2009-07-27   REALEASE OF VERSION 1.3.2
 2009-07-27   Do not ask if document should be saved when closing search results browser
 2009-07-27   Added <<citeid>> document ID placeholder that keeps both IDs syncronized
diff --git a/configure b/configure
index e06c18a..8434bb3 100755
--- a/configure
+++ b/configure
@@ -40,33 +40,38 @@ f_icondir=/usr/share/pixmaps
 
 f_qmake=NO
 f_make=NO
+f_disable_cbpoll=NO
+f_disable_lzo=NO
 
 while test -n "$1";  do
   case $1 in
     --prefix | -prefix)
-       shift; f_prefix="$1" ; f_bindir="$1/bin" ; f_datadir="$1/share/cb2bib" ; f_desktopdatadir="$1/share/applications" ; f_icondir="$1/share/pixmaps"
+       shift; f_prefix="$1" ; f_bindir=$1/bin ; f_datadir=$1/share/cb2bib ; f_desktopdatadir=$1/share/applications ; f_icondir=$1/share/pixmaps
        ;;
     --bindir | -bindir)
-       shift; unset f_prefix ; f_bindir="$1"
+       shift; unset f_prefix ; f_bindir=$1
        ;;
     --datadir | -datadir)
-       shift; unset f_prefix ; f_datadir="$1/cb2bib"
+       shift; unset f_prefix ; f_datadir=$1/cb2bib
        ;;
     --desktopdatadir | -desktopdatadir)
-       shift; unset f_prefix ; f_desktopdatadir="$1"
+       shift; unset f_prefix ; f_desktopdatadir=$1
        ;;
     --icondir | -icondir)
-       shift; unset f_prefix ; f_icondir="$1"
+       shift; unset f_prefix ; f_icondir=$1
        ;;
     --qmakepath | -qmakepath)
-       shift; unset f_qmake ; f_qmake="$1"
+       shift; unset f_qmake ; f_qmake=$1
        ;;
-    -h | -help | --help)
+    -h | --help | -help)
        f_help=y
        ;;
     --disable_cbpoll | -disable_cbpoll)
        f_disable_cbpoll=y
        ;;
+    --disable_lzo | -disable_lzo)
+       f_disable_lzo=y
+       ;;
     *)
        echo $1: unknown argument
        f_help=y
@@ -93,6 +98,7 @@ Options:
                         [default:  /usr/bin]
   --datadir dir         Data installation directory
                         [default:  /usr/share/bin/cb2bib]
+  --disable_lzo         Disables linking with lzo library
 
   Unix/Linux only:
   --desktopdatadir dir  Desktop data installation directory
@@ -190,7 +196,7 @@ echo "Checking for Qt/qmake:"
       echo "using $QTDIR/bin/qmake."
     fi
   fi
-  "$f_qmake" -v
+  $f_qmake -v
 
 
 #------------------------------------------------------------------------------
@@ -239,23 +245,29 @@ sed 's%^.*desktop.path .*$%desktop.path = '$f_desktopdatadir'%g' tmp.pro > src/s
 sed 's%^.*icons.path .*$%icons.path = '$f_icondir'%g' src/src.pro > tmp.pro
 mv -f tmp.pro src/src.pro
 if test "$f_disable_cbpoll" = y; then
-  echo "Setting clipboardPoll Disabled"
+  echo "Setting clipboardPoll disabled"
   sed 's% disable_cbpoll%%g' src/src.pro > tmp.pro
   sed 's%^CONFIG.*= %CONFIG += disable_cbpoll %g' tmp.pro > src/src.pro
 else
-  echo "Setting clipboardPoll Enabled (Unix/Linux only)"
+  echo "Setting clipboardPoll enabled (Unix/Linux only)"
   sed 's% disable_cbpoll%%g' src/src.pro > tmp.pro
   mv -f tmp.pro src/src.pro
 fi
 sed 's%^const QString C2B_DATA_DIR.*$%const QString C2B_DATA_DIR("'$f_datadir'/");%g' src/c2b/cb2bib_parameters.h > tmp.par
 mv -f tmp.par src/c2b/cb2bib_parameters.h
 
+f_configs=
+if test "$f_disable_lzo" = y; then
+  echo "Setting lzo disabled"
+  f_configs="-config disable_lzo"
+fi
+
 if test "$platform" = Darwin; then
-echo "Running $f_qmake -spec macx-g++ -o Makefile"
-"$f_qmake" -spec macx-g++ -o Makefile
+echo "Running $f_qmake -spec macx-g++ $f_configs -o Makefile"
+$f_qmake -spec macx-g++ $f_configs -o Makefile
 else
-echo "Running $f_qmake -o Makefile"
-"$f_qmake" -o Makefile
+echo "Running $f_qmake $f_configs -o Makefile"
+$f_qmake $f_configs -o Makefile
 fi
 
 echo " "
@@ -272,4 +284,7 @@ else
   echo "  permissions. Also, it will set cb2bib, c2bimport, and c2bciter"
   echo "  desktop files."
   echo "-----------------------------------------------------------------------"
+  echo "- NOTE: cb2Bib requires lzo library. If it were unavailable in your"
+  echo "  platform, reconfigure using --disable_lzo."
+  echo "-----------------------------------------------------------------------"
 fi
diff --git a/data/abbreviations.txt b/data/abbreviations.txt
index 905c5c5..3604abf 100644
--- a/data/abbreviations.txt
+++ b/data/abbreviations.txt
@@ -3,7 +3,7 @@ AA|Astron. Astrophys.|Astronomy and Astrophysics
 AAC|Antimicrob. Agents Chemother.|Antimicrobial Agents and Chemotherapy
 AAM|Adv. Appl. Math.|Advances in Applied Mathematics
 AAM|Adv. Appl. Microbiol.|Advances in Applied Microbiology
-AAMOP|Adv. At. Mol. Opt. Phy.|Advances in Atomic Molecular and Optical Physics
+AAMOP|Adv. At. Mol. Opt. Phys.|Advances in Atomic, Molecular, and Optical Physics
 AAQA|An. Asoc. Quim. Argent.|Anales de la Asociacion Quimica Argentina
 AB|Acta Biotechnol.|Acta Biotechnologica
 AB|Anal. Biochem.|Analytical Biochemistry
@@ -36,6 +36,7 @@ ACIP|Acta Cienc. Indica, Phys.|Acta Ciencia Indica Phyics
 ACIS|Adv. Colloid Interface Sci.|Advances in Colloid and Interface Science
 ACM|Adv. Compos. Mater|Advanced Composite Materials
 ACM|Appl. Compos. Mater.|Applied Composite Materials
+ACMTMS|ACM Trans. Math. Softw.|ACM Transactions on Mathematical Software
 ACP|Adv. Chem. Phys.|Advances in Chemical Physics
 ACR|Acc. Chem. Res.|Accounts of Chemical Research
 ACR|Ann. Chim. (Rome)|Annali di Chimica
@@ -585,8 +586,8 @@ JAC|J. Antimicrob. Chemother.|Journal of Antimicrobial Chemotherapy
 JAC|J. Appl. Crystallogr.|Journal of Applied Crystallography
 JAC|J. Autom. Chem.|Journal of Automatic Chemistry
 JACS0|J. Am. Ceram. Soc.|Journal of the American Ceramic Society
-JACS1|J. Amer. Chem. Soc.|Journal of the American Chemical Society
 JACS|J. Am. Chem. Soc.|Journal of the American Chemical Society
+JACS1|J. Amer. Chem. Soc.|Journal of the American Chemical Society
 JAE|J. Appl. Electrochem.|Journal of Applied Electrochemistry
 JAFC|J. Agric. Food. Chem.|Journal of Agricultural and Food Chemistry
 JA|J. Adhes.|Journal of Adhesion
@@ -761,6 +762,7 @@ JMC|J. Med. Chem.|Journal of Medicinal Chemistry
 JMC|J. Mol. Catal.|Journal of Molecular Catalysis
 JMCWM|J. Mater. Cycles Waste Manage.|Journal of Material Cycles and Waste Management
 JMEP|J. Mater. Eng. Perform.|Journal of Materials Engineering and Performance
+JMAP|J. Math. Anal. Appl.|Journal of Mathematical Analysis and Applications
 JMGM|J. Mol. Graphics Modell.|Journal of Molecular Graphics and Modelling
 JM|J. Microencapsulation|Journal of Microencapsulation
 JML|J. Mol. Liq.|Journal of Molecular Liquids
@@ -1009,6 +1011,7 @@ MTOM|Metalloved. Term. Obrab. Met.|Metallovedenie i Termicheskaya Obrabotka Meta
 MTS|Macromol. Theory Simul.|Macromolecular Theory and Simulations
 MWE|Mine Water Environ.|Mine Water and the Environment
 MW|Materialwiss. Werkstofftech.|Materialwissenschaft und Werkstofftechnik
+NA|Numer. Algor.|Numerical Algorithms
 NAR|Nucleic Acids Res.|Nucleic Acids Research
 NATOASISSA|NATO ASI Ser., Ser. A|NATO ASI Series, Series A Life Sciences
 NATOASISSB|NATO ASI Ser., Ser. B|NATO ASI Series, Series B Physics
diff --git a/data/tex2html.css b/data/tex2html.css
index ff94727..7e4a3cd 100644
--- a/data/tex2html.css
+++ b/data/tex2html.css
@@ -81,8 +81,6 @@ text-decoration: underline;
 .index {
 background-color: #AEAEA3;
 border-color: #72726A;
-#background-color: #818B93;
-#border-color: black;
 border-style: solid;
 border-width: 1px;
 font-family: sans-serif;
diff --git a/debian/README.Debian b/debian/README.Debian
deleted file mode 100644
index 79bbde3..0000000
--- a/debian/README.Debian
+++ /dev/null
@@ -1,29 +0,0 @@
-This package's suggestions enable the following optional features:
-
-* libimage-exiftool-perl: enable storage of bibliographic data (as
-   XMP-format metainformation) into PDF files.
-
-* konqueror: cb2Bib manages local and network files in an equivalent
-  manner. Network file retrieving, however, requires sometimes
-  password and/or cookies administration, both of which can be enabled
-  by the kfmclient utility, shipped within the konqueror package.
-
-* poppler-utils | xpdf-utils: enable conversion of PDF files to simple
-  text (required for cb2bib extraction of bibliographical data from
-  articles in PDF format).
-
-* bibutils: enable conversion between BibTeX, COPAC, EndNote refer,
-  EndNote XML, Pubmed XML, ISI web of science, US Library of Congress
-  MODS XML, RIS, and Word 2007 bibliography bibliographic data
-  formats.
-
-* jsmath: enable display of the mathematical notation in the text
-  notes.
-
-* texlive-latex-base: enable latex-based compilation of LaTeX
-  documents.
-
-* texlive-base-bin: enable dvipdfm-based conversion of DVI LaTeX
-  output to PDF.
-
- -- Filippo Rusconi <rusconi-debian at laposte.net>, Thu, 25 Jun 2009 22:03:56 +0200
diff --git a/debian/bib2pdf.1 b/debian/bib2pdf.1
deleted file mode 100644
index f009222..0000000
--- a/debian/bib2pdf.1
+++ /dev/null
@@ -1,63 +0,0 @@
-.TH "BIB2PDF" "1" "2009/06/24" "" ""
-.SH "NAME"
-bib2pdf \- script to convert BibTeX files to PDF
-
-.SH "SYNOPSIS"
-.HP 7
-\fBbib2pdf\fR <input.bib> <output.pdf>
-.PP
-
-
-.SH "DESCRIPTION"
-.PP
-\fBbib2pdf\fR is a script to convert a BibTeX file into a PDF
-file. The conversion is performed by first creating a small LaTeX file
-in which all the bibliographical records are inserted. That LaTeX file
-is then \fBlatex\fR\-compiled into a DVI file which, in turn, gets
-converted into a PDF file using \fBdvipdfm\fR\&. Note that the script
-might be configured to use \fBpdflatex\fR instead of \fBlatex\fR\&,
-thus producing the PDF output file with no extra conversion step.
-.PP
-This script is part of the \fBcb2bib\fR package and is located at
-/usr/share/cb2bib/c2btools/bib2pdf.
-
-
-.SH "BIBLIOGRAPHICAL REFERENCES TO BE CITED"
-.PP
-P. Constans (2009) "A simple extraction procedure for bibliographical author field", arXiv:0902.0755.
-.PP
-P. Constans (2007) "Approximate textual retrieval", arXiv:0705.0751.
-
-.RE
-.SH "SEE ALSO" 
-.PP 
-\fBcb2bib\fR (1); \fBmed2bib\fR (1); \fBisi2bib\fR (1); \fBris2bib\fR (1).
-
-.RE
-.SH "AUTHORS"
-.PP
-\fBPere Constans \&<constans\&@molspaces\&.com\&> and \fBFilippo
-Rusconi\fR <\&rusconi\&\-debian\&@laposte\&.net\&>
-.sp -1n
-.IP "" 4
-Program authors\&.
-.PP
-\fBFilippo Rusconi\fR <\&rusconi\&\-debian\&@laposte\&.net\&>
-.sp -1n
-.IP "" 4
-Man\-page author for the Debian distribution\&.
-.SH "COPYRIGHT"
-Copyright \(co 2004\-2008 Pere Constans
-.br
-Copyright \(co 2009 Filippo Rusconi
-.BR
-.PP
-This manual page was written for the Debian system (but may be used by others)\&.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU General Public License, Version 3 or (at
-your option) any later version published by the Free Software
-Foundation\&. On a Debian system the complete text of the GNU General
-Public License version 3 can be found in the file
-`/usr/share/common\-licenses/GPL\-3'.
-
diff --git a/debian/cb2bib.1 b/debian/cb2bib.1
deleted file mode 100644
index 418765f..0000000
--- a/debian/cb2bib.1
+++ /dev/null
@@ -1,182 +0,0 @@
-.TH "CB2BIB" "1" "September 2009" "" ""
-
-.SH "NAME"
-cb2bib \- software to extract bibliographic references from various sources
-
-.SH "SYNOPSIS"
-.HP 7
-\fBcb2bib\fR 
-.PP
-\fBcb2bib\fR  [\-\-conf [filename.conf]] [action] [filename1
-[filename2 ... ]]
-.PP
-\fBc2bimport\fR <imported reference file>
-.PP
-\fBc2bciter\fR [space\-separated list of BibTeX files or directories]
-
-
-.SH "DESCRIPTION"
-\fBcb2bib\fR is a software to extract bibliographic references from
-unformatted and non standard sources, like, for example 1) email
-alerts; 2) journal Web pages; 3) PDF files.
-.PP
-Captured references are provided to the user for inspection in a
-graphical form. Once validated, the references are transformed into
-BibTeX records which might be appended to a user\-defined BibTeX bib
-file.
-.PP
-The software allows to peruse a BibTeX file and to send to the
-clipboard a citation of all the records currently selected. A pipe is
-also setup with the LyX LaTeX editor.
-.PP
-When invoked with the \fB\-h\fR | \fB\-\-help\fR option, \fBcb2bib\fR
-lists all the options that are available on the command line.
-
-.SH "VARIANTS"
-.B cb2bib\fP is the main program.
-.PP
-.B c2bimport\fP is equivalent to using \fBcb2bib \-\-import\fR (this
-variant takes only \fBone\fR file name as parameter).
-.PP
-.B c2bciter\fP is equivalent to using \fBcb2bib \-\-citer\fR.
-
-
-.SH "OPTION"
-.TP
-.B \-\-conf [filename.conf]\fP	Use configuration file
-
-
-.SH "ACTIONS"
-.TP
-.B \-\-configure [filename.conf]\fP					Edit configuration
-.PP
-.B \-\-bibedit [filename1.bib [filename2.bib ... ]]\fP	Edit/browse BibTeX files
-.PP
-.B \-\-citer [filename1.bib [filename2.bib ... ]]\fP		Start cb2Bib citer
-.PP
-.B \-\-import <tmp_reference_filename>\fP				Imports reference, usually from ad hoc websites
-.PP
-.B \-\-doc2bib fn1.doc [fn2.doc ... ] reference.bib\fP	Extract reference from document file
-.PP
-.B \-\-txt2bib fn1.txt [fn2.txt ... ] reference.bib\fP	Extract reference from text file
-.PP
-.B \-\-html\-annote filename.tex\fP					Convert annote file to HTML
-.PP
-.B \-\-view\-annote filename.tex\fP					Convert and visualize annote file
-.PP
-.B \-\-view\-annote filename.tex.html\fP				Visualize annote file
-
-
-.SH "KEY SHORTCUTS"
-.HP 4
-\fBKey:\fR Description
-.PP 
-\fBAlt A:\fR Open cb2Bib Annote
-.PP 
-\fBAlt B:\fR Edit Bookmarks
-.PP 
-\fBAlt C:\fR Preparses cb2Bib's clipboard
-.PP 
-\fBAlt D:\fR Deletes temporary BibTeX output file
-.PP 
-\fBAlt E:\fR Edit Regular Expressions
-.PP q
-\fBAlt F:\fR Select File source filename
-.PP 
-\fBAlt I:\fR Insert Regular Expression
-.PP 
-\fBAlt J:\fR Edit Journal Abbreviations
-.PP 
-\fBAlt O:\fR Open File Document
-.PP 
-\fBAlt P:\fR Postprocess BibTeX
-.PP 
-\fBAlt R:\fR Restarts automatic recognition
-.PP 
-\fBEsc:\fR Quits cb2Bib popup menu
-.PP 
-\fBRight:\fR Click Editor popup menu
-
-.SH "EXAMPLES"
-.HP 4
-cb2bib                                        Starts cb2Bib extraction program
-.PP
-cb2bib \-\-import tmp_reference_filename        Imports a reference from a file
-.PP
-cb2bib \-\-bibedit filename.bib                 Edits BibTeX filename.bib
-.PP
-cb2bib \-\-conf                                 Starts cb2Bib in USB mode
-.PP
-cb2bib \-\-doc2bib *.pdf references.bib         Extracts references from PDF title pages
-.PP
-
-.SH "NOTES"
-.HP 4
-The file cb2bib.conf must be readable and writable. If it does not
-exist, the cb2Bib will create one based on predefined defaults.
-.PP
-Use switch \-\-conf to particularize specific settings for specific
-actions.
-.PP
-If starting the cb2Bib from a removable media use the command 'cb2bib
-\-\-conf' without configuration filename. Settings will be read from
-and written to /cb2bib/full/path/cb2bib.conf, being therefore
-independent of the mounting address that the host computer will
-provide.
-.PP
-To import references from a browser select when asked c2bimport, which
-expands to 'cb2bib \-\-import %f'. The browser will provide the
-temporary reference filename. The temporary file is deleted once
-imported.
-.PP
-A number of factors influence the reliability of automatic
-extractions. Consider writing customized regular expressions and
-network queries, and use metadata when available.
-.PP
-.IP \fBImportant\fR
-.PP
-The commands \-\-doc2bib and \-\-txt2bib do not append the references
-to the references.bib. They create a new file, or silently overwrites
-it if already exists.
-.PP
-The website http://www.molspaces.com/d_cb2bib\-overview.php has
-detailed instructions corresponding to different use cases.
-.PP
-
-
-.SH "BIBLIOGRAPHICAL REFERENCES TO BE CITED"
-P. Constans (2009) "A simple extraction procedure for bibliographical author field", arXiv:0902.0755.
-.PP
-P. Constans (2007) "Approximate textual retrieval", arXiv:0705.0751.
-
-.SH "SEE ALSO" 
-.BR bib2pdf (1),
-.BR med2bib (1),
-.BR isi2bib (1),
-.BR ris2bib (1)
-
-.SH "AUTHORS"
-\fBPere Constans\fR <\&constans at molspaces.com\&>
-.sp -1n
-.IP "" 4
-Program author\&.
-.PP
-\fBFilippo Rusconi\fR <\&rusconi-debian at laposte.net\&>
-.sp -1n
-.IP "" 4
-Man\-page author for the Debian distribution\&.
-.SH "COPYRIGHT"
-Copyright \(co 2004\-2008 Pere Constans
-.br
-Copyright \(co 2009 Filippo Rusconi
-.BR
-.PP
-This manual page was written for the Debian system by Filippo Rusconi
-<\&rusconi\-debian at laposte.net\&>\&. Permission is granted to copy,
-distribute and/or modify this document under the terms of the GNU
-General Public License, Version 3, published by the Free Software
-Foundation.
-.PP 
- On a Debian system the complete text of the GNU General Public
-License version 3 can be found in the file
-`\fI\%/usr/share/common-licenses/GPL\-3\fP'.
diff --git a/debian/cb2bib.dirs b/debian/cb2bib.dirs
deleted file mode 100644
index a75a4c0..0000000
--- a/debian/cb2bib.dirs
+++ /dev/null
@@ -1,3 +0,0 @@
-usr/bin
-usr/share/cb2bib/c2btools
-
diff --git a/debian/cb2bib.install b/debian/cb2bib.install
deleted file mode 100644
index a45c966..0000000
--- a/debian/cb2bib.install
+++ /dev/null
@@ -1,17 +0,0 @@
-debian/build/bin/* usr/bin
-c2bscripts/c2bciter usr/bin
-c2bscripts/c2bimport usr/bin
-
-c2bscripts/c2bciter.desktop usr/share/applications
-c2bscripts/c2bimport.desktop usr/share/applications
-c2bscripts/cb2bib.desktop usr/share/applications
-
-c2btools/bib2pdf usr/share/cb2bib/c2btools
-c2btools/isi2bib usr/share/cb2bib/c2btools
-c2btools/med2bib usr/share/cb2bib/c2btools
-c2btools/ris2bib usr/share/cb2bib/c2btools
-
-data /usr/share/cb2bib
-testPDFImport /usr/share/cb2bib
-debian/cb2bib.xpm usr/share/pixmaps
-src/icons/cb2bib.png usr/share/pixmaps
diff --git a/debian/cb2bib.manpages b/debian/cb2bib.manpages
deleted file mode 100644
index 240e374..0000000
--- a/debian/cb2bib.manpages
+++ /dev/null
@@ -1,5 +0,0 @@
-debian/cb2bib.1
-debian/bib2pdf.1
-debian/med2bib.1
-debian/isi2bib.1
-debian/ris2bib.1
diff --git a/debian/cb2bib.menu b/debian/cb2bib.menu
deleted file mode 100644
index fe256e2..0000000
--- a/debian/cb2bib.menu
+++ /dev/null
@@ -1,17 +0,0 @@
-?package(cb2bib):needs="X11" section="Applications/Text" \
-  title="cb2bib" \
-  longtitle="Extract bibliographical data from various sources" \
-  icon="/usr/share/pixmaps/cb2bib.xpm" \
-  command="/usr/bin/cb2bib"
-
-?package(cb2bib):needs="X11" section="Applications/Text" \
-  title="c2bciter" \
-  longtitle="Cite bibliographical references from BibTeX files to clipboard" \
-  icon="/usr/share/pixmaps/cb2bib.xpm" \
-  command="/usr/bin/c2bciter"
-
-?package(cb2bib):needs="X11" section="Applications/Text" \
-  title="c2bimport" \
-  longtitle="Parse an imported reference file to the cb2bib program window" \
-  icon="/usr/share/pixmaps/cb2bib.xpm" \
-  command="/usr/bin/c2bimport"
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 0bdd2bf..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,15 +0,0 @@
-cb2bib (1.3.2-1) unstable; urgency=low
-
-  * New upstream release;
-  * Small packaging modifications to accomodate the small changes in the
-    source tree.
-  * Fixed some glitches in the nroff formatting of the man page.
-
- -- Filippo Rusconi <rusconi-debian at laposte.net>  Wed, 09 Sep 2009 23:19:05 +0200
-
-cb2bib (1.3.0-1) unstable; urgency=low
-
-  * Initial release (Closes: #529399);
-
- -- Filippo Rusconi <rusconi-debian at laposte.net>  Fri, 04 Sep 2009 06:02:19 +0200
-
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index 7f8f011..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-7
diff --git a/debian/control b/debian/control
deleted file mode 100644
index fa8ef65..0000000
--- a/debian/control
+++ /dev/null
@@ -1,32 +0,0 @@
-Source: cb2bib
-Section: text
-Priority: optional
-Maintainer: Debian Science Maintainers <debian-science-maintainers at lists.alioth.debian.org>
-Uploaders: Filippo Rusconi <rusconi-debian at laposte.net>
-DM-Upload-Allowed: yes
-Build-Depends: debhelper (>= 7), libx11-dev, x11proto-core-dev, libqt4-dev (>=4.4), imagemagick
-Standards-Version: 3.8.3
-Homepage: http://www.molspaces.com/cb2bib/
-Vcs-Git: git://git.debian.org/git/debian-science/packages/cb2bib.git
-Vcs-Browser: http://git.debian.org/?p=debian-science/packages/cb2bib.git
-
-Package: cb2bib
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}
-Suggests: libimage-exiftool-perl, konqueror, poppler-utils | xpdf-utils, bibutils, jsmath, texlive-latex-base, texlive-base-bin
-Description: extract bibliographic references from various sources
- cb2bib is a program to extract bibliographic references from
- unformatted and non standard sources, like:
-  - email alerts;
-  - journal Web pages;
-  - and most interestingly PDF files.
- .
- Output references are written to BibTeX-formatted files. Other
- features include:
-  - article files can be linked and renamed by dragging them onto the
-    cb2Bib window;
-  - editing and browsing BibTeX files;
-  - citing references, searching references and the full contents of the
-    referenced documents;
-  - inserting bibliographic metadata to documents;
-  - writing short notes that interrelate several references.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index 89435db..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,49 +0,0 @@
-This package was debianized by Filippo Rusconi <rusconi-debian at laposte.net> on
-Sat, 16 May 2009 20:56:59 +0200.
-
-It was downloaded from http://www.molspaces.com/cb2bib/
-
-Author: Pere Constans <constans at molspaces.com>
-
-cb2bib Copyright © 2004-2008 Pere Constans
-
-License for cb2bib: GNU General Public License version 3
-
-    This program is free software: you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
- On Debian systems, the GNU General Public License version 3, is
- available as the file `/usr/share/common-licenses/GPL-3'.
-
-
- This work builds upon some code/artwork all licensed under Free
- Software licenses, as detailed below:
-
-  - Class clipboardPoll (files clipboardPoll.h & clipboardPoll.cpp) is
-    based on work by Lubos Lunak, 2003 (GPLv2 or later);
-
-  - Function citeToLyXPipe is adapted from work by Robby Stephenson,
-    2005 (file c2bReferenceList.cpp, from project Tellico, GPLv2 or
-    later);
-
-  - Class EQRegExp is based on work by Trolltech ASA, 2008 (files
-    findDialog.h, findDialog.cpp, c2bSaveRegExp.cpp & cb2Bib.cpp,
-    GPLv3);
-
-  - Icons come from the Oxygen, Crystal SVG, and Noia icon sets,
-    as published by the KDE Desktop Environment (GPL).
-
-
-The Debian packaging is © 2009, Filippo Rusconi
-<rusconi-debian at laposte.net> and is licensed under the GPL, see
-`/usr/share/common-licenses/GPL-3'.
diff --git a/debian/docs b/debian/docs
deleted file mode 100644
index b8c9a41..0000000
--- a/debian/docs
+++ /dev/null
@@ -1,2 +0,0 @@
-AUTHORS
-
diff --git a/debian/isi2bib.1 b/debian/isi2bib.1
deleted file mode 100644
index c333f7d..0000000
--- a/debian/isi2bib.1
+++ /dev/null
@@ -1,60 +0,0 @@
-.TH "ISI2BIB" "1" "2009/06/24" "" ""
-.SH "NAME"
-isi2bib \- script to convert ISI\-format files to PDF
-
-.SH "SYNOPSIS"
-.HP 7
-\fBisi2bib\fR <input.isi> <output.bib>
-.PP
-
-
-.SH "DESCRIPTION"
-.PP
-\fBisi2bib\fR is a script to convert an ISI\-format file into a PDF
-file. The conversion is a two step process: the ISI\-format file is
-first converted into an XML\-format file; that XML\-format file is in
-turn converted into the BibTeX\-format file (both utilities are
-shipped in the \fBbibutils\fR package).
-.PP
-This script is part of the \fBcb2bib\fR package and is located at
-/usr/share/cb2bib/c2btools/isi2bib.
-
-
-.SH "BIBLIOGRAPHICAL REFERENCES TO BE CITED"
-.PP
-P. Constans (2009) "A simple extraction procedure for bibliographical author field", arXiv:0902.0755.
-.PP
-P. Constans (2007) "Approximate textual retrieval", arXiv:0705.0751.
-
-.RE
-.SH "SEE ALSO" 
-.PP 
-\fBcb2bib\fR (1); \fBmed2bib\fR (1); \fBpdf2bib\fR (1); \fBris2bib\fR (1).
-
-.RE
-.SH "AUTHORS"
-.PP
-\fBPere Constans \&<constans\&@molspaces\&.com\&> and \fBFilippo
-Rusconi\fR <\&rusconi\&\-debian\&@laposte\&.net\&>
-.sp -1n
-.IP "" 4
-Program authors\&.
-.PP
-\fBFilippo Rusconi\fR <\&rusconi\&\-debian\&@laposte\&.net\&>
-.sp -1n
-.IP "" 4
-Man\-page author for the Debian distribution\&.
-.SH "COPYRIGHT"
-Copyright \(co 2004\-2008 Pere Constans
-.br
-Copyright \(co 2009 Filippo Rusconi
-.BR
-.PP
-This manual page was written for the Debian system (but may be used by others)\&.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU General Public License, Version 3 or (at
-your option) any later version published by the Free Software
-Foundation\&. On a Debian system the complete text of the GNU General
-Public License version 3 can be found in the file
-`/usr/share/common\-licenses/GPL\-3'.
diff --git a/debian/med2bib.1 b/debian/med2bib.1
deleted file mode 100644
index e816ebe..0000000
--- a/debian/med2bib.1
+++ /dev/null
@@ -1,54 +0,0 @@
-.TH "MED2BIB" "1" "2009/06/24" "" ""
-.SH "NAME"
-med2bib \- script to convert Pubmed\-format files to BibTeX\-format files
-
-.SH "SYNOPSIS"
-.HP 7
-\fBmed2bib\fR <input.med> <output.bib>
-.PP
-
-
-.SH "DESCRIPTION"
-.PP
-\fBmed2bib\fR is a script to convert a Pubmed\-format file into a
-BibTeX\-format file. The conversion is a two step process: the
-Pubmed\-format file is first converted into an XML\-format file; that
-XML\-format file is in turn converted into the BibTeX\-format file (both
-utilities are shipped in the \fBbibutils\fR package).
-.PP
-This script is part of the \fBcb2bib\fR package and is located at
-/usr/share/cb2bib/c2btools/med2bib.
-
-
-.SH "BIBLIOGRAPHICAL REFERENCES TO BE CITED"
-.PP
-P. Constans (2009) "A simple extraction procedure for bibliographical author field", arXiv:0902.0755.
-.PP
-P. Constans (2007) "Approximate textual retrieval", arXiv:0705.0751.
-
-.RE
-.SH "SEE ALSO" 
-.PP 
-\fBcb2bib\fR (1); \fBbib2pdf\fR (1); \fBisi2bib\fR (1); \fBris2bib\fR (1).
-
-.RE
-.SH "AUTHORS"
-.PP
-\fBFilippo Rusconi\fR <\&rusconi\&\-debian\&@laposte\&.net\&> basing
-the writing on previous work by \fBPere Constans \&<constans\&@molspaces\&.com\&>.
-.sp -1n
-.IP "" 4
-Program and man page (for the Debian distribution) author\&.
-.PP
-.SH "COPYRIGHT"
-Copyright \(co 2009 Filippo Rusconi
-.BR
-.PP
-This manual page was written for the Debian system (but may be used by others)\&.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU General Public License, Version 3 or (at
-your option) any later version published by the Free Software
-Foundation\&. On a Debian system the complete text of the GNU General
-Public License version 3 can be found in the file
-`/usr/share/common\-licenses/GPL\-3'.
diff --git a/debian/ris2bib.1 b/debian/ris2bib.1
deleted file mode 100644
index 7fc2f97..0000000
--- a/debian/ris2bib.1
+++ /dev/null
@@ -1,60 +0,0 @@
-.TH "RIS2BIB" "1" "2009/06/24" "" ""
-.SH "NAME"
-ris2bib \- script to convert RIS\-format files to PDF
-
-.SH "SYNOPSIS"
-.HP 7
-\fBris2bib\fR <input.ris> <output.bib>
-.PP
-
-
-.SH "DESCRIPTION"
-.PP
-\fBris2bib\fR is a script to convert an RIS\-format file into a PDF
-file. The conversion is a two step process: the RIS\-format file is
-first converted into an XML\-format file; that XML\-format file is in
-turn converted into the BibTeX\-format file (both utilities are
-shipped in the \fBbibutils\fR package).
-.PP
-This script is part of the \fBcb2bib\fR package and is located at
-/usr/share/cb2bib/c2btools/ris2bib.
-
-
-.SH "BIBLIOGRAPHICAL REFERENCES TO BE CITED"
-.PP
-P. Constans (2009) "A simple extraction procedure for bibliographical author field", arXiv:0902.0755.
-.PP
-P. Constans (2007) "Approximate textual retrieval", arXiv:0705.0751.
-
-.RE
-.SH "SEE ALSO" 
-.PP 
-\fBcb2bib\fR (1); \fBmed2bib\fR (1); \fBpdf2bib\fR (1); \fBisi2bib\fR (1).
-
-.RE
-.SH "AUTHORS"
-.PP
-\fBPere Constans \&<constans\&@molspaces\&.com\&> and \fBFilippo
-Rusconi\fR <\&rusconi\&\-debian\&@laposte\&.net\&>
-.sp -1n
-.IP "" 4
-Program authors\&.
-.PP
-\fBFilippo Rusconi\fR <\&rusconi\&\-debian\&@laposte\&.net\&>
-.sp -1n
-.IP "" 4
-Man\-page author for the Debian distribution\&.
-.SH "COPYRIGHT"
-Copyright \(co 2004\-2008 Pere Constans
-.br
-Copyright \(co 2009 Filippo Rusconi
-.BR
-.PP
-This manual page was written for the Debian system (but may be used by others)\&.
-.PP
-Permission is granted to copy, distribute and/or modify this document
-under the terms of the GNU General Public License, Version 3 or (at
-your option) any later version published by the Free Software
-Foundation\&. On a Debian system the complete text of the GNU General
-Public License version 3 can be found in the file
-`/usr/share/common\-licenses/GPL\-3'.
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index cb9e3ef..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,106 +0,0 @@
-#!/usr/bin/make -f
-# Based on the initial work of Joey Hess and Craig Small.
-
-# Uncomment this to turn on verbose mode.
-export DH_VERBOSE=1
-
-DEB_HOST_GNU_TYPE   ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
-DEB_BUILD_GNU_TYPE  ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
-
-
-PACKAGE=cb2bib
-
-BUILDDIR=$(CURDIR)/debian/build
-
-
-ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
-         NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
-         MAKEFLAGS += -j$(NUMJOBS)
-endif
-
-$(info "---------------------------------------")
-$(info NUMJOBS: $(NUMJOBS))
-$(info MAKEFLAGS: $(MAKEFLAGS))
-$(info DEB_BUILD_OPTIONS: $(DEB_BUILD_OPTIONS))
-$(info "---------------------------------------")
-
-
-.PHONY: clean
-clean: 
-	dh_testdir
-	dh_testroot
-
-	dh_clean
-
-	rm -rf $(BUILDDIR)
-	rm -f debian/cb2bib.xpm
-
-
-configure-stamp: 
-	dh_testdir
-
-	mkdir -p $(BUILDDIR)
-	cp -rpf cb2bib.pro cb2bib.rc configure src $(BUILDDIR)
-	cd $(BUILDDIR) && ./configure --qmakepath /usr/bin/qmake-qt4	\
-	--prefix /usr --bindir /usr/bin --datadir /usr/share		\
-	--desktopdatadir /usr/share/applications --icondir		\
-	/usr/share/pixmaps
-
-	touch configure-stamp
-
-
-build-arch-stamp: configure-stamp 
-	dh_testdir
-	dh_prep -a
-
-	$(MAKE) -C $(BUILDDIR)
-	convert src/icons/cb2bib.png -resize 32x32 debian/cb2bib.xpm
-
-	touch build-arch-stamp
-
-
-.PHONY: build-indep
-build-indep:
-
-
-.PHONY: build-arch
-build-arch: build-arch-stamp
-
-
-.PHONY: build
-build: build-indep build-arch
-
-
-# Build architecture-independent files here.
-.PHONY: binary-indep
-binary-indep: 
-
-
-# Build architecture-dependent files here.
-.PHONY: binary-arch
-binary-arch: build-arch-stamp
-	dh_testdir -a
-	dh_testroot -a
-	dh_installchangelogs -a
-	dh_installdocs -a
-	dh_installexamples -a
-	dh_install -a
-	dh_installmenu -a cb2bib.menu
-	dh_installman -a
-	dh_link -a usr/share/man/man1/cb2bib.1 usr/share/man/man1/c2bimport.1
-	dh_link -a usr/share/man/man1/cb2bib.1 usr/share/man/man1/c2bciter.1
-	dh_strip -a
-	dh_compress -a
-	dh_fixperms -a
-	dh_installdeb -a
-	dh_shlibdeps -a
-	dh_gencontrol -a
-	dh_md5sums -a
-	dh_builddeb -a
-
-
-.PHONY: binary
-binary: binary-indep binary-arch
-
-
-
diff --git a/debian/watch b/debian/watch
deleted file mode 100644
index d22769a..0000000
--- a/debian/watch
+++ /dev/null
@@ -1,6 +0,0 @@
-version=3
-
-opts=downloadurlmangle=s/d_cb2bib-download.php/\./ \
-http://www.molspaces.com/d_cb2bib-download.php/ \
-dl/progs/cb2bib-([\d\.]*)\.tar\.gz
-
diff --git a/src/bookmarkPlugin.cpp b/src/bookmarkPlugin.cpp
index c96b2fd..4f31402 100644
--- a/src/bookmarkPlugin.cpp
+++ b/src/bookmarkPlugin.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "bookmarkPlugin.h"
@@ -62,7 +62,7 @@ void bookmarkPlugin::parseBookmarks()
             const QStringList bm_parts(bookmarks.at(i).split('|', QString::KeepEmptyParts));
             if (bm_parts.count() != 4)
             {
-                qDebug(tr("[cb2bib] bookmarkPlugin::parseBookmarks: Syntax error at '%1'").arg(bookmarks.at(i)).toLatin1());
+                c2bUtils::warn(tr("bookmarkPlugin::parseBookmarks: Syntax error at '%1'").arg(bookmarks.at(i)));
                 continue;
             }
             QAction* act = addAction(bm_parts.at(0), this, SLOT(openBookmark()));
diff --git a/src/bookmarkPlugin.h b/src/bookmarkPlugin.h
index 52f128d..21124cd 100644
--- a/src/bookmarkPlugin.h
+++ b/src/bookmarkPlugin.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef BOOKMARKPLUGIN_H
diff --git a/src/c2b.cpp b/src/c2b.cpp
index 2a79008..3a79e80 100644
--- a/src/c2b.cpp
+++ b/src/c2b.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2b.h"
diff --git a/src/c2b.h b/src/c2b.h
index 7f44d71..9a7506f 100644
--- a/src/c2b.h
+++ b/src/c2b.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2B_H
diff --git a/src/c2b/approximatePattern.cpp b/src/c2b/approximatePattern.cpp
index a8cbc5f..03772f8 100644
--- a/src/c2b/approximatePattern.cpp
+++ b/src/c2b/approximatePattern.cpp
@@ -1,126 +1,147 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  *
  *   Class implementation of the approximate search algorithm
  *   P. Constans. Approximate textual retrieval. arXiv:0705.0751v1, 2007.
  ***************************************************************************/
 #include "approximatePattern.h"
+
 #include "cb2bib_utilities.h"
+#include "triads.h"
+
 
+approximatePattern::approximatePattern() : compositePattern()
+{}
 
-approximatePattern::approximatePattern(const QString newPattern, Qt::CaseSensitivity newCs) : compositePattern(newPattern, newCs)
+approximatePattern::approximatePattern(const QString& pattern, const Qt::CaseSensitivity cs) : compositePattern(pattern, cs)
 {
-    pre = c2bUtils::fileToString(":/txt/txt/prefixes.txt").split(c2bUtils::nonLetter, QString::SkipEmptyParts);
-    suf = c2bUtils::fileToString(":/txt/txt/suffixes.txt").split(c2bUtils::nonLetter, QString::SkipEmptyParts);
-    setPattern();
+    setPattern(pattern, cs);
 }
 
-approximatePattern::~approximatePattern()
-{}
 
-
-void approximatePattern::setPattern()
+void approximatePattern::setPattern(const QString& pattern, const Qt::CaseSensitivity cs)
 {
+    _string = pattern.simplified();
+    _case_sensitivity = cs;
+    _is_multipattern = false;
+    _matched_length = -1;
+    _subpattern_count = 0;
     // Exact match
-    if (pattern.length() < 5)
+    if (_string.length() < 5)
     {
-        arx.setPattern(escape(pattern, caseSensitivity));
+        _regexp.setPattern(escape(_string, _case_sensitivity));
         return;
     }
-
     // Single word: Allow 1 error (1 missing / 3 excess), anywhere
-    if (wordCount(pattern) == 1)
+    if (wordCount(_string) == 1)
     {
-        arx.setPattern(wordPattern(pattern, caseSensitivity));
+        _regexp.setPattern(wordPattern(_string, _case_sensitivity));
         return;
     }
-
     // Multiple words
+    _prefixes = c2bUtils::fileToString(":/txt/txt/prefixes.txt").split(c2bUtils::nonLetter, QString::SkipEmptyParts);
+    _suffixes = c2bUtils::fileToString(":/txt/txt/suffixes.txt").split(c2bUtils::nonLetter, QString::SkipEmptyParts);
     splitPattern();
-    if (patternPieces.count() < 3) // Cases: "qq pp", "qqq pp", etc
+    if (_string_pieces.count() < 3) // Cases: "qq pp", "qqq pp", etc
     {
-        arx.setPattern(wordPattern(pattern, caseSensitivity));
+        _regexp.setPattern(wordPattern(_string, _case_sensitivity));
         return;
     }
+    _is_multipattern = true;
 
     // Set parameters
-    const double percentScan(50.);
-    const double scanFactor(100. / percentScan);
-    const int maxBlocks(patternPieces.count() / 2);
-    const int requestedBlocks(c2bUtils::nearInteger(scanFactor));
-    const int nBlocks(qMin(maxBlocks, 1 + requestedBlocks));
-    int nPiecesPerBlock(patternPieces.count() / nBlocks);    // Ceiling
-    if ((patternPieces.count() % nBlocks) > 0)
-        nPiecesPerBlock++;
-
-//    qDebug() << patternPieces << maxBlocks << scanFactor << requestedBlocks << nPiecesPerBlock << patternPieces.count() % nBlocks;
-//    for (int b = 0; b < nBlocks; ++b)
-//        for (int i = 0; i < nPiecesPerBlock; ++i)
-//            if (b + (i*nBlocks) < patternPieces.count())
-//                qDebug() << "block#   " << b << "pick item " <<  b + (i*nBlocks) << patternPieces.at(b + (i*nBlocks));
-
-    QStringList subPatterns;
-    const QString _stretch(".{0,%1}%2");
-    QRegExp _asrx;
-    _asrx.setPatternSyntax(QRegExp::RegExp2);
-    _asrx.setMinimal(false);
-    _asrx.setCaseSensitivity(Qt::CaseSensitive);
-    QMap<double, QRegExp> sort_asrx;
-
-    for (int b = 0; b < nBlocks; ++b)
+    const double percent_scan(50.);
+    const double scan_factor(100. / percent_scan);
+    const int max_blocks(_string_pieces.count() / 2);
+    const int requested_blocks(c2bUtils::nearInteger(scan_factor));
+    const int blocks(qMin(max_blocks, 1 + requested_blocks));
+    int pieces_per_block(_string_pieces.count() / blocks); // Ceiling
+    if ((_string_pieces.count() % blocks) > 0)
+        ++pieces_per_block;
+
+#if C2B_DEBUG_APPROXIMATEPATTERN
+    qDebug() << _string_pieces << max_blocks << scan_factor << requested_blocks << pieces_per_block << _string_pieces.count() % blocks;
+    for (int b = 0; b < blocks; ++b)
+        for (int i = 0; i < pieces_per_block; ++i)
+            if (b + (i*blocks) < _string_pieces.count())
+                qDebug() << "block#   " << b << "pick item " <<  b + (i*blocks) << _string_pieces.at(b + (i*blocks));
+#endif
+
+    _ranks.clear();
+    QStringList submatcher;
+    QStringList subpattern;
+    QStringList substring;
+    const QString sp_stretch(".{0,%1}%2");
+    for (int b = 0; b < blocks; ++b)
     {
         int ii(b);
-        QString sp(escape(patternPieces.at(ii), caseSensitivity));
-        int stretch_product(1);
-        for (int j = 1; j < nPiecesPerBlock; ++j)
+        QString sm(_string_pieces.at(ii));
+        QString sp(escape(_string_pieces.at(ii), _case_sensitivity));
+        QString ss(_string_pieces.at(ii));
+        double stretch_product(1.);
+        for (int j = 1; j < pieces_per_block; ++j)
         {
-            int jj(b + (j * nBlocks));
-            if (jj < patternPieces.count())
+            int jj(b + (j * blocks));
+            if (jj < _string_pieces.count())
             {
                 const int st(stretch(ii, jj));
-                sp += _stretch.arg(st).arg(escape(patternPieces.at(jj), caseSensitivity));
+                sm += sp_stretch.arg(st).arg(_string_pieces.at(jj));
+                sp += sp_stretch.arg(st).arg(escape(_string_pieces.at(jj), _case_sensitivity));
+                ss += ' ' + _string_pieces.at(jj);
                 stretch_product *= st;
                 ii = jj;
             }
         }
-        subPatterns.append(sp);
-        _asrx.setPattern(sp);
-        // Sort according expectation (arXiv:0705.0751v1, Eq. 6)
-        sort_asrx.insert(-stretch_product * probability(sp), _asrx);
+        submatcher.append(sm);
+        subpattern.append(sp);
+        substring.append(ss);
+        _ranks.append(stretch_product * triads::textFrequency(ss)); // Rank according expectation (arXiv:0705.0751v1, Eq. 6)
+        ++_subpattern_count;
+    }
+    set_sort_index();
+    _regexp.setPattern(QString("(?:%1)").arg(subpattern.join("|")));
+    _submatchers.resize(_subpattern_count);
+    _subregexps.resize(_subpattern_count);
+    _substrings.clear();
+    for (int i = 0; i < _subpattern_count; ++i)
+    {
+        const int ii(_index.at(i));
+        _submatchers[i] = substringMatcher(submatcher.at(ii), _case_sensitivity);
+        _subregexps[i] = QRegExp(subpattern.at(ii), Qt::CaseSensitive, QRegExp::RegExp2);
+        _subregexps[i].setMinimal(false);
+        _substrings.append(substring.at(ii));
     }
-    asrx = sort_asrx.values();
-    arx.setPattern(QString("(?:%1)").arg(subPatterns.join("|")));
+    _p0.resize(_subpattern_count);
+    _pn.resize(_subpattern_count);
 }
 
 void approximatePattern::splitPattern()
 {
-    if (pattern.isEmpty())
+    if (_string.isEmpty())
         return;
-
     QStringList wordList;
     QList<int> wordStarts;
     QList<int> wordEnds;
-    splitPattern(pattern, &wordList, &wordStarts, &wordEnds);
-
+    splitPattern(_string, &wordList, &wordStarts, &wordEnds);
     for (int i = 0; i < wordList.count(); ++i)
     {
         const QStringList pieces(splitWord(wordList.at(i)));
         const QString prefix(pieces.at(0));
         if (prefix.length() > 2)
         {
-            patternPieces.append(prefix);
-            ppStarts.append(wordStarts.at(i));
-            ppEnds.append(wordStarts.at(i) + prefix.length());
+            _string_pieces.append(prefix);
+            _piece_starts.append(wordStarts.at(i));
+            _piece_ends.append(wordStarts.at(i) + prefix.length());
         }
         const QString suffix(pieces.at(1));
         if (suffix.length() > 2)
         {
-            patternPieces.append(suffix);
-            ppStarts.append(wordEnds.at(i) - suffix.length());
-            ppEnds.append(wordEnds.at(i));
+            _string_pieces.append(suffix);
+            _piece_starts.append(wordEnds.at(i) - suffix.length());
+            _piece_ends.append(wordEnds.at(i));
         }
     }
 }
@@ -141,7 +162,7 @@ void approximatePattern::splitPattern(const QString& p, QStringList* w, QList<in
         {
             if (in_word)
             {
-                // Word actually ends at i - 1. However, this convention simplifies things a little bit.
+                // Word actually ends at i - 1. However, this convention simplifies things.
                 w_ends = i;
                 w->append(str.mid(w_starts, w_ends - w_starts));
                 ws->append(w_starts);
@@ -157,7 +178,7 @@ void approximatePattern::splitPattern(const QString& p, QStringList* w, QList<in
         }
 }
 
-const QStringList approximatePattern::splitWord(const QString& word)
+const QStringList approximatePattern::splitWord(const QString& word) const
 {
     // Returns the pair "prefix+root root+suffix"
     const int minimum_length(5);
@@ -170,19 +191,19 @@ const QStringList approximatePattern::splitWord(const QString& word)
     int slen_min(wlen);
     int plen_max(0);
     int slen_max(0);
-    for (int i = 0; i < pre.count(); ++i)
-        if (w.startsWith(pre.at(i)))
+    for (int i = 0; i < _prefixes.count(); ++i)
+        if (w.startsWith(_prefixes.at(i)))
         {
-            const int plen(pre.at(i).length());
+            const int plen(_prefixes.at(i).length());
             if (plen < plen_min)
                 plen_min = plen;
             if (plen > plen_max)
                 plen_max = plen;
         }
-    for (int i = 0; i < suf.count(); ++i)
-        if (w.endsWith(suf.at(i)))
+    for (int i = 0; i < _suffixes.count(); ++i)
+        if (w.endsWith(_suffixes.at(i)))
         {
-            const int slen(suf.at(i).length());
+            const int slen(_suffixes.at(i).length());
             if (slen < slen_min)
                 slen_min = slen;
             if (slen > slen_max)
@@ -198,10 +219,10 @@ const QStringList approximatePattern::splitWord(const QString& word)
     const int wlenMs_min(qMax(slen_min, wlen - plen_min));
     const int wlenMp_max(qMax(plen_max, wlen - slen_max));
     const int wlenMs_max(qMax(slen_max, wlen - plen_max));
-
-//    qDebug() << wlenMp_min << wlenMs_min << w.left(wlenMp_min) << w.right(wlenMs_min);
-//    qDebug() << wlenMp_max << wlenMs_max << w.left(wlenMp_max) << w.right(wlenMs_max);
-
+#if C2B_DEBUG_APPROXIMATEPATTERN
+    qDebug() << wlenMp_min << wlenMs_min << w.left(wlenMp_min) << w.right(wlenMs_min);
+    qDebug() << wlenMp_max << wlenMs_max << w.left(wlenMp_max) << w.right(wlenMs_max);
+#endif
     if (wlenMp_max >= minimum_length && wlenMs_max >= minimum_length)
         return QStringList() << w.left(wlenMp_max) << w.right(wlenMs_max);
     else if (wlenMp_min >= minimum_length && wlenMs_min >= minimum_length)
@@ -218,7 +239,9 @@ QString approximatePattern::wordPattern(const QString& word, Qt::CaseSensitivity
     possible.append(escape(ord.left(len - 2), cs));
     for (int i = 1; i < len - 2; ++i)
         possible.append(QString("%1.{0,2}%2").arg(escape(ord.left(len - i - 3), cs)).arg(escape(ord.right(i), cs)));
-//qDebug() << "WordPattern: " << QString("(?:%1(?:%2)|%3)").arg(escape(word.at(0), cs)).arg(possible.join("|")).arg(escape(ord, cs));
+#if C2B_DEBUG_APPROXIMATEPATTERN
+    qDebug() << "WordPattern: " << QString("(?:%1(?:%2)|%3)").arg(escape(word.at(0), cs)).arg(possible.join("|")).arg(escape(ord, cs));
+#endif
     return QString("(?:%1(?:%2)|%3)").arg(escape(word.at(0), cs)).arg(possible.join("|")).arg(escape(ord, cs));
 }
 
@@ -232,8 +255,44 @@ int approximatePattern::stretch(int piece_i, int piece_j) const
 {
     const int minStretch(3);
     const int maxStretch(20);
-    if (patternPieces.at(piece_j).length() > 4)
-        return qMax((maxStretch*(piece_j - piece_i)), minStretch*(ppStarts.at(piece_j) - ppEnds.at(piece_i)));
+    if (_string_pieces.at(piece_j).length() > 4)
+        return qMax((maxStretch*(piece_j - piece_i)), minStretch*(_piece_starts.at(piece_j) - _piece_ends.at(piece_i)));
+    else
+        return minStretch*(_piece_starts.at(piece_j) - _piece_ends.at(piece_i));  // Estimated error ratio only
+}
+
+void approximatePattern::mergeIndices(int* index_in, const QString& str) const
+{
+    int index = str.length();
+    for (int i = 0; i < _subpattern_count; ++i)
+        if (_p0.at(i) != -1 && _p0.at(i) < index)
+            index = _p0.at(i);
+    if (index == str.length())
+        index = -1;
     else
-        return minStretch*(ppStarts.at(piece_j) - ppEnds.at(piece_i));  // Estimated error ratio only
+    {
+        int pn(0);
+        for (int i = 0; i < _subpattern_count; ++i)
+            if (_pn.at(i) > pn && _p0.at(i) == index)
+                pn = _pn.at(i);
+        for (int m = 0; m < _subpattern_count; ++m)
+            for (int i = 0; i < _subpattern_count; ++i)
+                if (_pn.at(i) > pn && _p0.at(i) < pn)
+                    pn = _pn.at(i);
+        // Beautify match by including whole words
+        for (int w = index - 1; w > std::max(0, index - 13); --w)
+            if (!str.at(w).isLetter())
+            {
+                index = w + 1;
+                break;
+            }
+        for (int w = pn; w < std::min(pn + 13, str.length()); ++w)
+            if (!str.at(w).isLetter())
+            {
+                pn = w;
+                break;
+            }
+        _matched_length = pn - index;
+    }
+    *index_in = index;
 }
diff --git a/src/c2b/approximatePattern.h b/src/c2b/approximatePattern.h
index d8e3325..19607c5 100644
--- a/src/c2b/approximatePattern.h
+++ b/src/c2b/approximatePattern.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  *
  *   Class implementation of the approximate search algorithm
@@ -12,29 +12,82 @@
 
 #include "compositePattern.h"
 
+#include "substringMatcher.h"
+
+#define C2B_DEBUG_APPROXIMATEPATTERN 0
+#if C2B_DEBUG_APPROXIMATEPATTERN
+#endif
+
 
 class approximatePattern : public compositePattern
 {
 
 public:
-    approximatePattern(const QString newPattern, Qt::CaseSensitivity newCs);
-    ~approximatePattern();
+    approximatePattern();
+    approximatePattern(const QString& pattern, const Qt::CaseSensitivity cs);
+    inline ~approximatePattern() {}
+
+    void setPattern(const QString& pattern, const Qt::CaseSensitivity cs = Qt::CaseSensitive);
+
+    inline bool matches(const QString& str) const
+    {
+        _matched_length = -1;
+        if (str.length() == 0)
+            return false;
+        if (_is_multipattern)
+        {
+            for (int i = 0; i < _subpattern_count; ++i)
+                if (_submatchers.at(i).indexIn(str) != -1)
+                    return true;
+            return false;
+        }
+        else
+            return _regexp.indexIn(str) != -1;
+    }
+    inline int indexIn(const QString& str, const int from = 0) const
+    {
+        _matched_length = -1;
+        if (str.length() == 0)
+            return -1;
+        int index;
+        if (_is_multipattern)
+        {
+            for (int i = 0; i < _subpattern_count; ++i)
+            {
+                _p0[i] = _submatchers.at(i).indexIn(str, from);
+                _pn[i] = _p0.at(i) + _submatchers.at(i).matchedLength();
+            }
+            mergeIndices(&index, str);
+        }
+        else
+        {
+            index = _regexp.indexIn(str, from);
+            _matched_length = _regexp.matchedLength();
+        }
+        return index;
+    }
+    inline const QVector<substringMatcher>& submatchers() const
+    {
+        return _submatchers;
+    }
 
 
 private:
-    QList<int> ppEnds;
-    QList<int> ppStarts;
     QString wordPattern(const QString& word, Qt::CaseSensitivity cs) const;
-    QStringList patternPieces;
-    QStringList pre;
-    QStringList suf;
-    const QStringList splitWord(const QString& word);
+    const QStringList splitWord(const QString& word) const;
     int stretch(int piece_i, int piece_j) const;
     int wordCount(const QString& str) const;
-    void setPattern();
+    void mergeIndices(int* index_in, const QString& str) const;
     void splitPattern();
     void splitPattern(const QString& p, QStringList* w, QList<int>* ws, QList<int>* we) const;
 
+    QList<int> _piece_ends;
+    QList<int> _piece_starts;
+    QStringList _prefixes;
+    QStringList _string_pieces;
+    QStringList _suffixes;
+    QVector<substringMatcher> _submatchers;
+
 };
 
 #endif
diff --git a/src/c2b/authorString.cpp b/src/c2b/authorString.cpp
index 39c1415..bdfbf87 100644
--- a/src/c2b/authorString.cpp
+++ b/src/c2b/authorString.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "authorString.h"
@@ -18,9 +18,6 @@
 authorString::authorString()
 {}
 
-authorString::~authorString()
-{}
-
 
 /** \page authorproc
 
@@ -142,7 +139,7 @@ QString authorString::toBibTeX(const QString& author, bool full_form)
         c2bUtils::debug(author_i);
         author_i.replace(QRegExp("\\.{0,1}\\s{0,1}-"), "-"); // Abbreviated cases, eg M.-H. Something
         author_i.replace(QRegExp("[^-'\\w,]"), " "); // Only these characters compose a name; keep commas
-        author_i = author_i.simplified();
+        author_i = c2bUtils::simplifyString(author_i);
 
         // Split author name
         QStringList fore_name_parts;
@@ -238,7 +235,7 @@ QString authorString::toBibTeX(const QString& author, bool full_form)
     _author_string.replace(QRegExp("_JR\\b", Qt::CaseInsensitive), " Jr");
     _author_string.replace(QRegExp(author::prefixes + '_', Qt::CaseInsensitive), "\\1 ");
     _author_string.replace(QRegExp("\\b" + author::double_initials + '_', Qt::CaseInsensitive), "\\1.");
-    _author_string = _author_string.simplified();
+    _author_string = c2bUtils::simplifyString(_author_string);
 
     return _author_string;
 }
@@ -538,7 +535,7 @@ void encoder::encode(const QString& raw)
 
     scapePattern("aL+[nN]{1,2}");
     scapePattern("a[nNw]&L+[nN]{1,2}"); // in Linear and / Sublinear Time
-    scapePattern(":L+[nN]{1,2}");
+    scapePattern(":L+[InN]{1,2}"); // ... Structure Classification: / A Survey
     scapePattern("[nN]*&L[nN]L"); // Not an & for author
 }
 
diff --git a/src/c2b/authorString.h b/src/c2b/authorString.h
index f383d31..b75d3c0 100644
--- a/src/c2b/authorString.h
+++ b/src/c2b/authorString.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef AUTHORSTRING_H
@@ -17,7 +17,7 @@
 namespace author
 {
 
-static const QString double_initials("(Al|Ch|Kh|Th|Ya|Yu|Zs)");
+static const QString double_initials("(Al|Ch|Kh|Md|Th|Xh|Ya|Yu|Zs)");
 static const QString prefixes("(da|de|dal|del|der|di|do|du|dos|la|le|lo|van|vande|von|zur)");
 
 static const QString name("(?:\\w[-'\\w]{1,})");
@@ -50,7 +50,7 @@ inline QString& simplifyString(QString& author, const bool full = false)
     author.replace(simplify_string_rx4, " ");
     author.remove(simplify_string_rx5); // Better remove if no conflict. It will help to not confuse with chemical formula.
     author.replace(simplify_string_rx6, " ");
-    author = author.simplified();
+    author = c2bUtils::simplifyString(author);
     return author;
 }
 
@@ -99,7 +99,7 @@ struct encoder
             if (code.at(i) != 'L')
                 code[i] = c;
     }
-    void scapePattern(const QString pattern, const QChar c = ' ')
+    void scapePattern(const QString& pattern, const QChar c = ' ')
     {
         QRegExp rx(pattern, Qt::CaseSensitive);
         rx.setMinimal(true);
@@ -147,7 +147,7 @@ class authorString
 
 public:
     authorString();
-    ~authorString();
+    inline ~authorString() {}
 
     QString toBibTeX(const QString& author, bool full_form = false);
 
diff --git a/src/c2b/bibExtractor.cpp b/src/c2b/bibExtractor.cpp
index d307f20..5c13374 100644
--- a/src/c2b/bibExtractor.cpp
+++ b/src/c2b/bibExtractor.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "bibExtractor.h"
@@ -23,6 +23,7 @@ bibExtractor::bibExtractor(QObject* parento) : QObject(parento), cout(*(new QTex
     _bpP = new bibParser(this);
     _mpP = new metadataParser(_bpP, this);
     _networkQP = new networkQuery(_bpP, this);
+    init();
 }
 
 bibExtractor::bibExtractor(bibParser* bp, metadataParser* mp, networkQuery* nq, QObject* parento) :
@@ -78,7 +79,7 @@ int bibExtractor::extract(const QStringList& input_fns, const QString& output_fn
             const QString text(c2bUtils::fileToString(input_fn));
             extract(text);
         }
-        if (_settingsP->value("cb2Bib/MovePdf").toBool() && !_document_fn.isEmpty() && _bpP->fieldCount() > 0)
+        if (_settingsP->value("cb2Bib/MovePdf").toBool() && !_document_fn.isEmpty() && isReliable())
         {
             const QString file(_bpP->documentFilename(_document_fn, output_fn));
             const QString target_doc_fn(c2bUtils::documentAbsoluteName(_settingsP->value("cb2Bib/RelativePdfDirectory").toBool(),
@@ -87,11 +88,11 @@ int bibExtractor::extract(const QStringList& input_fns, const QString& output_fn
             QDir doc_dir(doc_dirname);
             if (!doc_dir.exists())
                 if (!doc_dir.mkpath(doc_dirname))
-                    logMessage(tr("Unable to create directory %1.").arg(doc_dirname));
+                    logMessage(tr("Error: Unable to create directory %1.").arg(doc_dirname));
             if (doc_dir.exists())
             {
                 const QString CopyMovePdf(_settingsP->value("cb2Bib/CopyMovePdf").toString());
-                logMessage(tr("Copying/moving %1...").arg(_document_fn));
+                logMessage(tr("Copying/moving to %1...").arg(target_doc_fn));
                 _networkQP->networkPtr()->getFile(_document_fn, target_doc_fn, CopyMovePdf, this, SLOT(copyMoveEnded(bool)));
                 _event_loop->exec();
                 if (_is_copymove_ok)
@@ -101,7 +102,7 @@ int bibExtractor::extract(const QStringList& input_fns, const QString& output_fn
                         QString mp_error;
                         if (!_mpP->insertMetadata(_bpP->currentReference(), target_doc_fn, &mp_error))
                         {
-                            logMessage(tr("Unable to insert metadata to file %1.").arg(target_doc_fn));
+                            logMessage(tr("Warning: Unable to insert metadata to file %1.").arg(target_doc_fn));
                             logMessage(mp_error);
                         }
                     }
@@ -109,23 +110,28 @@ int bibExtractor::extract(const QStringList& input_fns, const QString& output_fn
                 }
                 else
                 {
-                    logMessage(tr("Skipping file field %1.").arg(_document_fn));
-                    _document_fn.clear();
+                    if (_settingsP->cl_sloppy)
+                    {
+                        logMessage(tr("Warning: Skipping file field %1.").arg(_document_fn));
+                        _document_fn.clear();
+                    }
+                    else
+                        _bpP->clearCurrentReference();
                 }
             }
         }
-        if (_bpP->fieldCount() > 0)
+        if (isReliable())
         {
             if (!_document_fn.isEmpty())
                 _bpP->setField("file", _document_fn);
             bibtex += _bpP->toBibTeX();
         }
         else
-            logMessage(tr("Empty reference for file %1.").arg(input_fn));
+            logMessage(tr("Warning: Skip writing reference for file %1.").arg(input_fn));
         logMessage("");
     }
     if (bibtex.isEmpty())
-        logMessage(tr("No reference extracted."));
+        logMessage(tr("Warning: No reference extracted."));
     else
     {
         logMessage(tr("Writing %1...").arg(output_fn));
@@ -147,10 +153,12 @@ int bibExtractor::extract(const QString& text, QString* bibtex)
     _input_type = PlainText;
     extract(text);
     *bibtex = _bpP->toBibTeX();
-    if (_bpP->fieldCount() > 0)
+    if (_bpP->isAutoRecognized() > 0)
         return 0;
-    else
+    else if (_bpP->fieldCount() > 0)
         return 1;
+    else
+        return 2;
 }
 
 void bibExtractor::extract(const QString& text)
@@ -173,7 +181,7 @@ void bibExtractor::_extract(const QString& text)
     _bpP->clearCurrentReference();
     if (text.trimmed().isEmpty())
     {
-        logMessage(tr("Empty input string."));
+        logMessage(tr("Warning: Empty input string."));
         return;
     }
     _bpP->setReferenceType("article");
@@ -206,7 +214,7 @@ void bibExtractor::copyMoveEnded(bool ok)
 void bibExtractor::proxyLogMessage() const
 {
     _networkQP->networkPtr()->cancelDownload();
-    logMessage(tr("Error: Proxy authentication dialog is disabled in command line mode."));
+    logMessage(tr("Warning: Proxy authentication dialog is disabled in command line mode."));
 }
 
 void bibExtractor::logMessage(const QString& ms) const
@@ -214,12 +222,20 @@ void bibExtractor::logMessage(const QString& ms) const
     cout << "[cb2bib] " << ms << endl;
 }
 
+bool bibExtractor::isReliable() const
+{
+    if (_settingsP->cl_sloppy)
+        return _bpP->fieldCount() > 0;
+    else
+        return _bpP->isAutoRecognized();
+}
+
 QString bibExtractor::documentToString(const QString& fn) const
 {
     document doc(fn, document::FirstPage);
     const QString text(doc.toString());
     if (!doc.errorString().isEmpty())
-        logMessage(doc.errorString());
+        logMessage("Error: " + doc.errorString());
     if (_settingsP->value("cb2Bib/AddMetadata").toBool())
     {
         // Add metadata to document text
diff --git a/src/c2b/bibExtractor.h b/src/c2b/bibExtractor.h
index 165bd3f..25ffc3c 100644
--- a/src/c2b/bibExtractor.h
+++ b/src/c2b/bibExtractor.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef BIBEXTRACTOR_H
@@ -47,6 +47,7 @@ private:
     QTextStream& cout;
     bibParser* _bpP;
     bool _is_copymove_ok;
+    bool isReliable() const;
     metadataParser* _mpP;
     networkQuery* _networkQP;
     settings* _settingsP;
diff --git a/src/c2b/bibParser.cpp b/src/c2b/bibParser.cpp
index 8894e3d..35b1533 100644
--- a/src/c2b/bibParser.cpp
+++ b/src/c2b/bibParser.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "bibParser.h"
@@ -98,7 +98,9 @@ QString bibParser::parse(const QString& field, const QString& value, const QStri
     else if (field == "keywords")
     {
         v.replace(" - ", ",");
-        v = v.split(QRegExp("[^\\w\\s-]"), QString::SkipEmptyParts).join(", ");
+        QStringList kl(v.split(QRegExp("[^\\w\\s-]"), QString::SkipEmptyParts));
+        kl.removeAll(" ");
+        v = kl.join(", ");
         v.replace(QRegExp("\\s+,"), ",");
         v = v.toLower();
     }
@@ -126,7 +128,7 @@ QString bibParser::parse(const QString& field, const QString& value, const QStri
         if (!init_value.isEmpty())
             v = init_value + ": " + v;
     }
-    return v.simplified();
+    return c2bUtils::simplifyString(v);
 }
 
 /**
@@ -209,7 +211,7 @@ QString bibParser::excerpt(const QString& text, const QStringList& hints) const
     txt.replace(QRegExp("\\b(january|february|march|april|may|june|july|august|september|october|november|december)\\b",
                         Qt::CaseInsensitive), " ");
     txt = hints.join(" ") + ' ' + txt;
-    txt = txt.simplified();
+    txt = c2bUtils::simplifyString(txt);
     const QStringList txtlist(txt.split(' ', QString::SkipEmptyParts));
     QStringList txtlistSimp;
     for (int i = 0; i < qMin(15, txtlist.count()); ++i)
@@ -348,7 +350,7 @@ void bibParser::parse(const QString& text, QString* out_text, QString* out_tagte
         otext = ' ' + otext;
         ottext = otext;
         ottext.replace(QRegExp("[\\n\\r]\\s*([A-Z]{1,4}\\s*-)"), "][\\1");
-        ottext = ottext.simplified();
+        ottext = c2bUtils::simplifyString(ottext);
         if (!ottext.contains(QRegExp("\\[FAU\\s+-")))
             ottext.replace(QRegExp("\\[(AU\\s*-\\s*[-'\\w]+)"), "[F\\1 ");
         QStringList fList(ottext.split("]["));
@@ -450,7 +452,7 @@ void bibParser::parse(const QString& text, QString* out_text, QString* out_tagte
             QRegExp rx(ItemX);
             rx.setMinimal(true);
             if (!rx.isValid())
-                qDebug(tr("[cb2Bib] RegExp |%1| is not valid.").arg(ItemX).toLatin1());
+                c2bUtils::warn(tr("RegExp |%1| is not valid").arg(ItemX));
 
             const QStringList list(fieldset.split(' ', QString::SkipEmptyParts));
             const int efields(list.count());
@@ -461,8 +463,7 @@ void bibParser::parse(const QString& text, QString* out_text, QString* out_tagte
             c2bUtils::debug(tr("Position: |%1|").arg(npos));
             if (efields != cfields)
             {
-                qDebug(tr("[cb2Bib] RegExp |%1| is not valid. Mismatch between expected and actual captures.")
-                       .arg(ItemX).toLatin1());
+                c2bUtils::warn(tr("RegExp |%1| is not valid. Mismatch between expected and actual captures").arg(ItemX));
                 npos = -1;
             }
             nfilters++;
@@ -520,13 +521,13 @@ void bibParser::checkRegExpFile(const QString& fn)
 {
     if (fn.isEmpty())
     {
-        qDebug(QObject::tr("[cb2Bib] No regular expression file especified.").toLatin1());
+        c2bUtils::warn(tr("No regular expression file especified"));
         return;
     }
     QFileInfo fi(fn);
     if (!fi.exists() || !fi.isReadable())
     {
-        qDebug(QObject::tr("[cb2Bib] Could not open regular expression file %1 for reading.").arg(fn).toLatin1());
+        c2bUtils::warn(tr("Could not open regular expression file %1 for reading").arg(fn));
         return;
     }
 }
@@ -559,7 +560,7 @@ QString bibParser::setTags(const QString& text) const
     for (int i = 0; i < n - 1; i++)
         tagged_text += spText.at(i) + QString("<Tab%1>").arg(i + 1);
     tagged_text += spText[n-1];
-    tagged_text = tagged_text.simplified();
+    tagged_text = c2bUtils::simplifyString(tagged_text);
     return tagged_text;
 }
 
@@ -570,6 +571,6 @@ QString bibParser::removeTags(const QString& text) const
     clean.remove("]]");
     clean.replace(QRegExp("<NewLine\\d+>"), " ");
     clean.replace(QRegExp("<Tab\\d+>"), " ");
-    clean = clean.simplified();
+    clean = c2bUtils::simplifyString(clean);
     return clean;
 }
diff --git a/src/c2b/bibParser.h b/src/c2b/bibParser.h
index d1e93b6..b539113 100644
--- a/src/c2b/bibParser.h
+++ b/src/c2b/bibParser.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef BIBPARSER_H
@@ -18,6 +18,7 @@ class heuristicBibParser;
 class idMaker;
 class preprocess;
 
+
 /**
     Class for bibliographic reference parsing and manipulation
 
diff --git a/src/c2b/bibPreparser.cpp b/src/c2b/bibPreparser.cpp
index 1025971..e0f34ab 100644
--- a/src/c2b/bibPreparser.cpp
+++ b/src/c2b/bibPreparser.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "bibPreparser.h"
@@ -19,9 +19,6 @@ bibPreparser::bibPreparser(QObject* parento) : QObject(parento)
     m_out_file = settingsP->tempPath() + "/cb2bib_clipborad_out.tmp_" + settingsP->applicationPid();
 }
 
-bibPreparser::~bibPreparser()
-{}
-
 
 void bibPreparser::preparse(const QString& text, QString* out_text)
 {
diff --git a/src/c2b/bibPreparser.h b/src/c2b/bibPreparser.h
index da9efd3..b029725 100644
--- a/src/c2b/bibPreparser.h
+++ b/src/c2b/bibPreparser.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef BIBPREPARSER_H
@@ -21,7 +21,7 @@ class bibPreparser : public QObject
 
 public:
     bibPreparser(QObject* parento = 0);
-    ~bibPreparser();
+    inline ~bibPreparser() {}
 
     void preparse(const QString& text, QString* out_text);
 
diff --git a/src/c2b/bibReference.h b/src/c2b/bibReference.h
index ab23e0a..bd2afcd 100644
--- a/src/c2b/bibReference.h
+++ b/src/c2b/bibReference.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef BIBREFERENCE_H
@@ -23,8 +23,7 @@ class bibReference : public QHash<QString, QString>
 {
 
 public:
-    bibReference()
-    {}
+    inline bibReference() {}
 
     void clearFields()
     {
diff --git a/src/c2bBibSearcher.cpp b/src/c2b/bibSearcher.cpp
similarity index 61%
rename from src/c2bBibSearcher.cpp
rename to src/c2b/bibSearcher.cpp
index 5209982..0024671 100644
--- a/src/c2bBibSearcher.cpp
+++ b/src/c2b/bibSearcher.cpp
@@ -1,15 +1,16 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
-#include "c2bBibSearcher.h"
+#include "bibSearcher.h"
 
-#include "c2b.h"
-#include "c2bBibParser.h"
-#include "c2bSettings.h"
-#include "c2bUtils.h"
+#include "bibParser.h"
+#include "cb2bib_utilities.h"
+#include "settings.h"
+
+#include <QCoreApplication>
 
 
 /** \page c2bsearch Search BibTeX files for references
@@ -88,184 +89,194 @@
 
     <p>&nbsp;</p>
 */
-c2bBibSearcher::c2bBibSearcher(QObject* parento) : QObject(parento)
+
+/**
+    Top level driver for searching BibTeX files
+*/
+bibSearcher::bibSearcher(bibParser* bp, QObject* parento) : QObject(parento), _bpP(bp)
 {
-    bp = c2b::bibParser();
+    clear();
 }
 
-c2bBibSearcher::~c2bBibSearcher()
-{}
-
 
-void c2bBibSearcher::addPattern(bool Not, bool caseSensitive, const QString& patternType, const QString& scope,
-                                const QString& yearScope, const QString& pattern)
+void bibSearcher::addPattern(bool Not, bool caseSensitive, const QString& patternType, const QString& scope,
+                             const QChar& yearScope, const QString& pattern)
 {
     if (pattern.trimmed().isEmpty())
         return;
-    patternList.append(c2bSearchPattern(Not, caseSensitive, patternType, scope, yearScope, pattern));
-    if (!fieldList.contains(scope))
-        fieldList.append(scope);
+    _patterns.append(searchPattern(Not, caseSensitive, patternType, scope, yearScope, pattern));
+    if (!_scopes.contains(scope))
+        _scopes.append(scope);
 }
 
-void c2bBibSearcher::exec()
+void bibSearcher::exec()
 {
-    if (patternList.count() == 0)
+    if (_patterns.count() == 0)
         return;
 
-    qSort(patternList);
-    p_include_pdf = p_include_pdf && (fieldList.contains("all") || fieldList.contains("file"));
-    if (p_include_pdf && !fieldList.contains("file"))
-        fieldList.append("file");
-    fieldList.removeAll("all");
+    qSort(_patterns);
+    _include_documents = _include_documents && (_scopes.contains("all") || _scopes.contains("file"));
+    if (_include_documents && !_scopes.contains("file"))
+        _scopes.append("file");
+    _scopes.removeAll("all");
 
-    QString AndOr;
-    if (p_boolean_and)
-        AndOr = ".AND.";
+    QString and_or;
+    if (_boolean_and)
+        and_or = ".AND.";
     else
-        AndOr = ".OR.";
-    for (int i = 0; i < patternList.count(); ++i)
+        and_or = ".OR.";
+    for (int i = 0; i < _patterns.count(); ++i)
     {
-        const c2bSearchPattern& pattern = patternList.at(i);
-        logString += tr("% Pattern%1: %2%3\n").arg(i + 1).arg(AndOr).arg(pattern.toString());
+        const searchPattern& pattern = _patterns.at(i);
+        _log_string += tr("% Pattern%1: %2%3\n").arg(i + 1).arg(and_or).arg(pattern.toString());
     }
 
     // Search In Files
     QFileInfoList flist;
-    if (p_all_bibtex_files)
+    if (_all_bibtex_files)
     {
-        QDir bibdir(p_bibtex_dir);
+        QDir bibdir(_bibtex_dir);
         flist = bibdir.entryInfoList(QStringList() << "*.bib");
     }
     else
-        flist.append(QFileInfo(p_bibtex_file));
+        flist.append(QFileInfo(_bibtex_file));
 
     for (int i = 0; i < flist.count(); ++i)
     {
         search(flist.at(i).absoluteFilePath());
-        if (p_aborted)
+        if (_aborted)
         {
             clear();
-            errorCounter = -1;
+            _error_counter = -1;
             return;
         }
     }
 
     // Search Done
-    logString += tr("% Scanned References: %1  BibTeX Files: %2  Linked Files: %3\n").
-                 arg(referenceCounter).arg(bibtexCounter).arg(pdfCounter);
-
-    if (hitMap.count() == 0)
+    _log_string += tr("% Scanned References: %1  BibTeX Files: %2  Linked Files: %3\n").
+                   arg(_reference_counter).arg(_bibtex_counter).arg(_document_counter);
+    if (_include_documents)
+        _documents.unload();
+    if (_hits_map.count() == 0)
         return;
-    hitString = "\n\n" + QStringList(hitMap.keys()).join("\n\n") + "\n\n";
-    logString += tr("% Total Unique Hits: %1\n").arg(hitMap.count());
+    _hits_string = "\n\n" + QStringList(_hits_map.keys()).join("\n\n") + "\n\n";
+    _log_string += tr("% Total Unique Hits: %1\n").arg(_hits_map.count());
 }
 
-void c2bBibSearcher::abort()
+void bibSearcher::abort()
 {
-    p_aborted = true;
+    _aborted = true;
 }
 
-void c2bBibSearcher::clear()
+void bibSearcher::clear()
 {
-    bibtexCounter = 0;
-    errorCounter = 0;
-    fieldList.clear();
-    hitMap.clear();
-    hitString.clear();
-    logString = "% cb2Bib " + C2B_VERSION + " / BibTeX Search Log\n";
-    p_aborted = false;
-    patternList.clear();
-    p_bibtex_dir.clear();
-    p_bibtex_file.clear();
-    p_boolean_and = true;
-    pdfCounter = 0;
-    p_simplify_source = false;
-    referenceCounter = 0;
+    _aborted = false;
+    _all_bibtex_files = false;
+    _bibtex_counter = 0;
+    _bibtex_dir.clear();
+    _bibtex_file.clear();
+    _boolean_and = true;
+    _document_counter = 0;
+    _error_counter = 0;
+    _hits_map.clear();
+    _hits_string.clear();
+    _include_documents = false;
+    _log_string = "% cb2Bib " + C2B_VERSION + " / BibTeX Search Log\n";
+    _patterns.clear();
+    _reference_counter = 0;
+    _scopes.clear();
+    _simplify_source = false;
 }
 
-void c2bBibSearcher::search(const QString& bib_file)
+void bibSearcher::search(const QString& bib_file)
 {
-    bibtexCounter++;
+    _bibtex_counter++;
     QString bib_file_contents;
     QFile file(bib_file);
     if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
     {
-        errorCounter++;
-        logString += tr("% [cb2bib] Unable to open the file %1 for reading. Error: '%2'.\n").arg(bib_file).arg(file.errorString());
+        _error_counter++;
+        _log_string += tr("% [cb2bib] Unable to open the file %1 for reading. Error: '%2'.\n").arg(bib_file).arg(file.errorString());
         return;
     }
     QTextStream stream(&file);
     stream.setCodec("UTF-8");
     stream.setAutoDetectUnicode(true);
     bib_file_contents = stream.readAll();
-    logString += tr("% Scanning file %1\n").arg(bib_file.trimmed());
-    if (p_include_pdf)
-        cache.load(bib_file, p_simplify_source);
+    _log_string += tr("% Scanning file %1\n").arg(bib_file.trimmed());
+    if (_include_documents)
+    {
+        if (_simplify_source)
+            _documents.load(bib_file, documentContents::Simplified);
+        else
+            _documents.load(bib_file, documentContents::Raw);
+    }
 
-    const int hits(hitMap.count());
+    const int hits(_hits_map.count());
     bibReference ref;
-    bp->initReferenceParsing(bib_file, fieldList, &ref);
-    while (bp->referencesIn(bib_file_contents, &ref))
+    _bpP->initReferenceParsing(bib_file, _scopes, &ref);
+    while (_bpP->referencesIn(bib_file_contents, &ref))
     {
-        referenceCounter++;
-        searchBib(bib_file, ref);
+        _reference_counter++;
+        searchReference(bib_file, ref);
         QCoreApplication::processEvents();
-        if (p_aborted)
+        if (_aborted)
             return;
     }
-    logString += tr("% File %1. Hits: %2\n").arg(bib_file.trimmed()).arg(hitMap.count() - hits);
+    _log_string += tr("% File %1. Hits: %2\n").arg(bib_file.trimmed()).arg(_hits_map.count() - hits);
 }
 
-void c2bBibSearcher::searchBib(const QString& bib_file, const bibReference& ref)
+void bibSearcher::searchReference(const QString& bib_file, const bibReference& ref)
 {
-    const QString pdf_file_name(ref.value("file"));
-    QString pdf_file_contents("unread");
+    const bool include_document(_include_documents &&
+                                _documents.setCurrent(ref.value("file"), &_document_counter, &_log_string, &_error_counter));
 
     // Initialize composite search
-    bool hit(p_boolean_and);
+    bool hit(_boolean_and);
 
     // Composite search
-    for (int i = 0; i < patternList.count(); ++i)
+    for (int i = 0; i < _patterns.count(); ++i)
     {
-        const c2bSearchPattern& pattern = patternList.at(i);
+        const searchPattern& pattern = _patterns.at(i);
+        const searchPattern::modifiers& modifier = pattern.modifier();
         bool ihit(false);
 
-        if (pattern.scope == "year")
+        if (modifier.scope == "year")
         {
-            int istr(ref.value(pattern.scope).toInt());
-            int jstr(pattern.pattern.toInt());
-            if (pattern.yearScope == "=")
+            int istr(ref.value(modifier.scope).toInt());
+            int jstr(modifier.string.toInt());
+            if (modifier.yearScope == '=')
                 ihit = istr == jstr;
-            else if (pattern.yearScope == ">")
+            else if (modifier.yearScope == '>')
                 ihit = istr >= jstr;
-            else if (pattern.yearScope == "<")
+            else if (modifier.yearScope == '<')
                 ihit = istr <= jstr;
         }
-        else if (pattern.scope == "all")
+        else if (modifier.scope == "all")
         {
-            if (p_simplify_source)
-                ihit = pattern.matches(c2bUtils::toAscii(ref.unicodeReference, c2bUtils::KeepWords));
+            if (_simplify_source)
+                ihit = pattern.matches(c2bUtils::toAscii(ref.unicodeReference, c2bUtils::FromBibTeX));
             else
                 ihit = pattern.matches(ref.unicodeReference);
             if (!ihit)
-                if (include_pdf(p_include_pdf, pdf_file_name, &pdf_file_contents))
-                    ihit = pattern.matches(pdf_file_contents);
+                if (include_document)
+                    ihit = pattern.matches(_documents.current());
         }
-        else if (pattern.scope == "journal")
+        else if (modifier.scope == "journal")
         {
-            const QString pattern_full(bp->fullJournal(pattern.pattern));
-            const QString j_orig(ref.value(pattern.scope));
-            const QString j_full(bp->fullJournal(j_orig));
-            ihit = j_orig.contains(pattern.rx) || j_full.contains(pattern.rx) || j_full == pattern_full;
+            const QString pattern_full(_bpP->fullJournal(modifier.string));
+            const QString j_orig(ref.value(modifier.scope));
+            const QString j_full(_bpP->fullJournal(j_orig));
+            ihit = j_full == pattern_full || pattern.matches(j_orig) || pattern.matches(j_full);
         }
-        else if (pattern.scope == "file" && include_pdf(p_include_pdf, pdf_file_name, &pdf_file_contents))
-            ihit = pattern.matches(pdf_file_contents);
+        else if (modifier.scope == "file" && include_document)
+            ihit = pattern.matches(_documents.current());
         else
-            ihit = pattern.matches(ref.value(pattern.scope));
+            ihit = pattern.matches(ref.value(modifier.scope));
 
-        if (pattern.Not)
+        if (modifier.NOT)
             ihit = !ihit;
-        if (p_boolean_and)
+        if (_boolean_and)
         {
             hit = hit && ihit;
             if (!hit)
@@ -279,39 +290,40 @@ void c2bBibSearcher::searchBib(const QString& bib_file, const bibReference& ref)
         }
     }
     if (hit)
-        if (!hitMap.contains(ref.rawReference))
+        if (!_hits_map.contains(ref.rawReference))
         {
-            if (include_pdf(p_include_pdf, pdf_file_name, &pdf_file_contents))
-                hitMap.insert(ref.rawReference, location(bib_file, ref) + excerpts(pdf_file_contents));
+            if (include_document)
+                _hits_map.insert(ref.rawReference, location(bib_file, ref) + excerpts(_documents.current().text()));
             else
-                hitMap.insert(ref.rawReference, location(bib_file, ref));
+                _hits_map.insert(ref.rawReference, location(bib_file, ref));
         }
 }
 
-const QString c2bBibSearcher::excerpts(const QString& contents)
+const QString bibSearcher::excerpts(const QString& contents) const
 {
     const int max_excerpts(25);
     const int max_unmerged_excerpts(max_excerpts + 10);
     QMap<int, int> exc_endpos;
 
-    for (int i = 0; i < patternList.count(); ++i)
+    for (int i = 0; i < _patterns.count(); ++i)
     {
-        const c2bSearchPattern& pattern = patternList.at(i);
-        if (pattern.Not)
+        const searchPattern& pattern = _patterns.at(i);
+        const searchPattern::modifiers& modifier = pattern.modifier();
+        if (modifier.NOT)
             continue;
-        if (pattern.scope != "all" && pattern.scope != "file")
+        if (modifier.scope != "all" && modifier.scope != "file")
             continue;
         int n_excerpts(0);
         int pos(0);
         while (pos >= 0)
         {
-            pos = pattern.rx.indexIn(contents, pos);
+            pos = pattern.indexIn(contents, pos);
             if (pos > -1)
             {
                 if (++n_excerpts > max_unmerged_excerpts)
                     break;
-                exc_endpos.insert(pos, qMax(pos + pattern.rx.matchedLength(), exc_endpos.value(pos)));
-                pos += pattern.rx.matchedLength();
+                exc_endpos.insert(pos, qMax(pos + pattern.matchedLength(), exc_endpos.value(pos)));
+                pos += pattern.matchedLength();
             }
         }
     }
@@ -335,7 +347,7 @@ const QString c2bBibSearcher::excerpts(const QString& contents)
     }
     i_pos = exc_endpos.keys();
 
-    const int context_length(40);
+    const int context_length(75);
     QString exc;
     QRegExp lead_truncated_words("^.*\\s(?=\\w)");
     lead_truncated_words.setMinimal(true);
@@ -387,26 +399,27 @@ const QString c2bBibSearcher::excerpts(const QString& contents)
     return exc;
 }
 
-const QString c2bBibSearcher::highlight(const QString& abstract)
+const QString bibSearcher::highlight(const QString& abstract) const
 {
     if (abstract.isEmpty())
         return abstract;
     QMap<int, int> endpos;
-    for (int i = 0; i < patternList.count(); ++i)
+    for (int i = 0; i < _patterns.count(); ++i)
     {
-        const c2bSearchPattern& pattern = patternList.at(i);
-        if (pattern.Not)
+        const searchPattern& pattern = _patterns.at(i);
+        const searchPattern::modifiers& modifier = pattern.modifier();
+        if (modifier.NOT)
             continue;
-        if (pattern.scope != "all" && pattern.scope != "abstract")
+        if (modifier.scope != "all" && modifier.scope != "abstract")
             continue;
         int pos(0);
         while (pos >= 0)
         {
-            pos = pattern.rx.indexIn(abstract, pos);
+            pos = pattern.indexIn(abstract, pos);
             if (pos > -1)
             {
-                endpos.insert(pos, qMax(pos + pattern.rx.matchedLength(), endpos.value(pos)));
-                pos += pattern.rx.matchedLength();
+                endpos.insert(pos, qMax(pos + pattern.matchedLength(), endpos.value(pos)));
+                pos += pattern.matchedLength();
             }
         }
     }
@@ -436,15 +449,15 @@ const QString c2bBibSearcher::highlight(const QString& abstract)
     {
         const int pos(i_pos.at(i));
         const int length(endpos.value(pos) - pos);
-        hla +=  c2bUtils::toHtmlString(abstract.mid(npos, pos - npos)) + "<span>" +
-                c2bUtils::toHtmlString(abstract.mid(pos, length)) + "</span>";
+        hla += c2bUtils::toHtmlString(abstract.mid(npos, pos - npos)) + "<span>" +
+               c2bUtils::toHtmlString(abstract.mid(pos, length)) + "</span>";
         npos = endpos.value(pos);
     }
     hla += c2bUtils::toHtmlString(abstract.mid(npos, abstract.length() - npos));
     return hla;
 }
 
-const QString c2bBibSearcher::location(const QString& fn, const bibReference& ref)
+const QString bibSearcher::location(const QString& fn, const bibReference& ref) const
 {
     const QString at("<a href=\"Edit reference '%1' from file [%2:%3]\" class=\"anchor\">"
                      "<img src=\":/icons/icons/edit16.png\" alt=\"action\" width=\"16\" height=\"16\" /></a>");
diff --git a/src/c2b/bibSearcher.h b/src/c2b/bibSearcher.h
new file mode 100644
index 0000000..ea50600
--- /dev/null
+++ b/src/c2b/bibSearcher.h
@@ -0,0 +1,121 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#ifndef BIBSEARCHER_H
+#define BIBSEARCHER_H
+
+#include "documentCache.h"
+#include "searchPattern.h"
+
+#include <QMap>
+#include <QObject>
+#include <QStringList>
+
+
+class bibParser;
+class bibReference;
+
+
+class bibSearcher : public QObject
+{
+
+    Q_OBJECT
+
+public:
+    bibSearcher(bibParser* bp, QObject* parento = 0);
+    ~bibSearcher() {}
+
+    const QString highlight(const QString& abstract) const;
+    void addPattern(bool Not, bool caseSensitive, const QString& patternType, const QString& scope,
+                    const QChar& yearScope, const QString& pattern);
+    void clear();
+    void exec();
+
+    inline void setBoolean(bool AND)
+    {
+        _boolean_and = AND;
+    }
+
+    inline void setSearchScope(const QString& file, const QString& dir, bool all, bool documents)
+    {
+        _bibtex_file = file;
+        _bibtex_dir = dir;
+        _all_bibtex_files = all;
+        _include_documents = documents;
+    }
+
+    inline void setSimplifySource(bool simplify)
+    {
+        _simplify_source = simplify;
+    }
+
+    inline int errorsCount() const
+    {
+        return _error_counter;
+    }
+
+    inline int hitsCount() const
+    {
+        return _hits_map.count();
+    }
+
+    inline QString hitsString() const
+    {
+        return _hits_string;
+    }
+
+    inline QString hitValue(const QString& key) const
+    {
+        return _hits_map.value(key);
+    }
+
+    inline int patternsCount() const
+    {
+        return _patterns.count();
+    }
+
+    inline int referencesCount() const
+    {
+        return _reference_counter;
+    }
+
+    inline QString logString() const
+    {
+        return _log_string;
+    }
+
+
+public slots:
+    void abort();
+
+
+private:
+    QList<searchPattern> _patterns;
+    QMap<QString, QString> _hits_map;
+    QString _bibtex_dir;
+    QString _bibtex_file;
+    QString _hits_string;
+    QString _log_string;
+    QStringList _scopes;
+    bibParser* _bpP;
+    bool _aborted;
+    bool _all_bibtex_files;
+    bool _boolean_and;
+    bool _include_documents;
+    bool _simplify_source;
+    const QString excerpts(const QString& contents) const;
+    const QString location(const QString& fn, const bibReference& ref) const;
+    documentCache _documents;
+    int _bibtex_counter;
+    int _document_counter;
+    int _error_counter;
+    int _reference_counter;
+    void search(const QString& bib_file);
+    void searchReference(const QString& bib_file, const bibReference& ref);
+
+};
+
+#endif
diff --git a/src/c2b/c2blib.pro b/src/c2b/c2blib.pro
index fbaf8b8..47a2f4f 100644
--- a/src/c2b/c2blib.pro
+++ b/src/c2b/c2blib.pro
@@ -14,3 +14,11 @@ CONFIG += staticlib
 VERSION = 0.0.0
 TEMPLATE = lib
 QMAKE_CXXFLAGS_DEBUG += -DC2B_DEBUG
+CONFIG += use_lzo
+use_lzo {
+    DEFINES += C2B_USE_LZO
+}
+disable_lzo {
+    CONFIG -= use_lzo
+    DEFINES -= C2B_USE_LZO
+}
diff --git a/src/c2b/c2blib.qrc b/src/c2b/c2blib.qrc
index 3bdb790..bccb7a1 100644
--- a/src/c2b/c2blib.qrc
+++ b/src/c2b/c2blib.qrc
@@ -10,6 +10,7 @@
     <qresource prefix="/txt" >
         <file>txt/prefixes.txt</file>
         <file>txt/suffixes.txt</file>
+        <file>txt/triads.txt</file>
         <file>txt/word_prefix_lexicon.txt</file>
     </qresource>
 </RCC>
diff --git a/src/c2b/cb2bib_parameters.h b/src/c2b/cb2bib_parameters.h
index 7a0dde1..22139a5 100644
--- a/src/c2b/cb2bib_parameters.h
+++ b/src/c2b/cb2bib_parameters.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef CB2BIB_PARAMETERS_H
@@ -33,7 +33,7 @@ const QString C2B_ICON_DISCONNECT_B("connect_no.png");
 const QString C2B_ICON_VIEWBIB_B("viewbib.png");
 const QString C2B_ICON_VIEWC2B_B("viewcb.png");
 const QString C2B_ORGANIZATION("MOLspaces");
-const QString C2B_VERSION("1.3.2");
+const QString C2B_VERSION("1.3.3");
 
 // File Manager Client
 #ifdef Q_WS_X11
diff --git a/src/c2b/cb2bib_utilities.cpp b/src/c2b/cb2bib_utilities.cpp
index 7ce57a4..75774fa 100644
--- a/src/c2b/cb2bib_utilities.cpp
+++ b/src/c2b/cb2bib_utilities.cpp
@@ -1,11 +1,16 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "cb2bib_utilities.h"
 
+#ifdef C2B_USE_LZO
+#include <lzo/lzoconf.h>
+#include <lzo/lzo1x.h>
+#endif
+
 namespace c2bUtils
 {
 
@@ -27,51 +32,156 @@ QString setCapitalization(const QString& str)
     return (cap_string);
 }
 
-QString toAscii(const QString& str, const AsciiConversion type)
+QString& simplifyString(QString& str)
 {
-    QString ascii(str);
-    if (type == KeepWords)
-        cleanEquations(ascii);
-    // Escape diacritics
-    for (int i = 0; i < ascii.length(); ++i)
+    if (str.length() == 0)
+        return str;
+    const ushort space(QChar(' ').unicode());
+    ushort* const c0 = (ushort*)str.data();
+    ushort* const cn = c0 + str.length();
+    ushort* c = c0;
+    ushort* o = c0;
+    QChar* cc = str.data();
+    while (c < cn)
+    {
+        if ((*c > 32 && *c < 160) || !(*c == space || cc->isSpace()))
+            *o++ = *c;
+        else if (o > c0 && *(o - 1) != space)
+            *o++ = space;
+        ++c;
+        ++cc;
+    }
+    if (o > c0 && *(o - 1) == space)
+        --o;
+    str.truncate(int(o - c0));
+    return str;
+}
+
+static inline QString& _to_ascii_strip_diacritics(QString& str)
+{
+    if (str.length() == 0)
+        return str;
+    ushort* const c0 = (ushort*)str.data();
+    ushort* const cn = c0 + str.length();
+    ushort* c = c0 - 1;
+    bool do_ligatures_198(false);
+    bool do_ligatures_223(false);
+    bool do_ligatures_230(false);
+    bool do_ligatures_338(false);
+    bool do_ligatures_339(false);
+    while (c < cn)
     {
-        QCharRef c = ascii[i];
-        if (!c.isLetter())
+        ++c;
+        if (*c < 128)
             continue;
-        if (c.decompositionTag() == QChar::NoDecomposition)
+        QChar qc(*c);
+        if (!qc.isLetter())
+            continue;
+        switch (*c)
+        {
+        case 216:
+            *c = QChar('O').unicode();
+            break;
+        case 248:
+            *c = QChar('o').unicode();
+            break;
+        case 321:
+            *c = QChar('L').unicode();
+            break;
+        case 322:
+            *c = QChar('l').unicode();
+            break;
+        case 198:
+            do_ligatures_198 = true;
+            break;
+        case 223:
+            do_ligatures_223 = true;
+            break;
+        case 230:
+            do_ligatures_230 = true;
+            break;
+        case 338:
+            do_ligatures_338 = true;
+            break;
+        case 339:
+            do_ligatures_339 = true;
+            break;
+        }
+        if (qc.decompositionTag() == QChar::NoDecomposition)
             continue;
-        c = c.decomposition().at(0);
-        if (c.decompositionTag() == QChar::NoDecomposition)
+        qc = qc.decomposition().at(0);
+        *c = qc.unicode();
+        if (qc.decompositionTag() == QChar::NoDecomposition)
             continue;
-        c = c.decomposition().at(0);
+        qc = qc.decomposition().at(0);
+        *c = qc.unicode();
+    }
+    if (do_ligatures_198)
+        str.replace(QChar(198), "AE", Qt::CaseSensitive);
+    if (do_ligatures_223)
+        str.replace(QChar(223), "ss", Qt::CaseSensitive);
+    if (do_ligatures_230)
+        str.replace(QChar(230), "ae", Qt::CaseSensitive);
+    if (do_ligatures_338)
+        str.replace(QChar(338), "OE", Qt::CaseSensitive);
+    if (do_ligatures_339)
+        str.replace(QChar(339), "oe", Qt::CaseSensitive);
+    return str;
+}
+
+static inline QString& _to_ascii_keep_words(QString& str)
+{
+    // Do:
+    // const QRegExp nonAsciiWords("[^A-Za-z0-9\\+\\- ]");
+    // str.replace(nonAsciiWords, " ");
+    // str = str.simplified();
+    if (str.length() == 0)
+        return str;
+    const ushort dash(QChar('-').unicode());
+    const ushort la(QChar('a').unicode());
+    const ushort lz(QChar('z').unicode());
+    const ushort n0(QChar('0').unicode());
+    const ushort n9(QChar('9').unicode());
+    const ushort plus(QChar('+').unicode());
+    const ushort space(QChar(' ').unicode());
+    const ushort ua(QChar('A').unicode());
+    const ushort uz(QChar('Z').unicode());
+
+    ushort* const c0 = (ushort*)str.data();
+    ushort* const cn = c0 + str.length();
+    ushort* c = c0;
+    ushort* o = c0;
+
+    while (c < cn)
+    {
+        if ((*c >= la && *c <= lz) || (*c >= ua && *c <= uz) || (*c >= n0 && *c <= n9) || *c == dash || *c == plus)
+            *o++ = *c;
+        else if (o > c0 && *(o - 1) != space)
+            *o++ = space;
+        ++c;
     }
-    ascii.replace(QChar(198), "AE", Qt::CaseSensitive);
-    ascii.replace(QChar(216), 'O', Qt::CaseSensitive);
-    ascii.replace(QChar(223), "ss", Qt::CaseSensitive);
-    ascii.replace(QChar(230), "ae", Qt::CaseSensitive);
-    ascii.replace(QChar(248), 'o', Qt::CaseSensitive);
-    ascii.replace(QChar(321), 'L', Qt::CaseSensitive);
-    ascii.replace(QChar(322), 'l', Qt::CaseSensitive);
-    ascii.replace(QChar(338), "OE", Qt::CaseSensitive);
-    ascii.replace(QChar(339), "oe", Qt::CaseSensitive);
+    if (o > c0 && *(o - 1) == space)
+        --o;
+    str.truncate(int(o - c0));
+    return str;
+}
+
+QString toAscii(const QString& str, const AsciiConversion type)
+{
+    QString ascii(str);
+    if (type == FromBibTeX)
+        cleanEquations(ascii);
+    _to_ascii_strip_diacritics(ascii);
     if (type == Collation)
     {
         for (int i = 0; i < ascii.length(); ++i)
-        {
-            QCharRef c = ascii[i];
-            if (c.category() == QChar::Punctuation_Dash)
-                c = ' ';
-        }
+            if (ascii.at(i).category() == QChar::Punctuation_Dash)
+                ascii[i] = ' ';
         return ascii.toCaseFolded();
     }
-    // Delete possibly remaining non-ASCII characters
-    if (type == KeepWords)
-    {
-        ascii.replace(nonAsciiWords, " ");
-        ascii = ascii.simplified();
-    }
-    // Cleanup
-    else
+    if (type == KeepWords || type == FromBibTeX)
+        _to_ascii_keep_words(ascii);
+    else // Cleanup
         ascii.remove(nonAsciiLetter);
     return ascii;
 }
@@ -154,7 +264,7 @@ QString& c2bToBib(QString& str)
     str.replace(QChar(381), "{\\v{Z}}");
     str.replace(QChar(382), "{\\v{z}}");
     // Escape common Greek and math
-    str.replace(QChar(913), "$\\Alpha$");       // Some uppercases might require engrec package
+    str.replace(QChar(913), "$\\Alpha$"); // Some uppercases might require engrec package
     str.replace(QChar(914), "$\\Beta$");
     str.replace(QChar(915), "$\\Gamma$");
     str.replace(QChar(916), "$\\Delta$");
@@ -379,4 +489,127 @@ QString& bibToC2b(QString& str)
     return str;
 }
 
+const QString fromUtf8(const QByteArray& ba)
+{
+// Based on Qt's QString::fromUtf8 function. Input ba must be an UTF-8
+// encoded array produced by QString::toUtf8. Encoding correctness is
+// assumed and checking omitted. It performs a 20% faster compared to
+// Qt 4.5, and expected more compared to Qt 4.6.
+
+    const char* b = ba.constData();
+    const char* const bn = b + ba.length();
+    QString output;
+    output.resize(ba.length());
+    ushort* o = (ushort*)output.unicode();
+    uint c;
+    while (b < bn)
+    {
+        c = uint(*b);
+        if (c & 0x80)
+        {
+            if ((c & 0xe0) == 0xc0)
+            {
+                c &= 0x1f;
+                c = (uint)((c << 6) | (*++b & 0x3f));
+            }
+            else if ((c & 0xf0) == 0xe0)
+            {
+                c &= 0x0f;
+                c = (uint)((c << 6) | (b[1] & 0x3f));
+                c = (uint)((c << 6) | (b[2] & 0x3f));
+                b += 2;
+            }
+            else if ((c & 0xf8) == 0xf0)
+            {
+                c &= 0x07;
+                c = (uint)((c << 6) | (b[1] & 0x3f));
+                c = (uint)((c << 6) | (b[2] & 0x3f));
+                c = (uint)((c << 6) | (b[3] & 0x3f));
+                *o++ = QChar::highSurrogate(c);
+                c = QChar::lowSurrogate(c);
+                b += 3;
+            }
+            else
+                c = QChar::ReplacementCharacter;
+        }
+        *o++ = ushort(c);
+        ++b;
+    }
+    output.truncate(int(o - (ushort*)output.unicode()));
+//    QString check = QString::fromUtf8(ba);
+//    qDebug() << (check == output);
+    return output;
+}
+
+#ifdef C2B_USE_LZO
+const QByteArray lzo::compress(const QByteArray& data)
+{
+    const lzo_uint src_s(data.size());
+    if (src_s == 0)
+        return QByteArray();
+    if (lzo_init() != LZO_E_OK)
+    {
+        warn("compress: lzo: internal error - initialization failed");
+        return QByteArray();
+    }
+    const lzo_bytep src_p = reinterpret_cast<const lzo_bytep>(data.constData());
+
+    QByteArray compressed;
+    const lzo_uint dest_s = HEADER_LENGTH + (src_s + src_s / 16 + 64 + 3);
+    compressed.resize((int)dest_s);
+    lzo_bytep compressed_p = reinterpret_cast<lzo_bytep>(compressed.data());
+    lzo_bytep dest_p = compressed_p + HEADER_LENGTH;
+    lzo_uint enc_dest_s = dest_s - HEADER_LENGTH;
+
+    QByteArray wrkmem;
+    wrkmem.resize(LZO1X_999_MEM_COMPRESS);
+    lzo_bytep wrkmem_p = reinterpret_cast<lzo_bytep>(wrkmem.data());
+
+    if (lzo1x_999_compress(src_p, src_s, dest_p, &enc_dest_s, wrkmem_p) == LZO_E_OK)
+    {
+        compressed.resize((int)enc_dest_s + HEADER_LENGTH);
+        QByteArray header(QByteArray::number((qulonglong)src_s));
+        for (int i = 0; i < qMin(header.length(), HEADER_LENGTH); ++i)
+            compressed[i] = header[i];
+        for (int i = qMin(header.length(), HEADER_LENGTH); i < HEADER_LENGTH; ++i)
+            compressed[i] = ' ';
+        return compressed;
+    }
+    else
+    {
+        warn("compress: lzo: internal error - compression failed");
+        return QByteArray();
+    }
+}
+
+const QByteArray lzo::uncompress(const QByteArray& data)
+{
+    const lzo_uint data_s(data.size());
+    if (data_s <= (unsigned int)HEADER_LENGTH)
+        return QByteArray();
+    if (lzo_init() != LZO_E_OK)
+    {
+        warn("uncompress: lzo: internal error - initialization failed");
+        return QByteArray();
+    }
+    const lzo_bytep data_p = reinterpret_cast<const lzo_bytep>(data.constData());
+    const lzo_bytep src_p = data_p + HEADER_LENGTH;
+    const lzo_uint src_s = data_s - HEADER_LENGTH;
+
+    QByteArray uncompressed;
+    const ulong expected_dest_s = data.left(HEADER_LENGTH).trimmed().toULong();
+    lzo_uint dest_s = qMax(expected_dest_s, lzo_uint(1));
+    uncompressed.resize((int)dest_s);
+    lzo_bytep dest_p = reinterpret_cast<lzo_bytep>(uncompressed.data());
+
+    if (lzo1x_decompress(src_p, src_s, dest_p, &dest_s, NULL) == LZO_E_OK && (ulong)dest_s == expected_dest_s)
+        return uncompressed;
+    else
+    {
+        warn("uncompress: lzo: internal error - uncompression failed");
+        return QByteArray();
+    }
+}
+#endif
+
 } // namespace c2bUtils
diff --git a/src/c2b/cb2bib_utilities.h b/src/c2b/cb2bib_utilities.h
index 0ad9595..957ba47 100644
--- a/src/c2b/cb2bib_utilities.h
+++ b/src/c2b/cb2bib_utilities.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef CB2BIB_UTILITIES_H
@@ -12,6 +12,7 @@
 #include <QFileInfo>
 #include <QRegExp>
 #include <QString>
+#include <QStringMatcher>
 #include <QtDebug>
 
 
@@ -22,11 +23,12 @@
 namespace c2bUtils
 {
 
-enum AsciiConversion {Cleanup, KeepWords, Collation};
-extern QString toAscii(const QString& str, const AsciiConversion type);
+enum AsciiConversion {Cleanup, Collation, FromBibTeX, KeepWords};
 extern QString setCapitalization(const QString& str);
+extern QString toAscii(const QString& str, const AsciiConversion type);
 extern QString& bibToC2b(QString& str);
 extern QString& c2bToBib(QString& str);
+extern QString& simplifyString(QString& str);
 
 static const QRegExp pnasGreekLetters("[\\{\\[\\(](alpha|beta|gamma|delta|varepsilon|"
                                       "zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|"
@@ -36,7 +38,6 @@ static const QRegExp pnasGreekLetters("[\\{\\[\\(](alpha|beta|gamma|delta|vareps
                                       Qt::CaseInsensitive); // Only used in QString::replace which keeps QRegExp const
 static const QRegExp isBibToC2b("[\\{\\[\\$\\(\\\\<>]");
 static const QRegExp nonAsciiLetter("[^A-Za-z]");
-static const QRegExp nonAsciiWords("[^A-Za-z0-9\\+- ]");
 static const QRegExp nonLetter("\\W");
 static const QStringMatcher hasLatexDiacritic("{\\");
 static const QStringMatcher hasLatexSymbol("$\\");
@@ -68,25 +69,30 @@ inline QString& fullBibToC2b(QString& str)
 inline QString& cleanEquations(QString& str)
 {
     // Simplify equations
-    if (!str.contains('$'))
+    const QChar eq('$');
+    int i(str.indexOf(eq));
+    if (i == -1)
         return str;
+    const QChar ob('{');
+    const QChar cb('}');
+    const QChar ca('^');
+    const QChar sl('\\');
+    const QChar us('_');
     const int n(str.length());
-    int p(0);
-    int i(0);
+    int p(i);
     while (i < n)
     {
-        if (str.at(i) == '$')
+        if (str.at(i) == eq)
         {
             bool has_eq(false);
             for (int j = i + 1; j < qMin(i + 70, n); ++j) // Set a max equation length
-                if (str.at(j) == '$')
+                if (str.at(j) == eq)
                 {
                     has_eq = true;
-                    QChar ck;
                     for (int k = i + 1; k < j; ++k)
                     {
-                        ck = str.at(k);
-                        if (ck != '_' && ck != '^' && ck != '\\' && ck != '{' && ck != '}')
+                        const QChar& ck = str.at(k);
+                        if (ck != us && ck != ca && ck != sl && ck != ob && ck != cb)
                             str[p++] = str.at(k);
                     }
                     i = j;
@@ -110,7 +116,7 @@ inline QString& cleanTitle(QString& title, const bool clean_period = false)
     title.remove('{');
     title.remove('}');
     title = title.trimmed();
-    if (clean_period)
+    if (clean_period && title.length() > 0)
         if (title[title.length() - 1] == '.')
             title.chop(1);
     return title;
@@ -130,8 +136,8 @@ inline QString toHtmlString(QString str)
 
 inline QString firstPage(QString pages)
 {
-    pages.simplified();
-    pages.remove(QRegExp("[\\s-].*$"));
+    simplifyString(pages);
+    pages.remove(QRegExp("[\\s\\-].*$"));
     return pages;
 }
 
@@ -280,13 +286,15 @@ inline bool inBraces(const int pos, const QString& str, QString* in)
     if (str.at(pos - 1) == '{') // pos > 0 always
     {
         int open_braces(1);
+        const QChar open('{');
+        const QChar close('}');
         QChar si;
         for (int i = pos; i < str.length(); ++i)
         {
             si = str.at(i);
-            if (si == '{')
+            if (si == open)
                 open_braces++;
-            else if (si == '}')
+            else if (si == close)
                 open_braces--;
             if (open_braces == 0)
             {
@@ -296,13 +304,17 @@ inline bool inBraces(const int pos, const QString& str, QString* in)
         }
     }
     else // in Quotes
+    {
+        const QChar quote('"');
+        const QChar comma(',');
         for (int i = pos; i < str.length() - 1; ++i)
-            if (str.at(i) == '"')
-                if (str.at(i + 1) == ',')
+            if (str.at(i) == quote)
+                if (str.at(i + 1) == comma)
                 {
                     *in = str.mid(pos, i - pos);
                     return true;
                 }
+    }
     return false;
 }
 
@@ -335,6 +347,11 @@ inline QString toQtXmlString(QString str)
     return (str);
 }
 
+inline void warn(const QString& ms)
+{
+    qWarning("[cb2bib] %s.", (const char*)ms.toLatin1());
+}
+
 inline void debug(const QString&
 #ifdef C2B_DEBUG
                   debug_ms
@@ -346,6 +363,37 @@ inline void debug(const QString&
 #endif
 }
 
+extern const QString fromUtf8(const QByteArray& ba);
+
+#ifdef C2B_USE_LZO
+namespace lzo
+{
+static const int HEADER_LENGTH = 10;
+extern const QByteArray compress(const QByteArray& data);
+extern const QByteArray uncompress(const QByteArray& data);
+} // namespace lzo
+
+inline const QByteArray compress(const QByteArray& data)
+{
+    return lzo::compress(data);
+}
+
+inline const QByteArray uncompress(const QByteArray& data)
+{
+    return lzo::uncompress(data);
+}
+#else
+inline const QByteArray compress(const QByteArray& data)
+{
+    return qCompress(data);
+}
+
+inline const QByteArray uncompress(const QByteArray& data)
+{
+    return qUncompress(data);
+}
+#endif
+
 } // namespace c2bUtils
 
 #endif
diff --git a/src/c2b/compositePattern.cpp b/src/c2b/compositePattern.cpp
index 85883cf..ee0fc2a 100644
--- a/src/c2b/compositePattern.cpp
+++ b/src/c2b/compositePattern.cpp
@@ -1,27 +1,52 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "compositePattern.h"
 
+#include "cb2bib_utilities.h"
 
-compositePattern::compositePattern(const QString newPattern, Qt::CaseSensitivity newCs)
+
+template <typename T> class descending
+{
+public:
+    descending(const T& data) : _data(data) {}
+    inline bool operator()(const int i, const int j)
+    {
+        return _data.at(i) > _data.at(j);
+    }
+private:
+    const T& _data;
+};
+
+
+compositePattern::compositePattern() :
+        _case_sensitivity(Qt::CaseSensitive),
+        _is_multipattern(false),
+        _subpattern_count(0),
+        _matched_length(-1)
 {
-    pattern = newPattern.simplified();
-    caseSensitivity = newCs;
-    arx.setPatternSyntax(QRegExp::RegExp2);
-    arx.setMinimal(false);
-    // Setting arx case sensitive for efficiency
-    arx.setCaseSensitivity(Qt::CaseSensitive);
+    _regexp.setCaseSensitivity(Qt::CaseSensitive); // Setting _regexp case sensitive for efficiency
+    _regexp.setMinimal(false);
+    _regexp.setPatternSyntax(QRegExp::RegExp2);
 }
 
-compositePattern::~compositePattern()
-{}
+compositePattern::compositePattern(const QString& pattern, const Qt::CaseSensitivity cs) :
+        _string(pattern.simplified()),
+        _case_sensitivity(cs),
+        _is_multipattern(false),
+        _subpattern_count(0),
+        _matched_length(-1)
+{
+    _regexp.setCaseSensitivity(Qt::CaseSensitive); // Setting _regexp case sensitive for efficiency
+    _regexp.setMinimal(false);
+    _regexp.setPatternSyntax(QRegExp::RegExp2);
+}
 
 
-QString compositePattern::escape(const QString& str, Qt::CaseSensitivity cs) const
+QString compositePattern::escape(const QString& str, const Qt::CaseSensitivity cs) const
 {
     if (cs == Qt::CaseSensitive)
         return QRegExp::escape(str);
@@ -34,99 +59,12 @@ QString compositePattern::escape(const QString& str, Qt::CaseSensitivity cs) con
     return scaped;
 }
 
-double compositePattern::probability(const QString& str) const
+void compositePattern::set_sort_index()
 {
-    // Estimate string probability
-    // Frequencies as found on a 306945065 letter set
-    double f(1.0);
-    for (int i = 0; i < str.length(); ++i)
-    {
-        if (!str.at(i).isLetter())
-            continue;
-        switch (str.at(i).toLower().toAscii())
-        {
-        case 'a':
-            f *= 0.0770;
-            break;
-        case 'b':
-            f *= 0.0160;
-            break;
-        case 'c':
-            f *= 0.0391;
-            break;
-        case 'd':
-            f *= 0.0337;
-            break;
-        case 'e':
-            f *= 0.1196;
-            break;
-        case 'f':
-            f *= 0.0248;
-            break;
-        case 'g':
-            f *= 0.0174;
-            break;
-        case 'h':
-            f *= 0.0407;
-            break;
-        case 'i':
-            f *= 0.0785;
-            break;
-        case 'j':
-            f *= 0.0033;
-            break;
-        case 'k':
-            f *= 0.0054;
-            break;
-        case 'l':
-            f *= 0.0427;
-            break;
-        case 'm':
-            f *= 0.0288;
-            break;
-        case 'n':
-            f *= 0.0727;
-            break;
-        case 'o':
-            f *= 0.0733;
-            break;
-        case 'p':
-            f *= 0.0255;
-            break;
-        case 'q':
-            f *= 0.0034;
-            break;
-        case 'r':
-            f *= 0.0628;
-            break;
-        case 's':
-            f *= 0.0641;
-            break;
-        case 't':
-            f *= 0.0911;
-            break;
-        case 'u':
-            f *= 0.0269;
-            break;
-        case 'v':
-            f *= 0.0114;
-            break;
-        case 'w':
-            f *= 0.0121;
-            break;
-        case 'x':
-            f *= 0.0076;
-            break;
-        case 'y':
-            f *= 0.0143;
-            break;
-        case 'z':
-            f *= 0.0027;
-            break;
-        default:
-            f *= 0.0003; // Maximum found for a non ascii letter
-            break;
-        }
-    }
-    return f;
+    Q_ASSERT_X(_ranks.count() == _subpattern_count, "compositePattern", "Mismatch in subexpression initialization");
+    _index.resize(_subpattern_count);
+    for (int i = 0; i < _subpattern_count; ++i)
+        _index[i] = i;
+    descending< QList<double> > sort(_ranks);
+    qSort(_index.begin(), _index.end(), sort);
 }
diff --git a/src/c2b/compositePattern.h b/src/c2b/compositePattern.h
index e61b699..75e4836 100644
--- a/src/c2b/compositePattern.h
+++ b/src/c2b/compositePattern.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef COMPOSITEPATTERN_H
@@ -9,33 +9,71 @@
 
 #include <QRegExp>
 #include <QStringList>
+#include <QVector>
 
 
 class compositePattern
 {
 
 public:
-    compositePattern(const QString newPattern, Qt::CaseSensitivity newCs);
-    virtual ~compositePattern();
+    compositePattern();
+    compositePattern(const QString& pattern, const Qt::CaseSensitivity cs);
+    inline virtual ~compositePattern() {}
 
-    const QRegExp toRegExp() const
+
+    inline const QString strings() const
     {
-        return arx;
+        return _string;
     }
-
-    const QList<QRegExp> subpatterns() const
+    inline const QStringList substrings() const
+    {
+        return _substrings;
+    }
+    inline const QRegExp& regexp() const
+    {
+        return _regexp;
+    }
+    inline const QVector<QRegExp>& subregexps() const
+    {
+        return _subregexps;
+    }
+    inline Qt::CaseSensitivity caseSensitivity() const
     {
-        return asrx;
+        return _case_sensitivity;
+    }
+    inline int subpatternCount() const
+    {
+        return _subpattern_count;
+    }
+    inline int matchedLength() const
+    {
+        return _matched_length;
+    }
+    inline bool isMultipattern() const
+    {
+        return _is_multipattern;
     }
 
+    virtual bool matches(const QString& str) const = 0;
+    virtual int indexIn(const QString& str, const int from) const = 0;
+
 
 protected:
-    QList<QRegExp> asrx;
-    QRegExp arx;
-    QString escape(const QString& str, Qt::CaseSensitivity cs) const;
-    QString pattern;
-    Qt::CaseSensitivity caseSensitivity;
-    double probability(const QString& str) const;
+    QString escape(const QString& str, const Qt::CaseSensitivity cs) const;
+    void set_sort_index();
+
+    QList<double> _ranks;
+    QRegExp _regexp;
+    QString _string;
+    QStringList _substrings;
+    QVector<QRegExp> _subregexps;
+    QVector<int> _index;
+    Qt::CaseSensitivity _case_sensitivity;
+    bool _is_multipattern;
+    int _subpattern_count;
+    mutable QVector<int> _p0;
+    mutable QVector<int> _pn;
+    mutable int _matched_length;
 
 };
 
diff --git a/src/c2b/coreBibParser.cpp b/src/c2b/coreBibParser.cpp
index 76a46b5..cb98919 100644
--- a/src/c2b/coreBibParser.cpp
+++ b/src/c2b/coreBibParser.cpp
@@ -1,13 +1,15 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "coreBibParser.h"
 
 
-coreBibParser::coreBibParser(QObject* parento) : QObject(parento)
+coreBibParser::coreBibParser(QObject* parento) :
+        QObject(parento),
+        _close(QChar('}')), _comma(QChar(',')), _open(QChar('{')), _space(QChar(' '))
 {
     _settingsP = settings::instance();
 
@@ -21,9 +23,28 @@ coreBibParser::coreBibParser(QObject* parento) : QObject(parento)
     setRegularExpressions();
 }
 
-coreBibParser::~coreBibParser()
-{}
 
+bool coreBibParser::referencesIn(const QString& str, bibReference* ref)
+{
+    // File parsing for given fields in ref
+    ref->clearReference();
+    const int pos(referenceStarts(str, ref->pos));
+    if (pos < 0)
+        return false;
+    referenceContents(str, ref, pos);
+    return true;
+}
+
+bool coreBibParser::referenceAtKey(const QString& key, const QString& str, bibReference* ref)
+{
+    // File parsing for given fields in ref
+    ref->clearReference();
+    const int pos(referenceStarts(key, str));
+    if (pos < 0)
+        return false;
+    referenceContents(str, ref, pos);
+    return true;
+}
 
 QString coreBibParser::referenceToFomattedBibTeX(const bibReference& ref) const
 {
@@ -90,7 +111,7 @@ QString coreBibParser::adjacentNumbers(const QString& numbers) const
     // Originary for pages. However also used for multiple volume, number and year
     QString pages(numbers);
     pages.replace(c2bUtils::nonLetter, " ");
-    pages = pages.simplified();
+    pages = c2bUtils::simplifyString(pages);
     pages.replace(' ', '-');
     QRegExp rx1("^(\\d+)-(\\d+)-*pp$");
     QRegExp rx2("^(\\d+)-(\\d+)$");
@@ -238,7 +259,7 @@ bibReference coreBibParser::wholeReference(const QString& str)
         return ref;
     QString str_ref(referenceAt(str, &pos));
     c2bUtils::fullBibToC2b(str_ref);
-    str_ref = str_ref.simplified();
+    c2bUtils::simplifyString(str_ref);
     _bib_type_re.indexIn(str_ref);
     ref.typeName = _bib_type_re.cap(1).toLower();
     setReferenceEnd(&str_ref, str_ref.length());
diff --git a/src/c2b/coreBibParser.h b/src/c2b/coreBibParser.h
index afee152..bfcdfe6 100644
--- a/src/c2b/coreBibParser.h
+++ b/src/c2b/coreBibParser.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef COREBIBPARSER_H
@@ -28,11 +28,13 @@ class coreBibParser : public QObject
 
 public:
     coreBibParser(QObject* parento = 0);
-    virtual ~coreBibParser();
+    inline virtual ~coreBibParser() {}
 
     QString referenceToBibTeX(const bibReference& ref) const;
     QString referenceToFomattedBibTeX(const bibReference& ref) const;
     bibReference wholeReference(const QString& str);
+    bool referenceAtKey(const QString& key, const QString& str, bibReference* ref);
+    bool referencesIn(const QString& str, bibReference* ref);
     void initReferenceParsing(const QString& dir, const QStringList& fields, bibReference* ref);
 
     inline const QStringList& bibliographicFields() const
@@ -60,26 +62,6 @@ public:
         else
             return _bib_begin1_re.indexIn(str) > -1;
     }
-    inline bool referencesIn(const QString& str, bibReference* ref)
-    {
-        // File parsing for given fields in ref
-        ref->clearReference();
-        const int pos(referenceStarts(str, ref->pos));
-        if (pos < 0)
-            return false;
-        referenceContents(str, ref, pos);
-        return true;
-    }
-    inline bool referenceAtKey(const QString& key, const QString& str, bibReference* ref)
-    {
-        // File parsing for given fields in ref
-        ref->clearReference();
-        const int pos(referenceStarts(key, str));
-        if (pos < 0)
-            return false;
-        referenceContents(str, ref, pos);
-        return true;
-    }
     inline int fieldCount(const bibReference& ref) const
     {
         // Counting Non Empty Fields
@@ -118,6 +100,10 @@ private:
     QRegExp _bib_key_re;
     QRegExp _bib_type_re;
     QString _bib_file_dir;
+    const QChar _close;
+    const QChar _comma;
+    const QChar _open;
+    const QChar _space;
     void setFields();
     void setRegularExpressions();
     void setTypes();
@@ -137,7 +123,6 @@ private:
             return i;
         return _bib_begin_re.indexIn(str, i);
     }
-
     inline int referenceStarts(const QString& key, const QString& str) const
     {
         if (!str.contains(key))
@@ -149,7 +134,6 @@ private:
             return i;
         return str.indexOf(QRegExp("@\\w+\\s*\\{" + key + ','), i);
     }
-
     inline int referenceEnds(const QString& str, int pos = 0) const
     {
         // If referenceStarts call is successful, we know for sure
@@ -162,31 +146,28 @@ private:
         int ref_length(referenceStarts(str, pos + 2) - 1);
         if (ref_length < 0)
             ref_length = str.length();
-        const int brace_pos(str.indexOf('{', pos));
+        const int brace_pos(str.indexOf(_open, pos));
         int open_braces(1);
         for (int i = brace_pos + 1; i < ref_length; ++i)
         {
-            const QChar& si = str[i];
-            if (si == '{')
+            const QChar& si = str.at(i);
+            if (si == _open)
                 open_braces++;
-            else if (si == '}')
+            else if (si == _close)
                 open_braces--;
             if (open_braces == 0)
                 return i;
         }
         return ref_length - 1;
     }
-
     inline void setReferenceEnd(QString* str, const int& length) const
     {
         // Set safer termination: field="..." } -> field="...",}
-        QCharRef c = (*str)[length - 2];
-        if (c == ' ')
-            c = ',';
+        if (str->at(length - 2) == _space)
+            (*str)[length - 2] = _comma;
         else
-            (*str)[length - 1] = ',';
+            (*str)[length - 1] = _comma;
     }
-
     inline QString referenceAt(const QString& str, int* pos) const
     {
         // String str contains one or multiple references (file contents)
@@ -195,7 +176,6 @@ private:
         *pos = pos_;
         return str_ref;
     }
-
     inline void referenceContents(const QString& str, bibReference* ref, int pos)
     {
         // File parsing for given fields in ref
@@ -204,7 +184,7 @@ private:
         ref->pos = pos;
         ref->rawReference = str_ref;
         c2bUtils::bibToC2b(str_ref);
-        str_ref = str_ref.simplified();
+        c2bUtils::simplifyString(str_ref);
         ref->unicodeReference = str_ref;
         _bib_key_re.indexIn(str_ref);
         ref->citeidName = _bib_key_re.cap(1);
diff --git a/src/c2b/document.cpp b/src/c2b/document.cpp
index 10edd11..d19c4fb 100644
--- a/src/c2b/document.cpp
+++ b/src/c2b/document.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "document.h"
@@ -20,9 +20,6 @@ document::document(const QString& fn, const Conversion mode)
     setConverter(mode);
 }
 
-document::~document()
-{}
-
 
 QString document::fileToString(const QString& fn)
 {
@@ -56,7 +53,7 @@ QString document::toString()
     args.append(_converter_output);
     int conversion_max_wait;
     if (_conversion_mode == Raw)
-        conversion_max_wait = 600000;
+        conversion_max_wait = -1;
     else
         conversion_max_wait = 150000;
     converter.start(_converter_bin, args);
@@ -69,7 +66,7 @@ QString document::toString()
     if (!converter.waitForFinished(conversion_max_wait))
     {
         converter.kill();
-        qDebug(QObject::tr("[cb2bib] Error: Document conversion timeout for file '%1'.").arg(_document_fn).toLatin1());
+        c2bUtils::warn(QObject::tr("Error: Document conversion timeout for file '%1'").arg(_document_fn));
     }
     QString doc(c2bUtils::fileToString(_converter_output, true));
     _log_string = QString::fromUtf8(converter.readAllStandardOutput().trimmed());
@@ -78,7 +75,7 @@ QString document::toString()
     {
         _error_string += QObject::tr("[%1 %2] Conversion failed for file %3\n")
                          .arg(_converter_bin).arg(_converter_arg).arg(_document_fn);
-        qDebug(QObject::tr("[cb2bib] Warning: Text conversion for file '%1' is empty.").arg(_document_fn).toLatin1());
+        c2bUtils::warn(QObject::tr("Warning: Text conversion for file '%1' is empty").arg(_document_fn));
         return QString();
     }
 
@@ -266,6 +263,7 @@ QString document::toString()
     doc.remove(QChar(888));
     // Skip control codes
     // Many are improper conversions from PDF to text mathematical symbols
+    doc.replace(QChar(127), ' ');
     for (int i = 0; i < doc.length(); ++i)
     {
         QCharRef c = doc[i];
diff --git a/src/c2b/document.h b/src/c2b/document.h
index c552263..0d2b502 100644
--- a/src/c2b/document.h
+++ b/src/c2b/document.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef DOCUMENT_H
@@ -19,7 +19,7 @@ public:
     enum Conversion {FirstPage, Raw};
 
     document(const QString& fn = QString(), const Conversion mode = FirstPage);
-    ~document();
+    inline ~document() {}
 
     QString fileToString(const QString& fn);
     QString toString();
diff --git a/src/c2b/documentCache.cpp b/src/c2b/documentCache.cpp
new file mode 100644
index 0000000..ca06913
--- /dev/null
+++ b/src/c2b/documentCache.cpp
@@ -0,0 +1,125 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#include "documentCache.h"
+
+#include "cb2bib_utilities.h"
+#include "document.h"
+#include "settings.h"
+#include "triads.h"
+
+
+documentCache::documentCache() :
+        _current(_cache),
+        _content_type(documentContents::Raw),
+        _cache_load_size(0),
+        _settingsP(settings::instance())
+{}
+
+documentCache::~documentCache()
+{
+    save();
+}
+
+
+void documentCache::load(const QString& fn, const documentContents::Type type)
+{
+    _content_type = type;
+    if (_load_filename == fn)
+        return;
+    unload();
+    _load_filename = fn;
+    const QString cache_dir(_settingsP->fileName("cb2Bib/CacheDirectory"));
+    if (QFileInfo(cache_dir).exists() && QFileInfo(cache_dir).isDir())
+        _cache_filename = QDir::cleanPath(cache_dir + '/' + QFileInfo(_load_filename).fileName() + ".c2b");
+    else
+        _cache_filename = _load_filename.trimmed() + ".c2b";
+    if (QFileInfo(_cache_filename).exists())
+    {
+        QFile file(_cache_filename);
+        if (file.open(QIODevice::ReadOnly))
+        {
+            QDataStream ds(&file);
+            ds >> _cache;
+        }
+    }
+#ifdef C2B_USE_LZO
+    if (!_cache.contains("lzo"))
+    {
+        _cache.clear();
+        _cache.insert("lzo", QByteArray());
+    }
+#else
+    if (!_cache.contains("zlib"))
+    {
+        _cache.clear();
+        _cache.insert("zlib", QByteArray());
+    }
+#endif
+    _cache_load_size = _cache.size();
+}
+
+void documentCache::unload()
+{
+    // Release cache memory
+    save();
+    _cache.clear();
+    _cache_filename.clear();
+    _cache_load_size = 0;
+    _load_filename.clear();
+}
+
+bool documentCache::setCurrent(const QString& fn, int* pdfCounter, QString* logString, int* errorCounter)
+{
+    const QString doc_fn(fn.trimmed());
+    if (doc_fn.isEmpty())
+    {
+        _current.clear();
+        return false;
+    }
+    const QString skey("sign:" + doc_fn);
+    const QString tkey(doc_fn);
+    _current.preload(skey, tkey, _content_type);
+
+    if (!_cache.contains(tkey))
+    {
+        document doc(doc_fn, document::Raw);
+        _current._text = doc.toString();
+        if (!doc.errorString().isEmpty())
+        {
+            ++(*errorCounter);
+            (*logString) += QObject::tr("% [cb2bib] %1\n").arg(doc.errorString());
+            return false;
+        }
+        _current._text = c2bUtils::simplifyString(_current._text);
+        _cache.insert(doc_fn, c2bUtils::compress(_current._text.toUtf8()));
+        if (_content_type == documentContents::Simplified)
+        {
+            _current._text = c2bUtils::toAscii(_current._text, c2bUtils::KeepWords);
+            _current._signature = triads::asciiTextSignature(_current._text);
+        }
+        else
+            _current._signature = triads::textSignature(_current._text);
+        _cache.insert(skey, _current._signature.toUtf8());
+        _current._is_text_loaded = true;
+        _current._is_signature_loaded = true;
+    }
+    ++(*pdfCounter);
+    return true;
+}
+
+void documentCache::save()
+{
+    if (_cache_load_size != _cache.size() && !_cache_filename.isEmpty())
+    {
+        QFile file(_cache_filename);
+        if (file.open(QIODevice::WriteOnly))
+        {
+            QDataStream ds(&file);
+            ds << _cache;
+        }
+    }
+}
diff --git a/src/c2b/documentCache.h b/src/c2b/documentCache.h
new file mode 100644
index 0000000..84e227d
--- /dev/null
+++ b/src/c2b/documentCache.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#ifndef DOCUMENTCACHE_H
+#define DOCUMENTCACHE_H
+
+#include "documentContents.h"
+
+#include <QHash>
+
+
+class settings;
+
+class documentCache
+{
+
+public:
+    documentCache();
+    ~documentCache();
+
+    bool setCurrent(const QString& fn, int* pdfCounter, QString* logString, int* errorCounter);
+    void load(const QString& fn, const documentContents::Type type);
+    void unload();
+
+    inline const documentContents& current() const
+    {
+        return _current;
+    }
+
+    inline const QHash<QString, QByteArray>& cacheData() const
+    {
+        return _cache;
+    }
+
+
+private:
+    QHash<QString, QByteArray> _cache;
+    QString _cache_filename;
+    QString _load_filename;
+    documentContents _current;
+    documentContents::Type _content_type;
+    int _cache_load_size;
+    settings* _settingsP;
+    void save();
+
+};
+
+#endif
diff --git a/src/c2b/documentContents.h b/src/c2b/documentContents.h
new file mode 100644
index 0000000..cabbb69
--- /dev/null
+++ b/src/c2b/documentContents.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#ifndef DOCUMENTCONTENTS_H
+#define DOCUMENTCONTENTS_H
+
+#include "cb2bib_utilities.h"
+
+#include <QHash>
+#include <QString>
+
+
+class documentContents
+{
+
+public:
+    enum Type {Simplified, Raw};
+
+    inline const QString& signature() const
+    {
+        if (!_is_signature_loaded)
+        {
+            _signature = QString::fromUtf8(_cache.value(_signature_key));
+            _is_signature_loaded = true;
+        }
+        return _signature;
+    }
+
+    inline const QString& text() const
+    {
+        if (!_is_text_loaded)
+        {
+            if (_type == Simplified)
+                _text = c2bUtils::toAscii(c2bUtils::fromUtf8(c2bUtils::uncompress(_cache.value(_text_key))), c2bUtils::KeepWords);
+            else
+                _text = c2bUtils::fromUtf8(c2bUtils::uncompress(_cache.value(_text_key)));
+            _is_text_loaded = true;
+        }
+        return _text;
+    }
+
+
+private:
+    inline documentContents(const QHash<QString, QByteArray>& cache) : _cache(cache) {}
+    inline ~documentContents() {}
+
+
+    inline void clear()
+    {
+        _is_signature_loaded = false;
+        _is_text_loaded = false;
+        _signature.clear();
+        _signature_key.clear();
+        _text.clear();
+        _text_key.clear();
+    }
+
+    inline void preload(const QString& skey, const QString& tkey, const Type type)
+    {
+        clear();
+        _signature_key = skey;
+        _text_key = tkey;
+        _type = type;
+    }
+
+    QString _signature_key;
+    QString _text_key;
+    Type _type;
+    const QHash<QString, QByteArray>& _cache;
+    mutable QString _signature;
+    mutable QString _text;
+    mutable bool _is_signature_loaded;
+    mutable bool _is_text_loaded;
+
+    friend class documentCache;
+
+};
+
+#endif
diff --git a/src/c2b/heuristicBibParser.cpp b/src/c2b/heuristicBibParser.cpp
index aed4580..9a72009 100644
--- a/src/c2b/heuristicBibParser.cpp
+++ b/src/c2b/heuristicBibParser.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "heuristicBibParser.h"
@@ -38,8 +38,8 @@ heuristicBibParser::heuristicBibParser(bibParser* bp) :
         _word_prefix_lexicon[i].replace('_', ' ');
         _word_prefix_lexicon[i].squeeze();
     }
-    const QString author_lc_t("(?:n%1n|n%1%1n|%1n|%1nn|%1%1n|%1%1%1n|n%1nn|nn%1n|%1%1nn|nn|nnn)");
-    const QString author_uc_t("(?:[nN]%1N|[nN]%1%1N|%1N|%1[nN]N|%1%1N|%1%1%1N|[nN]%1[nN]N|[nN]N%1N|%1%1[nN]N|[nN]N|[nN][nN]N)");
+    const QString author_lc_t("(?:n%1n|n%1%1n|%1n|%1nn|%1%1n|%1%1%1n|n%1nn|nn%1n|%1%1nn|%1n%1n|nn|nnn)");
+    const QString author_uc_t("(?:[nN]%1N|[nN]%1%1N|%1N|%1[nN]N|%1%1N|%1%1%1N|[nN]%1[nN]N|[nN]N%1N|%1%1[nN]N|%1[nN]%1N|[nN]N|[nN][nN]N)");
     const QString author_initial("Ip{0,1}");
     const QString author_line("L%1(?:[,;&L]+%1)*(?=L)");
     const QString author_lc(author_line.arg(author_lc_t.arg(author_initial)));
diff --git a/src/c2b/heuristicBibParser.h b/src/c2b/heuristicBibParser.h
index 26a207f..2f82cd9 100644
--- a/src/c2b/heuristicBibParser.h
+++ b/src/c2b/heuristicBibParser.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef HEURISTICBIBPARSER_H
@@ -10,8 +10,6 @@
 #include "authorString.h"
 #include "bibReference.h"
 
-#include <QtDebug>
-
 
 class EQRegExp;
 class bibParser;
diff --git a/src/c2b/htm/tex2html.css b/src/c2b/htm/tex2html.css
index ff94727..7e4a3cd 100644
--- a/src/c2b/htm/tex2html.css
+++ b/src/c2b/htm/tex2html.css
@@ -81,8 +81,6 @@ text-decoration: underline;
 .index {
 background-color: #AEAEA3;
 border-color: #72726A;
-#background-color: #818B93;
-#border-color: black;
 border-style: solid;
 border-width: 1px;
 font-family: sans-serif;
diff --git a/src/c2b/idMaker.cpp b/src/c2b/idMaker.cpp
index 99e6cb2..f879849 100644
--- a/src/c2b/idMaker.cpp
+++ b/src/c2b/idMaker.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  *
  *   Improvements and modifications:
@@ -19,9 +19,6 @@ idMaker::idMaker(const QString& patternKey, QObject* parento) : QObject(parento)
     connect(settings::instance(), SIGNAL(newSettings()), this, SLOT(loadSettings()));
 }
 
-idMaker::~idMaker()
-{}
-
 
 /** \page id_placeholders Predefined cite and document ID placeholders
 
@@ -138,7 +135,7 @@ void idMaker::make_author_all_abbreviated(QString* id)
     QRegExp rx("([-'\\w]{1,3})(?:[-'\\w]*)(?:\\sand|$)");
     rx.setMinimal(true);
     rx.indexIn(_author);
-    int pos = 0;
+    int pos(0);
     while ((pos = rx.indexIn(_author, pos)) != -1)
     {
         temp_author += rx.cap(1);
@@ -176,14 +173,15 @@ void idMaker::make_ppages_first(QString* id)
 {
     _pages = c2bUtils::firstPage(_pages);
     if (!_pages.isEmpty())
-        _pages = 'p' + _pages;
+        if (_pages.at(0).isDigit())
+            _pages = 'p' + _pages;
     id->replace("<<ppages_first>>", _pages);
 }
 
 void idMaker::make_title(QString* id)
 {
     if (_title.contains(c2bUtils::nonAsciiLetter))
-        _title = c2bUtils::toAscii(_title, c2bUtils::KeepWords);
+        _title = c2bUtils::toAscii(_title, c2bUtils::FromBibTeX);
     _title = _title.left(_title_max_length).trimmed(); // Avoid possible trailing blank
     if (_is_title_underscored)
         _title.replace(' ', '_');
diff --git a/src/c2b/idMaker.h b/src/c2b/idMaker.h
index 2393923..dcecc09 100644
--- a/src/c2b/idMaker.h
+++ b/src/c2b/idMaker.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  *
  *   Improvements and modifications:
@@ -25,7 +25,7 @@ class idMaker : public QObject
 
 public:
     idMaker(const QString& patternKey, QObject* parento = 0);
-    ~idMaker();
+    inline ~idMaker() {}
 
     QString makeID(const bibReference& reference);
 
diff --git a/src/c2b/journalDB.cpp b/src/c2b/journalDB.cpp
index 1b043ff..e8a3906 100644
--- a/src/c2b/journalDB.cpp
+++ b/src/c2b/journalDB.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "journalDB.h"
@@ -17,14 +17,14 @@ journalDB::journalDB(const QString& dbfile)
 {
     if (dbfile.isEmpty())
     {
-        qDebug(QObject::tr("[cb2Bib] No journal file especified.").toLatin1());
+        c2bUtils::warn(QObject::tr("No journal file especified"));
         return;
     }
     _nitems = 0;
     QFile file(dbfile);
     if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
     {
-        qDebug(QObject::tr("[cb2Bib] Could not open journal file %1 for reading.").arg(dbfile).toLatin1());
+        c2bUtils::warn(QObject::tr("Could not open journal file %1 for reading").arg(dbfile));
         return;
     }
     QTextStream stream(&file);
@@ -41,7 +41,7 @@ journalDB::journalDB(const QString& dbfile)
             const QStringList spLine(line.split('|'));
             if (spLine.count() != 3)
             {
-                qDebug(QObject::tr("[cb2Bib] Syntax error in journal file at line %1.").arg(line_number).toLatin1());
+                c2bUtils::warn(QObject::tr("Syntax error in journal file at line %1").arg(line_number));
                 continue;
             }
             _nitems++;
@@ -49,7 +49,8 @@ journalDB::journalDB(const QString& dbfile)
             JAbbrev += spLine.at(1);
             QString dum(spLine.at(1).toLower());
             dum.replace(c2bUtils::nonLetter, " "); // Keeps word structure
-            JAbbrev_simp_w += dum.simplified();
+            c2bUtils::simplifyString(dum);
+            JAbbrev_simp_w += dum;
             dum.remove(' '); // Removes whitespaces also
             JAbbrev_simp += dum;
             JExtended += spLine.at(2);
@@ -61,9 +62,6 @@ journalDB::journalDB(const QString& dbfile)
     file.close();
 }
 
-journalDB::~journalDB()
-{}
-
 
 /** \page journalproc Processing of journal names
 
diff --git a/src/c2b/journalDB.h b/src/c2b/journalDB.h
index a3664e1..ea9f6e8 100644
--- a/src/c2b/journalDB.h
+++ b/src/c2b/journalDB.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef JOURNALDB_H
@@ -21,7 +21,7 @@ class journalDB
 
 public:
     journalDB(const QString& dbfile);
-    ~journalDB();
+    inline ~journalDB() {}
 
     QString retrieve(const QString& JQuery) const;
     QString retrieveFull(const QString& JQuery) const;
diff --git a/src/c2b/metadataParser.cpp b/src/c2b/metadataParser.cpp
index 6180167..f12d75d 100644
--- a/src/c2b/metadataParser.cpp
+++ b/src/c2b/metadataParser.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "metadataParser.h"
@@ -9,6 +9,7 @@
 #include "coreBibParser.h"
 #include "settings.h"
 
+#include <QDate>
 #include <QProcess>
 #include <QXmlStreamReader>
 
@@ -113,19 +114,16 @@ metadataParser::metadataParser(coreBibParser* cbp, QObject* parento) : QObject(p
     init();
 }
 
-metadataParser::~metadataParser()
-{}
-
 
 void metadataParser::init()
 {
     _settingsP = settings::instance();
     // Set bibliographic fields
     // Remove fields file (it is itself) and pages (usually number of pages) from list
-    _fields = QRegExp("\\b(?:abstract|address|annote|author|booktitle|chapter|"
+    _fields = QRegExp("\\b(?:abstract|address|annote|author|authors|booktitle|chapter|"
                       "doi|edition|editor|eprint|institution|isbn|issn|journal|"
                       "keyword|keywords|key words|month|note|number|organization|"
-                      "pages|publisher|school|series|title|url|volume|year)\\b");
+                      "pagerange|publicationname|publisher|school|series|title|url|volume|year)\\b");
     _fields.setCaseSensitivity(Qt::CaseInsensitive);
     // Recognition from BibTeX entries
     _bibtex_fields = QRegExp("\\bbibtex:(?:abstract|address|annote|author|booktitle|chapter|"
@@ -133,6 +131,15 @@ void metadataParser::init()
                              "keywords|month|note|number|organization|pages|publisher|"
                              "school|series|title|url|volume|year)\\b");
     _bibtex_fields.setCaseSensitivity(Qt::CaseInsensitive);
+    // Set field keys equivalences
+    const QStringList& bibliographicFields = _cbpP->bibliographicFields();
+    for (int i = 0; i < bibliographicFields.count(); ++i)
+        _bibtex_key.insert(bibliographicFields.at(i), bibliographicFields.at(i));
+    _bibtex_key.insert("authors", "author");
+    _bibtex_key.insert("key words", "keywords");
+    _bibtex_key.insert("keyword", "keywords");
+    _bibtex_key.insert("pagerange", "pages");
+    _bibtex_key.insert("publicationname", "journal");
 }
 
 const QString metadataParser::metadata(const QString& fn)
@@ -184,6 +191,7 @@ bool metadataParser::_metadata(const QString& fn)
     _ref.typeName = "article";
     _has_bibtex = false;
     _has_cb2bib = false;
+    _has_prism = false;
 
     QStringList xmls;
     _metadataXmp(fn, raw_contents, &xmls);
@@ -224,6 +232,7 @@ void metadataParser::_metadataXmp(const QString& fn, const QByteArray& raw_conte
                 xmls->append(c2bUtils::toQtXmlString(QString::fromUtf8(raw_contents.mid(pos, posn - pos + 19))));
                 _has_bibtex = _has_bibtex || xmls->last().contains("bibtex:");
                 _has_cb2bib = _has_cb2bib || xmls->last().contains("http://www.molspaces.com/cb2bib");
+                _has_prism = _has_prism || xmls->last().contains("http://prismstandard.org/namespaces/basic/2.0");
                 pos = posn;
             }
             else
@@ -236,10 +245,11 @@ void metadataParser::_metadataXmp(const QString& fn, const QByteArray& raw_conte
 
 void metadataParser::_miscellaneousData(const QString& fn, const QByteArray& raw_contents)
 {
-    // Get title and author from here whenever no cb2Bib BibTeX data is available
+    // Get title, author, and keywords from here whenever no cb2Bib BibTeX data is available
     QString data;
     QRegExp pdf_author_rx;
     QRegExp pdf_title_rx;
+    QRegExp pdf_keywords_rx;
     const QString exiftool_bin(_settingsP->fileName("cb2Bib/ExifToolBin"));
     bool is_exiftool_available = !exiftool_bin.isEmpty();
     if (is_exiftool_available)
@@ -255,6 +265,7 @@ void metadataParser::_miscellaneousData(const QString& fn, const QByteArray& raw
         {
             pdf_author_rx.setPattern("Author\\s*:\\s+(.*)\\n");
             pdf_title_rx.setPattern("Title\\s*:\\s+(.*)\\n");
+            pdf_keywords_rx.setPattern("Subject\\s*:\\s+(.*)\\n");
         }
         else
             is_exiftool_available = false;
@@ -273,6 +284,17 @@ void metadataParser::_miscellaneousData(const QString& fn, const QByteArray& raw
     if (pdf_author_rx.indexIn(data) > -1)
         if (!pdf_author_rx.cap(1).trimmed().isEmpty())
             _ref["author"] = pdf_author_rx.cap(1);
+
+    // Dublin Core Metadata keywords if exiftool is available
+    if (_has_prism && is_exiftool_available)
+    {
+        pdf_keywords_rx.setMinimal(true);
+        pdf_keywords_rx.setCaseSensitivity(Qt::CaseSensitive);
+        if (pdf_keywords_rx.indexIn(data) > -1)
+            if (!pdf_keywords_rx.cap(1).trimmed().isEmpty())
+                _ref["keywords"] = pdf_keywords_rx.cap(1);
+    }
+
     // Done if BibTeX, otherwise try checking dictionary for title
     if (_has_bibtex)
         return;
@@ -321,6 +343,7 @@ void metadataParser::_metadataXmpExifTool(const QString& fn, QStringList* xmls)
         xmls->append(xmp);
         _has_bibtex = _has_bibtex || xmls->last().contains("bibtex:");
         _has_cb2bib = _has_cb2bib || xmls->last().contains("http://www.molspaces.com/cb2bib");
+        _has_prism = _has_prism || xmls->last().contains("http://prismstandard.org/namespaces/basic/2.0");
     }
 }
 
@@ -353,13 +376,11 @@ void metadataParser::_fuzzyParser(const QString& data)
                 if (value.isEmpty())
                     continue;
                 if (field.contains(*fields))
-                    _ref[key] = value;
-                else if (QString::compare(field, "authors", Qt::CaseInsensitive) == 0)
-                    _ref["author"] = value;
+                    _ref[_bibtex_key.value(key)] = value;
                 else if (QString::compare(field, "summary", Qt::CaseInsensitive) == 0 ||
                          QString::compare(field, "subject", Qt::CaseInsensitive) == 0)
                 {
-                    if (!_ref.contains(field))  // Prefer BibTeX field name than synonyms
+                    if (!_ref.contains("abstract")) // Prefer BibTeX field key if exists than synonyms
                         _ref["abstract"] = value;
                 }
                 else if (QString::compare(field, "bibtex:type", Qt::CaseInsensitive) == 0 ||
@@ -375,21 +396,27 @@ void metadataParser::_fuzzyParser(const QString& data)
                 parser.readNext();
                 value = parser.text().toString().trimmed();
                 if (!value.isEmpty())
-                    _ref[key] = value;
+                    _ref[_bibtex_key.value(key)] = value;
             }
-            else if (QString::compare(field, "authors", Qt::CaseInsensitive) == 0)
+            else if (!_has_bibtex && QString::compare(field, "prism:coverDate", Qt::CaseSensitive) == 0)
             {
                 parser.readNext();
                 value = parser.text().toString().trimmed();
-                if (!value.isEmpty())
-                    _ref["author"] = value;
+                const QDate pdate(QDate::fromString(value, Qt::ISODate));
+                const QString pyear(pdate.toString("yyyy"));
+                // Prefer BibTeX date over Prism
+                if (!pyear.isEmpty() && !_ref.contains("year"))
+                    _ref["year"] = pyear;
+                const QString pmonth(pdate.toString("d MMMM"));
+                if (!pmonth.isEmpty() && !_ref.contains("month"))
+                    _ref["month"] = pmonth;
             }
             else if (QString::compare(field, "summary", Qt::CaseInsensitive) == 0 ||
                      QString::compare(field, "subject", Qt::CaseInsensitive) == 0)
             {
                 parser.readNext();
                 value = parser.text().toString().trimmed();
-                if (!value.isEmpty() && !_ref.contains(field))  // Prefer BibTeX field name than synonyms
+                if (!value.isEmpty() && !_ref.contains("abstract")) // Prefer BibTeX field key if exists than synonyms
                     _ref["abstract"] = value;
             }
             else if (QString::compare(field, "bibtex:type", Qt::CaseInsensitive) == 0 ||
diff --git a/src/c2b/metadataParser.h b/src/c2b/metadataParser.h
index 26716c6..d5048fd 100644
--- a/src/c2b/metadataParser.h
+++ b/src/c2b/metadataParser.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef METADATAPARSER_H
@@ -23,7 +23,7 @@ class metadataParser : public QObject
 public:
     metadataParser(QObject* parento = 0);
     metadataParser(coreBibParser* bp, QObject* parento = 0);
-    ~metadataParser();
+    inline ~metadataParser() {}
 
     bool insertMetadata(const bibReference& ref, const QString& fn, QString* error = 0) const;
     bool metadata(const QString& fn, bibReference* ref);
@@ -35,11 +35,13 @@ signals:
 
 
 private:
+    QHash<QString, QString> _bibtex_key;
     QRegExp _bibtex_fields;
     QRegExp _fields;
     bibReference _ref;
     bool _has_bibtex;
     bool _has_cb2bib;
+    bool _has_prism;
     bool _metadata(const QString& fn);
     const QString _pdfDictionary(const QByteArray& rawpdf);
     coreBibParser* _cbpP;
diff --git a/src/c2b/monthDB.cpp b/src/c2b/monthDB.cpp
index cd18269..5706b14 100644
--- a/src/c2b/monthDB.cpp
+++ b/src/c2b/monthDB.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "monthDB.h"
@@ -16,9 +16,6 @@ monthDB::monthDB() :
         _month_full(QString("January|February|March|April|May|June|July|August|September|October|November|December").split('|'))
 {}
 
-monthDB::~monthDB()
-{}
-
 
 QString monthDB::retrieve(const QString& month_query)
 {
diff --git a/src/c2b/monthDB.h b/src/c2b/monthDB.h
index 6359bd3..8d44dd2 100644
--- a/src/c2b/monthDB.h
+++ b/src/c2b/monthDB.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef MONTHDB_H
@@ -21,7 +21,7 @@ class monthDB
 
 public:
     monthDB();
-    ~monthDB();
+    inline ~monthDB() {}
 
     QString retrieve(const QString& month_query);
 
diff --git a/src/c2b/network.cpp b/src/c2b/network.cpp
index a3e32af..6343b66 100644
--- a/src/c2b/network.cpp
+++ b/src/c2b/network.cpp
@@ -1,11 +1,12 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "network.h"
 
+#include "cb2bib_utilities.h"
 #include "settings.h"
 
 #include <QNetworkCookie>
@@ -28,9 +29,6 @@ network::network(QObject* parento) : QObject(parento)
     ncj->setCookiesFromUrl(QList<QNetworkCookie>() << nc, QUrl("http://scholar.google.com"));
 }
 
-network::~network()
-{}
-
 
 /****************************************************************************
 
@@ -43,7 +41,7 @@ void network::getFile(const QString& orig, const QString& dest, const QString& a
 {
     if (_is_fetching)
     {
-        qDebug("[cb2bib] network::getFile: File requested while still fetching previous one. Returned.");
+        c2bUtils::warn(tr("network::getFile: File requested while still fetching previous one. Returned"));
         return;
     }
 
@@ -328,5 +326,5 @@ void network::fetcherReadyRead()
 
 void network::logError()
 {
-    qDebug(tr("[cb2bib] network::QNetworkReply Log: %1.").arg(_current_reply->errorString()).toUtf8());
+    c2bUtils::warn(tr("network::QNetworkReply Log: %1").arg(_current_reply->errorString()));
 }
diff --git a/src/c2b/network.h b/src/c2b/network.h
index 759ca8d..68cdf2f 100644
--- a/src/c2b/network.h
+++ b/src/c2b/network.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef NETWORK_H
@@ -26,7 +26,7 @@ class network : public QObject
 
 public:
     network(QObject* parento = 0);
-    ~network();
+    inline ~network() {}
 
     void getFile(const QString& orig, const QString& dest, const QString& action = "copy", QObject* receiver = 0,
                  const char* callback = 0, const bool overwrite = false);
diff --git a/src/c2b/networkQuery.cpp b/src/c2b/networkQuery.cpp
index cee8b6b..073717c 100644
--- a/src/c2b/networkQuery.cpp
+++ b/src/c2b/networkQuery.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "networkQuery.h"
@@ -28,9 +28,6 @@ networkQuery::networkQuery(bibParser* bp, network* net, QObject* parento) : QObj
     init();
 }
 
-networkQuery::~networkQuery()
-{}
-
 
 void networkQuery::init()
 {
@@ -56,11 +53,11 @@ void networkQuery::submitQuery(const bibReference& reference, const QString& raw
     if (!_Qdoi.isEmpty() && !_Qdoi.contains(QRegExp("^10.[\\d\\.]+/\\S+$")))
     {
         _Qdoi.clear();
-        qDebug(qPrintable(tr("[cb2bib] Warning: DOI skipped: '%1' is not a valid DOI.").arg(_Qdoi)));
+        c2bUtils::warn(tr("Warning: DOI skipped: '%1' is not a valid DOI").arg(_Qdoi));
     }
     _Qauthor = reference.value("author");
     _Qauthor.replace(QRegExp("(?:\\b\\w\\b|\\band\\b|\\W)"), " ");
-    _Qauthor = _Qauthor.simplified();
+    _Qauthor = c2bUtils::simplifyString(_Qauthor);
     _Qexcerpt = _bpP->excerpt(raw_reference, QStringList() << _Qdoi << _Qauthor << _Qtitle);
 
     submitQuery1();
@@ -135,7 +132,7 @@ void networkQuery::submitQuery2(bool stat)
     QRegExp rx(_captionQ);
     rx.setMinimal(true);
     if (!rx.isValid())
-        qDebug(qPrintable(tr("[cb2bib] Warning: RegExp '%1' is not valid.").arg(_captionQ)));
+        c2bUtils::warn(tr("Warning: RegExp '%1' is not valid").arg(_captionQ));
     const int ncap(rx.indexIn(lines));
     if (ncap > -1)
         lines = fromHtmlString(rx.cap(1));
@@ -367,13 +364,13 @@ bool networkQuery::checkQueryFile(const QString& fn) const
 {
     if (fn.isEmpty())
     {
-        qDebug(QObject::tr("[cb2Bib] No network query file especified.").toLatin1());
+        c2bUtils::warn(tr("No network query file especified"));
         return false;
     }
     QFileInfo fi(fn);
     if (!fi.exists() || !fi.isReadable())
     {
-        qDebug(QObject::tr("[cb2Bib] Could not open network query file %1 for reading.").arg(fn).toLatin1());
+        c2bUtils::warn(tr("Could not open network query file %1 for reading").arg(fn));
         return false;
     }
     return true;
diff --git a/src/c2b/networkQuery.h b/src/c2b/networkQuery.h
index b305820..17142c3 100644
--- a/src/c2b/networkQuery.h
+++ b/src/c2b/networkQuery.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef NETWORKQUERY_H
@@ -29,7 +29,7 @@ class networkQuery : public QObject
 public:
     networkQuery(bibParser* bp, QObject* parento = 0);
     networkQuery(bibParser* bp, network* net, QObject* parento = 0);
-    virtual ~networkQuery();
+    inline virtual ~networkQuery() {}
 
     void submitQuery(const bibReference& reference, const QString& raw_reference = QString());
     inline QString errorString() const
diff --git a/src/c2b/preprocess.cpp b/src/c2b/preprocess.cpp
index e47445b..e94b9eb 100644
--- a/src/c2b/preprocess.cpp
+++ b/src/c2b/preprocess.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "preprocess.h"
@@ -14,9 +14,6 @@ preprocess::preprocess(QObject* parento) : QObject(parento)
     connect(settings::instance(), SIGNAL(newSettings()), this, SLOT(loadSettings()));
 }
 
-preprocess::~preprocess()
-{}
-
 
 void preprocess::loadSettings()
 {
diff --git a/src/c2b/preprocess.h b/src/c2b/preprocess.h
index eea9dc3..8cc4a84 100644
--- a/src/c2b/preprocess.h
+++ b/src/c2b/preprocess.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef PREPROCESS_H
@@ -21,7 +21,7 @@ class preprocess : public QObject
 
 public:
     preprocess(QObject* parento = 0);
-    ~preprocess();
+    inline ~preprocess() {}
 
 
 public:
diff --git a/src/c2b/pubmedXml.cpp b/src/c2b/pubmedXml.cpp
index 2410d05..399c1e4 100644
--- a/src/c2b/pubmedXml.cpp
+++ b/src/c2b/pubmedXml.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "pubmedXml.h"
@@ -22,9 +22,6 @@ pubmedXml::pubmedXml(const QString& xml) : QXmlStreamReader()
     }
 }
 
-pubmedXml::~pubmedXml()
-{}
-
 
 void pubmedXml::readReference()
 {
@@ -80,7 +77,12 @@ void pubmedXml::readAuthors()
             else if (name() == "Suffix")
             {
                 readNext();
-                a = a + ' ' + text().toString();
+                if (text() == "2nd")
+                    a = a + " II";
+                else if (text() == "3rd")
+                    a = a + " III";
+                else
+                    a = a + ' ' + text().toString();
             }
         authors.append(a);
     }
diff --git a/src/c2b/pubmedXml.h b/src/c2b/pubmedXml.h
index 60df993..706f7e2 100644
--- a/src/c2b/pubmedXml.h
+++ b/src/c2b/pubmedXml.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef PUBMEDXML_H
@@ -17,7 +17,7 @@ class pubmedXml : public QXmlStreamReader
 
 public:
     pubmedXml(const QString& xml);
-    ~pubmedXml();
+    inline ~pubmedXml() {}
 
     inline bibReference reference() const
     {
diff --git a/src/c2b/qtregexp/eqregexp.cpp b/src/c2b/qtregexp/eqregexp.cpp
index 3487bdb..6cc2c2b 100644
--- a/src/c2b/qtregexp/eqregexp.cpp
+++ b/src/c2b/qtregexp/eqregexp.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Modified QRegExp
  *   constans at molspaces.com, 2009
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *
  ***************************************************************************
 ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
diff --git a/src/c2b/qtregexp/eqregexp.h b/src/c2b/qtregexp/eqregexp.h
index 51310f3..93be26d 100644
--- a/src/c2b/qtregexp/eqregexp.h
+++ b/src/c2b/qtregexp/eqregexp.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Modified QRegExp
  *   constans at molspaces.com, 2009
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *
  ***************************************************************************
 ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
diff --git a/src/c2b/searchPattern.cpp b/src/c2b/searchPattern.cpp
new file mode 100644
index 0000000..27a27bb
--- /dev/null
+++ b/src/c2b/searchPattern.cpp
@@ -0,0 +1,213 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#include "searchPattern.h"
+
+#include "triads.h"
+
+#include <QMap>
+
+
+/**
+    Top level driver for calling cb2Bib search types
+*/
+searchPattern::searchPattern(const QString& pattern, const QString& patternType) :
+        _matcher(pattern.simplified(), typemap().value(patternType), Qt::CaseInsensitive)
+{
+    _modifier.NOT = false;
+    _modifier.string = pattern.simplified();
+    _rank = 0;
+}
+
+searchPattern::searchPattern(const bool NOT, const bool caseSensitive, const QString& patternType,
+                             const QString& scope, const QChar& yearScope, const QString& pattern) :
+        _matcher(pattern.simplified(), typemap().value(patternType), qtcase(caseSensitive))
+{
+    _modifier.NOT = NOT;
+    _modifier.string = pattern.simplified();
+    _modifier.scope = scope;
+    _modifier.yearScope = yearScope;
+
+    if (_modifier.NOT)
+        _formatted_string += "NOT.";
+    _formatted_string += QString(" [%1][%2|case=%3]").arg(_modifier.string).arg(patternType).arg(caseSensitive);
+    if (_modifier.scope == "year")
+        _formatted_string += QString(" IN [%1(%2)]").arg(_modifier.scope).arg(_modifier.yearScope);
+    else
+        _formatted_string += QString(" IN [%1]").arg(_modifier.scope);
+
+    // Set an approximate ranking to speed up composite searches
+    _rank = 0;
+    if (_modifier.scope == "file")
+        _rank += 200;
+    else if (_modifier.scope == "all")
+        _rank += 100;
+    else if (_modifier.scope == "year" || _modifier.scope == "volume" || _modifier.scope == "pages")
+        _rank += 50;
+    else
+        _rank += 1;
+    if (!caseSensitive)
+        _rank *= 2;
+    if (_matcher.type == FixedStringAllWords || _matcher.type == FixedStringAnyWord)
+        _rank *= 5;
+    else if (_matcher.type == ApproximateString)
+        _rank *= 10;
+}
+
+const QStringList searchPattern::types()
+{
+    return typemap().keys();
+}
+
+const QString searchPattern::type(const Type t)
+{
+    return typemap().key(t);
+}
+
+const QMap<QString, searchPattern::Type> searchPattern::typemap()
+{
+    QMap<QString, Type> tm;
+    tm.insert(QObject::tr("Approximate string"), ApproximateString);
+    tm.insert(QObject::tr("Fixed string: All Words"), FixedStringAllWords);
+    tm.insert(QObject::tr("Fixed string: Any Word"), FixedStringAnyWord);
+    tm.insert(QObject::tr("Fixed string: Context"), FixedStringContext);
+    tm.insert(QObject::tr("Fixed string"), FixedString);
+    tm.insert(QObject::tr("Regular expression"), RegularExpression);
+    tm.insert(QObject::tr("Wildcard"), Wildcard);
+    return tm;
+}
+
+
+searchPattern::matcher::matcher(const QString& pattern, const Type t, const Qt::CaseSensitivity cs) : type(t), length(-1)
+{
+    switch (type)
+    {
+    default:
+        c2bUtils::warn(QObject::tr("Internal Error: Invalid search pattern type. Set to 'Approximate string'"));
+    case ApproximateString:
+    {
+        appexp.setPattern(pattern, cs);
+        if (appexp.isMultipattern()) // Skip regular expression cases
+        {
+            signature = triads::textSignature(pattern);
+            subsignatures = triads::textSignature(appexp.substrings());
+        }
+    }
+    break;
+    case FixedStringAnyWord:
+    {
+        wordexp.setPattern(pattern, wordPattern::AnyWord, cs);
+        signature = triads::textSignature(pattern);
+        subsignatures = triads::textSignature(wordexp.substrings());
+    }
+    break;
+    case FixedStringAllWords:
+    {
+        wordexp.setPattern(pattern, wordPattern::AllWords, cs);
+        signature = triads::textSignature(pattern);
+        subsignatures.fill(signature, wordexp.subpatternCount());
+    }
+    break;
+    case FixedStringContext:
+    {
+        cwordexp.setPattern(pattern, cs);
+        signature = triads::textSignature(pattern);
+    }
+    break;
+    case FixedString:
+    {
+        strexp.setPattern(pattern);
+        strexp.setCaseSensitivity(cs);
+        signature = triads::textSignature(pattern);
+    }
+    break;
+    case RegularExpression:
+    {
+        regexp.setPattern(pattern);
+        regexp.setCaseSensitivity(cs);
+        regexp.setPatternSyntax(QRegExp::RegExp2);
+        regexp.setMinimal(true);
+    }
+    break;
+    case Wildcard:
+    {
+        regexp.setPattern(pattern);
+        regexp.setCaseSensitivity(cs);
+        regexp.setPatternSyntax(QRegExp::Wildcard);
+        regexp.setMinimal(true);
+        signature = triads::textSignature(pattern);
+    }
+    break;
+    }
+}
+
+bool searchPattern::matcher::match(const QString& contents) const
+{
+    length = -1;
+    switch (type)
+    {
+    case ApproximateString:
+        return appexp.matches(contents);
+    case FixedStringAnyWord:
+    case FixedStringAllWords:
+        return wordexp.matches(contents);
+    case FixedStringContext:
+        return cwordexp.indexIn(contents) != -1;
+    case FixedString:
+        return strexp.indexIn(contents) != -1;
+    default:
+        return regexp.indexIn(contents) != -1;
+    }
+}
+
+bool searchPattern::matcher::match(const documentContents& contents) const
+{
+    length = -1;
+    switch (type)
+    {
+    case ApproximateString:
+        return _match_any(appexp.subpatternCount(), appexp.submatchers(), contents);
+    case FixedStringAnyWord:
+        return _match_any(wordexp.subpatternCount(), wordexp.submatchers(), contents);
+    case FixedStringAllWords:
+        return _match_all(wordexp.subpatternCount(), wordexp.submatchers(), contents);
+    case FixedStringContext:
+        return _match(cwordexp, signature, contents);
+    case FixedString:
+        return _match(strexp, signature, contents);
+    default:
+        return _match(regexp, signature, contents);
+    }
+}
+
+int searchPattern::matcher::index(const QString& contents, const int from) const
+{
+    int i;
+    switch (type)
+    {
+    case ApproximateString:
+        i = appexp.indexIn(contents, from);
+        length = appexp.matchedLength();
+        return i;
+    case FixedStringAnyWord:
+    case FixedStringAllWords:
+        i = wordexp.indexIn(contents, from);
+        length = wordexp.matchedLength();
+        return i;
+    case FixedStringContext:
+        i = cwordexp.indexIn(contents, from);
+        length = cwordexp.matchedLength();
+        return i;
+    case FixedString:
+        i = strexp.indexIn(contents, from);
+        length = strexp.pattern().length();
+        return i;
+    default:
+        i = regexp.indexIn(contents, from);
+        length = regexp.matchedLength();
+        return i;
+    }
+}
diff --git a/src/c2b/searchPattern.h b/src/c2b/searchPattern.h
new file mode 100644
index 0000000..e37a96c
--- /dev/null
+++ b/src/c2b/searchPattern.h
@@ -0,0 +1,153 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#ifndef SEARCHPATTERN_H
+#define SEARCHPATTERN_H
+
+#include "approximatePattern.h"
+#include "documentContents.h"
+#include "wordMatcher.h"
+#include "wordPattern.h"
+
+#include <QRegExp>
+#include <QList>
+
+
+class searchPattern
+{
+
+public:
+    searchPattern(const QString& pattern, const QString& patternType);
+    searchPattern(const bool NOT, const bool caseSensitive, const QString& patternType,
+                  const QString& scope, const QChar& yearScope, const QString& pattern);
+    inline ~searchPattern() {}
+
+    enum Type {ApproximateString = 1,
+               FixedStringAllWords = 2,
+               FixedStringAnyWord = 3,
+               FixedStringContext = 4,
+               FixedString = 5,
+               RegularExpression = 6,
+               Wildcard = 7
+              };
+    static const QString type(const Type t);
+    static const QStringList types();
+
+    struct modifiers
+    {
+        QChar yearScope;
+        QString scope;
+        QString string;
+        bool NOT;
+    };
+
+    inline const modifiers& modifier() const
+    {
+        return _modifier;
+    }
+    inline bool matches(const QString& contents) const
+    {
+        return _matcher.match(contents);
+    }
+    inline bool matches(const documentContents& contents) const
+    {
+        return _matcher.match(contents);
+    }
+    inline int indexIn(const QString& contents, const int from) const
+    {
+        return _matcher.index(contents, from);
+    }
+    inline int indexIn(const documentContents& contents, const int from) const
+    {
+        return _matcher.index(contents.text(), from);
+    }
+    inline int matchedLength() const
+    {
+        return _matcher.length;
+    }
+    inline const QString toString() const
+    {
+        return _formatted_string;
+    }
+    inline bool operator< (const searchPattern& p) const
+    {
+        return (_rank < p._rank);
+    }
+
+
+private:
+    struct matcher
+    {
+        matcher(const QString& pattern, const Type t, const Qt::CaseSensitivity cs);
+
+        QRegExp regexp;
+        QString signature;
+        QStringMatcher strexp;
+        QVector<QString> subsignatures;
+        Type type;
+        approximatePattern appexp;
+        mutable int length;
+        wordMatcher cwordexp;
+        wordPattern wordexp;
+
+        bool match(const QString& contents) const;
+        bool match(const documentContents& contents) const;
+        int index(const QString& contents, const int from) const;
+
+        inline bool _match_signature(const QString& ps, const QString& cs) const
+        {
+            const int pl(ps.length()); // Always pl > 0
+            const int cl(cs.length());
+            const ushort* ups = (const ushort*) ps.unicode();
+            const ushort* p = ups;
+            const ushort* pn = ups + pl;
+            const ushort* ucs = (const ushort*) cs.unicode();
+            const ushort* c = ucs - 1;
+            const ushort* cn = ucs + cl;
+            while (++c != cn)
+                if (*c == *p)
+                    if (++p == pn)
+                        return true;
+            return false;
+        }
+        template <typename T> inline bool _match(const T& submatcher, const QString& psignature, const documentContents& contents) const
+        {
+            // Skip signature check for patterns that do not define it
+            if (psignature.length() == 0 || _match_signature(psignature, contents.signature()))
+                return submatcher.indexIn(contents.text()) != -1;
+            else
+                return false;
+        }
+        template <typename T> inline bool _match_all(const int n, const T& submatchers, const documentContents& contents) const
+        {
+            for (int i = n - 1; i >= 0; --i)
+                if (!_match(submatchers.at(i), subsignatures.at(i), contents))
+                    return false;
+            return true;
+        }
+        template <typename T> inline bool _match_any(const int n, const T& submatchers, const documentContents& contents) const
+        {
+            for (int i = 0; i < n; ++i)
+                if (_match(submatchers.at(i), subsignatures.at(i), contents))
+                    return true;
+            return false;
+        }
+    };
+
+    QString _formatted_string;
+    int _rank;
+    matcher _matcher;
+    modifiers _modifier;
+
+    static const QMap<QString, searchPattern::Type> typemap();
+    inline static Qt::CaseSensitivity qtcase(bool caseSensitive)
+    {
+        return caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+    }
+
+};
+
+#endif
diff --git a/src/c2b/settings.cpp b/src/c2b/settings.cpp
index fc59571..8e2a5d2 100644
--- a/src/c2b/settings.cpp
+++ b/src/c2b/settings.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "settings.h"
@@ -50,6 +50,7 @@ void settings::init(bool command_line)
     cl_doc2bib = false;
     cl_html_annote = false;
     cl_import = false;
+    cl_sloppy = false;
     cl_txt2bib = false;
     cl_user_configured = false;
     cl_view_annote = false;
@@ -179,8 +180,8 @@ void settings::setDefaults()
     defaults["cb2Bib/UseFullNames"] = false;
 
     // Pdf2Text arguments
-    defaults["c2bBibSearcher/Pdf2TextArg"] = "-raw";
-    defaults["c2bPdfImport/Pdf2TextArg"] = "-f 1 -l 1";
+    defaults["c2bBibSearcher/Pdf2TextArg"] = "-raw -enc UTF-8";
+    defaults["c2bPdfImport/Pdf2TextArg"] = "-f 1 -l 1 -enc UTF-8";
 
     // Construct current settings
     const QStringList keys(defaults.keys());
@@ -202,9 +203,6 @@ settings* settings::_c2b_global_settings = 0;
  Usage: cb2bib
         cb2bib [action] [filename1 [filename2 ... ]] [--conf [filename.conf]]
 
- Switch:
-        --conf [filename.conf]                             Use configuration file
-
  Actions:
         --configure [filename.conf]                        Edit configuration
 
@@ -219,6 +217,10 @@ settings* settings::_c2b_global_settings = 0;
         --view-annote filename.tex                         Convert and visualize annote file
         --view-annote filename.tex.html                    Visualize annote file
 
+ Switches:
+        --conf [filename.conf]                             Use configuration file
+        --sloppy                                           Accept guesses in automatic reference extraction
+
  Examples:
         cb2bib                                             Start cb2Bib extraction panel
         cb2bib --import tmp_reference_filename             Import reference
@@ -247,6 +249,9 @@ settings* settings::_c2b_global_settings = 0;
  - <b>Note:</b> On Windows use <tt>c2bconsole</tt> instead of <tt>cb2bib</tt>.
  See \ref relnotes130.
 
+ - <b>Note:</b> If using reference extraction command, see \ref
+ faq_automatic_extraction.
+
 */
 
 bool settings::isConsoleMode(int& argc, char** argv)
@@ -309,15 +314,15 @@ const QString settings::configuredFilename()
     QFileInfo fi(filename);
     if (fi.isDir())
     {
-        fprintf(stdout, QObject::tr("[cb2Bib] Error: Could not open %1 configuration file for reading/writing.").arg(filename).toLatin1());
-        fprintf(stdout, QObject::tr("[cb2Bib] Error: Filename is a directory.").toLatin1());
+        c2bUtils::warn(QObject::tr("Error: Could not open %1 configuration file for reading/writing").arg(filename));
+        c2bUtils::warn(QObject::tr("Error: Filename is a directory"));
         exit(1);
     }
     QFile file(filename);
     if (!file.open(QIODevice::ReadWrite | QIODevice::Text))
     {
-        fprintf(stdout, QObject::tr("[cb2Bib] Error: Could not open %1 configuration file for reading/writing.").arg(filename).toLatin1());
-        fprintf(stdout, QObject::tr("[cb2Bib] Error: %1.").arg(file.errorString()).toLatin1());
+        c2bUtils::warn(QObject::tr("Error: Could not open %1 configuration file for reading/writing").arg(filename));
+        c2bUtils::warn(QObject::tr("Error: %1.").arg(file.errorString()));
         exit(1);
     }
     return filename;
@@ -331,11 +336,18 @@ void settings::readCommandLine()
     for (int i = 1; i < arguments.count(); ++i)
         if (arguments.at(i).startsWith('-'))
         {
+            // switches
             if (arguments.at(i) == "--conf")
             {
                 checkCommand(&cl_user_configured, &actions);
                 --actions;
             }
+            else if (arguments.at(i) == "--sloppy")
+            {
+                checkCommand(&cl_sloppy, &actions);
+                --actions;
+            }
+            // actions
             else if (arguments.at(i) == "--configure")
                 checkCommand(&cl_configure, &actions);
             else if (arguments.at(i) == "--bibedit")
@@ -361,6 +373,8 @@ void settings::readCommandLine()
         _is_loaded = false;
     if (cl_user_configured && cl_configure)
         _is_loaded = false;
+    if (cl_sloppy && !(cl_doc2bib || cl_txt2bib))
+        _is_loaded = false;
     if (!_is_loaded)
     {
         printUsage();
@@ -485,9 +499,6 @@ void settings::printUsage()
     fprintf(stdout, "Usage: cb2bib\n");
     fprintf(stdout, "       cb2bib [action] [filename1 [filename2 ... ]] [--conf [filename.conf]]\n");
     fprintf(stdout, "\n");
-    fprintf(stdout, "Switch:\n");
-    fprintf(stdout, "       --conf [filename.conf]                             Use configuration file\n");
-    fprintf(stdout, "\n");
     fprintf(stdout, "Actions:\n");
     fprintf(stdout, "       --configure [filename.conf]                        Edit configuration\n");
     fprintf(stdout, "\n");
@@ -502,6 +513,10 @@ void settings::printUsage()
     fprintf(stdout, "       --view-annote filename.tex                         Convert and visualize annote file\n");
     fprintf(stdout, "       --view-annote filename.tex.html                    Visualize annote file\n");
     fprintf(stdout, "\n");
+    fprintf(stdout, "Switches:\n");
+    fprintf(stdout, "       --conf [filename.conf]                             Use configuration file\n");
+    fprintf(stdout, "       --sloppy                                           Accept guesses in automatic reference extraction\n");
+    fprintf(stdout, "\n");
     fprintf(stdout, "Examples:\n");
     fprintf(stdout, "       cb2bib                                             Start cb2Bib extraction panel\n");
     fprintf(stdout, "       cb2bib --import tmp_reference_filename             Import reference\n");
diff --git a/src/c2b/settings.h b/src/c2b/settings.h
index 71686d0..8897edb 100644
--- a/src/c2b/settings.h
+++ b/src/c2b/settings.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef SETTINGS_H
@@ -42,6 +42,7 @@ public:
     bool cl_doc2bib;
     bool cl_html_annote;
     bool cl_import;
+    bool cl_sloppy;
     bool cl_txt2bib;
     bool cl_user_configured;
     bool cl_view_annote;
diff --git a/src/c2b/substringMatcher.cpp b/src/c2b/substringMatcher.cpp
new file mode 100644
index 0000000..47ad046
--- /dev/null
+++ b/src/c2b/substringMatcher.cpp
@@ -0,0 +1,94 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#include "substringMatcher.h"
+
+#include "cb2bib_utilities.h"
+#include "triads.h"
+
+
+substringMatcher::substringMatcher() : _hook(-1), _matched_length(-1)
+{}
+
+substringMatcher::substringMatcher(const QString& pattern, const Qt::CaseSensitivity cs) : _hook(-1), _matched_length(-1)
+{
+    QRegExp sep("\\.\\{(\\d+),(\\d+)\\}");
+    QStringList substrings(pattern.split(sep, QString::SkipEmptyParts));
+    Q_ASSERT_X(substrings.count() >= 2, "substringMatcher", "Expected at least two substrings in pattern");
+    int s(0);
+    QList<int> stretches;
+    while ((s = sep.indexIn(pattern, s)) != -1)
+    {
+        Q_ASSERT_X(sep.numCaptures() == 2, "substringMatcher", "Expected two digits in repetition");
+        Q_ASSERT_X(sep.cap(1).toInt() == 0, "substringMatcher", "Expected zero in first repetition digit");
+        stretches.append(sep.cap(2).toInt());
+        s += sep.matchedLength();
+    }
+    Q_ASSERT_X(substrings.count() == stretches.count() + 1, "substringMatcher", "Mismatch in pattern");
+
+    _substring_count = substrings.count();
+    _substrings.resize(_substring_count);
+    _lengths.resize(_substring_count);
+    for (int i = 0; i < _substring_count; ++i)
+    {
+        _substrings[i] = QStringMatcher(substrings.at(i), cs);
+        _lengths[i] = substrings.at(i).length();
+    }
+    _stretches.resize(_substring_count);
+    _stretches[0] = 0;
+    for (int i = 1; i < _substring_count; ++i)
+        _stretches[i] = stretches.at(i - 1);
+    _acc_lengths.fill(0, _substring_count);
+    for (int i = 1; i < _substring_count; ++i)
+        _acc_lengths[i] = _acc_lengths[i-1] + _lengths.at(i - 1);
+
+    int lf(10000);
+    for (int i = 0; i < _substring_count; ++i)
+    {
+        const int f(triads::textFrequency(substrings.at(i)));
+        if (f < lf)
+        {
+            lf = f;
+            _hook = i;
+        }
+    }
+#if C2B_DEBUG_SUBSTRINGMATCHER
+    qDebug() << "Pattern:" << pattern;
+    qDebug() << "Hook:" << substrings.at(_hook);
+#endif
+}
+
+
+int substringMatcher::indexIn(const QString& str, const int from) const
+{
+    _matched_length = -1;
+    if (_hook == -1)
+    {
+        c2bUtils::warn(QObject::tr("Warning: Uninitialized substringMatcher"));
+        return -1;
+    }
+    _p0 = from;
+    if (_p0 < 0)
+        _p0 = 0;
+    _pn = str.length();
+    if (_pn == 0)
+        return -1;
+
+    int hp(_p0);
+    int p(-1);
+    while (p == -1)
+    {
+        hp = _index_in(_hook, str, hp + _acc_lengths.at(_hook));
+#if C2B_DEBUG_SUBSTRINGMATCHER
+        qDebug() << "Hook at" << hp;
+#endif
+        if (hp == -1)
+            return -1;
+        p = _index_around(str, hp);
+        hp += _lengths.at(_hook);
+    }
+    return p;
+}
diff --git a/src/c2b/substringMatcher.h b/src/c2b/substringMatcher.h
new file mode 100644
index 0000000..d2ffdd0
--- /dev/null
+++ b/src/c2b/substringMatcher.h
@@ -0,0 +1,128 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#ifndef SUBSTRINGMATCHER_H
+#define SUBSTRINGMATCHER_H
+
+#include <QStringMatcher>
+#include <QVector>
+
+#define C2B_DEBUG_SUBSTRINGMATCHER 0
+#if C2B_DEBUG_SUBSTRINGMATCHER
+#endif
+
+
+class substringMatcher
+{
+
+public:
+    substringMatcher();
+    substringMatcher(const QString& pattern, const Qt::CaseSensitivity cs = Qt::CaseSensitive);
+    inline ~substringMatcher() {}
+
+
+    int indexIn(const QString& str, const int from = 0) const;
+    inline int matchedLength() const
+    {
+        return _matched_length;
+    }
+
+
+private:
+    inline int _index_in(const int& s, const QString& str, const int& p0) const
+    {
+        return _substrings.at(s).indexIn(str, p0);
+    }
+    inline int _index_in(const int& s, const QString& str, const int& p0, const int& pn) const
+    {
+#if C2B_DEBUG_SUBSTRINGMATCHER
+        qDebug() << "Search for substring:" << _substrings.at(s).pattern() << "in interval" << p0 << pn;
+        int i;
+        if (p0 >= pn)
+            i = -1;
+        else
+            i = _substrings.at(s).indexIn(str.unicode(), std::min(_pn, pn), p0);
+        qDebug() << "Returned index:" << i;
+        return i;
+#else
+        if (p0 >= pn)
+            return -1;
+#if QT_VERSION >= 0x040500
+        return _substrings.at(s).indexIn(str.unicode(), std::min(_pn, pn), p0);
+#else
+        const QString substr(QString::fromRawData(str.unicode(), std::min(_pn, pn)));
+        return _substrings.at(s).indexIn(substr, p0);
+#endif
+#endif
+    }
+    inline int _p_back(const int s, const int p0) const
+    {
+        return std::max(_p0 + _acc_lengths.at(s), p0 - _stretches.at(s + 1) - _lengths.at(s));
+    }
+    inline int _p_forth(const int s, const int p0) const
+    {
+        return std::min(_pn, p0 + _stretches.at(s) + _lengths.at(s));
+    }
+    inline int _index_back(const int s, const QString& str, int p0, const int pn) const
+    {
+        while ((p0 = _index_in(s, str, p0, pn)) != -1)
+        {
+            if (s == 0)
+                return p0;
+            const int i(_index_back(s - 1, str, _p_back(s - 1, p0), p0));
+            if (i != -1)
+                return i;
+            p0 += _lengths.at(s);
+        }
+        return -1;
+    }
+    inline int _index_forth(const int s, const QString& str, int p0, const int pn) const
+    {
+        while ((p0 = _index_in(s, str, p0, pn)) != -1)
+        {
+            p0 += _lengths.at(s);
+            if (s + 1 == _substring_count)
+                return p0;
+            const int i(_index_forth(s + 1, str, p0, _p_forth(s + 1, p0)));
+            if (i != -1)
+                return i;
+        }
+        return -1;
+    }
+    inline int _index_around(const QString& str, const int phook) const
+    {
+        int bp(phook);
+        if (_hook > 0)
+        {
+            bp = _index_back(_hook - 1, str, _p_back(_hook - 1, bp), bp);
+            if (bp == -1)
+                return -1;
+        }
+        int fp(phook + _lengths.at(_hook));
+        if (_hook + 1 < _substring_count)
+        {
+
+            fp = _index_forth(_hook + 1, str, fp, _p_forth(_hook + 1, fp));
+            if (fp == -1)
+                return -1;
+        }
+        _matched_length = fp - bp;
+        return bp;
+    }
+
+    QVector<QStringMatcher> _substrings;
+    QVector<int> _acc_lengths;
+    QVector<int> _lengths;
+    QVector<int> _stretches;
+    int _hook;
+    int _substring_count;
+    mutable int _matched_length;
+    mutable int _p0;
+    mutable int _pn;
+
+};
+
+#endif
diff --git a/src/c2b/texParser.cpp b/src/c2b/texParser.cpp
index 9d68739..d695cb5 100644
--- a/src/c2b/texParser.cpp
+++ b/src/c2b/texParser.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "texParser.h"
@@ -9,13 +9,6 @@
 #include "cb2bib_utilities.h"
 
 
-texParser::texParser()
-{}
-
-texParser::~texParser()
-{}
-
-
 void texParser::parse(QString tex)
 {
     _stream.setString(&tex, QIODevice::ReadOnly);
@@ -107,7 +100,7 @@ void texParser::gotoEndBraces(const QString& e)
     _element = _line;
     while (!_stream.atEnd() && !c2bUtils::inBraces(pos, _element, &in))
         _element += '\n' + readLine();
-    flushElement(e, in.simplified());
+    flushElement(e, c2bUtils::simplifyString(in));
 }
 
 void texParser::gotoEndMacro(const QString& e)
@@ -127,7 +120,7 @@ void texParser::gotoEndMacro(const QString& e)
                     _element += '\n' + readLine();
                 in = _element;
                 in.remove('\\' + e);
-                flushElement(e, in.simplified());
+                flushElement(e, c2bUtils::simplifyString(in));
                 return;
             }
         // Try next line
diff --git a/src/c2b/texParser.h b/src/c2b/texParser.h
index 0211563..271542f 100644
--- a/src/c2b/texParser.h
+++ b/src/c2b/texParser.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef TEXPARSER_H
@@ -18,8 +18,8 @@ class texParser
 {
 
 public:
-    texParser();
-    virtual ~texParser();
+    inline texParser() {}
+    inline virtual ~texParser() {}
 
 
 protected:
diff --git a/src/c2b/texToHtml.cpp b/src/c2b/texToHtml.cpp
index e794670..39d13f9 100644
--- a/src/c2b/texToHtml.cpp
+++ b/src/c2b/texToHtml.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "texToHtml.h"
@@ -23,9 +23,6 @@ texToHtml::texToHtml() : texParser()
     _settingsP = settings::instance();
 }
 
-texToHtml::~texToHtml()
-{}
-
 
 void texToHtml::toHtml(const QString& tex, const QString& fn)
 {
@@ -331,7 +328,7 @@ void texToHtml::referencesToHtml(QString* reference_list_html)
             author = _cbp.authorFromBibTeX(author);
             author.remove(nonletters);
             author.replace(" and ", ", ");
-            author = author.simplified();
+            c2bUtils::simplifyString(author);
             author += '.';
         }
 
diff --git a/src/c2b/texToHtml.h b/src/c2b/texToHtml.h
index a746353..51c6e37 100644
--- a/src/c2b/texToHtml.h
+++ b/src/c2b/texToHtml.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef TEXTOHTML_H
@@ -20,7 +20,7 @@ class texToHtml : public texParser
 
 public:
     texToHtml();
-    ~texToHtml();
+    inline ~texToHtml() {}
 
     QString toHtml(const QString& tex);
     void toHtml(const QString& tex, const QString& fn);
diff --git a/src/c2b/triads.cpp b/src/c2b/triads.cpp
new file mode 100644
index 0000000..5db3f14
--- /dev/null
+++ b/src/c2b/triads.cpp
@@ -0,0 +1,106 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#include "triads.h"
+
+#include "cb2bib_utilities.h"
+
+#include <QHash>
+
+
+const QString triads::textSignature(const QString& str)
+{
+    if (str.isEmpty())
+        return QString();
+    else
+        return asciiTextSignature(c2bUtils::toAscii(str, c2bUtils::KeepWords));
+}
+
+const QVector<QString> triads::textSignature(const QStringList& strs)
+{
+    QVector<QString> s(strs.count());
+    for (int i = 0; i < strs.count(); ++i)
+        s[i] = textSignature(strs.at(i));
+    return s;
+}
+
+const QString triads::asciiTextSignature(const QString& str)
+{
+    QString s(str);
+    s.replace(c2bUtils::nonAsciiLetter, " ");
+    s = s.toLower();
+    s = c2bUtils::simplifyString(s);
+
+    const int nletters(26);
+    const int ngram(5);
+    const int slength(s.length());
+    const int code0(QChar('a').unicode());
+
+    QHash<int, int> triads;
+    for (int i = 0; i <= slength - ngram; ++i)
+    {
+        const QString t(s.mid(i, ngram));
+        if (t.contains(' '))
+            continue;
+        int t1 = s.at(i).unicode() - code0;
+        int t2 = s.at(i + 2).unicode() - code0;
+        int t3 = s.at(i + 4).unicode() - code0;
+        int code = code0 + t1 * nletters * nletters + t2 * nletters + t3;
+        if (!triads.contains(code))
+            triads.insert(code, 1);
+    }
+    QList<int> codes(triads.keys());
+    qSort(codes);
+    s.clear();
+    for (int i = 0; i < codes.count(); ++i)
+        s += QChar(codes.at(i));
+    return s;
+}
+
+int triads::textFrequency(const QString& str)
+{
+    const QString sign(textSignature(str));
+    if (sign.length() == 0)
+        return 1000 - str.length();
+    else
+        return _rank(str, sign, c2bUtils::fileToString(":txt/txt/triads.txt"));
+
+}
+
+const QVector<int> triads::textFrequency(const QStringList& strs)
+{
+    if (strs.count() == 0)
+        return QVector<int>();
+    const QString ranks(c2bUtils::fileToString(":txt/txt/triads.txt"));
+    QVector<int> fr(strs.count());
+    for (int i = 0; i < strs.count(); ++i)
+    {
+        const QString sign(textSignature(strs.at(i)));
+        if (sign.length() == 0)
+            fr[i] = 1000 - strs.at(i).length();
+        else
+            fr[i] = _rank(strs.at(i), sign, ranks);
+    }
+    return fr;
+}
+
+int triads::_rank(const QString& str, const QString& sign, const QString& ranks)
+{
+    const int m(sign.length());
+    const int n(ranks.length());
+    int counter(0);
+    int j0(0);
+    for (int i = 0; i < m; ++i)
+        for (int j = j0; j < n; ++j)
+            if (sign[i] == ranks[j])
+            {
+                ++counter;
+                j0 = j + 1;
+                break;
+            }
+    counter = 100 * (m - counter) + str.length();
+    return 1000 - counter;
+}
diff --git a/src/c2b/triads.h b/src/c2b/triads.h
new file mode 100644
index 0000000..71869e7
--- /dev/null
+++ b/src/c2b/triads.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#ifndef TRIADS_H
+#define TRIADS_H
+
+
+#include <QStringList>
+
+
+class triads
+{
+
+public:
+    static const QString asciiTextSignature(const QString& str);
+    static const QString textSignature(const QString& str);
+    static const QVector<QString> textSignature(const QStringList& strs);
+
+    static const QVector<int> textFrequency(const QStringList& strs);
+    static int textFrequency(const QString& str);
+
+
+private:
+    inline triads() {}
+    inline ~triads() {}
+
+
+    static int _rank(const QString& str, const QString& sign, const QString& ranks);
+
+};
+
+#endif
diff --git a/src/c2b/txt/triads.txt b/src/c2b/txt/triads.txt
new file mode 100644
index 0000000..f8b35cc
--- /dev/null
+++ b/src/c2b/txt/triads.txt
@@ -0,0 +1 @@
+aeiloty ¦§³»¼ÀÂÉÍÑÛÜÝáþāĎďģıIJĵĶķĹļľĿŃńŅʼnƂƐƑƕƦƶǀdžǍǑǓǔǕǟǠǧǫǯǴǵȝȟȲȳȷȹȽɁɃɆɇɈɏɑɓɛɜɝɠɢɤɩɭɻɼ˙̪͍̒Ϳ΀΂ϛжџӜӫӳӷӾԁԐֱֶֻּ֭֩֯؈ؙؓؕؖآأؤحٹٽٿځچڌۋۘۙۚۛ۟ۡ۩۬ۮۯ۵ۻۿ܃܆܉܌܎܏ܘܙܧܳݣݥݧݫݰݱݵށޅދޏޚޥޱ޵޹޼߄ߜࡑࡕ࡛ࢄࢉࢍ࢓࢔࣓ࣜथ঍঒ণধফলৠਉਊਜਡਧਲਵ੉ੌੲ੺૱૵ૹૼ૾૿଀ଃ଄ଅଜଥ଩ଭଷୂୌ୙୛ଡ଼ଢ଼ୟୡ୥୧୪୫୬ୱ୵஄஑ஔச஠பயழஸு௅ே௉ௌ௎௓௔௕఑జశ఼౎ౖౠౡ౥౷౹౻಄ಅಈಭಯಲಳಶಷಸ಼ಽಾೃೈ೐೒೓ೖ೗೘೟ೡೢೣ೤೧೪೫೬೭೰ೲ೴೷೹೽ഄആഊഌഖഞതറാ෍෗ෛො฀กฐฑโ๭ແ໪໺ཏནབཛྷརལྠွ၀၁။ၓႳႴ폐ᅾᆋᆏᆖᆜᆩᆴሆቨጹᐍᐗᐠᐧᐨᐳᑍᑏᑡᑧᒙᒛᒜᒥᒳᓨᓬᔮᖅᖉᖌᖓᖔᖙᖟᖹᗇᗉᗑᗜᗞᗦᗩᗭᗱᗺᗻᗼᗾᘁᘔᘡᘪᘮᙄᙈᙉᙑᙔᙕᙗᙙᙜᙞᙢᙣᙥᙩᚱᚷᛖᛗᛞᛤᛥᛱᜋᜏ᜘᜚ᝌ᝙᝱ᝲ᝵᝷᝼᝽កជញឍទបលវឮ឴ᡡ᱂ᵱᵵᵿᶀᶒᶩᶬᶲᶴᷦᷨḋḖṃṈẲẸếểịốỒỡừἫἺὅὉὓ὞ὟὩὬὰήᾚᾶῺ ’‣‥⁅⁐₊₋ℱℳℷ℻⅀⅁⅂ⅆ⅖ⅣⅧⅫⅯⅰⅵⅶↁↅ←⇍⇒⇶∁∃∇∍∐−∗∙∝∡≳⊮⊸⊹⊽⋂⋉⋍⋭⌝⌟⌡⌣⌥〉⌬⌮⌯⌰⌲⍈⍤⎅⎉⎋⎍⎐⎒⎘⎙⎝⏖⏥⏦⏫⏭⏯⏱⏾␋␏␙␭␳␶⑙⑯⑲⑷⑺⒂⒇⒣⒥⒦⒧⒰⒱⒴⒵ⒶⒷⒽⓨ╝╡╤╦▀▆▜▞▴▸►◁◅◈◉◎◒◓◔◕◣◬☠☩☭☯☰☱☴☶☻☼♅⚃⚄⚍⚔⚜⚞⚤⚫⚭⚯⚽⛉⛍⛓⛗⛝⛣⛧⛬⛰⛱⛲✓✕✗✛✞✟✥✭✮✰✵✾✿❇❊❏❓❔❕❥❩❴➈➌⟗⠁⠱⠵⠶⠹⡂⡩⡭⡶⡷⣍⣏⣐⣑⣓⣕⣚⣟⣠⤝⤟⤨⤬⤮⥓⥗⥜⥩⥫⥭⥮⥱⥴⥷⥺⥼⥽⦷⦻⦿⧂⧃⧅⧉⧊⧋⧎⧙⧤⧯⧸⧼⧾⩵⪥⪩⪴⬋⬜⭱⭵ⵇⵉⵌⵍⵐⵓⵗⵘⵠⵢⵣ⵲⵼⵽ⶁⶄⶆⶋⶍⶕ⶗ⶭ⶯ⶱⶵⶼ⶿ⷀⷘⷡⷥⷮⷯⷴ⸌⸕⸙⸛⸝⸠⸢⸦⸧⸨⸩⸱⹶⺅⺊⺐⺙⺛⺜⺟⺢⺥⺩⺵⺹⺽⻃⻋⻏⻓⻜⻝⻩⻭⼙⼜⼝⼡⼤⼦⼧⼪⼵⼶⼷⼻⼿⽀⽁⽄⽆⽍⽐⽑⽔⽪⽺⾧⿫⿬⿭⿱⿴⿼〇〖〝〥〨〪えごすっつらろグスタチツテニネㄉㄋㄏㄙㄚㄥㄬㄴㄻㄿㅃㅆㅕㅘㅙㅝㅠㅡㅢㅧㅨㅽㆀㆍㆣㆤㆥㆧㆫㆰㆲㆶ㇁㇥㇩㇬ㇵㇹ㈂㈃㊑㊕㊘㊚㊟㊠㊫㋅㋌㋎㋵㋹㋽㌁㌂㌆㌇㌈㌩㌺㍡㍣㍥㍯㍰㍱㎞㏇㏐㏗㏘㏞㏟㏣㏧㏭㏱㏹㏽㏿㐁㐇㐋㐌㐍㑇㑉㑋㑏㑒㑔㑕㑙㑚㑛㑩㑽㒆㒉㒍㒎㒨㒺㓁㓂㔵㔹㕜㕭㖐㖡㖬㖵㘅㘇㘎㙢㙧㚇㚋㚎㚗㛈㛉㛸㛽㜅㜍㜟㜢㜣㜬㜭㜮㜰㝄㠗㣳㣷㤀㤂㥓㦏㦓㦕㦗㦚㧑㫥㭍㭐㱅㲄㲬㶍㶘㹠㹨㻩㿉䂑䄌䄵䆻䑡
\ No newline at end of file
diff --git a/src/c2b/txt/word_prefix_lexicon.txt b/src/c2b/txt/word_prefix_lexicon.txt
index 571e130..9702c26 100644
--- a/src/c2b/txt/word_prefix_lexicon.txt
+++ b/src/c2b/txt/word_prefix_lexicon.txt
@@ -44,6 +44,7 @@ _bindi
 _bioc
 _bioi
 _biolog
+_biom
 _biosy
 _blood
 _bound
@@ -100,7 +101,6 @@ _core_
 _corpo
 _correla
 _couple
-_coupli
 _crystall
 _cubat
 _cult
@@ -195,7 +195,6 @@ _granul
 _group
 _growt
 _hamiltoni
-_helic
 _hepa
 _heter
 _highly
@@ -206,7 +205,6 @@ _htm
 _hybr
 _hydr
 _hyper
-_hypo
 _iden
 _image
 _imagi
@@ -281,6 +279,8 @@ _muscl
 _mutant
 _mutati
 _myco
+_nanop
+_nanos
 _nanot
 _natu
 _nerve
@@ -298,7 +298,6 @@ _numer
 _obj
 _obse
 _of_
-_oligo
 _on_
 _onl
 _oper
@@ -332,6 +331,7 @@ _phot
 _phylo
 _phys
 _plasm
+_polymer_
 _polymera
 _popu
 _postin
diff --git a/src/c2b/wordMatcher.cpp b/src/c2b/wordMatcher.cpp
new file mode 100644
index 0000000..b710f7a
--- /dev/null
+++ b/src/c2b/wordMatcher.cpp
@@ -0,0 +1,81 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#include "wordMatcher.h"
+
+#include "triads.h"
+#include "cb2bib_utilities.h"
+
+
+wordMatcher::wordMatcher() : _hook(-1), _matched_length(-1)
+{}
+
+wordMatcher::wordMatcher(const QString& pattern, const Qt::CaseSensitivity cs)
+{
+    setPattern(pattern, cs);
+}
+
+
+void wordMatcher::setPattern(const QString& pattern, const Qt::CaseSensitivity cs)
+{
+    _hook = -1;
+    _matched_length = -1;
+    const QStringList substrings(pattern.split(c2bUtils::nonLetter, QString::SkipEmptyParts));
+    if (substrings.count() == 0)
+        return;
+    _substring_count = substrings.count();
+    _substrings.resize(_substring_count);
+    _lengths.resize(_substring_count);
+    _sp0.resize(_substring_count);
+    _stretch = 0;
+    for (int i = 0; i < _substring_count; ++i)
+    {
+        _substrings[i] = QStringMatcher(substrings.at(i), cs);
+        _lengths[i] = substrings.at(i).length();
+        if (_lengths.at(i) > 4)
+            _stretch += 50;
+        else
+            _stretch += 10;
+    }
+    int lf(10000);
+    for (int i = 0; i < _substring_count; ++i)
+    {
+        const int f(triads::textFrequency(substrings.at(i)));
+        if (f < lf)
+        {
+            lf = f;
+            _hook = i;
+        }
+    }
+}
+
+int wordMatcher::indexIn(const QString& str, const int from) const
+{
+    _matched_length = -1;
+    if (_hook == -1)
+    {
+        c2bUtils::warn(QObject::tr("Warning: Uninitialized wordMatcher"));
+        return -1;
+    }
+    _p0 = from;
+    if (_p0 < 0)
+        _p0 = 0;
+    _pn = str.length();
+    if (_pn == 0)
+        return -1;
+
+    int hp(_p0);
+    int p(-1);
+    while (p == -1)
+    {
+        hp = _index_in(_hook, str, hp);
+        if (hp == -1)
+            return -1;
+        p = _index_around(str, hp);
+        hp += _lengths.at(_hook);
+    }
+    return p;
+}
diff --git a/src/c2b/wordMatcher.h b/src/c2b/wordMatcher.h
new file mode 100644
index 0000000..6f1c5fe
--- /dev/null
+++ b/src/c2b/wordMatcher.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ *   Copyright (C) 2004-2009 by Pere Constans
+ *   constans at molspaces.com
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
+ *   See the LICENSE file that comes with this distribution.
+ ***************************************************************************/
+#ifndef WORDMATCHER_H
+#define WORDMATCHER_H
+
+#include <QStringMatcher>
+#include <QVector>
+
+
+class wordMatcher
+{
+
+public:
+    wordMatcher();
+    wordMatcher(const QString& pattern, const Qt::CaseSensitivity cs = Qt::CaseSensitive);
+    inline ~wordMatcher() {}
+
+
+    int indexIn(const QString& str, const int from = 0) const;
+    void setPattern(const QString& pattern, const Qt::CaseSensitivity cs);
+    inline int matchedLength() const
+    {
+        return _matched_length;
+    }
+
+
+private:
+    inline int _index_in(const int& s, const QString& str, const int& p0) const
+    {
+        return _substrings.at(s).indexIn(str, p0);
+    }
+    inline int _index_in(const int& s, const QString& str, const int& p0, const int& pn) const
+    {
+        if (p0 >= pn)
+            return -1;
+#if QT_VERSION >= 0x040500
+        return _substrings.at(s).indexIn(str.unicode(), std::min(_pn, pn), p0);
+#else
+        const QString substr(QString::fromRawData(str.unicode(), std::min(_pn, pn)));
+        return _substrings.at(s).indexIn(substr, p0);
+#endif
+    }
+    inline int _index_around(const QString& str, const int phook) const
+    {
+        _sp0.fill(-1);
+        _sp0[_hook] = phook;
+
+        const int bp0 = std::max(_p0, phook - _stretch);
+        const int bpn = std::min(_pn, phook + _stretch);
+        for (int i = 0; i < _substring_count; ++i)
+            if (_sp0.at(i) == -1)
+            {
+                const int p0(_index_in(i, str, bp0, bpn));
+                if (p0 == -1)
+                    return -1;
+                _sp0[i] = p0;
+            }
+
+        int bp(_pn);
+        int fp(_p0);
+        for (int i = 0; i < _substring_count; ++i)
+        {
+            const int p0 = _sp0.at(i);
+            if (bp > p0)
+                bp = p0;
+            const int pn = p0 + _lengths.at(i);
+            if (fp < pn)
+                fp = pn;
+        }
+        _matched_length = fp - bp;
+        return bp;
+    }
+
+    QVector<QStringMatcher> _substrings;
+    QVector<int> _lengths;
+    int _stretch;
+    int _hook;
+    int _substring_count;
+    mutable QVector<int> _sp0;
+    mutable int _matched_length;
+    mutable int _p0;
+    mutable int _pn;
+
+};
+
+#endif
diff --git a/src/c2b/wordPattern.cpp b/src/c2b/wordPattern.cpp
index 99270a8..32c154f 100644
--- a/src/c2b/wordPattern.cpp
+++ b/src/c2b/wordPattern.cpp
@@ -1,44 +1,64 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "wordPattern.h"
+
 #include "cb2bib_utilities.h"
+#include "triads.h"
+
 
+wordPattern::wordPattern() : compositePattern()
+{}
 
-wordPattern::wordPattern(const QString newPattern, Qt::CaseSensitivity newCs) : compositePattern(newPattern, newCs)
+wordPattern::wordPattern(const QString& pattern, const Type type, const Qt::CaseSensitivity cs) :
+        compositePattern(pattern, cs), _type(type)
 {
-    setPattern();
+    setPattern(pattern, type, cs);
 }
 
-wordPattern::~wordPattern()
-{}
-
 
-void wordPattern::setPattern()
+void wordPattern::setPattern(const QString& pattern, const Type type, const Qt::CaseSensitivity cs)
 {
-    const QStringList patternPieces(pattern.split(c2bUtils::nonLetter, QString::SkipEmptyParts));
-    if (patternPieces.count() < 2)
-    {
-        arx.setPattern(escape(pattern, caseSensitivity));
+    _string = pattern.simplified();
+    _type = type;
+    _case_sensitivity = cs;
+    _is_multipattern = false;
+    _matched_length = -1;
+
+    const QStringList words(_string.split(c2bUtils::nonLetter, QString::SkipEmptyParts));
+    _subpattern_count = words.count();
+    if (_subpattern_count == 0)
         return;
+
+    _ranks.clear();
+    QStringList subpattern;
+    QStringList substring;
+    for (int i = 0; i < words.count(); ++i)
+    {
+        const QString& wi = words.at(i);
+        const QString sp(escape(wi, _case_sensitivity));
+        subpattern.append(sp);
+        substring.append(wi);
+        _ranks.append(triads::textFrequency(wi)); // Rank according expectation (arXiv:0705.0751v1, Eq. 6)
     }
-    QStringList subPatterns;
-    QRegExp _asrx;
-    _asrx.setPatternSyntax(QRegExp::RegExp2);
-    _asrx.setMinimal(false);
-    _asrx.setCaseSensitivity(Qt::CaseSensitive);
-    QMap<double, QRegExp> sort_asrx;
-    for (int i = 0; i < patternPieces.count(); ++i)
+    set_sort_index();
+    if (_subpattern_count == 1)
+        _regexp.setPattern(escape(_string, _case_sensitivity));
+    else
+        _regexp.setPattern(QString("(?:%1)").arg(subpattern.join("|")));
+    _submatchers.resize(_subpattern_count);
+    _subregexps.resize(_subpattern_count);
+    _substrings.clear();
+    for (int i = 0; i < _subpattern_count; ++i)
     {
-        const QString sp(escape(patternPieces.at(i), caseSensitivity));
-        subPatterns.append(sp);
-        _asrx.setPattern(sp);
-        // Sort according expectation (arXiv:0705.0751v1, Eq. 6)
-        sort_asrx.insert(-probability(sp), _asrx);
+        const int ii(_index.at(i));
+        _submatchers[i] = QStringMatcher(substring.at(ii), _case_sensitivity);
+        _subregexps[i] = QRegExp(subpattern.at(ii), Qt::CaseSensitive, QRegExp::RegExp2);
+        _subregexps[i].setMinimal(false);
+        _substrings.append(substring.at(ii));
     }
-    asrx = sort_asrx.values();
-    arx.setPattern(QString("(?:%1)").arg(subPatterns.join("|")));
+    _is_multipattern = _subpattern_count > 1;
 }
diff --git a/src/c2b/wordPattern.h b/src/c2b/wordPattern.h
index a8541b4..c838b43 100644
--- a/src/c2b/wordPattern.h
+++ b/src/c2b/wordPattern.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef WORDPATTERN_H
@@ -10,16 +10,71 @@
 #include "compositePattern.h"
 
 
+#include <QStringMatcher>
+
+
 class wordPattern : public compositePattern
 {
 
 public:
-    wordPattern(const QString newPattern, Qt::CaseSensitivity newCs);
-    ~wordPattern();
+    enum Type {AllWords, AnyWord};
+
+    wordPattern();
+    wordPattern(const QString& pattern, const Type type, const Qt::CaseSensitivity cs);
+    inline ~wordPattern() {}
+
+
+    void setPattern(const QString& pattern, const Type type, const Qt::CaseSensitivity cs = Qt::CaseSensitive);
+
+    inline bool matches(const QString& str) const
+    {
+        _matched_length = -1;
+        if (str.length() == 0)
+            return false;
+        if (_type == AllWords)
+        {
+            for (int i = _subpattern_count - 1; i >= 0; --i)
+                if (_submatchers.at(i).indexIn(str) == -1)
+                    return false;
+            return true;
+        }
+        else
+        {
+            for (int i = 0; i < _subpattern_count; ++i)
+                if (_submatchers.at(i).indexIn(str) != -1)
+                    return true;
+            return false;
+        }
+    }
+    inline int indexIn(const QString& str, const int from = 0) const
+    {
+        // Do not match. Get index for (w1|w2|...).
+        _matched_length = -1;
+        if (str.length() == 0)
+            return -1;
+        int index(str.length());
+        for (int i = 0; i < _subpattern_count; ++i)
+        {
+            const int p(_submatchers.at(i).indexIn(str, from));
+            if (p != -1 && p < index)
+            {
+                index = p;
+                _matched_length = _substrings.at(i).length();
+            }
+        }
+        if (index == str.length())
+            index = -1;
+        return index;
+    }
+    inline const QVector<QStringMatcher>& submatchers() const
+    {
+        return _submatchers;
+    }
 
 
 private:
-    void setPattern();
+    QVector<QStringMatcher> _submatchers;
+    Type _type;
 
 };
 
diff --git a/src/c2bAnnote.cpp b/src/c2bAnnote.cpp
index f13f65f..2f70eee 100644
--- a/src/c2bAnnote.cpp
+++ b/src/c2bAnnote.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bAnnote.h"
diff --git a/src/c2bAnnote.h b/src/c2bAnnote.h
index 5f30c05..f963942 100644
--- a/src/c2bAnnote.h
+++ b/src/c2bAnnote.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BANNOTE_H
diff --git a/src/c2bBibHighlighter.cpp b/src/c2bBibHighlighter.cpp
index 3e7cad8..f130b71 100644
--- a/src/c2bBibHighlighter.cpp
+++ b/src/c2bBibHighlighter.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bBibHighlighter.h"
diff --git a/src/c2bBibHighlighter.h b/src/c2bBibHighlighter.h
index 175e191..d977674 100644
--- a/src/c2bBibHighlighter.h
+++ b/src/c2bBibHighlighter.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BBIBHIGHLIGHTER_H
diff --git a/src/c2bBibParser.cpp b/src/c2bBibParser.cpp
index 19fd703..a3d20ef 100644
--- a/src/c2bBibParser.cpp
+++ b/src/c2bBibParser.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bBibParser.h"
diff --git a/src/c2bBibParser.h b/src/c2bBibParser.h
index 0b4686a..c65017d 100644
--- a/src/c2bBibParser.h
+++ b/src/c2bBibParser.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BBIBPARSER_H
diff --git a/src/c2bBibPreparserLog.cpp b/src/c2bBibPreparserLog.cpp
index 8561ebf..49cd4c1 100644
--- a/src/c2bBibPreparserLog.cpp
+++ b/src/c2bBibPreparserLog.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bBibPreparserLog.h"
diff --git a/src/c2bBibPreparserLog.h b/src/c2bBibPreparserLog.h
index 599f40e..d457458 100644
--- a/src/c2bBibPreparserLog.h
+++ b/src/c2bBibPreparserLog.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BBIBPREPARSERLOG_H
diff --git a/src/c2bBibSearcher.h b/src/c2bBibSearcher.h
deleted file mode 100644
index 1a228f6..0000000
--- a/src/c2bBibSearcher.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2004-2009 by Pere Constans
- *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
- *   See the LICENSE file that comes with this distribution.
- ***************************************************************************/
-#ifndef C2BBIBSEARCHER_H
-#define C2BBIBSEARCHER_H
-
-#include "c2bBibSearcherCache.h"
-#include "c2bSearchPattern.h"
-
-#include <QMap>
-#include <QObject>
-#include <QStringList>
-
-
-class bibReference;
-class c2bBibParser;
-
-class c2bBibSearcher : public QObject
-{
-
-    Q_OBJECT
-
-public:
-    c2bBibSearcher(QObject* parento = 0);
-    ~c2bBibSearcher();
-
-    const QString highlight(const QString& abstract);
-    QMap<QString, QString> hitMap;
-    QString hitString;
-    QString logString;
-    void addPattern(bool Not, bool caseSensitive, const QString& patternType, const QString& scope,
-                    const QString& yearScope, const QString& pattern);
-    void exec();
-
-    inline void setBoolean(bool And)
-    {
-        p_boolean_and = And;
-    }
-
-    inline void setScope(const QString& file, const QString& dir, bool all, bool includePdf)
-    {
-        clear();
-        p_bibtex_file = file;
-        p_bibtex_dir = dir;
-        p_all_bibtex_files = all;
-        p_include_pdf = includePdf;
-    }
-
-    inline void setSimplifySource(bool simplify)
-    {
-        p_simplify_source = simplify;
-    }
-
-    inline int errorCount() const
-    {
-        return errorCounter;
-    }
-
-    inline int hitCount() const
-    {
-        return hitMap.count();
-    }
-
-    inline int patternCount() const
-    {
-        return patternList.count();
-    }
-
-    inline int referenceCount() const
-    {
-        return referenceCounter;
-    }
-
-
-public slots:
-    void abort();
-
-
-private:
-    QList<c2bSearchPattern> patternList;
-    QString p_bibtex_dir;
-    QString p_bibtex_file;
-    QStringList fieldList;
-    bool p_aborted;
-    bool p_all_bibtex_files;
-    bool p_boolean_and;
-    bool p_include_pdf;
-    bool p_simplify_source;
-    c2bBibParser* bp;
-    c2bBibSearcherCache cache;
-    const QString excerpts(const QString& contents);
-    const QString location(const QString& fn, const bibReference& ref);
-    int bibtexCounter;
-    int errorCounter;
-    int pdfCounter;
-    int referenceCounter;
-    void clear();
-    void search(const QString& bib_file);
-    void searchBib(const QString& bib_file, const bibReference& ref);
-
-    inline bool include_pdf(bool include, const QString& file_name, QString* file_contents)
-    {
-        if (!include)
-            return false;
-        if (*file_contents == "unread")
-            *file_contents = cache.pdfToText(file_name, &pdfCounter, &logString, &errorCounter);
-        return !(file_contents->isEmpty());
-    }
-
-};
-
-#endif
diff --git a/src/c2bBibSearcherCache.cpp b/src/c2bBibSearcherCache.cpp
deleted file mode 100644
index 63206d1..0000000
--- a/src/c2bBibSearcherCache.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2004-2009 by Pere Constans
- *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
- *   See the LICENSE file that comes with this distribution.
- ***************************************************************************/
-#include "c2bBibSearcherCache.h"
-
-#include "c2bSettings.h"
-#include "c2bUtils.h"
-
-#include <document.h>
-
-#include <QDir>
-
-
-c2bBibSearcherCache::c2bBibSearcherCache(QObject* parento) : QObject(parento)
-{
-    cache_size = fileContents.size();
-    settings = c2bSettingsP;
-    p_simplify_source = false;
-}
-
-c2bBibSearcherCache::~c2bBibSearcherCache()
-{
-    save();
-}
-
-
-void c2bBibSearcherCache::load(const QString& filename, bool simplify_source)
-{
-    p_simplify_source = simplify_source;
-    p_cache_dir = settings->fileName("cb2Bib/CacheDirectory");
-    if (filename == load_filename)
-        return;
-    load_filename = filename;
-    save();
-    fileContents.clear();
-    if (QFileInfo(p_cache_dir).exists() && QFileInfo(p_cache_dir).isDir())
-        cache_filename = QDir::cleanPath(p_cache_dir + '/' + QFileInfo(load_filename).fileName() + ".c2b");
-    else
-        cache_filename = load_filename.trimmed() + ".c2b";
-    if (QFileInfo(cache_filename).exists())
-    {
-        QFile file(cache_filename);
-        file.open(QIODevice::ReadOnly);
-        QDataStream ds(&file);
-        ds >> fileContents;
-    }
-    cache_size = fileContents.size();
-}
-
-void c2bBibSearcherCache::save()
-{
-    if (cache_size != fileContents.size())
-    {
-        QFile file(cache_filename);
-        file.open(QIODevice::WriteOnly);
-        QDataStream ds(&file);
-        ds << fileContents;
-    }
-}
-
-const QString c2bBibSearcherCache::pdfToText(const QString& filename, int* pdfCounter, QString* logString, int* errorCounter)
-{
-    const QString pdf_file(filename.trimmed());
-    if (pdf_file.isEmpty())
-        return QString();
-    QFileInfo fi(pdf_file);
-    if (!fi.exists() || !fi.isFile())
-    {
-        (*errorCounter)++;
-        (*logString) += tr("% [cb2bib] File %1 does not exists\n").arg(pdf_file);
-        return QString();
-    }
-
-    (*pdfCounter)++;
-    if (p_simplify_source)
-    {
-        if (fileContents.contains("simp:" + pdf_file))
-            return QString::fromUtf8(qUncompress(fileContents.value("simp:" + pdf_file)));
-    }
-    else
-    {
-        if (fileContents.contains(pdf_file))
-            return QString::fromUtf8(qUncompress(fileContents.value(pdf_file)));
-    }
-
-    document doc(pdf_file, document::Raw);
-    QString text(doc.toString());
-    const QString error(doc.errorString());
-    if (!error.isEmpty())
-    {
-        (*errorCounter)++;
-        (*logString) += tr("% [cb2bib] %1\n").arg(error);
-        return QString();
-    }
-    text = text.simplified();
-    fileContents.insert(pdf_file, qCompress(QByteArray(text.toUtf8())));
-    const QString simp_text(c2bUtils::toAscii(text, c2bUtils::KeepWords));
-    fileContents.insert("simp:" + pdf_file, qCompress(QByteArray(simp_text.toUtf8())));
-    if (p_simplify_source)
-        return simp_text;
-    else
-        return text;
-}
diff --git a/src/c2bBibSearcherCache.h b/src/c2bBibSearcherCache.h
deleted file mode 100644
index 407fe8b..0000000
--- a/src/c2bBibSearcherCache.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2004-2009 by Pere Constans
- *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
- *   See the LICENSE file that comes with this distribution.
- ***************************************************************************/
-#ifndef C2BBIBSEARCHERCACHE_H
-#define C2BBIBSEARCHERCACHE_H
-
-#include <QHash>
-#include <QObject>
-
-class c2bSettings;
-
-class c2bBibSearcherCache : public QObject
-{
-
-    Q_OBJECT
-
-public:
-    c2bBibSearcherCache(QObject* parento = 0);
-    ~c2bBibSearcherCache();
-
-    const QString pdfToText(const QString& filename, int* pdfCounter, QString* logString, int* errorCounter);
-    void load(const QString& filename, bool simplify_source);
-
-
-private:
-    QHash<QString, QByteArray> fileContents;
-    QString cache_filename;
-    QString load_filename;
-    QString p_cache_dir;
-    bool p_simplify_source;
-    c2bSettings* settings;
-    int cache_size;
-    void save();
-
-};
-
-#endif
diff --git a/src/c2bCiter.cpp b/src/c2bCiter.cpp
index 14040cd..a877e38 100644
--- a/src/c2bCiter.cpp
+++ b/src/c2bCiter.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bCiter.h"
diff --git a/src/c2bCiter.h b/src/c2bCiter.h
index 2aa3d6c..74ecc40 100644
--- a/src/c2bCiter.h
+++ b/src/c2bCiter.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCITER_H
diff --git a/src/c2bCiterModel.cpp b/src/c2bCiterModel.cpp
index 86fd10d..29d46cb 100644
--- a/src/c2bCiterModel.cpp
+++ b/src/c2bCiterModel.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bCiterModel.h"
@@ -259,7 +259,7 @@ void c2bCiterModel::_add_citations(const QString& fn)
             author.remove(initials1);
             author.remove(initials2);
             author.replace(" and ", ", ");
-            author = author.simplified();
+            c2bUtils::simplifyString(author);
         }
 
         QString title(ref.anyTitle());
diff --git a/src/c2bCiterModel.h b/src/c2bCiterModel.h
index 9a5017a..9af2121 100644
--- a/src/c2bCiterModel.h
+++ b/src/c2bCiterModel.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCITERMODEL_H
diff --git a/src/c2bCiterView.cpp b/src/c2bCiterView.cpp
index 86ac93d..74b9aa8 100644
--- a/src/c2bCiterView.cpp
+++ b/src/c2bCiterView.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bCiterView.h"
diff --git a/src/c2bCiterView.h b/src/c2bCiterView.h
index 47e07d3..6a01bcb 100644
--- a/src/c2bCiterView.h
+++ b/src/c2bCiterView.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCITERVIEW_H
diff --git a/src/c2bClipEdit.cpp b/src/c2bClipEdit.cpp
index 6fb5448..93aa7eb 100644
--- a/src/c2bClipEdit.cpp
+++ b/src/c2bClipEdit.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bClipEdit.h"
diff --git a/src/c2bClipEdit.h b/src/c2bClipEdit.h
index 7843c92..1b4d053 100644
--- a/src/c2bClipEdit.h
+++ b/src/c2bClipEdit.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCLIPEDIT_H
diff --git a/src/c2bClipboard.cpp b/src/c2bClipboard.cpp
index af5ab24..1ea1ea6 100644
--- a/src/c2bClipboard.cpp
+++ b/src/c2bClipboard.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bClipboard.h"
@@ -28,6 +28,7 @@ c2bClipboard::c2bClipboard(QObject* parento) : QObject(parento)
     interval = 1000;
     // Uncomment the 4 timer-related lines if clipboard appears unresponsive
     // and you cannot compile with cbpoll option
+    timer = 0;
     //     timer = new QTimer( this );
     //     connect(timer, SIGNAL(timeout() ), this, SLOT(checkData()));
 
diff --git a/src/c2bClipboard.h b/src/c2bClipboard.h
index 341a15a..ff36332 100644
--- a/src/c2bClipboard.h
+++ b/src/c2bClipboard.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCLIPBOARD_H
diff --git a/src/c2bColors.cpp b/src/c2bColors.cpp
index 4cdcb22..ffd004b 100644
--- a/src/c2bColors.cpp
+++ b/src/c2bColors.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bColors.h"
diff --git a/src/c2bColors.h b/src/c2bColors.h
index 667c735..89a436f 100644
--- a/src/c2bColors.h
+++ b/src/c2bColors.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCOLORS_H
diff --git a/src/c2bComboBox.cpp b/src/c2bComboBox.cpp
index 7df6142..ce8d42f 100644
--- a/src/c2bComboBox.cpp
+++ b/src/c2bComboBox.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bComboBox.h"
diff --git a/src/c2bComboBox.h b/src/c2bComboBox.h
index 7691bb2..a6d9f31 100644
--- a/src/c2bComboBox.h
+++ b/src/c2bComboBox.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef F_COMBOBOX_H
diff --git a/src/c2bConfigure.cpp b/src/c2bConfigure.cpp
index bccbebc..f91be98 100644
--- a/src/c2bConfigure.cpp
+++ b/src/c2bConfigure.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bConfigure.h"
@@ -100,11 +100,12 @@
     \htmlonly
     <a href="http://arxiv.org/abs/0705.0751v1" target="_blank">approximate string</a>
     \endhtmlonly
-    search pattern. If similar references are found, the search result are
-    displayed in the browser. Pressing the <b>save button one second time will
-    proceed to actually saving the current reference</b>. Note that this
-    feature is not applied in command line mode, when using <tt>cb2bib
-    --txt2bib</tt> or <tt>cb2bib --doc2bib</tt>. See also \ref keyboard.
+    search pattern. If similar references are found, the current reference is
+    not saved, and the similar ones are displayed. Pressing the <b>save button
+    one second time will proceed to actually saving the current reference</b>.
+    Note that this feature is not applied in command line mode, when using
+    <tt>cb2bib --txt2bib</tt> or <tt>cb2bib --doc2bib</tt>. See also \ref
+    keyboard.
 
     - <b>External BibTeX Postprocessing</b> \n Use this box to select a BibTeX
     postprocessing external tool. The name of the executable, the command
@@ -224,8 +225,10 @@
     \htmlonly
     <a href="http://www.sno.phy.queensu.ca/~phil/exiftool/" target="_blank">ExifTool</a>
     \endhtmlonly
-    for writing bibliographic metadata to the attached documents. Select here the
-    ExifTool path name.
+    for writing bibliographic metadata to the attached documents. Select here
+    the ExifTool path name. On Windows, remember renaming
+    <tt>exiftool(-k).exe</tt> to <tt>exiftool.exe</tt> for command line use.
+    See also \ref metadata_write.
 
 
 \section c2bconf_files Configuring Files
@@ -347,7 +350,7 @@
       (/usr/bin/archmage -d "$1" > "$2") >& /dev/null
       if ($status) exit 1
    else
-      /usr/bin/pdftotext -raw "$1" "$2"
+      /usr/bin/pdftotext -raw -enc UTF-8 "$1" "$2"
       if ($status) exit 1
    endif
    \endverbatim
@@ -762,7 +765,7 @@ void c2bConfigure::getNetworkFile()
 void c2bConfigure::getBrowserCssFile()
 {
     const QString fn(ui.BrowserCssFile->text());
-    const QString new_fn(c2bFileDialog::getOpenFilename(this, tr("Select a filename (Restart editor to apply changes)"),
+    const QString new_fn(c2bFileDialog::getOpenFilename(this, tr("Select a filename (Restart browser to apply changes)"),
                          fn, tr("Cascading Style Sheets (*.css);;All (*)")));
     if (!new_fn.isEmpty())
         ui.BrowserCssFile->setText(new_fn);
diff --git a/src/c2bConfigure.h b/src/c2bConfigure.h
index 3a1b848..2ee97e6 100644
--- a/src/c2bConfigure.h
+++ b/src/c2bConfigure.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCONFIGURE_H
diff --git a/src/c2bConfigureFR.cpp b/src/c2bConfigureFR.cpp
index b8e3821..649b57a 100644
--- a/src/c2bConfigureFR.cpp
+++ b/src/c2bConfigureFR.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bConfigureFR.h"
diff --git a/src/c2bConfigureFR.h b/src/c2bConfigureFR.h
index bcedf0c..2aa3b9e 100644
--- a/src/c2bConfigureFR.h
+++ b/src/c2bConfigureFR.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCONFIGUREFR_H
diff --git a/src/c2bConsole.cpp b/src/c2bConsole.cpp
index 0f73db8..088f1a8 100644
--- a/src/c2bConsole.cpp
+++ b/src/c2bConsole.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bConsole.h"
@@ -58,8 +58,7 @@ int c2bConsole::cl_html_annote()
     }
     else
     {
-        fprintf(stdout, QObject::tr("[cb2Bib] Error: Could not open %1 file for reading.\n").
-                arg(c2bSettingsP->cl_annote_filename).toLatin1());
+        c2bUtils::warn(QObject::tr("Error: Could not open %1 file for reading").arg(c2bSettingsP->cl_annote_filename));
         return 1;
     }
 }
diff --git a/src/c2bConsole.h b/src/c2bConsole.h
index b7b2ed6..99af250 100644
--- a/src/c2bConsole.h
+++ b/src/c2bConsole.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCONSOLE_H
diff --git a/src/c2bCoreCiter.cpp b/src/c2bCoreCiter.cpp
index eaf5d75..780cc9d 100644
--- a/src/c2bCoreCiter.cpp
+++ b/src/c2bCoreCiter.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  *
  *   The LyX pipe procedure in citeToLyXPipe has been adapted from Tellico
diff --git a/src/c2bCoreCiter.h b/src/c2bCoreCiter.h
index 6676c30..aab9b55 100644
--- a/src/c2bCoreCiter.h
+++ b/src/c2bCoreCiter.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BCORECITER_H
diff --git a/src/c2bEditor.cpp b/src/c2bEditor.cpp
index e8a1456..1da7a72 100644
--- a/src/c2bEditor.cpp
+++ b/src/c2bEditor.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bEditor.h"
@@ -22,6 +22,8 @@
 #include "c2bUtils.h"
 #include "findDialog.h"
 
+#include <bibSearcher.h>
+
 #include <QCloseEvent>
 #include <QDir>
 #include <QDockWidget>
@@ -38,7 +40,7 @@
     The cb2Bib contains a practical editor suitable to manipulate the files
     related to a cb2Bib session. Abbreviations, bookmarks, regular expressions,
     and BibTeX are readily available. On BibTeX mode, the editor contains a
-    Reference List to easy file navigation and to extend the editor
+    Reference List to ease file navigation, and to extend the editor
     functionality. The BibTeX editor can optionally be turned to a reference
     browser.
 
@@ -210,26 +212,26 @@ summary="Summary table of Additional Functionality">
 
 c2bEditor::c2bEditor(const QString& file, const QString& mode, QWidget* main, QWidget* parentw) : QMainWindow(parentw)
 {
-    EFile = QDir::toNativeSeparators(file);
-    EditorMode = mode;
+    _editor_fn = QDir::toNativeSeparators(file);
+    _editor_mode = mode;
     _c2b_mainP = main;
-    bibSearcher = 0;
+    _searcherP = 0;
     initEditor();
 }
 
-c2bEditor::c2bEditor(const QString& file, c2bBibSearcher* searcher, QWidget* main, QWidget* parentw) : QMainWindow(parentw)
+c2bEditor::c2bEditor(const QString& file, bibSearcher* searcher, QWidget* main, QWidget* parentw) : QMainWindow(parentw)
 {
-    EFile = QDir::toNativeSeparators(file);
-    EditorMode = "BibTeX";
+    _editor_fn = QDir::toNativeSeparators(file);
+    _editor_mode = "BibTeX";
     _c2b_mainP = main;
-    bibSearcher = searcher;
+    _searcherP = searcher;
     initEditor();
 }
 
 c2bEditor::~c2bEditor()
 {
-    if (Browser)
-        settings->setValue("c2bEditor/BrowserFontPointSize", Browser->font().pointSize());
+    if (_browserP)
+        _settingsP->setValue("c2bEditor/BrowserFontPointSize", _browserP->font().pointSize());
 }
 
 
@@ -238,35 +240,35 @@ void c2bEditor::initEditor()
     ui.setupUi(this);
     setAttribute(Qt::WA_DeleteOnClose);
 
-    settings = c2bSettingsP;
-    if (EditorMode == "BibTeX")
-        bp = c2b::bibParser();
+    _settingsP = c2bSettingsP;
+    if (_editor_mode == "BibTeX")
+        _bpP = c2b::bibParser();
     else
-        bp = 0;
-    Browser = 0;
-    Editor = new c2bTextEdit(this);
-    RList = 0;
-    stackedWidget = new QStackedWidget(this);
-    setCentralWidget(stackedWidget);
-    stackedWidget->addWidget(Editor);
-    textFinder = new findDialog(this);
-    lineLabel = new QLabel();
-    lineLabel->setText(tr(" Line: 1 Col: 1 "));
-    lineLabel->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
-    lineLabel->setFrameStyle(QFrame::NoFrame);
-    lineLabel->setLineWidth(1);
-    lineLabel->setFixedHeight(lineLabel->fontMetrics().height());
-    statusBar()->addWidget(lineLabel, 1);
-    connect(Editor, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged()));
-    overwriteLabel = new QLabel();
-    overwriteLabel->setText(tr(" INS "));
-    overwriteLabel->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
-    overwriteLabel->setFrameStyle(QFrame::NoFrame);
-    overwriteLabel->setLineWidth(1);
-    overwriteLabel->setFixedHeight(overwriteLabel->fontMetrics().height());
-    statusBar()->addWidget(overwriteLabel);
-    Editor->setOverwriteMode(false);
-    connect(Editor, SIGNAL(overwriteModeChanged()), this, SLOT(overwriteModeChanged()));
+        _bpP = 0;
+    _browserP = 0;
+    _editorP = new c2bTextEdit(this);
+    _referencesP = 0;
+    _stackedWidgetP = new QStackedWidget(this);
+    setCentralWidget(_stackedWidgetP);
+    _stackedWidgetP->addWidget(_editorP);
+    _textFinderP = new findDialog(this);
+    _lineLabelP = new QLabel();
+    _lineLabelP->setText(tr(" Line: 1 Col: 1 "));
+    _lineLabelP->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
+    _lineLabelP->setFrameStyle(QFrame::NoFrame);
+    _lineLabelP->setLineWidth(1);
+    _lineLabelP->setFixedHeight(_lineLabelP->fontMetrics().height());
+    statusBar()->addWidget(_lineLabelP, 1);
+    connect(_editorP, SIGNAL(cursorPositionChanged()), this, SLOT(cursorPositionChanged()));
+    _overwriteLabelP = new QLabel();
+    _overwriteLabelP->setText(tr(" INS "));
+    _overwriteLabelP->setAlignment(Qt::AlignVCenter | Qt::AlignRight);
+    _overwriteLabelP->setFrameStyle(QFrame::NoFrame);
+    _overwriteLabelP->setLineWidth(1);
+    _overwriteLabelP->setFixedHeight(_overwriteLabelP->fontMetrics().height());
+    statusBar()->addWidget(_overwriteLabelP);
+    _editorP->setOverwriteMode(false);
+    connect(_editorP, SIGNAL(overwriteModeChanged()), this, SLOT(overwriteModeChanged()));
     connect(ui.fileCloseAction, SIGNAL(triggered()), this, SLOT(close()));
     connect(ui.fileExecAction, SIGNAL(triggered()), this, SLOT(saveAndExecute()));
     connect(ui.fileExitAction, SIGNAL(triggered()), c2b::instance(), SLOT(exitRequested()));
@@ -288,10 +290,10 @@ void c2bEditor::initEditor()
     ui.viewZoomOutAction->setShortcut(QKeySequence(QKeySequence::ZoomOut));
 
     // Editor Settings
-    resize(settings->value("c2bEditor/size", size()).toSize());
+    resize(_settingsP->value("c2bEditor/size", size()).toSize());
     ui.menuView->addAction(ui.toolBar->toggleViewAction());
     ui.setLyXPipeAction->setVisible(false);
-    Editor->setFont(settings->c2bMonoFont);
+    _editorP->setFont(_settingsP->c2bMonoFont);
     connect(ui.settingsCb2BibAction, SIGNAL(triggered()), c2b::instance(), SLOT(configure()));
 
     // Bookmarks
@@ -303,49 +305,49 @@ void c2bEditor::initEditor()
     load();
     setEditorMode();
     importActions();
-    connect(Editor->document(), SIGNAL(contentsChange(int, int, int)), this, SLOT(isModified(int, int, int)));
+    connect(_editorP->document(), SIGNAL(contentsChange(int, int, int)), this, SLOT(isModified(int, int, int)));
     connect(c2b::instance(), SIGNAL(statusMessage(const QString&)), this, SLOT(showMessage(const QString&)));
 }
 
 void c2bEditor::setEditorMode()
 {
-    if (EditorMode == "RegExp")
+    if (_editor_mode == "RegExp")
     {
-        sH = new c2bREHighlighter(Editor->document());
+        _shP = new c2bREHighlighter(_editorP->document());
         ui.fileExecAction->setText(tr("Restart Recognition"));
         ui.fileExecAction->setStatusTip(tr("Restart Recognition"));
         ui.fileExecAction->setShortcut(tr("Alt+R"));
         connect(this, SIGNAL(execute()), this, SIGNAL(restartEngine()));
-        ui.toolBar->setVisible(settings->value("c2bEditor/ToolBar", true).toBool());
+        ui.toolBar->setVisible(_settingsP->value("c2bEditor/ToolBar", true).toBool());
         setViewMode(true);
     }
-    else if (EditorMode == "NetQInfo")
+    else if (_editor_mode == "NetQInfo")
     {
-        sH = new c2bREHighlighter(Editor->document());
+        _shP = new c2bREHighlighter(_editorP->document());
         ui.fileExecAction->setText(tr("Restart Network Query"));
         ui.fileExecAction->setStatusTip(tr("Restart Network Query"));
         ui.fileExecAction->setShortcut(tr("Alt+N"));
         connect(this, SIGNAL(execute()), this, SIGNAL(restartQuery()));
-        ui.toolBar->setVisible(settings->value("c2bEditor/ToolBar", true).toBool());
+        ui.toolBar->setVisible(_settingsP->value("c2bEditor/ToolBar", true).toBool());
         setViewMode(true);
     }
-    else if (EditorMode == "JAbbrev")
+    else if (_editor_mode == "JAbbrev")
     {
         ui.fileExecAction->setVisible(false);
-        ui.toolBar->setVisible(settings->value("c2bEditor/ToolBar", true).toBool());
+        ui.toolBar->setVisible(_settingsP->value("c2bEditor/ToolBar", true).toBool());
         setViewMode(true);
     }
-    else if (EditorMode == "BibTeX")
+    else if (_editor_mode == "BibTeX")
     {
         // Editor
-        sH = new c2bBibHighlighter(Editor->document());
+        _shP = new c2bBibHighlighter(_editorP->document());
         ui.fileOpenAction->setVisible(true);
         connect(ui.fileOpenAction, SIGNAL(triggered()), this, SLOT(fileOpen()));
-        Editor->setBibTeXActions();
-        connect(Editor->pasteCurrentBibTeXAction, SIGNAL(triggered()), this, SLOT(pasteCurrentBibTeX()));
-        connect(Editor->journalsToFullAction, SIGNAL(triggered()), this, SLOT(journalsToFull()));
-        connect(Editor->journalsToAbbreviatedAction, SIGNAL(triggered()), this, SLOT(journalsToAbbreviated()));
-        connect(Editor->updateMetadataAction, SIGNAL(triggered()), this, SLOT(updateMetadata()));
+        _editorP->setBibTeXActions();
+        connect(_editorP->pasteCurrentBibTeXAction, SIGNAL(triggered()), this, SLOT(pasteCurrentBibTeX()));
+        connect(_editorP->journalsToFullAction, SIGNAL(triggered()), this, SLOT(journalsToFull()));
+        connect(_editorP->journalsToAbbreviatedAction, SIGNAL(triggered()), this, SLOT(journalsToAbbreviated()));
+        connect(_editorP->updateMetadataAction, SIGNAL(triggered()), this, SLOT(updateMetadata()));
         connect(_c2b_mainP, SIGNAL(addedBibToFile(const QString&)), this, SLOT(reload(const QString&)));
         ui.fileExecAction->setText(tr("Save and Postprocess"));
         ui.fileExecAction->setStatusTip(tr("Save and Postprocess"));
@@ -353,27 +355,27 @@ void c2bEditor::setEditorMode()
         connect(this, SIGNAL(execute()), this, SLOT(postProcess()));
 
         // Browser
-        Browser = new c2bTextBrowser(this);
-        Browser->setFont(QFont(QFont().family(), settings->value("c2bEditor/BrowserFontPointSize", QFont().pointSize()).toInt()));
-        stackedWidget->addWidget(Browser);
+        _browserP = new c2bTextBrowser(this);
+        _browserP->setFont(QFont(QFont().family(), _settingsP->value("c2bEditor/BrowserFontPointSize", QFont().pointSize()).toInt()));
+        _stackedWidgetP->addWidget(_browserP);
         ui.viewEditorModeAction->setVisible(true);
         connect(ui.viewEditorModeAction, SIGNAL(triggered(bool)), this, SLOT(setViewMode(bool)));
-        connect(ui.viewZoomInAction, SIGNAL(triggered()), Browser, SLOT(zoomIn()));
-        connect(ui.viewZoomOutAction, SIGNAL(triggered()), Browser, SLOT(zoomOut()));
+        connect(ui.viewZoomInAction, SIGNAL(triggered()), _browserP, SLOT(zoomIn()));
+        connect(ui.viewZoomOutAction, SIGNAL(triggered()), _browserP, SLOT(zoomOut()));
 
         // Reference List
         createReferenceList();
-        RList->loadList(Editor->toPlainText(), bibSearcher);
+        _referencesP->loadList(_editorP->toPlainText(), _searcherP);
         bool edit_mode(false);
-        if (bibSearcher)
+        if (_searcherP)
         {
-            edit_mode = (bibSearcher->hitCount() == 0 && bibSearcher->errorCount() > 0);
-            connect(RList, SIGNAL(openFile(const QString&)), this, SIGNAL(openFile(const QString&)));
+            edit_mode = (_searcherP->hitsCount() == 0 && _searcherP->errorsCount() > 0);
+            connect(_referencesP, SIGNAL(openFile(const QString&)), this, SIGNAL(openFile(const QString&)));
         }
-        if (!edit_reference_at_position.isEmpty())
+        if (!_edit_reference_at_position.isEmpty())
         {
             edit_mode = true;
-            RList->goToReference(edit_reference_at_position.toInt());
+            _referencesP->goToReference(_edit_reference_at_position.toInt());
         }
         ui.viewEditorModeAction->setChecked(edit_mode);
         setViewMode(edit_mode);
@@ -382,24 +384,24 @@ void c2bEditor::setEditorMode()
         // Export entries
         ui.fileExportEntriesAction->setVisible(true);
         connect(ui.fileExportEntriesAction, SIGNAL(triggered()), this, SLOT(exportEntries()));
-        connect(RList, SIGNAL(hasSelectedItems(bool)), ui.fileExportEntriesAction, SLOT(setEnabled(bool)));
+        connect(_referencesP, SIGNAL(hasSelectedItems(bool)), ui.fileExportEntriesAction, SLOT(setEnabled(bool)));
     }
     else
-        c2bUtils::debug(tr("c2bEditor::setEditorMode: '%1' invalid Editor Mode.").arg(EditorMode));
+        c2bUtils::debug(tr("c2bEditor::setEditorMode: '%1' invalid Editor Mode.").arg(_editor_mode));
 }
 
 void c2bEditor::importActions()
 {
-    QList<QAction*> acts = textFinder->actions();
+    QList<QAction*> acts = _textFinderP->actions();
     for (int i = 0; i < acts.count(); ++i)
         ui.menuEdit->addAction(acts.at(i));
-    acts = Editor->actions();
+    acts = _editorP->actions();
     for (int i = 0; i < acts.count(); ++i)
         ui.menuEdit->addAction(acts.at(i));
-    if (Browser)
+    if (_browserP)
     {
         ui.menuEdit->addSeparator();
-        acts = Browser->actions();
+        acts = _browserP->actions();
         for (int i = 0; i < acts.count(); ++i)
             ui.menuEdit->addAction(acts.at(i));
     }
@@ -407,19 +409,19 @@ void c2bEditor::importActions()
 
 void c2bEditor::createReferenceList()
 {
-    dwRList = new QDockWidget(this);
-    dwRList->setObjectName("dwRList");
-    RList = new c2bReferenceList(Editor, Browser, dwRList);
-    addDockWidget(Qt::BottomDockWidgetArea, dwRList);
-    dwRList->setWidget(RList);
-    dwRList->setWindowTitle("Reference List");
-    QByteArray state = settings->value("c2bEditor/state").toByteArray();
+    _dockWidgetP = new QDockWidget(this);
+    _dockWidgetP->setObjectName("dwRList");
+    _referencesP = new c2bReferenceList(_editorP, _browserP, _dockWidgetP);
+    addDockWidget(Qt::BottomDockWidgetArea, _dockWidgetP);
+    _dockWidgetP->setWidget(_referencesP);
+    _dockWidgetP->setWindowTitle("Reference List");
+    QByteArray state = _settingsP->value("c2bEditor/state").toByteArray();
     restoreState(state);
-    ui.menuView->addAction(dwRList->toggleViewAction());
+    ui.menuView->addAction(_dockWidgetP->toggleViewAction());
     // State contains toolBar info, too, but it can be changed from non BibTeX editors
     // State can not be used for non BibTeX editors. They don't have referenceList.
-    ui.toolBar->setVisible(settings->value("c2bEditor/ToolBar", true).toBool());
-    connect(ui.setLyXPipeAction, SIGNAL(triggered()), RList, SLOT(setLyXPipe()));
+    ui.toolBar->setVisible(_settingsP->value("c2bEditor/ToolBar", true).toBool());
+    connect(ui.setLyXPipeAction, SIGNAL(triggered()), _referencesP, SLOT(setLyXPipe()));
 }
 
 void c2bEditor::closeEvent(QCloseEvent* qevent)
@@ -449,10 +451,10 @@ bool c2bEditor::closeEditor()
         else if (button == QMessageBox::Cancel)
             return false;
     }
-    settings->setValue("c2bEditor/size", size());
-    if (EditorMode == "BibTeX")
-        settings->setValue("c2bEditor/state", saveState());
-    settings->setValue("c2bEditor/ToolBar", !ui.toolBar->isHidden());
+    _settingsP->setValue("c2bEditor/size", size());
+    if (_editor_mode == "BibTeX")
+        _settingsP->setValue("c2bEditor/state", saveState());
+    _settingsP->setValue("c2bEditor/ToolBar", !ui.toolBar->isHidden());
     return true;
 }
 
@@ -467,9 +469,9 @@ void c2bEditor::isModified(int position, int charsRemoved, int charsAdded)
 
 void c2bEditor::fileOpen()
 {
-    if (EditorMode == "BibTeX")
+    if (_editor_mode == "BibTeX")
     {
-        const QString filename(c2bFileDialog::getOpenFilename(this, "Select a BibTeX filename", EFile, "BibTeX (*.bib)"));
+        const QString filename(c2bFileDialog::getOpenFilename(this, "Select a BibTeX filename", _editor_fn, "BibTeX (*.bib)"));
         if (!filename.isEmpty())
             emit openFile(filename);
     }
@@ -477,23 +479,23 @@ void c2bEditor::fileOpen()
 
 bool c2bEditor::fileSave()
 {
-    if (EFile.contains("unnamed_"))
+    if (_editor_fn.contains("unnamed_"))
         return fileSaveAs();
-    QFile file(EFile);
+    QFile file(_editor_fn);
     if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
     {
         QMessageBox::warning(this, tr("Warning - cb2Bib"),
                              tr("Unable to open the file %1 for writing.\nError: '%2'.").
-                             arg(EFile).arg(file.errorString()),
+                             arg(_editor_fn).arg(file.errorString()),
                              QMessageBox::Ok);
         return false;
     }
     QTextStream stream(&file);
     stream.setCodec("UTF-8");
     stream.setAutoDetectUnicode(true);
-    stream << Editor->toPlainText();
+    stream << _editorP->toPlainText();
     ui.fileSaveAction->setEnabled(false);
-    Editor->document()->setModified(false);
+    _editorP->document()->setModified(false);
     setWindowModified(false);
     _is_modified_by_user = false;
     return true;
@@ -502,17 +504,17 @@ bool c2bEditor::fileSave()
 bool c2bEditor::fileSaveAs()
 {
     QString filename;
-    if (EditorMode == "BibTeX")
-        filename = c2bFileDialog::getSaveFilename(this, "", EFile, "BibTeX (*.bib);;All (*)");
+    if (_editor_mode == "BibTeX")
+        filename = c2bFileDialog::getSaveFilename(this, "", _editor_fn, "BibTeX (*.bib);;All (*)");
     else
-        filename = c2bFileDialog::getSaveFilename(this, "", EFile, "Text (*.txt);;All (*)");
+        filename = c2bFileDialog::getSaveFilename(this, "", _editor_fn, "Text (*.txt);;All (*)");
     if (filename.isEmpty() || filename.contains("unnamed_"))
         return false;
-    const QString old_name(EFile);
-    EFile = filename;
-    setWindowTitle(tr("%1[*] - cb2Bib").arg(EFile));
-    Editor->setEditorFilename(EFile);
-    emit editFileRenamed(old_name, EFile);
+    const QString old_name(_editor_fn);
+    _editor_fn = filename;
+    setWindowTitle(tr("%1[*] - cb2Bib").arg(_editor_fn));
+    _editorP->setEditorFilename(_editor_fn);
+    emit editFileRenamed(old_name, _editor_fn);
     return fileSave();
 }
 
@@ -532,8 +534,8 @@ void c2bEditor::saveAndExecute()
 void c2bEditor::load()
 {
     bool modified_flag(false);
-    QFileInfo fi(EFile);
-    if (EFile.isEmpty() || fi.isDir())  // Set an appropriate working name
+    QFileInfo fi(_editor_fn);
+    if (_editor_fn.isEmpty() || fi.isDir())  // Set an appropriate working name
     {
         QStringList unamedList;
         foreach(QWidget* widget, QApplication::topLevelWidgets())
@@ -543,27 +545,27 @@ void c2bEditor::load()
         }
         int i(1);
         while (unamedList.indexOf(QRegExp(QString(".*unnamed_%1.bib").arg(i))) > -1) ++i;
-        EFile = QDir::toNativeSeparators(QDir::cleanPath(EFile + QDir::separator() + QString("unnamed_%1.bib").arg(i)));
-        if (bibSearcher)
+        _editor_fn = QDir::toNativeSeparators(QDir::cleanPath(_editor_fn + QDir::separator() + QString("unnamed_%1.bib").arg(i)));
+        if (_searcherP)
         {
-            Editor->setPlainText(bibSearcher->logString + bibSearcher->hitString);
+            _editorP->setPlainText(_searcherP->logString() + _searcherP->hitsString());
             modified_flag = true;
         }
     }
     else
     {
         QRegExp edit_ref_id(":(\\d+)$");
-        if (edit_ref_id.indexIn(EFile) > -1)
+        if (edit_ref_id.indexIn(_editor_fn) > -1)
         {
-            edit_reference_at_position = edit_ref_id.cap(1);
-            EFile.remove(edit_ref_id);
+            _edit_reference_at_position = edit_ref_id.cap(1);
+            _editor_fn.remove(edit_ref_id);
         }
-        QFile file(EFile);
+        QFile file(_editor_fn);
         if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
         {
             QMessageBox::warning(_c2b_mainP,
                                  tr("Warning - cb2Bib"), tr("Unable to open the file %1 for reading.\nError: '%2'.").
-                                 arg(EFile).arg(file.errorString()),
+                                 arg(_editor_fn).arg(file.errorString()),
                                  QMessageBox::Ok);
         }
         else
@@ -571,22 +573,22 @@ void c2bEditor::load()
             QTextStream stream(&file);
             stream.setCodec("UTF-8");
             stream.setAutoDetectUnicode(true);
-            Editor->setPlainText(stream.readAll());
+            _editorP->setPlainText(stream.readAll());
         }
     }
-    setWindowTitle(tr("%1[*] - cb2Bib").arg(EFile));
-    Editor->setEditorFilename(EFile);
+    setWindowTitle(tr("%1[*] - cb2Bib").arg(_editor_fn));
+    _editorP->setEditorFilename(_editor_fn);
     ui.fileSaveAction->setEnabled(modified_flag);
-    Editor->document()->setModified(modified_flag);
+    _editorP->document()->setModified(modified_flag);
     setWindowModified(modified_flag);
     _is_modified_by_user = false;
 }
 
-void c2bEditor::reload(const QString& f)
+void c2bEditor::reload(const QString& fn)
 {
     // This function must be called ONLY in BibTeX mode
     // Pointers are undefined otherwise
-    if (EditorMode != "BibTeX" || EFile != f)
+    if (_editor_mode != "BibTeX" || _editor_fn != fn)
         return;
 
     if (ui.fileSaveAction->isEnabled())
@@ -605,60 +607,60 @@ void c2bEditor::reload(const QString& f)
         if (button == QMessageBox::Save)
         {
             fileSave();
-            RList->refreshList();
+            _referencesP->refreshList();
             return;
         }
         else if (button == QMessageBox::Cancel)
             return;
     }
     load();
-    RList->refreshList();
-    QTextCursor cur = Editor->textCursor();
+    _referencesP->refreshList();
+    QTextCursor cur = _editorP->textCursor();
     cur.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
-    Editor->setTextCursor(cur);
-    Editor->ensureCursorVisible();
+    _editorP->setTextCursor(cur);
+    _editorP->ensureCursorVisible();
 }
 
 void c2bEditor::exportEntries()
 {
-    const QStringList keys(RList->selectedKeys());
+    const QStringList keys(_referencesP->selectedKeys());
     if (keys.count() == 0)
         return;
-    c2bExportDialog ed(EFile, keys, this);
+    c2bExportDialog ed(_editor_fn, _editorP->toPlainText(), keys, this);
     if (ed.exec())
         emit openFile(ed.exportFilename());
 }
 
 void c2bEditor::pasteCurrentBibTeX()
 {
-    Editor->insertPlainText(bp->toBibTeX(false));
+    _editorP->insertPlainText(_bpP->toBibTeX(false));
 }
 
 void c2bEditor::journalsToFull()
 {
     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
-    const QString text(bp->setJournalsToFull(Editor->toPlainText()));
-    Editor->updatePlainText(text);
+    const QString text(_bpP->setJournalsToFull(_editorP->toPlainText()));
+    _editorP->updatePlainText(text);
     QApplication::restoreOverrideCursor();
 }
 
 void c2bEditor::journalsToAbbreviated()
 {
     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
-    const QString text(bp->setJournalsToAbbreviated(Editor->toPlainText()));
-    Editor->updatePlainText(text);
+    const QString text(_bpP->setJournalsToAbbreviated(_editorP->toPlainText()));
+    _editorP->updatePlainText(text);
     QApplication::restoreOverrideCursor();
 }
 
 void c2bEditor::updateMetadata()
 {
     c2bUpdateMetadata um(this);
-    um.update(EFile, Editor->toPlainText());
+    um.update(_editor_fn, _editorP->toPlainText());
 }
 
 void c2bEditor::postProcess()
 {
-    c2bPostprocess* ppBib = new c2bPostprocess(EFile, this);
+    c2bPostprocess* ppBib = new c2bPostprocess(_editor_fn, this);
     ppBib->show();
 }
 
@@ -682,33 +684,33 @@ void c2bEditor::setViewMode(bool edit_mode)
     QList<QAction*> acts;
     if (edit_mode)
     {
-        textFinder->setEditor(Editor);
-        if (Browser)
+        _textFinderP->setEditor(_editorP);
+        if (_browserP)
         {
-            acts = Browser->actions();
+            acts = _browserP->actions();
             for (int i = 0; i < acts.count(); ++i)
                 acts.at(i)->setVisible(false);
             ui.viewZoomInAction->setVisible(false);
             ui.viewZoomOutAction->setVisible(false);
         }
-        acts = Editor->actions();
+        acts = _editorP->actions();
         for (int i = 0; i < acts.count(); ++i)
             acts.at(i)->setVisible(true);
-        stackedWidget->setCurrentWidget(Editor);
+        _stackedWidgetP->setCurrentWidget(_editorP);
     }
     else
     {
         // Browser defined
-        textFinder->setEditor(Browser);
-        acts = Editor->actions();
+        _textFinderP->setEditor(_browserP);
+        acts = _editorP->actions();
         for (int i = 0; i < acts.count(); ++i)
             acts.at(i)->setVisible(false);
-        acts = Browser->actions();
+        acts = _browserP->actions();
         for (int i = 0; i < acts.count(); ++i)
             acts.at(i)->setVisible(true);
         ui.viewZoomInAction->setVisible(true);
         ui.viewZoomOutAction->setVisible(true);
-        stackedWidget->setCurrentWidget(Browser);
+        _stackedWidgetP->setCurrentWidget(_browserP);
     }
 }
 
@@ -720,22 +722,22 @@ void c2bEditor::showMessage(const QString& ms)
 void c2bEditor::cursorPositionChanged()
 {
     int lineNumber(0);
-    QTextBlock current = Editor->textCursor().block();
+    QTextBlock current = _editorP->textCursor().block();
     QTextBlock b;
-    for (b = Editor->document()->begin(); b.isValid(); b = b.next())
+    for (b = _editorP->document()->begin(); b.isValid(); b = b.next())
     {
         ++lineNumber;
         if (b == current)
             break;
     }
-    int linePosition(Editor->textCursor().position() - current.position() + 1);
-    lineLabel->setText(tr(" Line: %1 Col: %2 ").arg(lineNumber).arg(linePosition));
+    int linePosition(_editorP->textCursor().position() - current.position() + 1);
+    _lineLabelP->setText(tr(" Line: %1 Col: %2 ").arg(lineNumber).arg(linePosition));
 }
 
 void c2bEditor::overwriteModeChanged()
 {
-    if (Editor->overwriteMode())
-        overwriteLabel->setText(tr(" OVR "));
+    if (_editorP->overwriteMode())
+        _overwriteLabelP->setText(tr(" OVR "));
     else
-        overwriteLabel->setText(tr(" INS "));
+        _overwriteLabelP->setText(tr(" INS "));
 }
diff --git a/src/c2bEditor.h b/src/c2bEditor.h
index faaa256..b7d677b 100644
--- a/src/c2bEditor.h
+++ b/src/c2bEditor.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BEDITOR_H
@@ -9,8 +9,6 @@
 
 #include "ui_c2bEditor.h"
 
-#include "c2bBibSearcher.h"
-
 #include <QMainWindow>
 #include <QPointer>
 
@@ -19,6 +17,7 @@ class QDockWidget;
 class QLabel;
 class QStackedWidget;
 class QSyntaxHighlighter;
+class bibSearcher;
 class c2bBibParser;
 class c2bReferenceList;
 class c2bSettings;
@@ -34,13 +33,13 @@ class c2bEditor : public QMainWindow
 
 public:
     c2bEditor(const QString& file, const QString& mode, QWidget* main, QWidget* parentw = 0);
-    c2bEditor(const QString& file, c2bBibSearcher* searcher, QWidget* main, QWidget* parentw = 0);
+    c2bEditor(const QString& file, bibSearcher* searcher, QWidget* main, QWidget* parentw = 0);
 
     ~c2bEditor();
 
     inline QString editorFilename() const
     {
-        return EFile;
+        return _editor_fn;
     }
     bool closeEditor();
 
@@ -73,7 +72,7 @@ protected slots:
     void overwriteModeChanged();
     void pasteCurrentBibTeX();
     void postProcess();
-    void reload(const QString& f);
+    void reload(const QString& fn);
     void saveAndExecute();
     void setViewMode(bool edit_mode);
     void showMessage(const QString& ms);
@@ -82,24 +81,24 @@ protected slots:
 
 
 private:
-    QDockWidget* dwRList;
-    QLabel* lineLabel;
-    QLabel* overwriteLabel;
-    QPointer<c2bBibSearcher> bibSearcher;
-    QStackedWidget* stackedWidget;
-    QString EFile;
-    QString EditorMode;
-    QString edit_reference_at_position;
-    QSyntaxHighlighter* sH;
+    QDockWidget* _dockWidgetP;
+    QLabel* _lineLabelP;
+    QLabel* _overwriteLabelP;
+    QPointer<bibSearcher> _searcherP;
+    QStackedWidget* _stackedWidgetP;
+    QString _edit_reference_at_position;
+    QString _editor_fn;
+    QString _editor_mode;
+    QSyntaxHighlighter* _shP;
     QWidget* _c2b_mainP;
     Ui::c2bEditor ui;
     bool _is_modified_by_user;
-    c2bBibParser* bp;
-    c2bReferenceList* RList;
-    c2bSettings* settings;
-    c2bTextBrowser* Browser;
-    c2bTextEdit* Editor;
-    findDialog* textFinder;
+    c2bBibParser* _bpP;
+    c2bReferenceList* _referencesP;
+    c2bSettings* _settingsP;
+    c2bTextBrowser* _browserP;
+    c2bTextEdit* _editorP;
+    findDialog* _textFinderP;
     void createReferenceList();
     void importActions();
     void initEditor();
diff --git a/src/c2bExport.cpp b/src/c2bExport.cpp
index 4d570a2..970166b 100644
--- a/src/c2bExport.cpp
+++ b/src/c2bExport.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bExport.h"
@@ -21,20 +21,19 @@ c2bExport::~c2bExport()
 void c2bExport::exportEntries(const export_data& ed)
 {
     // Note. Assume caller performs export_data validity check for files and directories.
-    bibParser* bp = c2b::bibParser();
     // Prefer replacing filenames to a full BibTeX parsing: This will preserve the
     // original entry and possibly available non cb2Bib tags.
+    bibParser* bp = c2b::bibParser();
     QStringList fields;
     if (ed.copy_documents)
         fields.append("file");
     QRegExp filere("\\bfile\\s*=\\s*[\\{\"](.*)[\\}\"]", Qt::CaseInsensitive);
     filere.setMinimal(true);
-    const QString bibtex_contents(c2bUtils::fileToString(ed.bibtex_fn));
     QString export_contents("\n\n");
     QString export_log;
     bibReference ref;
     bp->initReferenceParsing(ed.bibtex_fn, fields, &ref);
-    while (bp->referencesIn(bibtex_contents, &ref))
+    while (bp->referencesIn(ed.bibtex_contents, &ref))
     {
         if (!ed.bibtex_keys.contains(ref.citeidName, Qt::CaseSensitive))
             continue;
@@ -65,5 +64,5 @@ void c2bExport::exportEntries(const export_data& ed)
     if (!export_log.isEmpty())
         export_contents = "% cb2Bib " + C2B_VERSION + " / Export Error Log\n" + export_log + export_contents;
     if (!c2bUtils::stringToFile(export_contents, ed.export_fn))
-        qDebug(tr("[cb2Bib] Unable to write file %1.").arg(ed.export_fn).toLatin1());
+        c2bUtils::warn(tr("Unable to write file %1").arg(ed.export_fn));
 }
diff --git a/src/c2bExport.h b/src/c2bExport.h
index fe6e6b5..41fba20 100644
--- a/src/c2bExport.h
+++ b/src/c2bExport.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BEXPORT_H
@@ -22,6 +22,7 @@ public:
 
     struct export_data
     {
+        QString bibtex_contents;
         QString bibtex_fn;
         QString documents_dir;
         QString export_fn;
diff --git a/src/c2bExportDialog.cpp b/src/c2bExportDialog.cpp
index 3ace042..ea70db1 100644
--- a/src/c2bExportDialog.cpp
+++ b/src/c2bExportDialog.cpp
@@ -1,13 +1,12 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bExportDialog.h"
 
 #include "c2b.h"
-#include "c2bExport.h"
 #include "c2bFileDialog.h"
 #include "c2bSettings.h"
 #include "c2bUtils.h"
@@ -16,13 +15,21 @@
 #include <QPushButton>
 
 
-c2bExportDialog::c2bExportDialog(const QString& fn, const QStringList& keys, QWidget* parentw) :
-        QDialog(parentw), _bibtex_fn(fn), _bibtex_keys(keys)
+c2bExportDialog::c2bExportDialog(const QString& fn, const QString& contents, const QStringList& keys, QWidget* parentw) :
+        QDialog(parentw)
 {
+    _ed.bibtex_fn = fn;
+    if (contents.isEmpty())
+        _ed.bibtex_contents = c2bUtils::fileToString(fn);
+    else
+        _ed.bibtex_contents = contents;
+    _ed.bibtex_keys = keys;
     ui.setupUi(this);
     setWindowTitle(tr("Export Entries - cb2Bib"));
     QPushButton* buttonExport = new QPushButton(tr("Export"));
     ui.buttonBox->addButton(buttonExport, QDialogButtonBox::ActionRole);
+    buttonExport->setAutoDefault(true);
+    buttonExport->setDefault(true);
     connect(buttonExport, SIGNAL(clicked()), this, SLOT(_export()));
 
     settings = c2bSettingsP;
@@ -51,26 +58,23 @@ c2bExportDialog::~c2bExportDialog()
 
 void c2bExportDialog::_export()
 {
-    c2bExport::export_data ed;
-    ed.bibtex_fn = _bibtex_fn;
-    ed.bibtex_keys = _bibtex_keys;
-    ed.copy_documents = ui.CopyDocuments->isChecked();
-    ed.documents_dir = ui.DocumentsDirectory->text();
-    ed.export_fn = ui.ExportFile->text();
-    ed.relative_dir = ui.RelativeDocumentDirectory->isChecked();
+    _ed.copy_documents = ui.CopyDocuments->isChecked();
+    _ed.documents_dir = ui.DocumentsDirectory->text();
+    _ed.export_fn = ui.ExportFile->text();
+    _ed.relative_dir = ui.RelativeDocumentDirectory->isChecked();
 
     // Check files
-    if (QFileInfo(ed.export_fn).exists())
+    if (QFileInfo(_ed.export_fn).exists())
     {
         const int button(QMessageBox::warning(this, tr("Warning - cb2Bib"),
-                                              tr("File %1 already exists.\nDo you want to replace it?").arg(ed.export_fn),
+                                              tr("File %1 already exists.\nDo you want to replace it?").arg(_ed.export_fn),
                                               QMessageBox::Yes | QMessageBox::No));
         if (button == QMessageBox::No)
             return;
     }
-    if (ed.copy_documents)
+    if (_ed.copy_documents)
     {
-        const QString ddname(c2bUtils::documentAbsoluteName(ed.relative_dir, ed.export_fn, ed.documents_dir, "") + QDir::separator());
+        const QString ddname(c2bUtils::documentAbsoluteName(_ed.relative_dir, _ed.export_fn, _ed.documents_dir, "") + QDir::separator());
         QDir doc_dir(ddname);
         if (!doc_dir.exists())
             if (!doc_dir.mkpath(ddname))
@@ -80,9 +84,10 @@ void c2bExportDialog::_export()
                 return;
             }
     }
-
+    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
     c2bExport e(this);
-    e.exportEntries(ed);
+    e.exportEntries(_ed);
+    QApplication::restoreOverrideCursor();
     accept();
 }
 
diff --git a/src/c2bExportDialog.h b/src/c2bExportDialog.h
index 0514c88..805b412 100644
--- a/src/c2bExportDialog.h
+++ b/src/c2bExportDialog.h
@@ -1,12 +1,14 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BEXPORTDIALOG_H
 #define C2BEXPORTDIALOG_H
 
+#include "c2bExport.h"
+
 #include "ui_c2bExportDialog.h"
 
 #include <QDialog>
@@ -20,7 +22,7 @@ class c2bExportDialog : public QDialog
     Q_OBJECT
 
 public:
-    c2bExportDialog(const QString& fn, const QStringList& keys, QWidget* parentw = 0);
+    c2bExportDialog(const QString& fn, const QString& contents, const QStringList& keys, QWidget* parentw = 0);
     ~c2bExportDialog();
 
     inline const QString exportFilename() const
@@ -31,9 +33,8 @@ public:
 
 private:
     Ui::c2bExportDialog ui;
+    c2bExport::export_data _ed;
     c2bSettings* settings;
-    const QString& _bibtex_fn;
-    const QStringList& _bibtex_keys;
 
 
 private slots:
diff --git a/src/c2bExportDialog.ui b/src/c2bExportDialog.ui
index ab2c3a1..5a9423a 100644
--- a/src/c2bExportDialog.ui
+++ b/src/c2bExportDialog.ui
@@ -5,17 +5,14 @@
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>635</width>
-    <height>280</height>
+    <width>563</width>
+    <height>306</height>
    </rect>
   </property>
   <property name="windowTitle" >
    <string>Dialog</string>
   </property>
   <layout class="QGridLayout" >
-   <property name="margin" >
-    <number>6</number>
-   </property>
    <item row="0" column="0" >
     <widget class="QGroupBox" name="groupBox2" >
      <property name="title" >
@@ -68,13 +65,22 @@
     </widget>
    </item>
    <item row="2" column="0" >
-    <widget class="QCheckBox" name="CopyDocuments" >
-     <property name="text" >
-      <string>Copy Documents</string>
-     </property>
-     <property name="shortcut" >
+    <widget class="QGroupBox" name="groupBox" >
+     <property name="title" >
       <string/>
      </property>
+     <layout class="QGridLayout" >
+      <item row="0" column="0" >
+       <widget class="QCheckBox" name="CopyDocuments" >
+        <property name="text" >
+         <string>Copy Documents</string>
+        </property>
+        <property name="shortcut" >
+         <string/>
+        </property>
+       </widget>
+      </item>
+     </layout>
     </widget>
    </item>
    <item row="3" column="0" >
diff --git a/src/c2bFileDialog.cpp b/src/c2bFileDialog.cpp
index 999039c..7d5fbff 100644
--- a/src/c2bFileDialog.cpp
+++ b/src/c2bFileDialog.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bFileDialog.h"
@@ -11,7 +11,6 @@
 #include <QLineEdit>
 #include <QPushButton>
 #include <QTimer>
-#include <QtDebug>
 
 
 c2bFileDialog::c2bFileDialog(QWidget* parentw, const QString& caption, const QString& fpath, const QString& ffilter)
diff --git a/src/c2bFileDialog.h b/src/c2bFileDialog.h
index aa57655..299ec29 100644
--- a/src/c2bFileDialog.h
+++ b/src/c2bFileDialog.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BFILEDIALOG_H
diff --git a/src/c2bHighlighter.cpp b/src/c2bHighlighter.cpp
index d9147f5..61ca7c7 100644
--- a/src/c2bHighlighter.cpp
+++ b/src/c2bHighlighter.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bHighlighter.h"
diff --git a/src/c2bHighlighter.h b/src/c2bHighlighter.h
index 4863631..f75491a 100644
--- a/src/c2bHighlighter.h
+++ b/src/c2bHighlighter.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BHIGHLIGHTER_H
diff --git a/src/c2bIdLineEdit.cpp b/src/c2bIdLineEdit.cpp
index 8ed7152..c7f5208 100644
--- a/src/c2bIdLineEdit.cpp
+++ b/src/c2bIdLineEdit.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  *
  *   Improvements and modifications:
@@ -70,7 +70,7 @@ c2bIdLineEdit::c2bIdLineEdit(QWidget* parentw) : c2bLineEdit(parentw)
     a_year_abbreviated->setText(tr("Insert <<year_abbreviated>>"));
     a_year_full->setText(tr("Insert <<year_full>>"));
 
-    a_reset->setText(tr("Reset CiteID Pattern"));
+    a_reset->setText(tr("Reset ID Pattern"));
 
     connect(a_author_all_abbreviated, SIGNAL(triggered()), this, SLOT(author_all_abbreviated()));
     connect(a_author_all_initials, SIGNAL(triggered()), this, SLOT(author_all_initials()));
diff --git a/src/c2bIdLineEdit.h b/src/c2bIdLineEdit.h
index f49631f..2b932d7 100644
--- a/src/c2bIdLineEdit.h
+++ b/src/c2bIdLineEdit.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  *
  *   Improvements and modifications:
diff --git a/src/c2bLineEdit.cpp b/src/c2bLineEdit.cpp
index 8440021..85b05e8 100644
--- a/src/c2bLineEdit.cpp
+++ b/src/c2bLineEdit.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bLineEdit.h"
diff --git a/src/c2bLineEdit.h b/src/c2bLineEdit.h
index df20f98..b810676 100644
--- a/src/c2bLineEdit.h
+++ b/src/c2bLineEdit.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BLINEEDIT_H
diff --git a/src/c2bNetworkQuery.cpp b/src/c2bNetworkQuery.cpp
index 2c8dabe..73a56d1 100644
--- a/src/c2bNetworkQuery.cpp
+++ b/src/c2bNetworkQuery.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bNetworkQuery.h"
diff --git a/src/c2bNetworkQuery.h b/src/c2bNetworkQuery.h
index 82dfb3f..7a9b8d5 100644
--- a/src/c2bNetworkQuery.h
+++ b/src/c2bNetworkQuery.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BNETWORKQUERY_H
diff --git a/src/c2bNetworkQueryInfo.cpp b/src/c2bNetworkQueryInfo.cpp
index 98d8ae8..eaac1a7 100644
--- a/src/c2bNetworkQueryInfo.cpp
+++ b/src/c2bNetworkQueryInfo.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bNetworkQueryInfo.h"
@@ -65,7 +65,7 @@ void c2bNetworkQueryInfo::parseBookmarks()
         {
             line.remove(_bookmark);
             if (line.count('|') == 0)
-                qDebug(tr("[cb2bib] c2bNetworkQueryInfo::parseBookmarks: Syntax error at '%1'").arg(line).toLatin1());
+                c2bUtils::warn(tr("c2bNetworkQueryInfo::parseBookmarks: Syntax error at '%1'").arg(line));
             else
                 BookmarkList.append(line);
         }
diff --git a/src/c2bNetworkQueryInfo.h b/src/c2bNetworkQueryInfo.h
index ea17cb8..d1c2202 100644
--- a/src/c2bNetworkQueryInfo.h
+++ b/src/c2bNetworkQueryInfo.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BNETWORKQUERYINFO_H
diff --git a/src/c2bPdfImport.cpp b/src/c2bPdfImport.cpp
index 6c1c477..ae10575 100644
--- a/src/c2bPdfImport.cpp
+++ b/src/c2bPdfImport.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bPdfImport.h"
@@ -46,7 +46,7 @@
     goal in the cb2Bib. Thus, at this point, the cb2Bib invites users to check
     their references. Poorly translated characters, accented letters,
     'forgotten' words, or some minor formatting in the titles might be worth
-    considering. See 
+    considering. See
     \htmlonly
     <a href="http://www.glyphandcog.com/textext.html" target="_blank">Text Extraction</a>
     \endhtmlonly
@@ -75,12 +75,12 @@
 
 
     - <b>Unsupervised processing</b>\n In this operation mode, all files will
-    be sequentially processed, following the chosen steps and rules. If the
-    processes is successful, the reference is automatically saved, and the next
-    file is processed. If it is not, the file is skipped and no reference is
-    saved. While processing, the clipboard is disabled for safety. Once
-    finished, this box is unchecked, to avoid a possible accidental saving of a
-    void reference. Network queries that require intervention, i.e., whose
+    be sequentially processed, following the chosen steps and rules. <b>If the
+    processes is successful</b>, the reference is automatically saved, and the
+    next file is processed. <b>If it is not</b>, the file is skipped and no
+    reference is saved. While processing, the clipboard is disabled for safety.
+    Once finished, this box is unchecked, to avoid a possible accidental saving
+    of a void reference. Network queries that require intervention, i.e., whose
     result is launching a given page, are disabled. The processes follows until
     all files are processed. However, it will stop to avoid a file being
     overwritten, as a result of a repeated key. In this case, it will resume
@@ -88,6 +88,129 @@
     '--txt2bib' and '--doc2bib'.
 
 
+
+    <p>&nbsp;</p>
+    \section faq_automatic_extraction Automatic Extraction: Questions and Answers
+
+    - <b>When does cb2Bib do automatic extractions?</b>
+    The cb2Bib is conceived as a lightweight tool to extract references and
+    manage bibliographies in a simple, fast, and accurate way. Accuracy is
+    better achieved in semi-automatic extractions. Such extractions are handy,
+    and allow user intervention and verification. However, in cases where one
+    has accumulated a large number of unindexed documents, automatic processing
+    can be convenient. The cb2Bib does automatic extraction when, in PDFImport
+    mode, 'Unsupervised processing' is checked, or, in command line mode, when
+    typing <tt>cb2bib --doc2bib *.pdf tmp_references.bib</tt>, or, on Windows,
+    <tt>c2bconsole.exe</tt> instead of <tt>cb2bib</tt>.
+
+    - <b>Are PDFImport and command line modes equivalent?</b>
+    Yes. There are, however, two minor differences. First, PDFImport adds each
+    reference to the current BibTeX file, as this behavior is the normal one in
+    cb2Bib. On the other hand, command line mode will, instead, overwrite
+    <tt>tmp_references.bib</tt> if it exists, as this is the expected behavior
+    for almost all command line tools. Second, as for now, command line mode
+    does not follow the configuration option 'Check Repeated On Save'.
+
+    - <b>How do I do automatic extraction?</b>
+    To test and learn about automatic extractions, the cb2Bib distribution
+    includes a set of four PDF files that mimic a paper title page. For these
+    files, distribution also includes a regular expression, in file
+    <tt>regexps.txt</tt> capable of extracting the reference fields, provided
+    the <tt>pdftotex</tt> flags are set to their default values. Processing
+    these files, should, therefore, be automatic, and four messages stating
+    <tt>Processed as 'PDF Import Example'</tt> should be seen in the logs. Note
+    that extractions are configurable. A reading of \ref c2bconf will provide
+    additional, useful information.
+
+    - <b>Why some entries are not saved and files not renamed?</b>
+    Once you move from the fabricated examples to real cases, you will realize
+    that some of the files, while being processed, are not renamed and their
+    corresponding BibTeX data is not written. For each document file, cb2Bib
+    converts its first page to text, and from this text it attempts to extract
+    the bibliographic reference. By design, when extraction fails, cb2bib does
+    nothing: no file is moved, no BibTeX is written. This way, you know that
+    the remaining files in the origin directory need special, manual attention.
+    <b>Extractions are always seen as failed, unless reliable data is found in
+    the text</b>.
+
+    - <b>What is <em>reliable data</em>?</b>
+    Note that computer processing of natural texts, as extracting the
+    bibliographic data from a title page, is nowadays an approximated
+    procedure. The cb2bib tries several strategies: <b>1)</b> allow for
+    including user regular expressions very specific to the extraction at hand,
+    <b>2)</b> use metadata if available, <b>3)</b> guess what is reasonable,
+    and, based on this, make customized queries. Then, cb2Bib considers
+    extracted <b>data is reliable if i)</b> data comes from a match to an user
+    supplied regular expression <b>ii)</b> document contains BibTeX metadata,
+    or <b>iii)</b> a guess is transformed through a query to formatted
+    bibliographic data. As formatted bibliographic data, cb2Bib only
+    understands BibTeX, and, as an exception, PubMed XML data. However, it
+    allows external processing if needed. Any other data, metadata, guesses,
+    and guesses on query results are considered unreliable data.
+
+    - <b>Is metadata reliable data?</b>
+    No. Only author, title, and keywords in standard PDF metadata can be mapped
+    to their corresponding bibliographic fields. Furthermore, publishers most
+    often misuse these three keys, placing, for instance, DOI in title, or
+    setting author to, perhaps, the document typesetter. Only BibTeX XMP
+    metadata is considered reliable, and only documents already processed with
+    cb2Bib or JabRef will have it. If you consider that a set of PDF files does
+    contain reliable data, you may force to accept it using the command line
+    switch <tt>--sloppy</tt> together with <tt>--doc2bib</tt>.
+
+    - <b>How successful is automatic extraction?</b>
+    As it follows from the given definition of reliable data, running automatic
+    extractions without adhoc <tt>regexps.txt</tt> and <tt>netqinf.txt</tt>
+    files will certainly give a zero success ratio. In practice, scenario 3)
+    often applies: cb2Bib guesses several fields, and, based on the
+    out-of-the-box <tt>netqinf.txt</tt> file, it obtains from the web either
+    BibTeX or PubMed XML data. Thus, biologists, for instance, usually have
+    success ratios close to 100%, since PubMed is almost complete for them, and
+    its data is extremely accurate.
+
+    - <b>What can I do to increase success ratio?</b>
+    First, set your favorite journals in file <tt>abbreviations.txt</tt>.
+    Besides increasing the chances of journal name recognition, it will provide
+    consistency across your BibTeX database. In general, do not write regular
+    expressions to extract directly from the PDF text. Conversion is often
+    poor. Special characters often break lines, thus breaking your regular
+    expressions too. Write customized queries. For instance, if your PDFs have
+    DOI in title page, set the simple query
+  \verbatim
+  journal=The Journal of Everything|
+  query=http://dx.doi.org/<<doi>>
+  capture_from_query=
+  referenceurl_prefix=
+  referenceurl_sufix=
+  pdfurl_prefix=
+  pdfurl_sufix=
+  action=htm2txt_query
+  \endverbatim
+    then, if it is feasible to extract the reference from the document's web
+    page using a regular expression, include it in file <tt>regexps.txt</tt>.
+    Note that querying in cb2Bib had been designed having in mind minority
+    fields of research, for which, established databases might not be
+    available. If cb2Bib failed to make reasonable guesses, then, you might
+    consider writing very simple regular expressions to extract directly from
+    the PDF text. For instance, obtain title only. Then, the posterior query
+    step can provide the remaining information. Note also, especially for old
+    documents, journal name is often missing from the paper title page. If in
+    need of processing a series of those papers, consider using a simple
+    script, that, in the cb2Bib preprocessing step, adds this missing
+    information.
+
+    - <b>Does successful extraction mean accurate extraction?</b>
+    No. An extraction is successful if reliable data, as defined above, is
+    found in the text, in the metadata, or in the text returned by a query.
+    Reference accuracy relies on whether or not user regular expressions are
+    robust, BibTeX metadata is correct, a guess is appropriate, a set of
+    queries can correct a partially incorrect guess, and the text returned by a
+    query is accurate. In general, well designed sets of regular expressions
+    are accurate. Publisher's abstract pages and PubMed are accurate. But, some
+    publishers are still using images for non-ASCII characters, and PubMed
+    algorithms may drop author middle names if a given author has 'too many
+    names'. Expect convenience over accuracy on other sources.
+
     <p>&nbsp;</p>
 */
 c2bPdfImport::c2bPdfImport(QWidget* parentw) : QDialog(parentw)
diff --git a/src/c2bPdfImport.h b/src/c2bPdfImport.h
index 4d149dc..f50d6cd 100644
--- a/src/c2bPdfImport.h
+++ b/src/c2bPdfImport.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BPDFIMPORT_H
diff --git a/src/c2bPostprocess.cpp b/src/c2bPostprocess.cpp
index 91e41e9..16d8dce 100644
--- a/src/c2bPostprocess.cpp
+++ b/src/c2bPostprocess.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bPostprocess.h"
diff --git a/src/c2bPostprocess.h b/src/c2bPostprocess.h
index 59f616a..e683f6b 100644
--- a/src/c2bPostprocess.h
+++ b/src/c2bPostprocess.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BPOSTPROCESS_H
diff --git a/src/c2bREHighlighter.cpp b/src/c2bREHighlighter.cpp
index 56f5deb..bf6615b 100644
--- a/src/c2bREHighlighter.cpp
+++ b/src/c2bREHighlighter.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bREHighlighter.h"
diff --git a/src/c2bREHighlighter.h b/src/c2bREHighlighter.h
index 94b2f62..92e3d3b 100644
--- a/src/c2bREHighlighter.h
+++ b/src/c2bREHighlighter.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BREHIGHLIGHTER_H
diff --git a/src/c2bRLWebSearchSettings.cpp b/src/c2bRLWebSearchSettings.cpp
index 500ae64..826a9a9 100644
--- a/src/c2bRLWebSearchSettings.cpp
+++ b/src/c2bRLWebSearchSettings.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bRLWebSearchSettings.h"
diff --git a/src/c2bRLWebSearchSettings.h b/src/c2bRLWebSearchSettings.h
index 38fbe25..8f53b60 100644
--- a/src/c2bRLWebSearchSettings.h
+++ b/src/c2bRLWebSearchSettings.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BRLWEBSEARCHSETTINGS_H
diff --git a/src/c2bReferenceList.cpp b/src/c2bReferenceList.cpp
index 223beda..9b974a3 100644
--- a/src/c2bReferenceList.cpp
+++ b/src/c2bReferenceList.cpp
@@ -1,14 +1,13 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bReferenceList.h"
 
 #include "c2b.h"
 #include "c2bBibParser.h"
-#include "c2bBibSearcher.h"
 #include "c2bCoreCiter.h"
 #include "c2bRLWebSearchSettings.h"
 #include "c2bSettings.h"
@@ -16,6 +15,8 @@
 #include "c2bTextEdit.h"
 #include "c2bUtils.h"
 
+#include <bibSearcher.h>
+
 #include <QHeaderView>
 #include <QMenu>
 #include <QScrollBar>
@@ -171,7 +172,7 @@ c2bReferenceList::~c2bReferenceList()
 {}
 
 
-void c2bReferenceList::loadList(const QString& txt, c2bBibSearcher* bibSearcher)
+void c2bReferenceList::loadList(const QString& txt, bibSearcher* searcher)
 {
     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
     c2bBibParser* bpP = c2b::bibParser();
@@ -210,12 +211,12 @@ void c2bReferenceList::loadList(const QString& txt, c2bBibSearcher* bibSearcher)
             author_long = author;
             author_long.remove(nonletters);
             author_long.replace(" and ", ", ");
-            author_long = author_long.simplified();
+            c2bUtils::simplifyString(author_long);
             author_long += '.';
             author.remove(initials1);
             author.remove(initials2);
             author.replace(" and ", ", ");
-            author = author.simplified();
+            c2bUtils::simplifyString(author);
         }
 
         QString title(ref.anyTitle());
@@ -281,9 +282,8 @@ void c2bReferenceList::loadList(const QString& txt, c2bBibSearcher* bibSearcher)
         bib_item_html.replace("GET_REFERENCE_TITLE", c2bUtils::toHtmlString(title));
         bib_item_html.replace("GET_REFERENCE_VOLUME", volume);
         bib_item_html.replace("GET_REFERENCE_YEAR", year);
-        if (bibSearcher)
-            bib_item_html.replace("GET_REFERENCE_ABSTRACT", bibSearcher->highlight(abstract) +
-                                  bibSearcher->hitMap.value(ref.rawReference));
+        if (searcher)
+            bib_item_html.replace("GET_REFERENCE_ABSTRACT", searcher->highlight(abstract) + searcher->hitValue(ref.rawReference));
         else
             bib_item_html.replace("GET_REFERENCE_ABSTRACT", c2bUtils::toHtmlString(abstract));
         references += bib_item_html;
@@ -597,27 +597,17 @@ void c2bReferenceList::setLyXPipe()
 
 void c2bReferenceList::setupFilterBar()
 {
-    _filter_mode = _settingsP->value("c2bReferenceList/FilterMode", "Approximate string").toString();
+    const QStringList types(searchPattern::types());
+    _filter_mode = _settingsP->value("c2bReferenceList/FilterMode", types.first()).toString();
     QActionGroup* filterMode = new QActionGroup(this);
     filterMode->setExclusive(true);
-    QAction* act = filterMode->addAction("Approximate string");
-    act->setCheckable(true);
-    if (_filter_mode == "Approximate string") act->setChecked(true);
-    act = filterMode->addAction("Fixed string");
-    act->setCheckable(true);
-    if (_filter_mode == "Fixed string") act->setChecked(true);
-    act = filterMode->addAction("Fixed string: All Words");
-    act->setCheckable(true);
-    if (_filter_mode == "Fixed string: All Words") act->setChecked(true);
-    act = filterMode->addAction("Fixed string: Any Word");
-    act->setCheckable(true);
-    if (_filter_mode == "Fixed string: Any Word") act->setChecked(true);
-    act = filterMode->addAction("Regular expression");
-    act->setCheckable(true);
-    if (_filter_mode == "Regular expression") act->setChecked(true);
-    act = filterMode->addAction("Wildcard");
-    act->setCheckable(true);
-    if (_filter_mode == "Wildcard") act->setChecked(true);
+    for (int i = 0; i < types.count(); ++i)
+    {
+        const QString& t = types.at(i);
+        QAction* act = filterMode->addAction(t);
+        act->setCheckable(true);
+        if (_filter_mode == t) act->setChecked(true);
+    }
     QMenu* filterModeM = new QMenu(this);
     filterModeM->addActions(filterMode->actions());
     ui.filterB->setMenu(filterModeM);
@@ -652,7 +642,7 @@ void c2bReferenceList::filterList()
     }
     else
     {
-        c2bSearchPattern pattern(text, _filter_mode);
+        searchPattern pattern(text, _filter_mode);
         QTreeWidgetItemIterator it(ui.listView);
         while (*it)
         {
diff --git a/src/c2bReferenceList.h b/src/c2bReferenceList.h
index e8bab94..225d4b5 100644
--- a/src/c2bReferenceList.h
+++ b/src/c2bReferenceList.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BREFERENCELIST_H
@@ -11,7 +11,8 @@
 
 #include <QWidget>
 
-class c2bBibSearcher;
+
+class bibSearcher;
 class c2bCoreCiter;
 class c2bRLWebSearchSettings;
 class c2bSettings;
@@ -44,7 +45,7 @@ public:
 
 
 public slots:
-    void loadList(const QString& txt, c2bBibSearcher* bibSearcher = 0);
+    void loadList(const QString& txt, bibSearcher* searcher = 0);
     void refreshList();
     void setLyXPipe();
 
diff --git a/src/c2bSaveREHighlighter.cpp b/src/c2bSaveREHighlighter.cpp
index 04261da..427d429 100644
--- a/src/c2bSaveREHighlighter.cpp
+++ b/src/c2bSaveREHighlighter.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bSaveREHighlighter.h"
diff --git a/src/c2bSaveREHighlighter.h b/src/c2bSaveREHighlighter.h
index 55e9da2..3f7140c 100644
--- a/src/c2bSaveREHighlighter.h
+++ b/src/c2bSaveREHighlighter.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BSAVEREHIGHLIGHTER_H
diff --git a/src/c2bSaveRegExp.cpp b/src/c2bSaveRegExp.cpp
index de3f3b1..a310e96 100644
--- a/src/c2bSaveRegExp.cpp
+++ b/src/c2bSaveRegExp.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bSaveRegExp.h"
@@ -108,7 +108,7 @@ journal
 */
 c2bSaveRegExp::c2bSaveRegExp(const QStringList& pattern, const QString& input, QWidget* parentw) : QDialog(parentw)
 {
-    Q_ASSERT_X(pattern.count() == 3, "c2bSaveRegExp", "expected exactly three strings for pattern");
+    Q_ASSERT_X(pattern.count() == 3, "c2bSaveRegExp", "Expected exactly three strings for pattern");
     ui.setupUi(this);
     connect(ui.buttonBox, SIGNAL(helpRequested()), this, SLOT(help()));
     c2bSettings* settings = c2bSettingsP;
diff --git a/src/c2bSaveRegExp.h b/src/c2bSaveRegExp.h
index 565fb85..6a3c424 100644
--- a/src/c2bSaveRegExp.h
+++ b/src/c2bSaveRegExp.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BSAVEREGEXP_H
diff --git a/src/c2bSearchInFiles.cpp b/src/c2bSearchInFiles.cpp
index a20e97d..4f85c29 100644
--- a/src/c2bSearchInFiles.cpp
+++ b/src/c2bSearchInFiles.cpp
@@ -1,15 +1,16 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bSearchInFiles.h"
 
 #include "c2b.h"
-#include "c2bBibSearcher.h"
 #include "c2bUtils.h"
 
+#include <bibSearcher.h>
+
 #include <QFileInfo>
 #include <QTime>
 
@@ -29,17 +30,17 @@ c2bSearchInFiles::c2bSearchInFiles(const QString& file, QWidget* parentw) : QDia
     ui.buttonBox->button(QDialogButtonBox::Abort)->setEnabled(false);
     ui.buttonBox->button(QDialogButtonBox::Close)->setAutoDefault(false);
     ui.buttonBox->button(QDialogButtonBox::Close)->setDefault(false);
-    searchB = new QPushButton(tr("Search"));
-    ui.buttonBox->addButton(searchB, QDialogButtonBox::ActionRole);
-    searchB->setAutoDefault(true);
-    searchB->setDefault(true);
-    searchB->setEnabled(false);
-
-    m_bibtex_file.clear();
-    m_bibtex_dir.clear();
+    _searchB = new QPushButton(tr("Search"));
+    ui.buttonBox->addButton(_searchB, QDialogButtonBox::ActionRole);
+    _searchB->setAutoDefault(true);
+    _searchB->setDefault(true);
+    _searchB->setEnabled(false);
+
+    _bibtex_file.clear();
+    _bibtex_dir.clear();
     setBibTeXFile(file);
 
-    connect(searchB, SIGNAL(clicked()), this, SLOT(searchB_clicked()));
+    connect(_searchB, SIGNAL(clicked()), this, SLOT(searchB_clicked()));
     connect(ui.allBibFiles, SIGNAL(clicked()), this, SLOT(setBibTeXFile()));
     connect(ui.buttonBox, SIGNAL(helpRequested()), this, SLOT(help()));
     connect(ui.pattern, SIGNAL(patternAvailable(bool)), this, SLOT(updateForm()));
@@ -56,7 +57,7 @@ void c2bSearchInFiles::updateForm()
     ui.addPatternB->setEnabled(ui.pattern->isAvailable());
     ui.Boolean->setEnabled((ui.patternList->topLevelItemCount() > 1) ||
                            (ui.pattern->isAvailable() && ui.patternList->topLevelItemCount() > 0));
-    searchB->setEnabled(ui.pattern->isAvailable() || ui.patternList->topLevelItemCount() > 0);
+    _searchB->setEnabled(!_bibtex_dir.isEmpty() && (ui.pattern->isAvailable() || ui.patternList->topLevelItemCount() > 0));
     if (ui.patternList->currentItem())
     {
         ui.deletePatternB->setEnabled(true);
@@ -67,12 +68,12 @@ void c2bSearchInFiles::updateForm()
         ui.deletePatternB->setEnabled(false);
         ui.editPatternB->setEnabled(false);
     }
-    ui.searchLog->setText(searchLogText);
+    ui.searchLog->setText(_search_log);
 }
 
 void c2bSearchInFiles::on_addPatternB_clicked()
 {
-    new QTreeWidgetItem(ui.patternList, ui.pattern->pattern());
+    new QTreeWidgetItem(ui.patternList, ui.pattern->patterns());
     for (int i = 0; i < ITEMS_IN_SEARCH_PATTERN; ++i)
         ui.patternList->resizeColumnToContents(i);
     ui.pattern->clear();
@@ -99,7 +100,7 @@ void c2bSearchInFiles::on_editPatternB_clicked()
             ui_editor.buttonBox->button(QDialogButtonBox::Ok), SLOT(setEnabled(bool)));
     if (editor.exec() == QDialog::Accepted)
     {
-        const QStringList pattern(ui_editor.pattern->pattern());
+        const QStringList pattern(ui_editor.pattern->patterns());
         for (int i = 0; i < ITEMS_IN_SEARCH_PATTERN; ++i)
             item->setText(i, pattern.at(i));
         for (int i = 0; i < ITEMS_IN_SEARCH_PATTERN; ++i)
@@ -110,19 +111,19 @@ void c2bSearchInFiles::on_editPatternB_clicked()
 void c2bSearchInFiles::searchB_clicked()
 {
     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
-    searchB->setEnabled(false);
+    _searchB->setEnabled(false);
     ui.buttonBox->button(QDialogButtonBox::Abort)->setEnabled(true);
 
-    ui.searchLog->setText(searchLogText);
-    c2bBibSearcher searcher;
+    ui.searchLog->setText(_search_log);
+    bibSearcher searcher(c2b::bibParser());
     connect(ui.buttonBox->button(QDialogButtonBox::Abort), SIGNAL(clicked()), &searcher, SLOT(abort()));
-    searcher.setScope(m_bibtex_file, m_bibtex_dir, ui.allBibFiles->isChecked(), ui.documentFiles->isChecked());
+    searcher.setSearchScope(_bibtex_file, _bibtex_dir, ui.allBibFiles->isChecked(), ui.documentFiles->isChecked());
     searcher.setSimplifySource(ui.simplifySource->isChecked());
     searcher.setBoolean(ui.Boolean->currentText() == "All");
     if (ui.addPatternB->isEnabled())
     {
-        const QStringList p(ui.pattern->pattern());
-        searcher.addPattern(p.at(0) == "NOT", p.at(1) == "Sensitive", p.at(2), p.at(3), p.at(4), p.at(5));
+        const QStringList p(ui.pattern->patterns());
+        searcher.addPattern(p.at(0) == "NOT", p.at(1) == "Sensitive", p.at(2), p.at(3), p.at(4).at(0), p.at(5));
     }
     QTreeWidgetItemIterator it(ui.patternList);
     while (*it)
@@ -130,33 +131,38 @@ void c2bSearchInFiles::searchB_clicked()
         QStringList p;
         for (int i = 0; i < ITEMS_IN_SEARCH_PATTERN; ++i)
             p.append((*it)->text(i));
-        searcher.addPattern(p.at(0) == "NOT", p.at(1) == "Sensitive", p.at(2), p.at(3), p.at(4), p.at(5));
+        searcher.addPattern(p.at(0) == "NOT", p.at(1) == "Sensitive", p.at(2), p.at(3), p.at(4).at(0), p.at(5));
         ++it;
     }
-    if (searcher.patternCount() == 0)
+    if (searcher.patternsCount() == 0)
         return;
 
     QTime t;
     t.start();
     searcher.exec();
 
-    if (searcher.hitCount() > 0 || searcher.errorCount() > 0)
+    QString search_status;
+    if (searcher.hitsCount() > 0 || searcher.errorsCount() > 0)
     {
-        if (searcher.hitCount() > 0)
-            ui.searchLog->setText(tr("Found %1 hits from %2 references (%3s)")
-                                  .arg(searcher.hitCount()).arg(searcher.referenceCount()).arg(t.elapsed() / 1000.0));
+        if (searcher.hitsCount() > 0)
+            search_status = tr("Found %1 hits from %2 references (%3s)")
+                            .arg(searcher.hitsCount()).arg(searcher.referencesCount()).arg(t.elapsed() / 1000.0);
         else
-            ui.searchLog->setText(searchLogText);
+            ui.searchLog->setText(_search_log);
         QApplication::processEvents();
-        emit searchDone(m_bibtex_dir, &searcher);
+        emit searchDone(_bibtex_dir, &searcher);
     }
-    else if (searcher.errorCount() < 0)
-        ui.searchLog->setText(tr("Search aborted"));
+    else if (searcher.errorsCount() < 0)
+        search_status = tr("Search aborted");
     else
-        ui.searchLog->setText(tr("No reference found (%1s)").arg(t.elapsed() / 1000.0));
-
+        search_status = tr("No reference found (%1s)").arg(t.elapsed() / 1000.0);
+    if (!search_status.isEmpty())
+    {
+        ui.searchLog->setText(search_status);
+        c2b::showMessage(search_status);
+    }
     ui.buttonBox->button(QDialogButtonBox::Abort)->setEnabled(false);
-    searchB->setEnabled(true);
+    _searchB->setEnabled(true);
     QApplication::restoreOverrideCursor();
 }
 
@@ -165,14 +171,22 @@ void c2bSearchInFiles::setBibTeXFile(const QString& file)
     if (!file.isEmpty())
     {
         QFileInfo fi(file);
-        m_bibtex_file = fi.absoluteFilePath();
-        m_bibtex_dir = fi.absolutePath();
+        QDir d(fi.absolutePath());
+        if (d.exists())
+        {
+            _bibtex_file = fi.absoluteFilePath();
+            _bibtex_dir = fi.absolutePath();
+        }
+        else
+            _bibtex_dir.clear();
     }
-    if (ui.allBibFiles->isChecked())
-        searchLogText = tr("Search in files at %1").arg(m_bibtex_dir);
+    if (_bibtex_dir.isEmpty())
+        _search_log = tr("No existing file or directory set for searching");
+    else if (ui.allBibFiles->isChecked())
+        _search_log = tr("Search in files at %1").arg(_bibtex_dir);
     else
-        searchLogText = tr("Search in file %1").arg(m_bibtex_file);
-    ui.searchLog->setText(searchLogText);
+        _search_log = tr("Search in file %1").arg(_bibtex_file);
+    updateForm();
 }
 
 void c2bSearchInFiles::setCurrentText(const QString& text)
diff --git a/src/c2bSearchInFiles.h b/src/c2bSearchInFiles.h
index 6783e64..fdabff8 100644
--- a/src/c2bSearchInFiles.h
+++ b/src/c2bSearchInFiles.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BSEARCHINFILES_H
@@ -13,7 +13,7 @@
 #include <QDialog>
 
 
-class c2bBibSearcher;
+class bibSearcher;
 
 class c2bSearchInFiles : public QDialog
 {
@@ -33,7 +33,7 @@ public slots:
 
 
 signals:
-    void searchDone(const QString& filename, c2bBibSearcher* searcher);
+    void searchDone(const QString& filename, bibSearcher* searcher);
 
 
 private slots:
@@ -46,12 +46,12 @@ private slots:
 
 
 private:
-    QPushButton* searchB;
-    QString m_bibtex_dir;
-    QString m_bibtex_file;
-    QString searchLogText;
-    Ui::c2bSearchInFilesPatternEdit ui_editor;
+    QPushButton* _searchB;
+    QString _bibtex_dir;
+    QString _bibtex_file;
+    QString _search_log;
     Ui::c2bSearchInFiles ui;
+    Ui::c2bSearchInFilesPatternEdit ui_editor;
 
 };
 
diff --git a/src/c2bSearchInFilesPattern.cpp b/src/c2bSearchInFilesPattern.cpp
index 50d917f..3c57934 100644
--- a/src/c2bSearchInFilesPattern.cpp
+++ b/src/c2bSearchInFilesPattern.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bSearchInFilesPattern.h"
@@ -10,6 +10,8 @@
 #include "c2bBibParser.h"
 #include "c2bSettings.h"
 
+#include <searchPattern.h>
+
 #include <QTreeWidgetItem>
 
 
@@ -17,8 +19,9 @@ c2bSearchInFilesPattern::c2bSearchInFilesPattern(QWidget* parentw) : QWidget(par
 {
     ui.setupUi(this);
     c2bBibParser* bp = c2b::bibParser();
-    ui.patternScope->addItems(bp->sortedBibliographicFields());
+    ui.patternType->addItems(searchPattern::types());
     ui.patternType->setCurrentIndex(c2bSettingsP->value("c2bSearchInFiles/PatternTypeIndex", 0).toInt());
+    ui.patternScope->addItems(bp->sortedBibliographicFields());
     ui.yearScope->hide();
     ui.inputPattern->setFocus();
 
@@ -50,55 +53,55 @@ void c2bSearchInFilesPattern::clear()
     ui.inputPattern->setFocus();
 }
 
-void c2bSearchInFilesPattern::setPattern(QTreeWidgetItem* newPattern)
+void c2bSearchInFilesPattern::setPattern(QTreeWidgetItem* pattern)
 {
-    if (!newPattern)
+    if (!pattern)
         return;
-    if (newPattern->columnCount() != ITEMS_IN_SEARCH_PATTERN)
+    if (pattern->columnCount() != ITEMS_IN_SEARCH_PATTERN)
         return;
 
-    if (newPattern->text(0) == "NOT")
+    if (pattern->text(0) == "NOT")
         ui.NOT->setChecked(true);
     else
         ui.NOT->setChecked(false);
-    if (newPattern->text(1) == "Sensitive")
+    if (pattern->text(1) == "Sensitive")
         ui.caseSensitive->setChecked(true);
     else
         ui.caseSensitive->setChecked(false);
-    ui.patternType->setCurrentIndex(ui.patternType->findText(newPattern->text(2)));
-    ui.patternScope->setCurrentIndex(ui.patternScope->findText(newPattern->text(3)));
-    if (newPattern->text(4) == "=")
+    ui.patternType->setCurrentIndex(ui.patternType->findText(pattern->text(2)));
+    ui.patternScope->setCurrentIndex(ui.patternScope->findText(pattern->text(3)));
+    if (pattern->text(4) == "=")
         ui.yearScope->setCurrentIndex(ui.yearScope->findText("Exact"));
-    else if (newPattern->text(4) == ">")
+    else if (pattern->text(4) == ">")
         ui.yearScope->setCurrentIndex(ui.yearScope->findText("Newer"));
     else
         ui.yearScope->setCurrentIndex(ui.yearScope->findText("Older"));
-    ui.inputPattern->setText(newPattern->text(5));
+    ui.inputPattern->setText(pattern->text(5));
 }
 
-const QStringList c2bSearchInFilesPattern::pattern()
+const QStringList c2bSearchInFilesPattern::patterns()
 {
-    QStringList _pattern;
+    QStringList p;
     if (ui.NOT->isChecked())
-        _pattern.append("NOT");
+        p.append("NOT");
     else
-        _pattern.append(QString());
+        p.append(QString());
     if (ui.caseSensitive->isChecked())
-        _pattern.append("Sensitive");
+        p.append("Sensitive");
     else
-        _pattern.append("Insensitive");
-    _pattern.append(ui.patternType->currentText());
-    _pattern.append(ui.patternScope->currentText());
+        p.append("Insensitive");
+    p.append(ui.patternType->currentText());
+    p.append(ui.patternScope->currentText());
     if (ui.yearScope->isHidden())
-        _pattern.append(QString());
+        p.append(" ");
     else if (ui.yearScope->currentText() == "Exact")
-        _pattern.append("=");
+        p.append("=");
     else if (ui.yearScope->currentText() == "Newer")
-        _pattern.append(">");
+        p.append(">");
     else if (ui.yearScope->currentText() == "Older")
-        _pattern.append("<");
-    _pattern.append(ui.inputPattern->text());
-    return _pattern;
+        p.append("<");
+    p.append(ui.inputPattern->text());
+    return p;
 }
 
 void c2bSearchInFilesPattern::showYearScope(const QString& scope)
diff --git a/src/c2bSearchInFilesPattern.h b/src/c2bSearchInFilesPattern.h
index a51083c..8291795 100644
--- a/src/c2bSearchInFilesPattern.h
+++ b/src/c2bSearchInFilesPattern.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BSEARCHINFILESPATTERN_H
@@ -25,9 +25,9 @@ public:
     c2bSearchInFilesPattern(QWidget* parentw = 0);
     ~c2bSearchInFilesPattern();
 
-    const QStringList pattern();
+    const QStringList patterns();
     void clear();
-    void setPattern(QTreeWidgetItem* newPattern);
+    void setPattern(QTreeWidgetItem* pattern);
     void setText(const QString& text);
 
     inline bool isAvailable() const
diff --git a/src/c2bSearchInFilesPattern.ui b/src/c2bSearchInFilesPattern.ui
index 7b94a1b..8262281 100644
--- a/src/c2bSearchInFilesPattern.ui
+++ b/src/c2bSearchInFilesPattern.ui
@@ -90,36 +90,6 @@
        <verstretch>0</verstretch>
       </sizepolicy>
      </property>
-     <item>
-      <property name="text" >
-       <string>Approximate string</string>
-      </property>
-     </item>
-     <item>
-      <property name="text" >
-       <string>Fixed string</string>
-      </property>
-     </item>
-     <item>
-      <property name="text" >
-       <string>Fixed string: All Words</string>
-      </property>
-     </item>
-     <item>
-      <property name="text" >
-       <string>Fixed string: Any Word</string>
-      </property>
-     </item>
-     <item>
-      <property name="text" >
-       <string>Regular expression</string>
-      </property>
-     </item>
-     <item>
-      <property name="text" >
-       <string>Wildcard</string>
-      </property>
-     </item>
     </widget>
    </item>
    <item row="2" column="1" >
diff --git a/src/c2bSearchPattern.cpp b/src/c2bSearchPattern.cpp
deleted file mode 100644
index d03b357..0000000
--- a/src/c2bSearchPattern.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2004-2009 by Pere Constans
- *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
- *   See the LICENSE file that comes with this distribution.
- ***************************************************************************/
-#include "c2bSearchPattern.h"
-
-#include <approximatePattern.h>
-#include <wordPattern.h>
-
-
-c2bSearchPattern::c2bSearchPattern(const QString& newPattern, const QString& newPatternType)
-{
-    pattern = newPattern;
-    rx.setCaseSensitivity(Qt::CaseInsensitive);
-    initType(newPatternType);
-    Not = false;
-    _rank = 0;
-}
-
-c2bSearchPattern::c2bSearchPattern(bool newNot, bool newCaseSensitive, const QString& newPatternType, const QString& newScope,
-                                   const QString& newYearScope, const QString& newPattern)
-{
-    Not = newNot;
-    pattern = newPattern;
-    scope = newScope;
-    yearScope = newYearScope;
-
-    if (newCaseSensitive)
-        rx.setCaseSensitivity(Qt::CaseSensitive);
-    else
-        rx.setCaseSensitivity(Qt::CaseInsensitive);
-    initType(newPatternType);
-    if (Not)
-        _pattern_string += "NOT.";
-    _pattern_string += QString(" [%1][%2|case=%3]").arg(pattern).arg(newPatternType).arg(newCaseSensitive);
-    if (scope == "year")
-        _pattern_string += QString(" IN [%1(%2)]").arg(scope).arg(yearScope);
-    else
-        _pattern_string += QString(" IN [%1]").arg(scope);
-
-    // Set an approximate ranking to speed up composite searches
-    _rank = 0;
-    if (scope == "all" || scope == "file")
-        _rank += 100;
-    else if (scope == "year" || scope == "volume" || scope == "pages")
-        _rank += 50;
-    else
-        _rank += 1;
-    if (!newCaseSensitive)
-        _rank *= 2;
-    if (newPatternType == "Fixed string: All Words" || newPatternType == "Fixed string: Any Word")
-        _rank *= 5;
-    else if (newPatternType == "Approximate string")
-        _rank *= 10;
-}
-
-
-void c2bSearchPattern::initType(const QString& type)
-{
-    if (type == "Approximate string")
-    {
-        approximatePattern ap(pattern, rx.caseSensitivity());
-        rx = ap.toRegExp();
-        subrx = ap.subpatterns();
-        _match_any_subpattern = true;
-    }
-    else if (type == "Fixed string: All Words")
-    {
-        wordPattern ap(pattern, rx.caseSensitivity());
-        rx = ap.toRegExp();
-        subrx = ap.subpatterns();
-        _match_any_subpattern = false;
-    }
-    else if (type == "Fixed string: Any Word")
-    {
-        wordPattern ap(pattern, rx.caseSensitivity());
-        rx = ap.toRegExp();
-        subrx = ap.subpatterns();
-        _match_any_subpattern = true;
-    }
-    else
-    {
-        rx.setPattern(pattern);
-        if (type == "Fixed string")
-            rx.setPatternSyntax(QRegExp::FixedString);
-        else if (type == "Regular Expresion")
-            rx.setPatternSyntax(QRegExp::RegExp);
-        else if (type == "Wildcard")
-            rx.setPatternSyntax(QRegExp::Wildcard);
-        rx.setMinimal(true);
-    }
-}
diff --git a/src/c2bSearchPattern.h b/src/c2bSearchPattern.h
deleted file mode 100644
index 59b851a..0000000
--- a/src/c2bSearchPattern.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/***************************************************************************
- *   Copyright (C) 2004-2009 by Pere Constans
- *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
- *   See the LICENSE file that comes with this distribution.
- ***************************************************************************/
-#ifndef C2BSEARCHPATTERN_H
-#define C2BSEARCHPATTERN_H
-
-#include <QRegExp>
-#include <QList>
-
-
-class c2bSearchPattern
-{
-
-public:
-    c2bSearchPattern(const QString& newPattern, const QString& newPatternType);
-    c2bSearchPattern(bool newNot, bool newCaseSensitive, const QString& newPatternType, const QString& newScope,
-                     const QString& newYearScope, const QString& newPattern);
-
-    QList<QRegExp> subrx;
-    QRegExp rx;
-    QString pattern;
-    QString scope;
-    QString yearScope;
-    bool Not;
-
-    inline bool matches(const QString& contents) const
-    {
-        if (subrx.count() > 0)
-        {
-            // Decompose pattern to scan long strings.
-            // Decomposing improves efficiency over a factor of two.
-            // Probability sorted subpatterns improves an additional ~15%.
-            if (_match_any_subpattern)
-            {
-                for (int i = 0; i < subrx.count(); ++i)
-                    if (contents.contains(subrx.at(i)))
-                        return true;
-                return false;
-            }
-            else
-            {
-                for (int i = subrx.count() - 1; i >= 0; --i)
-                    if (!contents.contains(subrx.at(i)))
-                        return false;
-                return true;
-            }
-        }
-        else
-            return contents.contains(rx);
-    }
-
-    inline const QString toString() const
-    {
-        return _pattern_string;
-    }
-
-    inline bool operator< (const c2bSearchPattern& p) const
-    {
-        return (_rank < p._rank);
-    }
-
-
-private:
-    QString _pattern_string;
-    bool _match_any_subpattern;
-    int _rank;
-    void initType(const QString& type);
-
-};
-
-#endif
diff --git a/src/c2bSettings.cpp b/src/c2bSettings.cpp
index d295045..f2db32b 100644
--- a/src/c2bSettings.cpp
+++ b/src/c2bSettings.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bSettings.h"
diff --git a/src/c2bSettings.h b/src/c2bSettings.h
index 3913a5c..136f3a7 100644
--- a/src/c2bSettings.h
+++ b/src/c2bSettings.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BSETTINGS_H
diff --git a/src/c2bTests.cpp b/src/c2bTests.cpp
index ac8dd8a..8f4e6b0 100644
--- a/src/c2bTests.cpp
+++ b/src/c2bTests.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #define C2B_CHECK_CAPITALIZATION 0
@@ -46,12 +46,62 @@ int c2bTests::allTests()
     heuristic_misc();
     heuristic_author();
     heuristic_check_patterns();
+    compression_check();
 
     cout << endl << endl;
     cout << "Tests done. Tests: " << _test_count << " Failed: " << _failed_test_count << endl;
     return 0;
 }
 
+void c2bTests::compression_check()
+{
+    QString test;
+    test += QChar(100);
+    test += QChar(200);
+    test += QChar(8700);
+    test += QChar(56200);
+    test += QChar(57000);
+    test += QChar(10);
+    test += QChar(100);
+    test += QChar(200);
+    test += QChar(8700);
+    test += QChar(56200);
+    test += QChar(57000);
+    test += QChar(10);
+    QByteArray ba = test.toUtf8();
+    bool passed(c2bUtils::fromUtf8(ba) == QString::fromUtf8(ba));
+    cout << endl;
+    if (passed)
+    {
+        cout << "-------------------------" << endl;
+        cout << "Check for c2b utf8 passed" << endl;
+    }
+    else
+    {
+        cout << "-------------------------------------------------------------" << endl;
+        cout << "WARNING: Check for c2b utf8 FAILED! Please report it as a bug" << endl;
+        ++_failed_test_count;
+    }
+    ++_test_count;
+
+    ba += "--------------------------------------";
+    QByteArray cba(c2bUtils::compress(ba));
+    QByteArray uba(c2bUtils::uncompress(cba));
+    passed = ba == uba && ba.length() > cba.length();
+    if (passed)
+    {
+        cout << "Check for zlib/lzo passed" << endl;
+        cout << "-------------------------" << endl;
+    }
+    else
+    {
+        cout << "WARNING: Check for zlib/lzo FAILED! Please report it as a bug" << endl;
+        cout << "-------------------------------------------------------------" << endl;
+        ++_failed_test_count;
+    }
+    ++_test_count;
+}
+
 void c2bTests::heuristic_author()
 {
     cout << endl;
@@ -172,7 +222,7 @@ void c2bTests::heuristic_author()
             while (bp.referencesIn(c2bUtils::fileToString(bib_file), &reference))
             {
                 const QString file(reference.value("file"));
-                if (excluded.contains(file))
+                if (excluded.contains(file) || file.contains("/stacks/"))
                     continue;
                 document d(file);
                 const QString doc(d.toString());
@@ -203,7 +253,7 @@ void c2bTests::heuristic_author()
             const QString file(reference.value("file"));
             if (file.isEmpty())
                 continue;
-            if (excluded.contains(file))
+            if (excluded.contains(file) || file.contains("/stacks/"))
                 continue;
             const QString doc(doc_cache.value(reference.value("file")));
             QString check_doc(doc);
diff --git a/src/c2bTests.h b/src/c2bTests.h
index b6ce287..55c7e39 100644
--- a/src/c2bTests.h
+++ b/src/c2bTests.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BTESTS_H
@@ -35,6 +35,7 @@ private:
     int _test_count;
     void author_parser();
     void check_test(const bool passed, const QString& input, const QString& output);
+    void compression_check();
     void heuristic(bibParser& bp, const bibReference& reference, const QString& text);
     void heuristic_author();
     void heuristic_check_patterns();
diff --git a/src/c2bTextBrowser.cpp b/src/c2bTextBrowser.cpp
index 20b5329..f5bd8bd 100644
--- a/src/c2bTextBrowser.cpp
+++ b/src/c2bTextBrowser.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bTextBrowser.h"
diff --git a/src/c2bTextBrowser.h b/src/c2bTextBrowser.h
index 3258906..0a8535f 100644
--- a/src/c2bTextBrowser.h
+++ b/src/c2bTextBrowser.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BTEXTBROWSER_H
diff --git a/src/c2bTextEdit.cpp b/src/c2bTextEdit.cpp
index b220250..41eb811 100644
--- a/src/c2bTextEdit.cpp
+++ b/src/c2bTextEdit.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bTextEdit.h"
diff --git a/src/c2bTextEdit.h b/src/c2bTextEdit.h
index 980cf8c..e46d5d7 100644
--- a/src/c2bTextEdit.h
+++ b/src/c2bTextEdit.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BTEXTEDIT_H
diff --git a/src/c2bUpdateMetadata.cpp b/src/c2bUpdateMetadata.cpp
index d4be2b7..1cb4445 100644
--- a/src/c2bUpdateMetadata.cpp
+++ b/src/c2bUpdateMetadata.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bUpdateMetadata.h"
@@ -20,11 +20,12 @@ c2bUpdateMetadata::c2bUpdateMetadata(QWidget* parentw) : QDialog(parentw)
     setWindowTitle(tr("Documents Updating Log - cb2Bib"));
     ui.Log->setFont(c2bSettingsP->c2bMonoFont);
     ui.Log->setLineWrapMode(QPlainTextEdit::NoWrap);
-    buttonAbort = new QPushButton(tr("Abort"));
-    ui.buttonBox->addButton(buttonAbort, QDialogButtonBox::ActionRole);
-    connect(buttonAbort, SIGNAL(clicked()), this, SLOT(aborted()));
+    _buttonAbort = new QPushButton(tr("Abort"));
+    ui.buttonBox->addButton(_buttonAbort, QDialogButtonBox::ActionRole);
+    connect(_buttonAbort, SIGNAL(clicked()), this, SLOT(aborted()));
     connect(ui.buttonBox, SIGNAL(helpRequested()), this, SLOT(help()));
     resize(c2bSettingsP->value("c2bLogWidget/size", size()).toSize());
+    _bpP = c2b::bibParser();
 }
 
 c2bUpdateMetadata::~c2bUpdateMetadata()
@@ -60,19 +61,18 @@ void c2bUpdateMetadata::update()
         }
     QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
     ui.buttonBox->button(QDialogButtonBox::Close)->setEnabled(false);
-    buttonAbort->setEnabled(true);
-    buttonAbort->setFocus();
+    _buttonAbort->setEnabled(true);
+    _buttonAbort->setFocus();
     _aborted = false;
     ui.Log->appendPlainText(tr("[cb2bib] Processing file %1...\n").arg(_fn));
 
     int doc_counter(0);
     int error_counter(0);
     int updated_counter(0);
-    bp = c2b::bibParser();
     metadataParser* mp = c2b::metaParser();
     bibReference ref;
-    bp->initReferenceParsing(_fn, bp->bibliographicFields(), &ref);
-    while (bp->referencesIn(_bibtex, &ref) && !_aborted)
+    _bpP->initReferenceParsing(_fn, _bpP->bibliographicFields(), &ref);
+    while (_bpP->referencesIn(_bibtex, &ref) && !_aborted)
     {
         QCoreApplication::processEvents();
         const QString file(ref.value("file"));
@@ -124,7 +124,7 @@ void c2bUpdateMetadata::update()
     QApplication::restoreOverrideCursor();
     ui.buttonBox->button(QDialogButtonBox::Close)->setEnabled(true);
     ui.buttonBox->button(QDialogButtonBox::Close)->setFocus();
-    buttonAbort->setEnabled(false);
+    _buttonAbort->setEnabled(false);
 
     ui.Log->appendPlainText(tr("\n[cb2bib] Checked %1 documents.").arg(doc_counter));
     if (doc_counter > 0 && updated_counter == 0 && error_counter == 0)
@@ -140,7 +140,7 @@ bool c2bUpdateMetadata::needsUpdating(const bibReference& ref, const bibReferenc
 {
     if (ref.typeName != mref.typeName)
         return true;
-    const QStringList& bibliographicFields = bp->bibliographicFields();
+    const QStringList& bibliographicFields = _bpP->bibliographicFields();
     for (int i = 0; i < bibliographicFields.count(); ++i)
     {
         const QString key(bibliographicFields.at(i));
@@ -163,7 +163,7 @@ void c2bUpdateMetadata::writeDifferences(const bibReference& ref, const bibRefer
     QString diff("  [Key] '%1'\n  [In Reference] '%2'\n  [In Document]  '%3'");
     if (ref.typeName != mref.typeName)
         ui.Log->appendPlainText(diff.arg("type").arg(ref.typeName).arg(mref.typeName));
-    const QStringList& bibliographicFields = bp->bibliographicFields();
+    const QStringList& bibliographicFields = _bpP->bibliographicFields();
     for (int i = 0; i < bibliographicFields.count(); ++i)
     {
         const QString key(bibliographicFields.at(i));
@@ -183,7 +183,7 @@ void c2bUpdateMetadata::writeDifferences(const bibReference& ref, const bibRefer
 void c2bUpdateMetadata::aborted()
 {
     _aborted = true;
-    buttonAbort->setEnabled(false);
+    _buttonAbort->setEnabled(false);
     ui.Log->appendPlainText(tr("\n\n[cb2bib] Aborted.\n"));
 }
 
diff --git a/src/c2bUpdateMetadata.h b/src/c2bUpdateMetadata.h
index 1928c1e..1e0988f 100644
--- a/src/c2bUpdateMetadata.h
+++ b/src/c2bUpdateMetadata.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BUPDATEMETADATA_H
@@ -35,13 +35,13 @@ private slots:
 
 
 private:
-    QPushButton* buttonAbort;
+    QPushButton* _buttonAbort;
     QString _bibtex;
     QString _fn;
     Ui::c2bLogWidget ui;
     bool _aborted;
     bool needsUpdating(const bibReference& ref, const bibReference& mref);
-    c2bBibParser* bp;
+    c2bBibParser* _bpP;
     void writeDifferences(const bibReference& ref, const bibReference& mref);
 
 };
diff --git a/src/c2bUtils.cpp b/src/c2bUtils.cpp
index 8ad16d4..9874f59 100644
--- a/src/c2bUtils.cpp
+++ b/src/c2bUtils.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bUtils.h"
diff --git a/src/c2bUtils.h b/src/c2bUtils.h
index 8c9ef0e..7041e6e 100644
--- a/src/c2bUtils.h
+++ b/src/c2bUtils.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BUTILS_H
diff --git a/src/c2bWebBrowser.cpp b/src/c2bWebBrowser.cpp
index c017de8..93f169f 100644
--- a/src/c2bWebBrowser.cpp
+++ b/src/c2bWebBrowser.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "c2bWebBrowser.h"
diff --git a/src/c2bWebBrowser.h b/src/c2bWebBrowser.h
index 510ae54..bb5e2cb 100644
--- a/src/c2bWebBrowser.h
+++ b/src/c2bWebBrowser.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef C2BWEBBROWSER_H
diff --git a/src/cb2Bib.cpp b/src/cb2Bib.cpp
index cbedf3d..26c9847 100644
--- a/src/cb2Bib.cpp
+++ b/src/cb2Bib.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "cb2Bib.h"
@@ -21,7 +21,9 @@
 #include "c2bSettings.h"
 #include "c2bTextBrowser.h"
 #include "c2bUtils.h"
-#include "network.h"
+
+#include <bibSearcher.h>
+#include <network.h>
 
 #include <QtGui>
 
@@ -52,7 +54,6 @@
 - \ref descrip
 - \ref usage
 - \ref detail
-- \ref deposform
 - \ref requirements
 - \ref credits
 
@@ -292,9 +293,10 @@
 
 
     <p>&nbsp;</p>
-\section detail The cb2Bib detailed procedure
+\section detail Advanced features
     Advanced features, and processing and extraction details are described in
     the following sections:
+    - \ref faq_automatic_extraction
     - \ref bibproc
     - \ref authorproc
     - \ref journalproc
@@ -316,20 +318,9 @@
       \endhtmlonly
     - \ref c2bciter
 
-    <p>&nbsp;</p>
-\section deposform Regular Expression Submission Form
-    cb2Bib usefullness increases when having a set of reliable regular
-    expressions. It can therefore be interesting to share one's favorite
-    regexps among cb2Bib users. If you have a working -which does not mean
-    perfect- regexp that could benefit other users, please take a moment and
-    fill out the \ref submission. These regexp will be later included into the
-    cb2Bib distribution, as received, without any additional editing.
-    Interested users could then copy/paste needed cb2Bib regexps into their own
-    regexp file. In this way, no much of anybody's time and effort should be
-    needed.
 
     <p>&nbsp;</p>
-\section requirements cb2Bib Requirements
+\section requirements Requirements
 
 \subsection requirements_comp Compilation
     To compile cb2Bib, the following libraries must be present and accessible:
@@ -345,6 +336,13 @@
     included in Qt > 4.4.0 library. No special action/flag is needed during
     compilation.
 
+    - LZO 2 library and headers, available at
+    \htmlonly
+    <a href="http://www.oberhumer.com/opensource/lzo/" target="_blank">http://www.oberhumer.com/opensource/lzo/</a>.
+    \endhtmlonly
+     If lzo2 was unavailable on a particular platform, type <tt>configure --disable_lzo</tt>
+     or, equivalently, <tt>qmake -config disable_lzo</tt> before compiling.
+
     - X11 header files if compiling on Unix platforms. Concretely, headers
     <tt>X11/Xlib.h</tt> and <tt>X11/Xatom.h</tt> are needed.
 
@@ -1486,8 +1484,8 @@ void cb2Bib::doSearchInFiles(const QString& string, const QString& fn)
     {
         _searchInFilesP = new c2bSearchInFiles(ui.bibtexfile->currentText());
         connect(ui.bibtexfile, SIGNAL(editTextChanged(const QString&)), _searchInFilesP, SLOT(setBibTeXFile(const QString&)));
-        connect(_searchInFilesP, SIGNAL(searchDone(const QString&, c2bBibSearcher*)),
-                this, SLOT(bibEditor(const QString&, c2bBibSearcher*)));
+        connect(_searchInFilesP, SIGNAL(searchDone(const QString&, bibSearcher*)),
+                this, SLOT(bibEditor(const QString&, bibSearcher*)));
         showMessage(tr("BibTeX Search launched."));
     }
     if (fn.isEmpty())
@@ -1974,7 +1972,7 @@ void cb2Bib::initAsBibTeXEditor()
         bibEditor(_settingsP->cl_bibedit_filenames.at(i));
 }
 
-void cb2Bib::bibEditor(const QString& bibtexfile, c2bBibSearcher* searcher)
+void cb2Bib::bibEditor(const QString& bibtexfile, bibSearcher* searcher)
 {
     if (bibtexfile.isEmpty())
         return;
@@ -2051,23 +2049,24 @@ bool cb2Bib::isReferenceRepeated()
 {
     QFileInfo fi(ui.bibtexfile->currentText());
     showMessage(tr("Checking for similar references at %1.").arg(fi.absolutePath()));
-    c2bBibSearcher searcher;
-    searcher.setScope(fi.absoluteFilePath(), fi.absolutePath(), true, false);
+    bibSearcher searcher(c2b::bibParser());
+    searcher.setSearchScope(fi.absoluteFilePath(), fi.absolutePath(), true, false);
     searcher.setSimplifySource(false);
     searcher.setBoolean(true);
-    searcher.addPattern(false, false, "Approximate string", "all", QString(), _bpP->currentReference().anyAuthor());
-    searcher.addPattern(false, false, "Approximate string", "all", QString(), _bpP->currentReference().anyTitle());
+    const QString type(searchPattern::type(searchPattern::ApproximateString));
+    searcher.addPattern(false, false, type, "all", QChar(), _bpP->currentReference().anyAuthor());
+    searcher.addPattern(false, false, type, "all", QChar(), _bpP->currentReference().anyTitle());
     searcher.exec();
-    const bool repeated(searcher.hitCount() > 0);
+    const bool repeated(searcher.hitsCount() > 0);
     if (repeated)
     {
         QApplication::processEvents();
         bibEditor(fi.absolutePath(), &searcher);
         QApplication::processEvents();
-        if (searcher.hitCount() == 1)
-            c2b::showMessage(tr("Found %1 similar reference.").arg(searcher.hitCount()));
+        if (searcher.hitsCount() == 1)
+            c2b::showMessage(tr("Found %1 similar reference.").arg(searcher.hitsCount()));
         else
-            c2b::showMessage(tr("Found %1 similar references.").arg(searcher.hitCount()));
+            c2b::showMessage(tr("Found %1 similar references.").arg(searcher.hitsCount()));
     }
     else
         showMessage(tr("No similar references found at %1.").arg(fi.absolutePath()));
diff --git a/src/cb2Bib.h b/src/cb2Bib.h
index 2fe287b..7e5dac6 100644
--- a/src/cb2Bib.h
+++ b/src/cb2Bib.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #ifndef CB2BIB_H
@@ -13,8 +13,8 @@
 #include <QMainWindow>
 #include <QPointer>
 
+class bibSearcher;
 class c2bBibParser;
-class c2bBibSearcher;
 class c2bCiter;
 class c2bClipEdit;
 class c2bClipboard;
@@ -88,7 +88,7 @@ private slots:
     void addEditors();
     void addToFile(bool ready);
     void anyPattern();
-    void bibEditor(const QString& bibtexfile, c2bBibSearcher* searcher = 0);
+    void bibEditor(const QString& bibtexfile, bibSearcher* searcher = 0);
     void bibModified(bool modified);
     void bookmarksEditor();
     void c2bInit();
diff --git a/src/clipboardPoll.cpp b/src/clipboardPoll.cpp
index 8f731fc..81b1388 100644
--- a/src/clipboardPoll.cpp
+++ b/src/clipboardPoll.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   clipboardPoll, modified by Pere Constans for the cb2Bib, 2005
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *
  *
  *   Author and Copyright (C) 2003 by Lubos Lunak <l.lunak at kde.org>
diff --git a/src/clipboardPoll.h b/src/clipboardPoll.h
index c6a8019..c14acf2 100644
--- a/src/clipboardPoll.h
+++ b/src/clipboardPoll.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   clipboardPoll, modified by Pere Constans for the cb2Bib, 2005
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *
  *
  *   Author and Copyright (C) 2003 by Lubos Lunak <l.lunak at kde.org>
diff --git a/src/findDialog.cpp b/src/findDialog.cpp
index 14bd234..c615299 100644
--- a/src/findDialog.cpp
+++ b/src/findDialog.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  *   findDialog was originally adapted from Qt Designer
  *   Copyright (C) 2001 Trolltech AS.  All rights reserved.
diff --git a/src/findDialog.h b/src/findDialog.h
index fffcf21..b0ec88c 100644
--- a/src/findDialog.h
+++ b/src/findDialog.h
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  *   findDialog is adapted from Qt Designer
  *   Copyright (C) 2001 Trolltech AS.  All rights reserved.
diff --git a/src/main.cpp b/src/main.cpp
index 9bfb772..ba517de 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include "qtsingleapplication/src/qtsingleapplication.h"
@@ -32,7 +32,7 @@ int main(int argc, char* argv[])
 
     if (c2bSettings::isConsoleMode(argc, argv))
     {
-        // Cannot use QCoreAppliation, QTextDocument is required by c2bUtils::fromHtmlString
+        // Cannot use QCoreApplication, QTextDocument is required by c2bUtils::fromHtmlString
 #ifdef Q_WS_WIN
         // Needs also workaround c2bSettings::decodeFilename()
         QApplication app(argc, argv);
diff --git a/src/qtsingleapplication/src/qtsinglecoreapplication.cpp b/src/qtsingleapplication/src/qtsinglecoreapplication.cpp
index 9b7fc40..89301ff 100644
--- a/src/qtsingleapplication/src/qtsinglecoreapplication.cpp
+++ b/src/qtsingleapplication/src/qtsinglecoreapplication.cpp
@@ -73,7 +73,7 @@
 /*!
     Creates a QtSingleCoreApplication object. The application identifier
     will be QCoreApplication::applicationFilePath(). \a argc and \a
-    argv are passed on to the QCoreAppliation constructor.
+    argv are passed on to the QCoreApplication constructor.
 */
 
 QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv)
@@ -87,7 +87,7 @@ QtSingleCoreApplication::QtSingleCoreApplication(int &argc, char **argv)
 /*!
     Creates a QtSingleCoreApplication object with the application
     identifier \a appId. \a argc and \a argv are passed on to the
-    QCoreAppliation constructor.
+    QCoreApplication constructor.
 */
 QtSingleCoreApplication::QtSingleCoreApplication(const QString &appId, int &argc, char **argv)
     : QCoreApplication(argc, argv)
diff --git a/src/src.pro b/src/src.pro
index 13af2f1..c4394df 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -21,8 +21,6 @@ HEADERS += qtsingleapplication/src/*.h \
            c2bBibHighlighter.h \
            c2bBibParser.h \
            c2bBibPreparserLog.h \
-           c2bBibSearcher.h \
-           c2bBibSearcherCache.h \
            c2bCiter.h \
            c2bCiterModel.h \
            c2bCiterView.h \
@@ -52,7 +50,6 @@ HEADERS += qtsingleapplication/src/*.h \
            c2bSaveRegExp.h \
            c2bSearchInFiles.h \
            c2bSearchInFilesPattern.h \
-           c2bSearchPattern.h \
            c2bSettings.h \
            c2bTests.h \
            c2bTextBrowser.h \
@@ -68,8 +65,6 @@ SOURCES += qtsingleapplication/src/*.cpp \
            c2bBibHighlighter.cpp \
            c2bBibParser.cpp \
            c2bBibPreparserLog.cpp \
-           c2bBibSearcher.cpp \
-           c2bBibSearcherCache.cpp \
            c2bCiter.cpp \
            c2bCiterModel.cpp \
            c2bCiterView.cpp \
@@ -99,7 +94,6 @@ SOURCES += qtsingleapplication/src/*.cpp \
            c2bSaveRegExp.cpp \
            c2bSearchInFiles.cpp \
            c2bSearchInFilesPattern.cpp \
-           c2bSearchPattern.cpp \
            c2bSettings.cpp \
            c2bTests.cpp \
            c2bTextBrowser.cpp \
@@ -140,6 +134,16 @@ use_webkit {
     SOURCES += c2bAnnote.cpp c2bWebBrowser.cpp
     DEFINES += C2B_WEBKIT
 }
+CONFIG += use_lzo
+use_lzo {
+    LIBS += -llzo2
+    DEFINES += C2B_USE_LZO
+}
+disable_lzo {
+    CONFIG -= use_lzo
+    LIBS -= -llzo2
+    DEFINES -= C2B_USE_LZO
+}
 TARGET = cb2bib
 DESTDIR = ../bin
 DEPENDPATH += .
diff --git a/src/win/main.cpp b/src/win/main.cpp
index 451e60a..b753438 100644
--- a/src/win/main.cpp
+++ b/src/win/main.cpp
@@ -1,7 +1,7 @@
 /***************************************************************************
  *   Copyright (C) 2004-2009 by Pere Constans
  *   constans at molspaces.com
- *   cb2Bib version 1.3.2. Licensed under the GNU GPL version 3.
+ *   cb2Bib version 1.3.3. Licensed under the GNU GPL version 3.
  *   See the LICENSE file that comes with this distribution.
  ***************************************************************************/
 #include <QFileInfo>

-- 
Extract bibliographic references from various sources



More information about the debian-science-commits mailing list