Index: m4/intltool.m4
===================================================================
--- m4/intltool.m4	(revision 0)
+++ m4/intltool.m4	(revision 0)
@@ -0,0 +1,234 @@
+## intltool.m4 - Configure intltool for the target system. -*-Shell-script-*-
+## Copyright (C) 2001 Eazel, Inc.
+## Author: Maciej Stachowiak <mjs@noisehavoc.org>
+##         Kenneth Christiansen <kenneth@gnu.org>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## As a special exception to the GNU General Public License, if you
+## distribute this file as part of a program that contains a
+## configuration script generated by Autoconf, you may include it under
+## the same distribution terms that you use for the rest of that program.
+
+dnl IT_PROG_INTLTOOL([MINIMUM-VERSION], [no-xml])
+# serial 36 IT_PROG_INTLTOOL
+AC_DEFUN([IT_PROG_INTLTOOL],
+[AC_PREREQ([2.50])dnl
+
+case "$am__api_version" in
+    1.[01234])
+	AC_MSG_ERROR([Automake 1.5 or newer is required to use intltool])
+    ;;
+    *)
+    ;;
+esac
+
+if test -n "$1"; then
+    AC_MSG_CHECKING([for intltool >= $1])
+
+    INTLTOOL_REQUIRED_VERSION_AS_INT=`echo $1 | awk -F. '{ print $ 1 * 1000 + $ 2 * 100 + $ 3; }'`
+    INTLTOOL_APPLIED_VERSION=`awk -F\" '/\\$VERSION / { print $ 2; }' ${ac_aux_dir}/intltool-update.in`
+    [INTLTOOL_APPLIED_VERSION_AS_INT=`awk -F\" '/\\$VERSION / { split($ 2, VERSION, "."); print VERSION[1] * 1000 + VERSION[2] * 100 + VERSION[3];}' ${ac_aux_dir}/intltool-update.in`
+    ]
+    AC_MSG_RESULT([$INTLTOOL_APPLIED_VERSION found])
+    test "$INTLTOOL_APPLIED_VERSION_AS_INT" -ge "$INTLTOOL_REQUIRED_VERSION_AS_INT" ||
+	AC_MSG_ERROR([Your intltool is too old.  You need intltool $1 or later.])
+fi
+
+  INTLTOOL_DESKTOP_RULE='%.desktop:   %.desktop.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+INTLTOOL_DIRECTORY_RULE='%.directory: %.directory.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+     INTLTOOL_KEYS_RULE='%.keys:      %.keys.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -k -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+     INTLTOOL_PROP_RULE='%.prop:      %.prop.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+      INTLTOOL_OAF_RULE='%.oaf:       %.oaf.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -p $(top_srcdir)/po $< [$]@'
+     INTLTOOL_PONG_RULE='%.pong:      %.pong.in      $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+   INTLTOOL_SERVER_RULE='%.server:    %.server.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -o -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+    INTLTOOL_SHEET_RULE='%.sheet:     %.sheet.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+INTLTOOL_SOUNDLIST_RULE='%.soundlist: %.soundlist.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+       INTLTOOL_UI_RULE='%.ui:        %.ui.in        $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+      INTLTOOL_XML_RULE='%.xml:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+      INTLTOOL_XML_NOMERGE_RULE='%.xml:       %.xml.in       $(INTLTOOL_MERGE) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< [$]@' 
+      INTLTOOL_XAM_RULE='%.xam:       %.xml.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+      INTLTOOL_KBD_RULE='%.kbd:       %.kbd.in       $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -m -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+    INTLTOOL_CAVES_RULE='%.caves:     %.caves.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+  INTLTOOL_SCHEMAS_RULE='%.schemas:   %.schemas.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -s -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+    INTLTOOL_THEME_RULE='%.theme:     %.theme.in     $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@' 
+    INTLTOOL_SERVICE_RULE='%.service: %.service.in   $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+   INTLTOOL_POLICY_RULE='%.policy:    %.policy.in    $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -x -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< [$]@'
+
+AC_SUBST(INTLTOOL_DESKTOP_RULE)
+AC_SUBST(INTLTOOL_DIRECTORY_RULE)
+AC_SUBST(INTLTOOL_KEYS_RULE)
+AC_SUBST(INTLTOOL_PROP_RULE)
+AC_SUBST(INTLTOOL_OAF_RULE)
+AC_SUBST(INTLTOOL_PONG_RULE)
+AC_SUBST(INTLTOOL_SERVER_RULE)
+AC_SUBST(INTLTOOL_SHEET_RULE)
+AC_SUBST(INTLTOOL_SOUNDLIST_RULE)
+AC_SUBST(INTLTOOL_UI_RULE)
+AC_SUBST(INTLTOOL_XAM_RULE)
+AC_SUBST(INTLTOOL_KBD_RULE)
+AC_SUBST(INTLTOOL_XML_RULE)
+AC_SUBST(INTLTOOL_XML_NOMERGE_RULE)
+AC_SUBST(INTLTOOL_CAVES_RULE)
+AC_SUBST(INTLTOOL_SCHEMAS_RULE)
+AC_SUBST(INTLTOOL_THEME_RULE)
+AC_SUBST(INTLTOOL_SERVICE_RULE)
+AC_SUBST(INTLTOOL_POLICY_RULE)
+
+# Check the gettext tools to make sure they are GNU
+AC_PATH_PROG(XGETTEXT, xgettext)
+AC_PATH_PROG(MSGMERGE, msgmerge)
+AC_PATH_PROG(MSGFMT, msgfmt)
+if test -z "$XGETTEXT" -o -z "$MSGMERGE" -o -z "$MSGFMT"; then
+    AC_MSG_ERROR([GNU gettext tools not found; required for intltool])
+fi
+xgversion="`$XGETTEXT --version|grep '(GNU ' 2> /dev/null`"
+mmversion="`$MSGMERGE --version|grep '(GNU ' 2> /dev/null`"
+mfversion="`$MSGFMT --version|grep '(GNU ' 2> /dev/null`"
+if test -z "$xgversion" -o -z "$mmversion" -o -z "$mfversion"; then
+    AC_MSG_ERROR([GNU gettext tools not found; required for intltool])
+fi
+
+# Use the tools built into the package, not the ones that are installed.
+AC_SUBST(INTLTOOL_EXTRACT, '$(top_builddir)/intltool-extract')
+AC_SUBST(INTLTOOL_MERGE, '$(top_builddir)/intltool-merge')
+AC_SUBST(INTLTOOL_UPDATE, '$(top_builddir)/intltool-update')
+
+AC_PATH_PROG(INTLTOOL_PERL, perl)
+if test -z "$INTLTOOL_PERL"; then
+   AC_MSG_ERROR([perl not found; required for intltool])
+fi
+if test -z "`$INTLTOOL_PERL -v | fgrep '5.' 2> /dev/null`"; then
+   AC_MSG_ERROR([perl 5.x required for intltool])
+fi
+if test "x$2" != "xno-xml"; then
+   AC_MSG_CHECKING([for XML::Parser])
+   if `$INTLTOOL_PERL -e "require XML::Parser" 2>/dev/null`; then
+       AC_MSG_RESULT([ok])
+   else
+       AC_MSG_ERROR([XML::Parser perl module is required for intltool])
+   fi
+fi
+
+# Substitute ALL_LINGUAS so we can use it in po/Makefile
+AC_SUBST(ALL_LINGUAS)
+
+# Set DATADIRNAME correctly if it is not set yet
+# (copied from glib-gettext.m4)
+if test -z "$DATADIRNAME"; then
+  AC_LINK_IFELSE(
+    [AC_LANG_PROGRAM([[]],
+                     [[extern int _nl_msg_cat_cntr;
+                       return _nl_msg_cat_cntr]])],
+    [DATADIRNAME=share],
+    [case $host in
+    *-*-solaris*)
+    dnl On Solaris, if bind_textdomain_codeset is in libc,
+    dnl GNU format message catalog is always supported,
+    dnl since both are added to the libc all together.
+    dnl Hence, we'd like to go with DATADIRNAME=share
+    dnl in this case.
+    AC_CHECK_FUNC(bind_textdomain_codeset,
+      [DATADIRNAME=share], [DATADIRNAME=lib])
+    ;;
+    *)
+    [DATADIRNAME=lib]
+    ;;
+    esac])
+fi
+AC_SUBST(DATADIRNAME)
+
+IT_PO_SUBDIR([po])
+
+dnl The following is very similar to
+dnl
+dnl	AC_CONFIG_FILES([intltool-extract intltool-merge intltool-update])
+dnl
+dnl with the following slight differences:
+dnl  - the *.in files are in ac_aux_dir,
+dnl  - if the file haven't changed upon reconfigure, it's not touched,
+dnl  - the evaluation of the third parameter enables a hack which computes
+dnl    the actual value of $libdir,
+dnl  - the user sees "executing intltool commands", instead of
+dnl    "creating intltool-extract" and such.
+dnl
+dnl Nothing crucial here, and we could use AC_CONFIG_FILES, if there were
+dnl a reason for it.
+
+AC_CONFIG_COMMANDS([intltool], [
+
+for file in intltool-extract intltool-merge intltool-update; do
+  sed -e "s|@INTLTOOL_EXTRACT@|`pwd`/intltool-extract|g" \
+      -e "s|@INTLTOOL_LIBDIR@|${INTLTOOL_LIBDIR}|g" \
+      -e "s|@INTLTOOL_PERL@|${INTLTOOL_PERL}|g" \
+	< ${ac_aux_dir}/${file}.in > ${file}.out
+  if cmp -s ${file} ${file}.out 2>/dev/null; then
+    rm -f ${file}.out
+  else
+    mv -f ${file}.out ${file}
+  fi
+  chmod ugo+x ${file}
+  chmod u+w ${file}
+done
+
+],
+[INTLTOOL_PERL='${INTLTOOL_PERL}' ac_aux_dir='${ac_aux_dir}'
+prefix="$prefix" exec_prefix="$exec_prefix" INTLTOOL_LIBDIR="$libdir" 
+INTLTOOL_EXTRACT='${INTLTOOL_EXTRACT}'])
+
+])
+
+
+# IT_PO_SUBDIR(DIRNAME)
+# ---------------------
+# All po subdirs have to be declared with this macro; the subdir "po" is
+# declared by IT_PROG_INTLTOOL.
+#
+AC_DEFUN([IT_PO_SUBDIR],
+[AC_PREREQ([2.53])dnl We use ac_top_srcdir inside AC_CONFIG_COMMANDS.
+dnl
+dnl The following CONFIG_COMMANDS should be exetuted at the very end
+dnl of config.status.
+AC_CONFIG_COMMANDS_PRE([
+  AC_CONFIG_COMMANDS([$1/stamp-it], [
+    rm -f "$1/stamp-it" "$1/stamp-it.tmp" "$1/POTFILES" "$1/Makefile.tmp"
+    >"$1/stamp-it.tmp"
+    [sed '/^#/d
+	 s/^[[].*] *//
+	 /^[ 	]*$/d
+	'"s|^|	$ac_top_srcdir/|" \
+      "$srcdir/$1/POTFILES.in" | sed '$!s/$/ \\/' >"$1/POTFILES"
+    ]
+    if test ! -f "$1/Makefile"; then
+      AC_MSG_ERROR([$1/Makefile is not ready.])
+    fi
+    mv "$1/Makefile" "$1/Makefile.tmp"
+    [sed '/^POTFILES =/,/[^\\]$/ {
+		/^POTFILES =/!d
+		r $1/POTFILES
+	  }
+	 ' "$1/Makefile.tmp" >"$1/Makefile"]
+    rm -f "$1/Makefile.tmp"
+    mv "$1/stamp-it.tmp" "$1/stamp-it"
+  ])
+])dnl
+])
+
+
+# deprecated macros
+AU_ALIAS([AC_PROG_INTLTOOL], [IT_PROG_INTLTOOL])
+# A hint is needed for aclocal from Automake <= 1.9.4:
+# AC_DEFUN([AC_PROG_INTLTOOL], ...)
+
Index: m4/berkeley_db.m4
===================================================================
--- m4/berkeley_db.m4	(revision 0)
+++ m4/berkeley_db.m4	(revision 0)
@@ -0,0 +1,94 @@
+dnl
+dnl @synopsis AX_BERKELEY_DB([MINIMUM-VERSION
+dnl                          [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl
+dnl This macro tries to find Berkeley DB. It honors MINIMUM-VERSION if given.
+dnl 
+dnl If libdb is found, DB_HEADER and DB_LIBS variables are set and 
+dnl ACTION-IF-FOUND shell code is executed if specified. DB_HEADER is set to 
+dnl location of db.h header in quotes (e.g. "db3/db.h") and AC_DEFINE_UNQUOTED
+dnl is called on it, so that you can type 
+dnl      #include DB_HEADER
+dnl in your C/C++ code. DB_LIBS is set to linker flags needed to link against
+dnl the library (e.g. -ldb3.1) and AC_SUBST is called on it.
+dnl
+dnl @version $Id: berkeley_db.m4 935 2005-07-04 20:53:00Z vaclavslavik $
+dnl @author Vaclav Slavik <vslavik@fastmail.fm>
+dnl
+AC_DEFUN([AX_BERKELEY_DB],
+[
+  old_LIBS="$LIBS"
+
+  minversion=ifelse([$1], ,,$1)
+                
+  DB_HEADER=""
+  DB_LIBS=""
+
+  if test -z $minversion ; then
+      minvermajor=0
+      minverminor=0
+      minverpatch=0
+      AC_MSG_CHECKING([for Berkeley DB])
+  else
+      minvermajor=`echo $minversion | cut -d. -f1`
+      minverminor=`echo $minversion | cut -d. -f2`
+      minverpatch=`echo $minversion | cut -d. -f3`
+      minvermajor=${minvermajor:-0}
+      minverminor=${minverminor:-0}
+      minverpatch=${minverpatch:-0}
+      AC_MSG_CHECKING([for Berkeley DB >= $minversion])
+  fi
+
+  for version in "" 5.0 4.9 4.8 4.7 4.6 4.5 4.4 4.3 4.2 4.1 4.0 3.6 3.5 3.4 3.3 3.2 3.1 ; do
+
+    if test -z $version ; then
+        db_lib="-ldb"
+        try_headers="db.h"
+    else
+        db_lib="-ldb-$version"
+        try_headers="db$version/db.h db`echo $version | sed -e 's,\..*,,g'`/db.h"
+    fi
+        
+    LIBS="$old_LIBS $db_lib"
+ 
+    for db_hdr in $try_headers ; do
+        if test -z $DB_HEADER ; then
+            AC_LINK_IFELSE(
+                [AC_LANG_PROGRAM(
+                    [
+                        #include <${db_hdr}>
+                    ],
+                    [
+                        #if !((DB_VERSION_MAJOR > (${minvermajor}) || \
+                              (DB_VERSION_MAJOR == (${minvermajor}) && \
+                                    DB_VERSION_MINOR > (${minverminor})) || \
+                              (DB_VERSION_MAJOR == (${minvermajor}) && \
+                                    DB_VERSION_MINOR == (${minverminor}) && \
+                                    DB_VERSION_PATCH >= (${minverpatch}))))
+                            #error "too old version"
+                        #endif
+                    
+                        DB *db;
+                        db_create(&db, NULL, 0);
+                    ])],
+                [
+                    AC_MSG_RESULT([header $db_hdr, library $db_lib])
+                                
+                    DB_HEADER="$db_hdr"
+                    DB_LIBS="$db_lib"
+                ])
+        fi
+    done
+  done
+
+  LIBS="$old_LIBS"
+
+  if test -z $DB_HEADER ; then
+    AC_MSG_RESULT([not found])
+    ifelse([$3], , :, [$3])
+  else
+    AC_DEFINE_UNQUOTED(DB_HEADER, ["$DB_HEADER"], [Berkeley DB header version])
+    AC_SUBST(DB_LIBS)
+    ifelse([$2], , :, [$2])
+  fi
+])
Index: m4/gtk-doc.m4
===================================================================
--- m4/gtk-doc.m4	(revision 0)
+++ m4/gtk-doc.m4	(revision 0)
@@ -0,0 +1,39 @@
+dnl -*- mode: autoconf -*-
+
+# serial 1
+
+dnl Usage:
+dnl   GTK_DOC_CHECK([minimum-gtk-doc-version])
+AC_DEFUN([GTK_DOC_CHECK],
+[
+  AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+  AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+  dnl for overriding the documentation installation directory
+  AC_ARG_WITH([html-dir],
+    AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),,
+    [with_html_dir='${datadir}/gtk-doc/html'])
+  HTML_DIR="$with_html_dir"
+  AC_SUBST([HTML_DIR])
+
+  dnl enable/disable documentation building
+  AC_ARG_ENABLE([gtk-doc],
+    AS_HELP_STRING([--enable-gtk-doc],
+                   [use gtk-doc to build documentation [[default=no]]]),,
+    [enable_gtk_doc=no])
+
+  if test x$enable_gtk_doc = xyes; then
+    ifelse([$1],[],
+      [PKG_CHECK_EXISTS([gtk-doc],,
+                        AC_MSG_ERROR([gtk-doc not installed and --enable-gtk-doc requested]))],
+      [PKG_CHECK_EXISTS([gtk-doc >= $1],,
+                        AC_MSG_ERROR([You need to have gtk-doc >= $1 installed to build gtk-doc]))])
+  fi
+
+  AC_MSG_CHECKING([whether to build gtk-doc documentation])
+  AC_MSG_RESULT($enable_gtk_doc)
+
+  AC_PATH_PROGS(GTKDOC_CHECK,gtkdoc-check,)
+
+  AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes])
+  AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"])
+])
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 3573)
+++ ChangeLog	(working copy)
@@ -1,3 +1,12 @@
+2008-07-07  Ignacio Casal Quinteiro  <nacho.resa@gmail.com>
+
+	* configure.ac:
+	* m4/berkeley_db.m4:
+	* m4/gtk-doc.m4:
+	* m4/intltool.m4:
+	
+	Added translation-memory backend and neccessary macros.
+
 2008-04-15  Ignacio Casal Quinteiro  <nacho.resa@gmail.com>
 
 	* plugins/insert-tags/insert-tags-plugin.c:
Index: src/utils.c
===================================================================
--- src/utils.c	(revision 3573)
+++ src/utils.c	(working copy)
@@ -30,6 +30,130 @@
 #include <glade/glade.h>
 #include <gtk/gtk.h>
 
+static const gchar * badwords[]= 
+{
+	"a",
+	//"all",
+	"an",
+	//"are",
+	//"can",
+	//"for",
+	//"from",
+	"have",
+	//"it",
+	//"may",
+	//"not",
+	"of",
+	//"that",
+	"the",
+	//"this",
+	//"was",
+	"will",
+	//"with",
+	//"you",
+	//"your",
+	NULL
+};
+
+static gchar *
+create_word_from_positions (const gchar *string,
+			    gint start,
+			    gint end)
+{
+	gchar toret[end+1 - start];
+	gint i = start;
+	gint j = 0;
+	
+	while (i <= end)
+	{
+		toret[j] = string[i];
+		j++;
+		i++;
+	}
+	toret[j] = '\0';
+	
+	return g_strdup (toret);
+}
+
+static gboolean
+check_good_word (const gchar *word)
+{
+	gboolean check = TRUE;
+	gchar *lower = g_utf8_strdown (word, -1);
+	gint i = 0;
+	
+	while (badwords[i] != NULL)
+	{
+		if (g_utf8_collate (lower, badwords[i]) == 0)
+		{
+			check = FALSE;
+			break;
+		}
+		i++;
+	}
+	return check;
+}
+
+/**
+ * gtranslator_utils_split_string_in_words:
+ * @string: the text to process
+ *
+ * Process a text and split it in words using pango.
+ * 
+ * Returns: an array of words of the processed text
+ */
+gchar **
+gtranslator_utils_split_string_in_words (const gchar *string)
+{
+	PangoLanguage *lang = pango_language_from_string ("en");
+	PangoLogAttr *attrs;
+	GPtrArray *array;
+	gint char_len;
+	gint i = 0;
+	gint start;
+
+	char_len = g_utf8_strlen (string, -1);
+	attrs = g_new (PangoLogAttr, char_len + 1);
+	
+	pango_get_log_attrs (string,
+			     strlen (string),
+			     -1,
+			     lang,
+			     attrs,
+			     char_len + 1);
+
+	array = g_ptr_array_new ();
+	
+	while (i <= char_len)
+	{
+		if (attrs[i].is_word_start)
+		{
+			start = i;
+			
+			if (attrs[i].is_word_end)
+			{
+				gchar *word = create_word_from_positions (string, start, i);
+				
+				if (check_good_word (word))
+					g_ptr_array_add (array, word);
+			}			
+		}
+		else if (attrs[i].is_word_end)
+		{
+			gchar *word = create_word_from_positions (string, start, i);
+			
+			if (check_good_word (word))
+				g_ptr_array_add (array, word);
+		}
+		i++;
+	}
+	
+	g_free (attrs);
+	g_ptr_array_add (array, NULL);
+	
+	return (gchar **)g_ptr_array_free (array, FALSE);
+}
+
 xmlDocPtr 
 gtranslator_xml_new_doc (const gchar *name) 
 {
Index: src/utils.h
===================================================================
--- src/utils.h	(revision 3573)
+++ src/utils.h	(working copy)
@@ -26,6 +26,8 @@
 #include <gtk/gtkwindow.h>
 #include <libxml/tree.h>
 
+gchar **       gtranslator_utils_split_string_in_words (const gchar *string);
+
 xmlDocPtr      gtranslator_xml_new_doc (const gchar *name);
 
 xmlDocPtr      gtranslator_xml_open_file (const gchar *filename);
Index: src/ChangeLog
===================================================================
--- src/ChangeLog	(revision 3573)
+++ src/ChangeLog	(working copy)
@@ -1,3 +1,63 @@
+2008-07-07  Ignacio Casal Quinteiro  <nacho.resa@gmail.com>
+
+	* translation-memory/Makefile.am:
+	* translation-memory/berkeley/Makefile.am:
+	* translation-memory/berkeley/berkeley.c
+	(gtranslator_berkeley_store), (union_of_db_keys), (advance_cycle),
+	(look_fuzzy), (gtranslator_berkeley_lookup),
+	(gtranslator_berkeley_set_max_omits),
+	(gtranslator_berkeley_set_max_delta),
+	(gtranslator_translation_memory_iface_init),
+	(gtranslator_berkeley_init), (gtranslator_berkeley_finalize),
+	(gtranslator_berkeley_class_init), (gtranslator_berkeley_new):
+	* translation-memory/berkeley/berkeley.h:
+	* translation-memory/berkeley/db-base.c (get_db_base_directory),
+	(gtranslator_db_base_init), (gtranslator_db_base_finalize),
+	(gtranslator_db_base_class_init),
+	(gtranslator_db_base_create_dabatase),
+	(gtranslator_db_base_show_error), (gtranslator_db_base_put),
+	(gtranslator_db_base_get):
+	* translation-memory/berkeley/db-base.h:
+	* translation-memory/berkeley/db-keys.c (gtranslator_db_keys_init),
+	(gtranslator_db_keys_finalize), (gtranslator_db_keys_class_init),
+	(gtranslator_db_keys_new), (gtranslator_db_keys_new_with_size),
+	(gtranslator_db_keys_get_list), (gtranslator_db_keys_get_count),
+	(gtranslator_db_keys_set_count):
+	* translation-memory/berkeley/db-keys.h:
+	* translation-memory/berkeley/db-orig.c (gtranslator_db_orig_init),
+	(gtranslator_db_orig_finalize), (gtranslator_db_orig_class_init),
+	(gtranslator_db_orig_new), (gtranslator_db_orig_write),
+	(gtranslator_db_orig_read):
+	* translation-memory/berkeley/db-orig.h:
+	* translation-memory/berkeley/db-trans.c
+	(gtranslator_db_trans_init), (gtranslator_db_trans_finalize),
+	(gtranslator_db_trans_class_init), (gtranslator_db_trans_new),
+	(gtranslator_db_trans_write_string), (gtranslator_db_trans_write),
+	(gtranslator_db_trans_read):
+	* translation-memory/berkeley/db-trans.h:
+	* translation-memory/berkeley/db-words.c
+	(gtranslator_db_words_init), (gtranslator_db_words_finalize),
+	(gtranslator_db_words_class_init), (gtranslator_db_words_new),
+	(gtranslator_db_words_append), (gtranslator_db_words_read):
+	* translation-memory/berkeley/db-words.h:
+	* translation-memory/translation-memory.c
+	(gtranslator_translation_memory_store),
+	(gtranslator_translation_memory_store_default),
+	(gtranslator_translation_memory_lookup),
+	(gtranslator_translation_memory_lookup_default),
+	(gtranslator_translation_memory_set_max_omits),
+	(gtranslator_translation_memory_set_max_omits_default),
+	(gtranslator_translation_memory_set_max_delta),
+	(gtranslator_translation_memory_set_max_delta_default),
+	(gtranslator_translation_memory_base_init),
+	(gtranslator_translation_memory_get_type):
+	* translation-memory/translation-memory.h:
+	* utils.c (create_word_from_positions), (check_good_word),
+	(gtranslator_utils_split_string_in_words):
+	* utils.h:
+	
+	Added translation-memory backend.
+
 2008-05-26  Pablo Sanxiao  <psanxiao@gmail.com>
 
 	* utils.{ch}:
Index: src/translation-memory/berkeley/db-keys.c
===================================================================
--- src/translation-memory/berkeley/db-keys.c	(revision 0)
+++ src/translation-memory/berkeley/db-keys.c	(revision 0)
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ *
+ *     Based in poedit transmem.cpp file:
+ *     Copyright (C) 2001-2007 Vaclav Slavik
+ * 
+ *     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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "db-keys.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include DB_HEADER
+#include <string.h>
+
+#define GTR_DB_KEYS_GET_PRIVATE(object)	(G_TYPE_INSTANCE_GET_PRIVATE ( \
+						 (object),		       \
+						 GTR_TYPE_DB_KEYS,     \
+						 GtranslatorDbKeysPrivate))
+
+G_DEFINE_TYPE(GtranslatorDbKeys, gtranslator_db_keys, G_TYPE_OBJECT)
+
+
+struct _GtranslatorDbKeysPrivate
+{
+	db_recno_t *list;
+	gsize count;
+};
+
+static void
+gtranslator_db_keys_init (GtranslatorDbKeys *db_keys)
+{
+	db_keys->priv = GTR_DB_KEYS_GET_PRIVATE (db_keys);
+}
+
+static void
+gtranslator_db_keys_finalize (GObject *object)
+{
+	GtranslatorDbKeys *keys = GTR_DB_KEYS (object);
+	
+	g_free (keys->priv->list);
+	
+	G_OBJECT_CLASS (gtranslator_db_keys_parent_class)->finalize (object);
+}
+
+static void
+gtranslator_db_keys_class_init (GtranslatorDbKeysClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GtranslatorDbKeysPrivate));
+
+	object_class->finalize = gtranslator_db_keys_finalize;
+}
+
+/**
+ * gtranslator_db_keys_new:
+ * @data: the db_recno_t with the list of keys stored into it
+ *
+ * Creates a new #GtranslatorDbKeys object.
+ *
+ * Returns: a new #GtranslatorDbKeys object
+ */
+GtranslatorDbKeys *
+gtranslator_db_keys_new (DBT *data)
+{
+	GtranslatorDbKeys *db_keys;
+
+	db_keys = g_object_new (GTR_TYPE_DB_KEYS, NULL);
+	
+	db_keys->priv->count = data->size / sizeof(db_recno_t);
+	db_keys->priv->list = g_new (db_recno_t, db_keys->priv->count);
+	memcpy (db_keys->priv->list, data->data, data->size);
+	
+	return db_keys;
+}
+
+/**
+ * gtranslator_db_keys_new_with_size:
+ * @cnt: the number of element for the list
+ *
+ * Creates a new #GtranslatorDbKeys object with #cnt elements.
+ *
+ * Returns: a new #GtranslatorDbKeys object
+ */
+GtranslatorDbKeys *
+gtranslator_db_keys_new_with_size (gsize cnt)
+{
+	GtranslatorDbKeys *db_keys;
+
+	db_keys = g_object_new (GTR_TYPE_DB_KEYS, NULL);
+	
+	db_keys->priv->list = g_new (db_recno_t, cnt);
+	db_keys->priv->count = cnt;
+	
+	return db_keys;
+}
+
+/**
+ * gtranslator_db_keys_get_list:
+ * @db_keys: a #GtranslatorDbKeys
+ * 
+ * Gets the list of keys.
+ * 
+ * Returns: the list of keys
+ */
+db_recno_t *
+gtranslator_db_keys_get_list (GtranslatorDbKeys *db_keys)
+{
+	g_return_val_if_fail (GTR_IS_DB_KEYS (db_keys), NULL);
+	
+	return db_keys->priv->list;
+}
+
+/**
+ * gtranslator_db_keys_get_count:
+ * @db_keys: a #GtranslatorDbKeys
+ *
+ * Gets the number of elements in the list.
+ *
+ * Returns: the number of elements in the list
+ */
+gsize
+gtranslator_db_keys_get_count (GtranslatorDbKeys *db_keys)
+{
+	g_return_val_if_fail (GTR_IS_DB_KEYS (db_keys), 0);
+	
+	return db_keys->priv->count;
+}
+
+void
+gtranslator_db_keys_set_count (GtranslatorDbKeys *db_keys,
+			       gsize count)
+{
+	g_return_if_fail (GTR_IS_DB_KEYS (db_keys));
+	
+	db_keys->priv->count = count;
+}
Index: src/translation-memory/berkeley/db-trans.h
===================================================================
--- src/translation-memory/berkeley/db-trans.h	(revision 0)
+++ src/translation-memory/berkeley/db-trans.h	(revision 0)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ * 
+ *     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/>.
+ */
+
+#ifndef __DB_TRANS_H__
+#define __DB_TRANS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "db-base.h"
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GTR_TYPE_DB_TRANS		(gtranslator_db_trans_get_type ())
+#define GTR_DB_TRANS(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GTR_TYPE_DB_TRANS, GtranslatorDbTrans))
+#define GTR_DB_TRANS_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GTR_TYPE_DB_TRANS, GtranslatorDbTransClass))
+#define GTR_IS_DB_TRANS(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GTR_TYPE_DB_TRANS))
+#define GTR_IS_DB_TRANS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GTR_TYPE_DB_TRANS))
+#define GTR_DB_TRANS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GTR_TYPE_DB_TRANS, GtranslatorDbTransClass))
+
+/* Private structure type */
+typedef struct _GtranslatorDbTransPrivate	GtranslatorDbTransPrivate;
+
+/*
+ * Main object structure
+ */
+typedef struct _GtranslatorDbTrans		GtranslatorDbTrans;
+
+struct _GtranslatorDbTrans
+{
+	GtranslatorDbBase parent_instance;
+	
+	/*< private > */
+	GtranslatorDbTransPrivate *priv;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GtranslatorDbTransClass	GtranslatorDbTransClass;
+
+struct _GtranslatorDbTransClass
+{
+	GtranslatorDbBaseClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType		 gtranslator_db_trans_get_type	      (void) G_GNUC_CONST;
+
+GType		 gtranslator_db_trans_register_type   (GTypeModule * module);
+
+GtranslatorDbTrans *gtranslator_db_trans_new	      (void);
+
+db_recno_t       gtranslator_db_trans_write_string    (GtranslatorDbTrans *db_trans,
+						       const gchar *translation,
+						       db_recno_t key);
+
+db_recno_t       gtranslator_db_trans_write           (GtranslatorDbTrans *db_trans,
+						       gchar **translations,
+						       db_recno_t index);	
+			    
+GPtrArray       *gtranslator_db_trans_read            (GtranslatorDbTrans *db_trans,
+						       db_recno_t index);
+
+G_END_DECLS
+
+#endif /* __DB_TRANS_H__ */
+
+
Index: src/translation-memory/berkeley/db-words.c
===================================================================
--- src/translation-memory/berkeley/db-words.c	(revision 0)
+++ src/translation-memory/berkeley/db-words.c	(revision 0)
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ *
+ *     Based in poedit transmem.cpp file:
+ *     Copyright (C) 2001-2007 Vaclav Slavik
+ * 
+ *     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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "db-words.h"
+#include "db-keys.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#define GTR_DB_WORDS_GET_PRIVATE(object)	(G_TYPE_INSTANCE_GET_PRIVATE ( \
+						 (object),		       \
+						 GTR_TYPE_DB_WORDS,     \
+						 GtranslatorDbWordsPrivate))
+
+G_DEFINE_TYPE(GtranslatorDbWords, gtranslator_db_words, GTR_TYPE_DB_BASE)
+
+
+struct _GtranslatorDbWordsPrivate
+{
+
+};
+
+static void
+gtranslator_db_words_init (GtranslatorDbWords *db_words)
+{
+	db_words->priv = GTR_DB_WORDS_GET_PRIVATE (db_words);
+	
+	gtranslator_db_base_create_dabatase (GTR_DB_BASE (db_words),
+					     _("words.db"),
+					     DB_HASH);
+}
+
+static void
+gtranslator_db_words_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gtranslator_db_words_parent_class)->finalize (object);
+}
+
+static void
+gtranslator_db_words_class_init (GtranslatorDbWordsClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GtranslatorDbWordsPrivate));
+
+	object_class->finalize = gtranslator_db_words_finalize;
+}
+
+GtranslatorDbWords *
+gtranslator_db_words_new ()
+{
+	GtranslatorDbWords *db_words;
+
+	db_words = g_object_new (GTR_TYPE_DB_WORDS, NULL);
+	
+	return db_words;
+}
+
+gboolean
+gtranslator_db_words_append (GtranslatorDbWords *db_words,
+			     const gchar *word,
+			     guint sentence_size,
+			     db_recno_t value)
+{
+	// VS: there is a dirty trick: it is always true that 'value' is 
+	//     greater than all values already present in the db, so we may
+	//     append it to the end of list while still keeping the list sorted.
+	//     This is important because it allows us to efficiently merge
+	//     these lists when looking up inexact translations...
+	
+	DBT key, data;
+	gsize len;
+	gsize buf_len;
+	GtranslatorDbKeys *keys;
+	db_recno_t *value_buf = NULL;
+	gint error = 0;
+	
+	/*
+	 * (sentence_size)(len)(word)
+	 */
+	len = strlen (word);
+	buf_len = sizeof (sentence_size) + sizeof (len) + len;
+	
+	//g_warning ("DEBUG: Append: %d|%d|%d|%s", sizeof (sentence_size), sizeof (len), len, word);
+	
+	//FIXME: use glib
+	u_int8_t *p, buf[buf_len];
+	
+	p = &buf[0];
+	memcpy (p, &sentence_size, sizeof (sentence_size));
+	p += sizeof (sentence_size);
+	memcpy (p, &len, sizeof (len));
+	p += sizeof (len);
+	memcpy (p, word, len);
+	
+	memset(&key, 0, sizeof(key));
+	memset(&data, 0, sizeof(data));
+	key.data = buf;
+	key.size = buf_len;
+	
+	keys = gtranslator_db_words_read (db_words, word, sentence_size);
+	if (keys == NULL)
+	{
+		data.data = &value;
+		data.size = sizeof(value);
+	}
+	else
+	{
+		gsize count = gtranslator_db_keys_get_count (keys);
+		db_recno_t *list = gtranslator_db_keys_get_list (keys);
+		
+		value_buf = g_new (db_recno_t, count + 1);
+		memcpy(value_buf, list, count * sizeof (db_recno_t));
+		value_buf[count] = value;
+		data.data = value_buf;
+		data.size = (count + 1) * sizeof(db_recno_t);
+	}
+
+	error = gtranslator_db_base_put (GTR_DB_BASE (db_words),
+					 &key,
+					 &data,
+					 0);
+	g_free (value_buf);
+	
+	if (error != 0)
+	{
+		gtranslator_db_base_show_error (GTR_DB_BASE (db_words), error);
+		return FALSE;
+	} 
+
+	return TRUE;
+}
+
+GtranslatorDbKeys *
+gtranslator_db_words_read (GtranslatorDbWords *db_words,
+			   const gchar *word,
+			   guint sentence_size)
+{
+	DBT key, data;
+	gsize len;
+	gsize buf_len;
+	GtranslatorDbKeys *keys;
+	gint error = 0;
+	
+	/*
+	 * (sentence_size)(len)(word)
+	 */
+	len = strlen (word);
+	buf_len = sizeof (sentence_size) + sizeof (len) + len;
+	//g_warning ("DEBUG: Read: %d|%d|%d|%s", sizeof (sentence_size), sizeof (len), len, word);
+	/*
+	 * Here we recreate the key and then with that key we get the list
+	 * of keys
+	 */
+	//FIXME: use glib
+	u_int8_t *p, buf[buf_len];
+	
+	p = &buf[0];
+	memcpy (p, &sentence_size, sizeof (sentence_size));
+	p += sizeof (sentence_size);
+	memcpy (p, &len, sizeof (len));
+	p += sizeof (len);
+	memcpy (p, word, len);
+	
+	memset (&key, 0, sizeof (key));
+	memset (&data, 0, sizeof (data));
+	key.data = buf;
+	key.size = buf_len;
+	
+	error = gtranslator_db_base_get (GTR_DB_BASE (db_words),
+					 &key,
+					 &data);
+	if (error != 0)
+	{
+		gtranslator_db_base_show_error (GTR_DB_BASE (db_words), error);
+		return NULL;
+	}
+	
+	keys = gtranslator_db_keys_new (&data);
+	
+	return keys;
+}
Index: src/translation-memory/berkeley/db-base.h
===================================================================
--- src/translation-memory/berkeley/db-base.h	(revision 0)
+++ src/translation-memory/berkeley/db-base.h	(revision 0)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ * 
+ *     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/>.
+ */
+
+#ifndef __DB_BASE_H__
+#define __DB_BASE_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include DB_HEADER
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GTR_TYPE_DB_BASE		(gtranslator_db_base_get_type ())
+#define GTR_DB_BASE(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GTR_TYPE_DB_BASE, GtranslatorDbBase))
+#define GTR_DB_BASE_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GTR_TYPE_DB_BASE, GtranslatorDbBaseClass))
+#define GTR_IS_DB_BASE(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GTR_TYPE_DB_BASE))
+#define GTR_IS_DB_BASE_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GTR_TYPE_DB_BASE))
+#define GTR_DB_BASE_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GTR_TYPE_DB_BASE, GtranslatorDbBaseClass))
+
+/* Private structure type */
+typedef struct _GtranslatorDbBasePrivate	GtranslatorDbBasePrivate;
+
+/*
+ * Main object structure
+ */
+typedef struct _GtranslatorDbBase		GtranslatorDbBase;
+
+struct _GtranslatorDbBase
+{
+	GObject parent_instance;
+	
+	/*< private > */
+	GtranslatorDbBasePrivate *priv;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GtranslatorDbBaseClass	GtranslatorDbBaseClass;
+
+struct _GtranslatorDbBaseClass
+{
+	GObjectClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType		 gtranslator_db_base_get_type	     (void) G_GNUC_CONST;
+
+GType		 gtranslator_db_base_register_type   (GTypeModule * module);
+
+void             gtranslator_db_base_create_dabatase (GtranslatorDbBase *base,
+						      const gchar *filename,
+						      DBTYPE type);
+						      
+void             gtranslator_db_base_show_error      (GtranslatorDbBase *base,
+						      gint error);
+						      
+gint             gtranslator_db_base_put             (GtranslatorDbBase *base,
+						      DBT *key,
+						      DBT *data,
+						      u_int32_t flags);
+						      
+gint             gtranslator_db_base_get             (GtranslatorDbBase *base,
+						      DBT *key,
+						      DBT *data);
+
+G_END_DECLS
+
+#endif /* __DB_BASE_H__ */
Index: src/translation-memory/berkeley/berkeley.c
===================================================================
--- src/translation-memory/berkeley/berkeley.c	(revision 0)
+++ src/translation-memory/berkeley/berkeley.c	(revision 0)
@@ -0,0 +1,594 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ *
+ *     Based in poedit transmem.cpp file:
+ *     Copyright (C) 2001-2007 Vaclav Slavik
+ * 
+ *     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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "berkeley.h"
+#include "translation-memory.h"
+#include DB_HEADER //This can be something like <db.h>
+#include "db-trans.h"
+#include "db-orig.h"
+#include "db-words.h"
+#include "utils.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#define GTR_BERKELEY_GET_PRIVATE(object)	(G_TYPE_INSTANCE_GET_PRIVATE ( \
+						 (object),		       \
+						 GTR_TYPE_BERKELEY,            \
+						 GtranslatorBerkeleyPrivate))
+
+static void gtranslator_translation_memory_iface_init (GtranslatorTranslationMemoryIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GtranslatorBerkeley,
+			 gtranslator_berkeley,
+			 G_TYPE_OBJECT,
+			 G_IMPLEMENT_INTERFACE (GTR_TYPE_TRANSLATION_MEMORY,
+				 		gtranslator_translation_memory_iface_init))
+
+struct _GtranslatorBerkeleyPrivate
+{
+	GtranslatorDbOrig *orig;
+	GtranslatorDbTrans *trans;
+	GtranslatorDbWords *words;
+	
+	gsize max_omits;
+	gsize max_delta;
+};
+
+static gboolean
+gtranslator_berkeley_store (GtranslatorTranslationMemory *tm,
+			    const gchar *original,
+			    const gchar *translation)
+{
+	GtranslatorBerkeley *ber = GTR_BERKELEY (tm);
+	gboolean ok;
+	db_recno_t key;
+	
+	g_return_val_if_fail (GTR_IS_BERKELEY (ber), FALSE);
+	
+	key = gtranslator_db_orig_read (ber->priv->orig,
+					original);
+	if (key == 0)
+	{
+		key = gtranslator_db_trans_write_string (ber->priv->trans,
+							 translation, 0);
+
+		ok = (key != 0) && gtranslator_db_orig_write (ber->priv->orig, original, key);
+		if (ok)
+		{
+			gchar **words = NULL;
+			gsize i;
+			
+			words = gtranslator_utils_split_string_in_words (original);
+			gsize sz = g_strv_length (words);
+			
+			for (i = 0; i < sz; i++)
+				gtranslator_db_words_append (ber->priv->words,
+							     words[i],
+							     sz,
+							     key);
+		}
+		return ok;
+	}
+	else
+	{
+		gboolean found = FALSE;
+		gint i = 0;
+		GPtrArray *t = gtranslator_db_trans_read (ber->priv->trans,
+							  key);
+		if (!t)
+			return FALSE;
+		
+		// -1 because we know that last element is NULL
+		while (i < t->len - 1)
+		{
+			if (g_utf8_collate (g_ptr_array_index (t, i), translation) == 0)
+			{
+				found = TRUE;
+				break;
+			}
+			
+			i++;
+		}
+		
+		if (!found)
+		{
+			gchar **translations = NULL;
+			
+			/*
+			 * We remove the previous NULL data and then we add the new data
+			 */
+			g_ptr_array_remove_index (t, t->len-1);
+			g_ptr_array_add (t, g_strdup (translation));
+			g_ptr_array_add (t, NULL);
+			
+			translations = (gchar **)g_ptr_array_free (t, FALSE);
+			
+			db_recno_t key2 = gtranslator_db_trans_write (ber->priv->trans,
+								      translations,
+								      key);
+			g_strfreev (translations);
+			ok = (key2 != 0);
+		}
+		else
+		{
+			ok = TRUE;
+			g_ptr_array_free (t, TRUE);
+		}
+
+		return ok;
+	}
+}
+
+static GtranslatorDbKeys *
+union_of_db_keys (GtranslatorBerkeley *ber,
+		  gsize cnt,
+		  GtranslatorDbKeys **keys,
+		  gboolean *mask)
+{
+	gsize i, minSize;
+	db_recno_t **heads = g_new (db_recno_t *, cnt);
+	gsize *counters = g_new (gsize, cnt);
+	GtranslatorDbKeys *result;
+	db_recno_t *res_list;
+
+	// initialize heads and counters _and_ find size of smallest keys list
+	// (union can't be larger than that)
+	for (minSize = 0, i = 0; i < cnt; i++)
+	{
+		if (mask[i])
+		{
+			gsize count = gtranslator_db_keys_get_count (keys[i]);
+			db_recno_t * list = gtranslator_db_keys_get_list (keys[i]);
+			
+			counters[i] = count;
+			heads[i] = list;
+			if (minSize == 0 || minSize > count)
+				minSize = count;
+		}
+		else
+		{
+			counters[i] = 0;
+			heads[i] = NULL;
+		}
+	}
+	if (minSize == 0)
+	{
+		g_free (counters);
+		g_free (heads);
+
+		return NULL;
+	}
+	
+	result = gtranslator_db_keys_new_with_size (minSize);
+	res_list = gtranslator_db_keys_get_list (result);
+	gsize res_count = 0;
+	
+	// Do union of 'cnt' sorted arrays. Algorithm: treat arrays as lists,
+	// remember pointer to first unprocessed item. In each iteration, do:
+	// if all heads have same value, add that value to output list, otherwise
+	// move the head with smallest value one item forward. (This way we won't
+	// miss any value that could possibly be in the output list, because 
+	// if the smallest value of all heads is not at the beginning of other
+	// lists, it cannot appear later in these lists due to their sorted nature.
+	// We end processing when any head reaches end of (its) list
+	db_recno_t smallestValue;
+	gsize smallestIndex = 0;
+	gboolean allSame;
+	for (;;)
+	{
+		allSame = TRUE;
+		smallestValue = 0;
+		
+		for (i = 0; i < cnt; i++)
+		{
+			if (counters[i] == 0)
+				continue;
+			if (smallestValue == 0)
+			{
+				smallestValue = *heads[i];
+				smallestIndex = i;
+			}
+			else if (smallestValue != *heads[i])
+			{
+				allSame = FALSE;
+				if (smallestValue > *heads[i])
+				{
+					smallestValue = *heads[i];
+					smallestIndex = i;
+				}
+			}
+		}
+		
+		if (smallestValue == 0)
+			break;
+		
+		if (allSame)
+		{
+			gboolean breakMe = FALSE;
+			res_list[res_count++] = smallestValue;
+			for (i = 0; i < cnt; i++)
+			{
+				if (counters[i] == 0)
+					continue;
+				if (--counters[i] == 0)
+				{
+					breakMe = TRUE;
+					break;
+				}
+				heads[i]++;
+			}
+			if (breakMe)
+				break;
+		}
+		else
+		{
+			if (--counters[smallestIndex] == 0)
+				break;
+			heads[smallestIndex]++;
+		}
+	}
+	
+	g_free (counters);
+	g_free (heads);
+	if (res_count == 0)
+	{
+		g_object_unref (result);
+		result = NULL;
+	}
+	else gtranslator_db_keys_set_count (result, res_count);
+	
+	return result;
+}
+
+static gboolean
+advance_cycle (gsize omitted[],
+	       gsize depth,
+	       gsize cnt)
+{
+	if (++omitted[depth] == cnt)
+	{
+		if (depth == 0) 
+			return FALSE;
+		depth--;
+		if (!advance_cycle (omitted, depth, cnt))
+			return FALSE;
+		depth++;
+		omitted[depth] = omitted[depth - 1] + 1;
+		if (omitted[depth] >= cnt)
+			return FALSE;
+		return TRUE;
+	}
+	else
+		return TRUE;
+}
+
+static gboolean
+look_fuzzy (GtranslatorBerkeley *ber,
+	    gchar **words,
+	    GHashTable **hash,
+	    gsize omits,
+	    gsize delta)
+{
+#define RETURN_WITH_CLEANUP(val) \
+	for (i = 0; i < cnt_orig; i++) \
+		if (keys[i]) \
+			g_object_unref (keys[i]); \
+	g_free (keys); \
+	g_free (mask); \
+	g_free (omitted); \
+	return (val);
+
+	gsize i, slot;
+	gsize missing;
+	GtranslatorDbKeys **keys;
+	gboolean *mask;
+	gsize *omitted;
+	gsize cnt = g_strv_length (words);
+	gsize cnt_orig = cnt;
+	GtranslatorDbKeys *result;
+	
+	if (omits >= cnt)
+		return FALSE;
+	if (cnt + delta <= 0)
+		return FALSE;
+	
+	keys = g_new (GtranslatorDbKeys *, cnt);
+	mask = g_new (gboolean, cnt);
+	omitted = g_new (gsize, omits);
+	
+	for (missing = 0, slot = 0, i = 0; i < cnt; i++)
+	{
+		keys[i] = NULL; // so that unused entries are NULL
+		keys[slot] = gtranslator_db_words_read (ber->priv->words,
+							words[i], cnt + delta);
+		if (keys[slot])
+			slot++;
+		else
+			missing++;
+	}
+	
+	if (missing >= cnt || missing > omits)
+	{
+		RETURN_WITH_CLEANUP(FALSE)
+	}
+	cnt -= missing;
+	omits -= missing;
+
+	if (omits == 0)
+	{
+		for (i = 0; i < cnt; i++)
+			mask[i] = TRUE;
+		
+		result = union_of_db_keys (ber, cnt,
+					   keys, mask);
+		if (result != NULL)
+		{
+			GPtrArray *array;
+			
+			db_recno_t *list = gtranslator_db_keys_get_list (result);
+			for (i = 0; i < gtranslator_db_keys_get_count (result); i++)
+			{	
+				array = gtranslator_db_trans_read (ber->priv->trans,
+								   list[i]);
+				if (array)
+				{
+					gint j = 0;
+					gint score = 0;
+					
+					score = (ber->priv->max_omits - omits) * 100 / 
+						(ber->priv->max_omits + 1) +
+						(ber->priv->max_delta - delta) * 100 /
+						((ber->priv->max_delta + 1) *
+						 (ber->priv->max_delta + 1));
+					
+					if (score == 0)
+						score = 1;
+
+					while (j < array->len -1)
+					{
+						gchar *string;
+						
+						string = (gchar *)g_ptr_array_index (array, j);
+						g_hash_table_insert (*hash, string,
+								     GINT_TO_POINTER (score));
+
+						j++;
+					}
+					g_ptr_array_free (array, TRUE);
+				}
+			}
+			g_object_unref (result);
+			RETURN_WITH_CLEANUP(TRUE)
+		}
+	}
+	else
+	{
+		gsize depth = omits - 1;
+		
+		for (i = 0; i < omits; i++)
+			omitted[i] = i;
+		for (;;)
+		{
+			for (i = 0; i < cnt; i++)
+				mask[i] = TRUE;
+			for (i = 0; i < omits; i++)
+				mask[omitted[i]] = FALSE;
+			
+			result = union_of_db_keys (ber, cnt, keys, mask);
+			if (result != NULL)
+			{		
+				GPtrArray *array;
+				
+				db_recno_t *list = gtranslator_db_keys_get_list (result);
+				for (i = 0; i < gtranslator_db_keys_get_count (result); i++)
+				{
+					array = gtranslator_db_trans_read (ber->priv->trans,
+									   list[i]);
+					if (array)
+					{
+						gint j = 0;
+						gint score = 0;
+						
+						score = (ber->priv->max_omits - omits) * 100 / 
+							(ber->priv->max_omits + 1) +
+							(ber->priv->max_delta - delta) * 100 /
+							((ber->priv->max_delta + 1) *
+							 (ber->priv->max_delta + 1));
+						
+						if (score == 0)
+							score = 1;
+						
+						while (j < array->len -1)
+						{
+							gchar *string;
+							
+							string = (gchar *)g_ptr_array_index (array, j);
+							g_hash_table_insert (*hash, string,
+									     GINT_TO_POINTER (score));
+							
+							j++;
+						}
+						g_ptr_array_free (array, TRUE);
+					}
+				}
+				g_object_unref (result);
+				RETURN_WITH_CLEANUP(TRUE)
+			}
+			
+			if (!advance_cycle (omitted, depth, cnt))
+				break;
+		}
+	}
+	RETURN_WITH_CLEANUP(FALSE)
+}
+
+static GList *
+gtranslator_berkeley_lookup (GtranslatorTranslationMemory *tm,
+			     const gchar *phrase)
+{
+	GPtrArray *array = NULL;
+	gchar **words;
+	gsize omits;
+	gsize delta;
+	GtranslatorBerkeley *ber = GTR_BERKELEY (tm);
+	GHashTable *hash;
+	GHashTableIter iter;
+	gpointer hkey, value;
+	gint index = 0;
+	GList *matches = NULL;
+	
+	g_return_val_if_fail (GTR_IS_BERKELEY (ber), NULL);
+	
+	hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	
+	// First of all, try exact match:
+	db_recno_t key = gtranslator_db_orig_read (ber->priv->orig, phrase);
+	if (key != 0)
+	{
+		gint i = 0;
+		
+		array = gtranslator_db_trans_read (ber->priv->trans,
+						   key);
+		
+		while (i < array->len -1)
+		{
+			g_hash_table_insert (hash, g_ptr_array_index (array, i),
+					     GINT_TO_POINTER (100));
+			i++;
+		}
+		
+		goto list;
+	}
+	
+	// Then, try to find inexact one within defined limits
+	// (MAX_OMITS is max permitted number of unmatched words,
+	// MAX_DELTA is max difference in sentences lengths).
+	// Start with best matches first, continue to worse ones.
+	words = gtranslator_utils_split_string_in_words (phrase);
+	for (omits = 0; omits <= ber->priv->max_omits; omits++)
+	{
+		for (delta = 0; delta <= ber->priv->max_delta; delta++)
+		{
+			look_fuzzy (ber, words, &hash, omits, delta);
+		}
+	}
+	
+list:   g_hash_table_iter_init (&iter, hash);
+	while (g_hash_table_iter_next (&iter, &hkey, &value)) 
+	{
+		GtranslatorTranslationMemoryMatch *match = g_new (GtranslatorTranslationMemoryMatch, 1);
+		match->match = g_strdup (hkey);
+		match->level = GPOINTER_TO_INT (value);
+		
+		matches = g_list_append (matches, match);
+		index++;
+	}
+
+	g_hash_table_unref (hash);
+	
+	return matches;
+}
+
+static void
+gtranslator_berkeley_set_max_omits (GtranslatorTranslationMemory *tm,
+				    gsize omits)
+{
+	GtranslatorBerkeley *ber = GTR_BERKELEY (tm);
+	
+	ber->priv->max_omits = omits;
+}
+
+static void
+gtranslator_berkeley_set_max_delta (GtranslatorTranslationMemory *tm,
+				    gsize delta)
+{
+	GtranslatorBerkeley *ber = GTR_BERKELEY (tm);
+	
+	ber->priv->max_delta = delta;
+}
+
+static void
+gtranslator_translation_memory_iface_init (GtranslatorTranslationMemoryIface *iface)
+{
+	iface->store = gtranslator_berkeley_store;
+	iface->lookup = gtranslator_berkeley_lookup;
+	iface->set_max_omits = gtranslator_berkeley_set_max_omits;
+	iface->set_max_delta = gtranslator_berkeley_set_max_delta;
+}
+
+static void
+gtranslator_berkeley_init (GtranslatorBerkeley *pf)
+{
+	pf->priv = GTR_BERKELEY_GET_PRIVATE (pf);
+
+	pf->priv->orig = gtranslator_db_orig_new ();
+	pf->priv->trans = gtranslator_db_trans_new ();
+	pf->priv->words = gtranslator_db_words_new ();
+	pf->priv->max_omits = 0;
+	pf->priv->max_delta = 0;
+}
+
+static void
+gtranslator_berkeley_finalize (GObject *object)
+{
+	GtranslatorBerkeley *ber = GTR_BERKELEY (object);
+	
+	g_object_unref (ber->priv->orig);
+	g_object_unref (ber->priv->trans);
+	g_object_unref (ber->priv->words);
+	
+	G_OBJECT_CLASS (gtranslator_berkeley_parent_class)->finalize (object);
+}
+
+static void
+gtranslator_berkeley_class_init (GtranslatorBerkeleyClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GtranslatorBerkeleyPrivate));
+
+	object_class->finalize = gtranslator_berkeley_finalize;
+}
+
+/**
+ * gtranslator_berkeley_new:
+ * 
+ * Creates a new #GtranslatorBerkeley object.
+ *
+ * Returns: a new #GtranslatorBerkeley object
+ */
+GtranslatorBerkeley *
+gtranslator_berkeley_new ()
+{
+	GtranslatorBerkeley *berkeley;
+
+	berkeley = g_object_new (GTR_TYPE_BERKELEY, NULL);
+	
+	return berkeley;
+}
+
Index: src/translation-memory/berkeley/db-orig.c
===================================================================
--- src/translation-memory/berkeley/db-orig.c	(revision 0)
+++ src/translation-memory/berkeley/db-orig.c	(revision 0)
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ *
+ *     Based in poedit transmem.cpp file:
+ *     Copyright (C) 2001-2007 Vaclav Slavik
+ * 
+ *     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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "db-orig.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#define GTR_DB_ORIG_GET_PRIVATE(object)	(G_TYPE_INSTANCE_GET_PRIVATE ( \
+						 (object),		       \
+						 GTR_TYPE_DB_ORIG,     \
+						 GtranslatorDbOrigPrivate))
+
+G_DEFINE_TYPE(GtranslatorDbOrig, gtranslator_db_orig, GTR_TYPE_DB_BASE)
+
+
+struct _GtranslatorDbOrigPrivate
+{
+
+};
+
+static void
+gtranslator_db_orig_init (GtranslatorDbOrig *db_orig)
+{
+	db_orig->priv = GTR_DB_ORIG_GET_PRIVATE (db_orig);
+	
+	gtranslator_db_base_create_dabatase (GTR_DB_BASE (db_orig),
+					     _("original.db"),
+					     DB_HASH);
+}
+
+static void
+gtranslator_db_orig_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gtranslator_db_orig_parent_class)->finalize (object);
+}
+
+static void
+gtranslator_db_orig_class_init (GtranslatorDbOrigClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GtranslatorDbOrigPrivate));
+
+	object_class->finalize = gtranslator_db_orig_finalize;
+}
+
+/**
+ * gtranslator_db_orig_new:
+ * 
+ * Creates a new #GtranslatorDbOrig object.
+ * 
+ * Returns: a newly #GtranslatorDbOrig object
+ */
+GtranslatorDbOrig *
+gtranslator_db_orig_new ()
+{
+	GtranslatorDbOrig *db_orig;
+
+	db_orig = g_object_new (GTR_TYPE_DB_ORIG, NULL);
+	
+	return db_orig;
+}
+
+/**
+ * gtranslator_db_orig_write:
+ * @orig: a #GtranslatorDbOrig
+ * @string: string to store in the database
+ * @value: the foreign key from #GtranslatorDbTrans
+ *
+ * Stores the @string in the database with the right foreign key @value.
+ * It returns TRUE if there was not any error.
+ *
+ * Returns: TRUE if it was successfully stored.
+ */
+gboolean
+gtranslator_db_orig_write (GtranslatorDbOrig *orig,
+			   const gchar *string,
+			   db_recno_t value)
+{
+	DBT key, data;
+	gint error;
+
+	memset (&key, 0, sizeof (key));
+	memset (&data, 0, sizeof (data));
+	key.data = (gpointer) string;
+	key.size = strlen (string);
+	data.data = &value;
+	data.size = sizeof (value);
+	
+	error = gtranslator_db_base_put (GTR_DB_BASE (orig),
+					 &key,
+					 &data,
+					 0);
+	if (error != 0)
+	{
+		gtranslator_db_base_show_error (GTR_DB_BASE (orig), error);
+		return FALSE;
+	}
+	
+	return TRUE;
+}
+
+/**
+ * gtranslator_db_orig_read:
+ * @orig: a #GtranslatorDbOrig
+ * @string: the primary key of the #GtranslatorDbOrig
+ *
+ * Gets the foreign key for #GtranslatorDbTrans for a given #GtranslatorDbOrig
+ * primary key.
+ *
+ * Returns: the foreign key for #GtranslatorDbTrans
+ */
+db_recno_t
+gtranslator_db_orig_read (GtranslatorDbOrig *orig,
+			  const gchar *string)
+{
+	DBT key, data;
+	gint error;
+
+	memset (&key, 0, sizeof (key));
+	memset (&data, 0, sizeof (data));
+	key.data = (gpointer)string;
+	key.size = strlen (string);
+	
+	error = gtranslator_db_base_get (GTR_DB_BASE (orig),
+					 &key, &data);
+	if (error != 0)
+	{
+		if (error != DB_NOTFOUND)
+			gtranslator_db_base_show_error (GTR_DB_BASE (orig),
+							error);
+		return 0;
+	}
+	
+	return *((db_recno_t*)data.data);
+}
Index: src/translation-memory/berkeley/db-keys.h
===================================================================
--- src/translation-memory/berkeley/db-keys.h	(revision 0)
+++ src/translation-memory/berkeley/db-keys.h	(revision 0)
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ * 
+ *     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/>.
+ */
+
+#ifndef __DB_KEYS_H__
+#define __DB_KEYS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include DB_HEADER
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GTR_TYPE_DB_KEYS		(gtranslator_db_keys_get_type ())
+#define GTR_DB_KEYS(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GTR_TYPE_DB_KEYS, GtranslatorDbKeys))
+#define GTR_DB_KEYS_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GTR_TYPE_DB_KEYS, GtranslatorDbKeysClass))
+#define GTR_IS_DB_KEYS(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GTR_TYPE_DB_KEYS))
+#define GTR_IS_DB_KEYS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GTR_TYPE_DB_KEYS))
+#define GTR_DB_KEYS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GTR_TYPE_DB_KEYS, GtranslatorDbKeysClass))
+
+/* Private structure type */
+typedef struct _GtranslatorDbKeysPrivate	GtranslatorDbKeysPrivate;
+
+/*
+ * Main object structure
+ */
+typedef struct _GtranslatorDbKeys		GtranslatorDbKeys;
+
+struct _GtranslatorDbKeys
+{
+	GObject parent_instance;
+	
+	/*< private > */
+	GtranslatorDbKeysPrivate *priv;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GtranslatorDbKeysClass	GtranslatorDbKeysClass;
+
+struct _GtranslatorDbKeysClass
+{
+	GObjectClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType		 gtranslator_db_keys_get_type	      (void) G_GNUC_CONST;
+
+GType		 gtranslator_db_keys_register_type    (GTypeModule * module);
+
+GtranslatorDbKeys *gtranslator_db_keys_new	      (DBT *data);
+
+GtranslatorDbKeys *gtranslator_db_keys_new_with_size  (gsize cnt);
+
+db_recno_t      *gtranslator_db_keys_get_list         (GtranslatorDbKeys *db_keys);
+
+gsize            gtranslator_db_keys_get_count        (GtranslatorDbKeys *db_keys);
+
+void             gtranslator_db_keys_set_count        (GtranslatorDbKeys *db_keys,
+						       gsize count);
+
+G_END_DECLS
+
+#endif /* __DB_KEYS_H__ */
Index: src/translation-memory/berkeley/db-words.h
===================================================================
--- src/translation-memory/berkeley/db-words.h	(revision 0)
+++ src/translation-memory/berkeley/db-words.h	(revision 0)
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ * 
+ *     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/>.
+ */
+
+#ifndef __DB_WORDS_H__
+#define __DB_WORDS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "db-base.h"
+#include "db-keys.h"
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GTR_TYPE_DB_WORDS		(gtranslator_db_words_get_type ())
+#define GTR_DB_WORDS(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GTR_TYPE_DB_WORDS, GtranslatorDbWords))
+#define GTR_DB_WORDS_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GTR_TYPE_DB_WORDS, GtranslatorDbWordsClass))
+#define GTR_IS_DB_WORDS(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GTR_TYPE_DB_WORDS))
+#define GTR_IS_DB_WORDS_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GTR_TYPE_DB_WORDS))
+#define GTR_DB_WORDS_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GTR_TYPE_DB_WORDS, GtranslatorDbWordsClass))
+
+/* Private structure type */
+typedef struct _GtranslatorDbWordsPrivate	GtranslatorDbWordsPrivate;
+
+/*
+ * Main object structure
+ */
+typedef struct _GtranslatorDbWords		GtranslatorDbWords;
+
+struct _GtranslatorDbWords
+{
+	GtranslatorDbBase parent_instance;
+	
+	/*< private > */
+	GtranslatorDbWordsPrivate *priv;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GtranslatorDbWordsClass	GtranslatorDbWordsClass;
+
+struct _GtranslatorDbWordsClass
+{
+	GtranslatorDbBaseClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType		 gtranslator_db_words_get_type	      (void) G_GNUC_CONST;
+
+GType		 gtranslator_db_words_register_type   (GTypeModule * module);
+
+GtranslatorDbWords *gtranslator_db_words_new	      (void);
+
+gboolean         gtranslator_db_words_append          (GtranslatorDbWords *db_words,
+						       const gchar *word,
+						       guint sentence_size,
+						       db_recno_t value);
+						       
+GtranslatorDbKeys *gtranslator_db_words_read          (GtranslatorDbWords *db_words,
+						       const gchar *word,
+						       guint sentence_size);
+
+G_END_DECLS
+
+#endif /* __DB_WORDS_H__ */
Index: src/translation-memory/berkeley/berkeley.h
===================================================================
--- src/translation-memory/berkeley/berkeley.h	(revision 0)
+++ src/translation-memory/berkeley/berkeley.h	(revision 0)
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ * 
+ *     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/>.
+ */
+
+#ifndef __BERKELEY_H__
+#define __BERKELEY_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GTR_TYPE_BERKELEY		(gtranslator_berkeley_get_type ())
+#define GTR_BERKELEY(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GTR_TYPE_BERKELEY, GtranslatorBerkeley))
+#define GTR_BERKELEY_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GTR_TYPE_BERKELEY, GtranslatorBerkeleyClass))
+#define GTR_IS_BERKELEY(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GTR_TYPE_BERKELEY))
+#define GTR_IS_BERKELEY_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GTR_TYPE_BERKELEY))
+#define GTR_BERKELEY_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GTR_TYPE_BERKELEY, GtranslatorBerkeleyClass))
+
+/* Private structure type */
+typedef struct _GtranslatorBerkeleyPrivate	GtranslatorBerkeleyPrivate;
+
+/*
+ * Main object structure
+ */
+typedef struct _GtranslatorBerkeley		GtranslatorBerkeley;
+
+struct _GtranslatorBerkeley
+{
+	GObject parent_instance;
+	
+	/*< private > */
+	GtranslatorBerkeleyPrivate *priv;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GtranslatorBerkeleyClass	GtranslatorBerkeleyClass;
+
+struct _GtranslatorBerkeleyClass
+{
+	GObjectClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType		 gtranslator_berkeley_get_type	  (void) G_GNUC_CONST;
+
+GType		 gtranslator_berkeley_register_type   (GTypeModule * module);
+
+GtranslatorBerkeley   *gtranslator_berkeley_new	  (void);
+
+G_END_DECLS
+
+#endif /* __BERKELEY_H__ */
Index: src/translation-memory/berkeley/Makefile.am
===================================================================
--- src/translation-memory/berkeley/Makefile.am	(revision 0)
+++ src/translation-memory/berkeley/Makefile.am	(revision 0)
@@ -0,0 +1,38 @@
+INCLUDES =                                                      \
+        -I$(top_srcdir)                                         \
+        -I$(top_builddir)                                       \
+        -I$(top_srcdir)/src                                     \
+        -I$(top_builddir)/src                                   \
+        -I$(top_srcdir)/src/translation-memory                  \
+	-I$(headerdir)						\
+	-DPIXMAPSDIR=\""$(datadir)"/pixmaps/gtranslator\"       \
+        $(GTRANSLATOR_CFLAGS)                                   \
+        $(WARN_CFLAGS)                                          \
+        $(DISABLE_DEPRECATED_CFLAGS)
+
+noinst_LTLIBRARIES = \
+	libberkeley.la
+
+libberkeley_la_SOURCES = \
+	berkeley.c \
+	berkeley.h \
+	db-base.h \
+	db-base.c \
+	db-trans.h \
+	db-trans.c \
+	db-orig.h \
+	db-orig.c \
+	db-words.h \
+	db-words.c \
+	db-keys.h \
+	db-keys.c
+
+libberkeley_la_CFLAGS = \
+	$(GTRANSLATOR_CFLAGS)			\
+	$(WARN_CFLAGS)				\
+	$(DISABLE_DEPRECATED)			\
+	-DCURSOR_DIR=\"$(pkgdatadir)\"		\
+	$(AM_CFLAGS)
+
+EXTRA_DIST = $(pixmaps__DATA)
+
Index: src/translation-memory/berkeley/db-orig.h
===================================================================
--- src/translation-memory/berkeley/db-orig.h	(revision 0)
+++ src/translation-memory/berkeley/db-orig.h	(revision 0)
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ * 
+ *     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/>.
+ */
+
+#ifndef __DB_ORIG_H__
+#define __DB_ORIG_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include "db-base.h"
+
+G_BEGIN_DECLS
+
+/*
+ * Type checking and casting macros
+ */
+#define GTR_TYPE_DB_ORIG		(gtranslator_db_orig_get_type ())
+#define GTR_DB_ORIG(o)		(G_TYPE_CHECK_INSTANCE_CAST ((o), GTR_TYPE_DB_ORIG, GtranslatorDbOrig))
+#define GTR_DB_ORIG_CLASS(k)	(G_TYPE_CHECK_CLASS_CAST((k), GTR_TYPE_DB_ORIG, GtranslatorDbOrigClass))
+#define GTR_IS_DB_ORIG(o)		(G_TYPE_CHECK_INSTANCE_TYPE ((o), GTR_TYPE_DB_ORIG))
+#define GTR_IS_DB_ORIG_CLASS(k)	(G_TYPE_CHECK_CLASS_TYPE ((k), GTR_TYPE_DB_ORIG))
+#define GTR_DB_ORIG_GET_CLASS(o)	(G_TYPE_INSTANCE_GET_CLASS ((o), GTR_TYPE_DB_ORIG, GtranslatorDbOrigClass))
+
+/* Private structure type */
+typedef struct _GtranslatorDbOrigPrivate	GtranslatorDbOrigPrivate;
+
+/*
+ * Main object structure
+ */
+typedef struct _GtranslatorDbOrig		GtranslatorDbOrig;
+
+struct _GtranslatorDbOrig
+{
+	GtranslatorDbBase parent_instance;
+	
+	/*< private > */
+	GtranslatorDbOrigPrivate *priv;
+};
+
+/*
+ * Class definition
+ */
+typedef struct _GtranslatorDbOrigClass	GtranslatorDbOrigClass;
+
+struct _GtranslatorDbOrigClass
+{
+	GtranslatorDbBaseClass parent_class;
+};
+
+/*
+ * Public methods
+ */
+GType		 gtranslator_db_orig_get_type	      (void) G_GNUC_CONST;
+
+GType		 gtranslator_db_orig_register_type    (GTypeModule * module);
+
+GtranslatorDbOrig *gtranslator_db_orig_new	      (void);
+
+gboolean         gtranslator_db_orig_write            (GtranslatorDbOrig *orig,
+						       const gchar *string,
+						       db_recno_t value);
+						       
+db_recno_t       gtranslator_db_orig_read             (GtranslatorDbOrig *orig,
+						       const gchar *string);
+
+G_END_DECLS
+
+#endif /* __DB_ORIG_H__ */
Index: src/translation-memory/berkeley/db-trans.c
===================================================================
--- src/translation-memory/berkeley/db-trans.c	(revision 0)
+++ src/translation-memory/berkeley/db-trans.c	(revision 0)
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ *
+ *     Based in poedit transmem.cpp file:
+ *     Copyright (C) 2001-2007 Vaclav Slavik
+ * 
+ *     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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "db-trans.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <string.h>
+
+#define GTR_DB_TRANS_GET_PRIVATE(object)	(G_TYPE_INSTANCE_GET_PRIVATE ( \
+						 (object),		       \
+						 GTR_TYPE_DB_TRANS,     \
+						 GtranslatorDbTransPrivate))
+
+G_DEFINE_TYPE(GtranslatorDbTrans, gtranslator_db_trans, GTR_TYPE_DB_BASE)
+
+
+struct _GtranslatorDbTransPrivate
+{
+
+};
+
+static void
+gtranslator_db_trans_init (GtranslatorDbTrans *db_trans)
+{
+	db_trans->priv = GTR_DB_TRANS_GET_PRIVATE (db_trans);
+	
+	gtranslator_db_base_create_dabatase (GTR_DB_BASE (db_trans),
+					     _("translations.db"),
+					     DB_RECNO);
+}
+
+static void
+gtranslator_db_trans_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (gtranslator_db_trans_parent_class)->finalize (object);
+}
+
+static void
+gtranslator_db_trans_class_init (GtranslatorDbTransClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GtranslatorDbTransPrivate));
+
+	object_class->finalize = gtranslator_db_trans_finalize;
+}
+
+/**
+ * gtranslator_db_trans_new:
+ * 
+ * Creates a new #GtranslatorDbTrans object.
+ * 
+ * Returns: a newly #GtranslatorDbTrans object
+ */
+GtranslatorDbTrans *
+gtranslator_db_trans_new ()
+{
+	GtranslatorDbTrans *db_trans;
+
+	db_trans = g_object_new (GTR_TYPE_DB_TRANS, NULL);
+	
+	return db_trans;
+}
+
+/**
+ * gtranslator_db_trans_write_string:
+ * @db_trans: a #GtranslatorDbTrans
+ * @translation: string to be stored in the database
+ * @key: the index record in the database to be modified
+ * 
+ * Writes @translation in the database and returns the new key index.
+ *
+ * Returns: if @index is 0 then returns the new index, else returns @index
+ */
+db_recno_t
+gtranslator_db_trans_write_string (GtranslatorDbTrans *db_trans,
+				   const gchar *translation,
+				   db_recno_t key)
+{
+	gchar *array[2];
+	db_recno_t toret;
+	
+	array[0] = g_strdup (translation);
+	array[1] = NULL;
+	
+	toret = gtranslator_db_trans_write (db_trans, array, key);
+	
+	g_free (array[0]);
+	
+	return toret;
+}
+
+/**
+ * gtranslator_db_trans_write:
+ * @db_trans: a #GtranslatorDbTrans
+ * @translations: array of translations
+ * @index: the index record in the database to be modified
+ *
+ * Writes @translations in the database and returns the new key index.
+ *
+ * Returns: if @index is 0 then returns the new index, else returns @index
+ */
+db_recno_t
+gtranslator_db_trans_write (GtranslatorDbTrans *db_trans,
+			    gchar **translations,
+			    db_recno_t index)
+{
+	DBT key, data;
+	gsize bufLen;
+	gsize i;
+	gint error = 0;
+	gsize len;
+	gint trans_len;
+	
+	trans_len = g_strv_length (translations);
+	
+	/*
+	 * Firstly we get buffer length to store:
+	 * - In the first position the number of strings
+	 * - then we store for each string: the length of the string
+	 *   and the string.
+	 * Graphic: (trans_len)(string_len)----->(string_len)----->.....
+	 * ----> = string data
+	 */
+	for (bufLen = 0, i = 0; i < trans_len; i++)
+	{
+		len = strlen (translations[i]);
+		bufLen += sizeof (len) + len;
+	}
+	bufLen += sizeof (trans_len);
+	
+	/*
+	 * Now we create the buffer with the length I've got in the previous
+	 * iteration and I store in that buffer what I said before.
+	 */
+	u_int8_t *p, buf[bufLen];
+	
+	p = &buf[0];
+	memcpy (p, &trans_len, sizeof (trans_len));
+	p += sizeof (trans_len);
+	
+	for (i = 0; i < g_strv_length (translations); i++)
+	{
+		len = strlen (translations[i]);
+		memcpy (p, &len, sizeof (len));
+		p += sizeof (len);
+		memcpy (p, translations[i], len);
+		p += len;
+	}
+	
+	/*
+	 * Storing the buffer with the length in the that and after that
+	 * we try to store it in the database.
+	 * If there is a problem we show it.
+	 */
+	memset (&key, 0, sizeof (key));
+	memset (&data, 0, sizeof (data));
+	data.data = buf;
+	data.size = bufLen;
+	
+	if (index == 0)
+	{
+		error = gtranslator_db_base_put (GTR_DB_BASE (db_trans),
+						 &key, &data, DB_APPEND);
+	}
+	else
+	{
+		key.data = &index;
+		key.size = sizeof (index);
+
+		error = gtranslator_db_base_put (GTR_DB_BASE (db_trans),
+						 &key, &data, 0);
+	}
+
+	if (error != 0)
+	{
+		gtranslator_db_base_show_error (GTR_DB_BASE (db_trans), error);
+		return 0;
+	}    
+	return (index == 0) ? *((db_recno_t*)key.data) : index;
+}
+
+/**
+ * gtranslator_db_trans_read:
+ * @db_trans: a #GtranslatorDbTrans
+ * @index: the index record in the database
+ *
+ * Retrieves translations stored under given @index. Returns an #GPtrArray of
+ * translations or NULL if the key is absent.
+ * The caller must free the #GPtrArray.
+ */
+GPtrArray *
+gtranslator_db_trans_read (GtranslatorDbTrans *db_trans,
+			   db_recno_t index)
+{
+	DBT key, data;
+	gint error;
+	GPtrArray *gparray;
+	gint bufLen;
+	u_int8_t *p;
+	u_int8_t *buf;
+	gint i =0;
+
+	memset (&key, 0, sizeof (key));
+	memset (&data, 0, sizeof (data));
+	key.data = &index;
+	key.size = sizeof (index);
+	
+	/*
+	 * We get the data from the key
+	 */
+	error = gtranslator_db_base_get (GTR_DB_BASE (db_trans),
+					 &key, &data);
+	if (error != 0)
+	{
+		gtranslator_db_base_show_error (GTR_DB_BASE (db_trans), error);
+		return NULL;
+	}
+	
+	/*
+	 * Once we have the data we have to parse the byte array
+	 * and store it in our GPtrArray
+	 */
+	gparray = g_ptr_array_new ();
+	
+	buf = data.data;
+	
+	p = &buf[0];
+	memcpy (&bufLen, p, sizeof (bufLen));
+	p += sizeof (bufLen);
+	
+	while (i < bufLen)
+	{
+		gsize len;
+		gchar *data;
+		
+		memcpy (&len, p, sizeof (len));
+		p += sizeof (len);
+		
+		data = g_malloc (len+1);
+		memcpy (data, p, len);
+		p += len;
+		data[len] = '\0';
+
+		g_ptr_array_add (gparray, (gpointer)data);
+		
+		i++;
+	}
+	
+	g_ptr_array_add (gparray, NULL);
+	
+	return gparray;
+}
Index: src/translation-memory/berkeley/db-base.c
===================================================================
--- src/translation-memory/berkeley/db-base.c	(revision 0)
+++ src/translation-memory/berkeley/db-base.c	(revision 0)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ *
+ *     Based in poedit transmem.cpp file:
+ *     Copyright (C) 2001-2007 Vaclav Slavik
+ * 
+ *     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/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "utils.h"
+#include "db-base.h"
+#include DB_HEADER
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <gio/gio.h>
+
+#define GTR_DB_BASE_GET_PRIVATE(object)	(G_TYPE_INSTANCE_GET_PRIVATE ( \
+						 (object),		       \
+						 GTR_TYPE_DB_BASE,     \
+						 GtranslatorDbBasePrivate))
+
+G_DEFINE_TYPE(GtranslatorDbBase, gtranslator_db_base, G_TYPE_OBJECT)
+
+
+struct _GtranslatorDbBasePrivate
+{
+	DB *db;
+};
+
+static gchar *
+get_db_base_directory ()
+{
+	gchar *config;
+	gchar *db_dir;
+	
+	config = gtranslator_utils_get_user_config_dir ();
+	
+	db_dir = g_build_filename (config, "berkeley", NULL);
+	g_free (config);
+	
+	if (!g_file_test (db_dir, G_FILE_TEST_IS_DIR))
+	{
+		GFile *file;
+		GError *error = NULL;
+		
+		file = g_file_new_for_path (db_dir);
+		
+		if (!g_file_make_directory (file, NULL, &error))
+		{
+			g_warning ("There was an error making the gtranslator berkeley directory: %s",
+				   error->message);
+					   
+			g_error_free (error);
+			g_object_unref (file);
+			g_free (db_dir);
+			return NULL;
+		}
+		
+		g_object_unref (file);
+	}
+	
+	return db_dir;
+}
+
+static void
+gtranslator_db_base_init (GtranslatorDbBase *panel)
+{
+	panel->priv = GTR_DB_BASE_GET_PRIVATE (panel);
+}
+
+static void
+gtranslator_db_base_finalize (GObject *object)
+{
+	GtranslatorDbBase *base = GTR_DB_BASE (object);
+	int err;
+	
+	if ((err = base->priv->db->close(base->priv->db, 0)) != 0)
+	       gtranslator_db_base_show_error (base, err);
+	
+	G_OBJECT_CLASS (gtranslator_db_base_parent_class)->finalize (object);
+}
+
+static void
+gtranslator_db_base_class_init (GtranslatorDbBaseClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (GtranslatorDbBasePrivate));
+
+	object_class->finalize = gtranslator_db_base_finalize;
+}
+
+void
+gtranslator_db_base_create_dabatase (GtranslatorDbBase *base,
+				     const gchar *filename,
+				     DBTYPE type)
+{
+	gint error;
+	gchar *db_dir;
+	gchar *fullname;
+	
+	g_return_if_fail (GTR_IS_DB_BASE (base));
+	
+	error = db_create(&base->priv->db, NULL, 0);
+	if (error != 0)
+	{
+		gtranslator_db_base_show_error (base, error);
+		return;
+	}
+	
+	db_dir = get_db_base_directory ();
+	fullname = g_build_filename (db_dir, filename, NULL);
+	g_free (db_dir);
+
+	error = base->priv->db->open (base->priv->db,
+				      NULL,
+				      fullname,
+				      NULL,
+				      type,
+				      DB_CREATE,
+				      0);
+	
+	g_free (fullname);
+	
+	if (error != 0)
+	{
+		gtranslator_db_base_show_error (base, error);
+		return;
+	}
+}
+
+void
+gtranslator_db_base_show_error (GtranslatorDbBase *base,
+				int error)
+{
+	gchar *err = NULL;
+	
+	if (error != DB_NOTFOUND)
+	{
+		err = g_strdup_printf (_("There was an error in database: %s"),
+				       db_strerror (error));
+	
+		g_warning (err);
+		g_free (err);
+	}
+}
+
+gint
+gtranslator_db_base_put (GtranslatorDbBase *base,
+			 DBT *key,
+			 DBT *data,
+			 u_int32_t flags)
+{
+	return base->priv->db->put (base->priv->db, NULL, key, data, flags);
+}
+
+gint
+gtranslator_db_base_get (GtranslatorDbBase *base,
+			 DBT *key,
+			 DBT *data)
+{
+	return base->priv->db->get (base->priv->db, NULL, key, data, 0);
+}
Index: src/translation-memory/translation-memory.c
===================================================================
--- src/translation-memory/translation-memory.c	(revision 0)
+++ src/translation-memory/translation-memory.c	(revision 0)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ * 
+ *     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/>.
+ */
+
+#include "translation-memory.h"
+
+gboolean
+gtranslator_translation_memory_store (GtranslatorTranslationMemory *obj,
+				      const gchar *original,
+				      const gchar *translation)
+{
+	g_return_val_if_fail (GTR_IS_TRANSLATION_MEMORY (obj), FALSE);
+	return GTR_TRANSLATION_MEMORY_GET_IFACE (obj)->store (obj, original, translation);
+}
+
+/* Default implementation */
+static gboolean
+gtranslator_translation_memory_store_default (GtranslatorTranslationMemory *obj,
+					      const gchar *original,
+					      const gchar *translation)
+{
+	g_return_val_if_reached (FALSE);
+}
+
+GList *
+gtranslator_translation_memory_lookup (GtranslatorTranslationMemory *obj,
+				       const gchar *phrase)
+{
+	g_return_val_if_fail (GTR_IS_TRANSLATION_MEMORY (obj), 0);
+	return GTR_TRANSLATION_MEMORY_GET_IFACE (obj)->lookup (obj, phrase);
+}
+
+/* Default implementation */
+static GList *
+gtranslator_translation_memory_lookup_default (GtranslatorTranslationMemory *obj,
+					       const gchar *phrase)
+{
+	g_return_val_if_reached (0);
+}
+
+void
+gtranslator_translation_memory_set_max_omits (GtranslatorTranslationMemory *obj,
+					      gsize omits)
+{
+	g_return_if_fail (GTR_IS_TRANSLATION_MEMORY (obj));
+	GTR_TRANSLATION_MEMORY_GET_IFACE (obj)->set_max_omits (obj, omits);
+}
+
+/* Default implementation */
+static void
+gtranslator_translation_memory_set_max_omits_default (GtranslatorTranslationMemory *obj,
+						      gsize omits)
+{
+	g_return_if_reached ();
+}
+
+void
+gtranslator_translation_memory_set_max_delta (GtranslatorTranslationMemory *obj,
+					      gsize delta)
+{
+	g_return_if_fail (GTR_IS_TRANSLATION_MEMORY (obj));
+	GTR_TRANSLATION_MEMORY_GET_IFACE (obj)->set_max_delta (obj, delta);
+}
+
+/* Default implementation */
+static void
+gtranslator_translation_memory_set_max_delta_default (GtranslatorTranslationMemory *obj,
+						      gsize omits)
+{
+	g_return_if_reached ();
+}
+
+static void
+gtranslator_translation_memory_base_init (GtranslatorTranslationMemoryIface* klass)
+{
+	static gboolean initialized = FALSE;
+
+	klass->store = gtranslator_translation_memory_store_default;
+	klass->lookup = gtranslator_translation_memory_lookup_default;
+	klass->set_max_omits = gtranslator_translation_memory_set_max_omits_default;
+	klass->set_max_delta = gtranslator_translation_memory_set_max_delta_default;
+	
+	if (!initialized) {
+
+		initialized = TRUE;
+	}
+}
+
+GType
+gtranslator_translation_memory_get_type (void)
+{
+	static GType type = 0;
+	if (!type) {
+		static const GTypeInfo info = {
+			sizeof (GtranslatorTranslationMemoryIface),
+			(GBaseInitFunc) gtranslator_translation_memory_base_init,
+			NULL, 
+			NULL,
+			NULL,
+			NULL,
+			0,
+			0,
+			NULL
+		};
+		type = g_type_register_static (G_TYPE_INTERFACE, "GtranslatorTranslationMemory", &info, 0);
+		g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+	}
+	return type;			
+}
Index: src/translation-memory/Makefile.am
===================================================================
--- src/translation-memory/Makefile.am	(revision 0)
+++ src/translation-memory/Makefile.am	(revision 0)
@@ -0,0 +1,43 @@
+SUBDIRS = berkeley
+
+INCLUDES =                                                      \
+        -I$(top_srcdir)                                         \
+        -I$(top_builddir)                                       \
+        -I$(top_srcdir)/src                                     \
+        -I$(top_builddir)/src                                   \
+	-I$(headerdir)						\
+	-DPIXMAPSDIR=\""$(datadir)"/pixmaps/gtranslator\"       \
+        $(GTRANSLATOR_CFLAGS)                                   \
+        $(WARN_CFLAGS)                                          \
+        $(DISABLE_DEPRECATED_CFLAGS)
+
+noinst_LTLIBRARIES = \
+	libtranslationmemory.la
+
+INST_H_FILES = \
+	translation-memory.h
+
+headerdir = $(prefix)/include/gtranslator-@GTR_API_VERSION@/gtranslator
+
+header_DATA = \
+	$(INST_H_FILES)	
+
+libtranslationmemory_la_SOURCES = \
+	$(INST_H_FILES) \
+	translation-memory.c
+
+libtranslationmemory_la_CFLAGS = \
+	$(GTRANSLATOR_CFLAGS)			\
+	$(WARN_CFLAGS)				\
+	$(DISABLE_DEPRECATED)			\
+	-DCURSOR_DIR=\"$(pkgdatadir)\"		\
+	$(AM_CFLAGS)
+
+libtranslationmemory_la_LDFLAGS = \
+	-export-dynamic
+
+libtranslationmemory_la_LIBADD = \
+	berkeley/libberkeley.la
+
+EXTRA_DIST = $(pixmaps__DATA)
+
Index: src/translation-memory/translation-memory.h
===================================================================
--- src/translation-memory/translation-memory.h	(revision 0)
+++ src/translation-memory/translation-memory.h	(revision 0)
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008  Ignacio Casal Quinteiro <nacho.resa@gmail.com>
+ * 
+ *     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/>.
+ */
+
+#ifndef _GTR_TRANSLATION_MEMORY_H_
+#define _GTR_TRANSLATION_MEMORY_H_
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define GTR_TYPE_TRANSLATION_MEMORY (gtranslator_translation_memory_get_type ())
+#define GTR_TRANSLATION_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTR_TYPE_TRANSLATION_MEMORY, GtranslatorTranslationMemory))
+#define GTR_IS_TRANSLATION_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTR_TYPE_TRANSLATION_MEMORY))
+#define GTR_TRANSLATION_MEMORY_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GTR_TYPE_TRANSLATION_MEMORY, GtranslatorTranslationMemoryIface))
+
+typedef struct _GtranslatorTranslationMemory GtranslatorTranslationMemory;
+typedef struct _GtranslatorTranslationMemoryIface GtranslatorTranslationMemoryIface;
+
+struct _GtranslatorTranslationMemoryIface {
+	GTypeInterface g_iface;
+	
+
+	gboolean (*store) (GtranslatorTranslationMemory *obj,
+			   const gchar *original,
+			   const gchar *translation);
+	GList * (*lookup) (GtranslatorTranslationMemory *obj,
+			   const gchar *phrase);
+	void (*set_max_omits) (GtranslatorTranslationMemory *obj,
+			       gsize omits);
+	void (*set_max_delta) (GtranslatorTranslationMemory *obj,
+			       gsize delta);
+};
+
+typedef struct _GtranslatorTranslationMemoryMatch GtranslatorTranslationMemoryMatch;
+struct _GtranslatorTranslationMemoryMatch {
+	gchar *match;
+	gint level;
+};
+
+GType  gtranslator_translation_memory_get_type            (void);
+
+gboolean   gtranslator_translation_memory_store           (GtranslatorTranslationMemory *obj,
+							   const gchar *original,
+							   const gchar *translation);
+						       
+GList *   gtranslator_translation_memory_lookup           (GtranslatorTranslationMemory *obj,
+							   const gchar *phrase);
+
+void      gtranslator_translation_memory_set_max_omits    (GtranslatorTranslationMemory *obj,
+							   gsize omits);
+
+void      gtranslator_translation_memory_set_max_delta    (GtranslatorTranslationMemory *obj,
+							   gsize delta);
+
+G_END_DECLS
+
+#endif
Index: configure.ac
===================================================================
--- configure.ac	(revision 3573)
+++ configure.ac	(working copy)
@@ -8,6 +8,7 @@
 	http://bugzilla.gnome.org/enter_bug.cgi?product=gtranslator)
 
 AC_CONFIG_SRCDIR(src/main.c)
+AC_CONFIG_MACRO_DIR([m4])
 AM_CONFIG_HEADER(config.h)
 
 GTR_API_VERSION=2.0
@@ -143,6 +144,17 @@
 ])
 
 dnl -------------------------------------------------------------------
+dnl Check for libdb >= 4.1
+dnl -------------------------------------------------------------------
+AX_BERKELEY_DB(4.1, [
+	AC_DEFINE([HAVE_DB_BERKELEY], 1, [A usable libdb library was found])
+	AC_DEFINE_UNQUOTED(DB_HEADER, ["$DB_HEADER"])
+	LDFLAGS="$LDFLAGS $DB_LIBS"
+],[
+	AC_MSG_ERROR([Cannot find Berkeley DB >= 4.1])
+])
+
+dnl -------------------------------------------------------------------
 dnl Check for gtkspell >= 2.0 and use it if found
 dnl -------------------------------------------------------------------
 have_gtkspell=no
@@ -295,6 +307,8 @@
 src/dialogs/Makefile
 src/toolbareditor/Makefile
 src/plugin-system/Makefile
+src/translation-memory/Makefile
+src/translation-memory/berkeley/Makefile
 ])
 
 dnl ------------------------------------------------------------------
