]> Dogcows Code - chaz/homebank/commitdiff
Merge branch 'master' into ext-perl
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 28 Dec 2016 22:59:58 +0000 (15:59 -0700)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Wed, 28 Dec 2016 22:59:58 +0000 (15:59 -0700)
22 files changed:
1  2 
Makefile.am
configure.ac
plugins/hello.pl
src/Makefile.am
src/dsp_mainwindow.c
src/ext-perl.xs
src/hb-account.c
src/hb-archive.c
src/hb-assign.c
src/hb-category.c
src/hb-payee.c
src/hb-preferences.c
src/hb-preferences.h
src/hb-tag.c
src/hb-transaction.c
src/hb-xml.c
src/homebank.c
src/homebank.h
src/ui-pref.c
src/ui-pref.h
themes/hicolor/Makefile.am
themes/hicolor/hicolor_status_48x48_prf-plugins.png

diff --combined Makefile.am
index ac9cc1c743eb55e2148d5656cdc424a565821b8e,0a662030ff8fc8ca804ced95a7eaae5a6dfba5a7..de75d0f3cfbe7415f044a9ac8338a23cec6568b2
@@@ -1,9 -1,7 +1,9 @@@
  # HomeBank Makefile.am
  
 +ACLOCAL_AMFLAGS       = -I m4
 +
  #SUBDIRS = src
- SUBDIRS = src data images mime po doc plugins
 -SUBDIRS = src data images mime pixmaps themes po doc
++SUBDIRS = src data images mime pixmaps themes po doc plugins
  
  
  # don't forget to do a 'make check' 
@@@ -20,9 -18,3 +20,9 @@@ DISTCLEANFILES = ... intltool-extract 
                   intltool-merge \
                   intltool-update \
                   po/.intltool-merge-cache
 +
 +run: all
 +      PERL5LIB=src src/homebank
 +
 +debug: all
 +      PERL5LIB=src gdb src/homebank
diff --combined configure.ac
index dfaa66d48e303bd8ca6dcc9021bce1ed7a4a4a37,b4680b5425d2f2212fe210033710c0b70a322232..83f65098fc6c15ec96e0ddfb9dc83a35d1c31d02
@@@ -2,16 -2,13 +2,17 @@@
  # Process this file with autoconf to produce a configure script.
  
  AC_PREREQ(2.52)
- AC_INIT([homebank], [4.6.3])
+ AC_INIT([homebank], [5.1.2])
+ #AC_INIT([homebank], [x.x-rc])
  
  AM_CONFIG_HEADER(config.h)
  
  AM_INIT_AUTOMAKE([1.9 foreign])
  
 +LT_PREREQ([2.2])
 +LT_INIT([dlopen])
 +AC_CONFIG_MACRO_DIR([m4])
 +
  # If the source code has changed at all, increment REVISION
  # If any interfaces have been added, removed, or changed, increment CURRENT, and set REVISION to 0.
  # If any interfaces have been added since the last public release, then increment AGE.
@@@ -25,19 -22,26 +26,26 @@@ AC_PROG_INSTAL
  AC_PROG_INTLTOOL
  
  # Checks for libraries.
- PKG_CHECK_MODULES(DEPS, gtk+-2.0 >= 2.24 glib-2.0 >= 2.28 gmodule-2.0 >= 2.28)
 -PKG_CHECK_MODULES(DEPS, gtk+-3.0 >= 3.12 glib-2.0 >= 2.39)
++PKG_CHECK_MODULES(DEPS, gtk+-3.0 >= 3.12 glib-2.0 >= 2.39 gmodule-2.0 >= 2.39)
  AC_SUBST(DEPS_CFLAGS)
  AC_SUBST(DEPS_LIBS)
  AC_CHECK_LIB(m, pow)
  
+ PKG_CHECK_MODULES(LIBSOUP, [libsoup-2.4 >= 2.26])
+ AC_SUBST(LIBSOUP_CFLAGS)
+ AC_SUBST(LIBSOUP_LIBS)
  # general usage flags
  CFLAGS="${CFLAGS} -Wall -Wmissing-prototypes"
  
+ # disable deprecated warnings
+ CFLAGS="${CFLAGS} -Wno-deprecated-declarations"
  # extended flags
  #CFLAGS="${CFLAGS} -Wextra -Wno-unused-parameter"
  
- #valgrind flags
- #CFLAGS="${CFLAGS} -g -O0"
+ # profiling valgrind/gprof flags
+ #CFLAGS="${CFLAGS} -g -O0 -pg"
  
  # pre-relase # 2 - error as warning for 
  #CFLAGS="${CFLAGS} -Werror"
@@@ -62,7 -66,7 +70,7 @@@ the
      then
          AC_CHECK_LIB(ofx, ofx_set_status_cb, OFX_0_7="-DOFX_ENABLE")
          DEPS_LIBS="-lofx ${DEPS_LIBS}"
 -        CFLAGS="${CFLAGS} $OFX_0_7"
 +        CPPFLAGS="${CPPFLAGS} $OFX_0_7"
      else
          noofx=true
          AC_MSG_RESULT([Libofx header missing. Check your libofx installation])
@@@ -74,41 -78,6 +82,41 @@@ els
  fi
  AM_CONDITIONAL(NOOFX, test x$noofx = xtrue)
  
 +AC_ARG_WITH(perl,
 +      [  --with-perl             build with perl plug-in support [default=without]],
 +      [build_perl=$withval],
 +      [build_perl=no]
 +)
 +if test x$build_perl != xno
 +then
 +      test x$build_perl != xyes -a -x "$build_perl" && PERL=$build_perl
 +      AC_PATH_PROG(PERL, perl, perl)
 +      AC_MSG_CHECKING(if perl can be embedded)
 +      if $PERL -MExtUtils::Embed -e "use v5.8" >/dev/null 2>&1
 +      then
 +              AC_MSG_RESULT(yes)
 +              CPPFLAGS="${CPPFLAGS} -DPERL_ENABLE"
 +              PERL_CPPFLAGS="`$PERL -MExtUtils::Embed -e ccopts`"
 +              PERL_OBJS="ext-perl.o perlxsi.o"
 +              PERL_PRIVLIBEXP="`$PERL -MConfig -e 'print $Config{privlibexp}'`"
 +              PERL_SITELIBEXP="`$PERL -MConfig -e 'print $Config{sitelibexp}'`"
 +              DEPS_LIBS="`$PERL -MExtUtils::Embed -e ldopts` ${DEPS_LIBS}"
 +              if test -e "$PERL_SITELIBEXP/ExtUtils/xsubpp"
 +              then
 +                      XSUBPP="$PERL $PERL_SITELIBEXP/ExtUtils/xsubpp"
 +              else
 +                      XSUBPP="$PERL $PERL_PRIVLIBEXP/ExtUtils/xsubpp"
 +              fi
 +      else
 +              AC_MSG_ERROR([no working perl found, or perl not version >= 5.8])
 +      fi
 +fi
 +AC_SUBST(PERL_CPPFLAGS)
 +AC_SUBST(PERL_OBJS)
 +AC_SUBST(PERL_PRIVLIBEXP)
 +AC_SUBST(PERL_SITELIBEXP)
 +AC_SUBST(XSUBPP)
 +
  # Checks for header files.
  AC_HEADER_STDC
  AC_CHECK_HEADERS([libintl.h locale.h stdlib.h string.h])
@@@ -123,7 -92,7 +131,7 @@@ AC_C_VOLATIL
  AC_CHECK_FUNCS([floor localeconv memset modf pow setlocale sqrt strcasecmp strtoul])
  
  # International support
- ALL_LINGUAS="af ar ast be bg br ca cs cy da de el en_AU en_CA en_GB es et eu fa fi fr ga gl he hr hu id is it ja ka ko lt lv mr ms nb nds nl oc pl pt_BR pt pt_PT ro ru si sk sl sr sv tr uk vi zh_CN zh_TW" 
+ ALL_LINGUAS="af ar ast be bg br ca cs cy da de el en_AU en_CA en_GB es et eu fa fi fr gl he hr hu id is it ja ko lt lv mr ms nb nds nl oc pl pt_BR pt pt_PT ro ru si sk sl sr sv tr uk vi zh_CN zh_TW" 
  
  AM_GLIB_GNU_GETTEXT
  
@@@ -136,14 -105,15 +144,16 @@@ Makefil
  src/Makefile 
  data/homebank.desktop.in
  data/Makefile
- data/icons/Makefile
  data/datas/Makefile
  images/Makefile
  mime/Makefile
- po/Makefile.in 
+ pixmaps/Makefile
+ themes/Makefile
+ themes/hicolor/Makefile
+ po/Makefile.in
  doc/Makefile
  doc/images/Makefile
 +plugins/Makefile
  ])
  
  AC_OUTPUT
@@@ -156,7 -126,6 +166,7 @@@ echo $PACKAGE $VERSIO
  echo 
  echo Compiler................ : $CC
  echo Build with OFX support.. : $build_ofx
 +echo Build with perl support. : $build_perl
  if test "x$noofx" = "xtrue" ; then
  echo ........................ : **error** libofx header is missing, ofx feature will be disabled. Check your libofx installation
  fi
diff --combined plugins/hello.pl
index c6abdf9e79cb6f6dad767455a065b0d2db84437a,0000000000000000000000000000000000000000..9171bb208eb119808ed03ba7973d23b4c2be7ec8
mode 100644,000000..100644
--- /dev/null
@@@ -1,281 -1,0 +1,234 @@@
-     $self->create_menuitem;
 +
 +# NAME:     Hello World
 +# VERSION:  0.01
 +# ABSTRACT: This is the "hello world" of HomeBank plugins.
 +# AUTHOR:   Charles McGarvey <chazmcgarvey@brokenzipper.com>
 +# WEBSITE:  http://acme.tld/
 +# (These comments are read, before the plugin is executed, to provide some
 +# information to HomeBank and the user about what this plugin is.)
 +
 +eval { HomeBank->version } or die "Cannot run outside of HomeBank";
 +
 +use warnings;
 +use strict;
 +
 +use Scalar::Util qw/weaken/;
 +
 +#use Moose;
 +
 +#has "cool_beans",
 +    #is      => 'rw',
 +    #isa     => 'Str',
 +    #lazy    => 1,
 +    #default => "Booya!!!";
 +
 +
 +our $counter = 0;
 +our $temp;
 +
 +my $ACC;
 +
 +sub new {
 +    my $class = shift;
 +    my $self  = $class->SUPER::new(@_);
 +
 +    $self->on(account_inserted => sub {
 +            my $acc = shift;
 +            print "account inserted: ", Dumper($acc);
 +            print "account name is ", $acc->name, " and balance is ", $acc->bank_balance, "\n";
 +            #$acc->name("FOOOOBAR!");
 +            if ($acc->name eq 'Vacation') {
 +                $acc->remove;
 +                $ACC = $acc;
 +            }
 +            print Dumper($acc->is_inserted);
 +            if ($acc->is_inserted) {
 +                print "IT IS INSERTED\n";
 +            } else {
 +                print "not inserted\n";
 +            }
 +            print Dumper($acc->transactions);
 +        });
 +
 +    #print $self->cool_beans, "\n";
 +    #$self->cool_beans(123);
 +    #print $self->cool_beans, "\n";
 +
-         require Gtk2;
 +    $self;
 +}
 +
 +sub on_create_main_window {
 +    my $self = shift;
 +    my $window = shift;
 +
 +    if (!$window) {
-     $self->create_menuitem;
++        require Gtk3;
 +        $window = HomeBank->main_window;
 +    }
 +
 +    Dump($window);
 +    print Dumper($window);
 +    $window->set_title("foo bar baz");
 +    print $window->get_title, "\n";
 +
 +    HomeBank->hook("my_hook", $window);
-     require Gtk2;
 +}
 +
 +my $test_win;
 +
 +sub on_test {
 +    my $self = shift;
-     my $window = Gtk2::Window->new('toplevel');
++    require Gtk3;
 +
-     #$window->signal_connect(delete_event => sub { Gtk2->main_quit });
++    my $window = Gtk3::Window->new('toplevel');
 +    use Devel::Peek;
 +    Dump($window);
 +    print Dumper($window);
 +    $window->set_title("Hello World");
-     my $button = Gtk2::Button->new('Click Me!');
++    #$window->signal_connect(delete_event => sub { Gtk3->main_quit });
 +    $window->signal_connect(delete_event => sub { undef $test_win });
 +
-             print "Hello Gtk2-Perl: $counter (perl plugin: $self)\n";
++    my $button = Gtk3::Button->new('Click Me!');
 +    Dump($button);
 +    print Dumper($button);
 +    $button->signal_connect(clicked => sub {
-     #require Gtk2;
++            print "Hello Gtk3-Perl: $counter (perl plugin: $self)\n";
 +            $counter++;
 +            #if ($temp->is_inserted) {
 +                #print "$temp is inserted\n";
 +            #} else {
 +                #print "$temp is NOT inserted\n";
 +            #}
 +            #if ($counter == 5) {
 +                #$temp = undef;
 +            #}
 +    my $acc = HomeBank::Account->get(rand(10));
 +    print "Changin account named ", $acc->name, " to ", $acc->name($acc), "\n";
 +    HomeBank->main_window->queue_draw;
 +
 +        });
 +    $window->add($button);
 +
 +    $window->show_all;
 +    $test_win = $window;
 +
 +    weaken $self;
 +}
 +
 +sub on_enter_main_loop {
 +    my $self = shift;
 +
 +    use Data::Dumper;
 +    print Dumper(\@_);
 +    my $t = HomeBank::Transaction->new;
 +    print "Transaction::::::::  $t: ", $t->amount, "\n";
 +
 +    $temp = HomeBank::Account->get(7);
 +    print "retained account: ", $temp->name, "\n";
 +
- sub on_main_window_disposal {
-     my $self = shift;
-     print "main window disposed so forgetting about merge id et al.\n";
-     delete $self->{merge_id};
-     delete $self->{action_group};
- }
++    #require Gtk3;
 +    #
 +    my $txn = HomeBank::Transaction->new;
 +    $txn->amount(12.3456);
 +    print Dumper($txn), $txn->amount, "\n";
 +    #$txn->open;
 +
 +    my @ret = HomeBank->hook("my_hook", @_, $temp, [qw/foo bar baz/, $txn], { asf => 42, quux => \1, meh => HomeBank->main_window });
 +    #my @ret = HomeBank->hook("my_hook", @_, HomeBank->main_window, {
 +    #foo => 'bar', baz => 42
 +    #});
 +    print Dumper(\@ret);
 +
 +    print "adding back account...\n";
 +    $ACC->name("vacation with a different name");
 +    $ACC->insert;
 +    HomeBank::Account->compute_balances;
 +    print "account name is ", $ACC->name, " and balance is ", $ACC->balance, "\n";
 +    print Dumper($ACC->transactions);
 +
 +    my $cloned = $ACC->clone;
 +    $cloned->name("vacation copy");
 +    $cloned->insert;
 +    #my $asdf = $cloned->open;
 +    #$asdf->set_title("this is a new friggin account");
 +
 +    #my $z = HomeBank::Account->get_by_name('Checking');
 +    for my $xc (HomeBank::File->transactions) {
 +        use DateTime;
 +        my $num = $xc->date;
 +        my $date = DateTime->new($xc->date)->datetime;
 +        print "transaction of amount: ", $xc->amount, "\t", $xc->wording, ", ", $xc->info, ", $num, $date\n";
 +    }
 +
 +    HomeBank::File->owner('Billy Murphy');
 +    #HomeBank::File->anonymize;
 +    print HomeBank::File->owner, "\n";
 +
 +    HomeBank::File->baz($ACC);
 +}
 +
 +sub on_deep_hook_recursion {
 +    my $self = shift;
 +    my $level = shift;
 +    print STDERR "recursion is too deep ($level)\n";
 +    exit -2;
 +}
 +
 +sub on_my_hook {
 +    my $self = shift;
 +    print "This is MY HOOK!!!!!!\n";
 +    print Dumper(\@_);
 +
 +    print Dumper($_[2]);
 +    Dump($_[2]);
 +    if ($_[2]) {
 +        print "meh\n";
 +    }
 +    if ($_[2]->isa('HomeBank::Boolean')) {
 +        print "it is a home;;boolean\n";
 +    }
 +    if ($_[2]->isa('Types::Serialiser::Boolean')) {
 +        print "it is a types serialiser thingy\n";
 +    }
 +    if ($_[2]->isa('HomeBank::BooleanBase')) {
 +        print "it is a base bool\n";
 +    }
 +
 +    my $win = $_[6];
 +    if ($win && ref($win) eq 'HASH') {
 +        my $w = $win->{meh};
 +        if ($w) {
 +            $w->set_title("this is MY HOOK setting a window title");
 +        }
 +    }
 +    #print Dumper($acc);
 +    #print "transferred account: ", $acc->name, "\n";
 +
 +    #my $fff = HomeBank::File->foo({foo => 'asdf', bar => 123456789});
 +    my $fff = HomeBank::File->meh([qw/hello this is a test 82/, \1, {foo => 'bar'}, 48]);
 +    print Dumper($fff);
 +
 +    print "my hook done\n";
 +}
 +
 +sub on_unhandled {
 +    my ($self, $hook) = @_;
 +    warn "Unhandled hook '$hook'\n";
 +    #HomeBank->warn($hook, 'Hook not handled.');
 +}
 +
-     $self->destroy_menuitem;
- }
- sub destroy_menuitem {
-     my $self = shift;
-     return unless $self->{merge_id};
-     my $ui_manager = HomeBank->main_ui_manager;
-     $ui_manager->remove_action_group($self->{action_group});
-     $ui_manager->remove_ui($self->{merge_id});
- }
- sub create_menuitem {
-     my $self = shift;
-     return if $self->{merge_id};
-     require Gtk2;
-     my $ui_manager = HomeBank->main_ui_manager;
-     print Dumper($ui_manager);
-     return unless $ui_manager;
-     $self->{merge_id} = $ui_manager->new_merge_id;
-     $self->{action_group} = Gtk2::ActionGroup->new('HelloActionGroup');
-     my $action = Gtk2::Action->new(name => 'HelloPlugin', label => 'Booyah!', stock_id => 'prf-plugins', tooltip => 'blaaaargh');
-     $action->signal_connect(activate => sub { print "hello!!!!!!!!\n" });
-     $self->{action_group}->add_action($action);
-     $ui_manager->insert_action_group($self->{action_group}, -1);
-     $ui_manager->add_ui($self->{merge_id}, 'ui/MenuBar/PluginMenu', 'HelloPlugin', 'HelloPlugin', 'auto', '');
-     #$self->{merge_id} = $ui_manager->new_merge_id;
-     $ui_manager->add_ui($self->{merge_id}, 'ui/ToolBar', 'HelloPluginTool', 'HelloPlugin', 'auto', '');
 +sub DESTROY {
 +    my $self = shift;
 +    print "DESTROYING HELLO WORLD!!!!!!\n";
 +    if ($test_win) {
 +        print "there is a test_win...\n";
 +    }
 +    $test_win->destroy if $test_win;
 +}
 +
 +sub EXECUTE {
 +    print "the perl plugin is being configured.....\n";
 +    HomeBank->info("Hello Prefs", "YEEEEEARGGH!!!!!");
 +}
 +
 +#__PACKAGE__->meta->make_immutable;
diff --combined src/Makefile.am
index 71c57f193b249e9e6bf3cf952f3539645e6ddad2,200e63c679872d99c5ad228b1c8c484db45b4cf4..484ce27b8a65ad79127df95daac4335f1d554c32
@@@ -1,8 -1,7 +1,8 @@@
  
  common_defines = \
        -DSHARE_DIR=\""$(pkgdatadir)"\" \
 -      -DDATA_DIR=\""$(datadir)"\"
 +      -DDATA_DIR=\""$(datadir)"\" \
 +      -DPKGLIB_DIR=\""$(pkglibdir)"\"
  
  
  bin_PROGRAMS = homebank
@@@ -22,6 -21,10 +22,10 @@@ homebank_SOURCES =  
        enums.h \
        gtk-chart.c \
        gtk-chart.h \
+       gtk-chart-colors.c \
+       gtk-chart-colors.h \
+       gtk-chart-stack.c \
+       gtk-chart-stack.h \
        gtk-dateentry.c \
        gtk-dateentry.h \
        hb-account.c \
@@@ -32,6 -35,8 +36,8 @@@
        hb-assign.h \
        hb-category.c \
        hb-category.h \
+       hb-currency.c \
+       hb-currency.h \
        hb-encoding.c \
        hb-encoding.h \
        hb-export.c \
@@@ -42,6 -47,9 +48,9 @@@
        hb-hbfile.h \
        hb-import.c \
        hb-import.h \
+       hb-import-ofx.c \
+       hb-import-qif.c \
+       hb-import-csv.c \
        hb-misc.c \
        hb-misc.h \
        hb-payee.c \
        hb-report.h \
        hb-tag.c \
        hb-tag.h \
+       hb-split.c \
+       hb-split.h \
        hb-transaction.c \
        hb-transaction.h \
        hb-xml.c \
        hb-xml.h \
        homebank.c \
        homebank.h \
-       imp_qif.c \
-       imp_qif.h \
-       import.c \
-       import.h \
        language.c \
        language.h \
        list_account.c \
        ui-archive.h \
        ui-assign.c \
        ui-assign.h \
+       ui-assist-import.c \
+       ui-assist-import.h \
        ui-assist-start.c \
        ui-assist-start.h \
        ui-budget.c \
        ui-budget.h \
        ui-category.c \
        ui-category.h \
+       ui-currency.c \
+       ui-currency.h \
        ui-dialogs.c \
        ui-dialogs.h \
        ui-filter.c \
        ui-payee.h \
        ui-pref.c \
        ui-pref.h \
+       ui-split.c \
+       ui-split.h \
        ui-transaction.c \
        ui-transaction.h \
        ui-widgets.c \
 -      ui-widgets.h
 +      ui-widgets.h \
-       gtk-chart-colors.c \
-       gtk-chart-colors.h \
 +      refcount.h \
 +      ext.c \
 +      ext.h \
 +      ext-value.c \
 +      ext-value.h \
 +      ext-native.c \
 +      ext-perl.xs
 +
 +EXTRA_homebank_DEPENDENCIES = $(PERL_OBJS)
  
- homebank_LDADD = $(PERL_OBJS) $(DEPS_LIBS)
+ homebank_LDADD = $(DEPS_LIBS) \
 -      $(LIBSOUP_LIBS)
++      $(LIBSOUP_LIBS) \
++      $(PERL_OBJS)
  
  AM_CPPFLAGS = \
        $(DEPS_CFLAGS) \
+       $(LIBSOUP_CFLAGS) \
        $(common_defines)
  
 +$(PERL_OBJS): CPPFLAGS += $(PERL_CPPFLAGS)
 +
 +ext-perl.c: ext-perl.xs typemap
 +      $(XSUBPP) -typemap $(PERL_PRIVLIBEXP)/ExtUtils/typemap -typemap typemap $< >$@
 +
 +perlxsi.c: Makefile
 +      $(PERL) -MExtUtils::Embed -e xsinit -- -std HomeBank
 +
 +CLEANFILES = ext-perl.c perlxsi.c
 +
 +pluginsupportdir = $(pkglibdir)
 +pluginsupport_DATA = HomeBank.pm
 +
diff --combined src/dsp_mainwindow.c
index 98c5ea1406b6a56da082d978602163f410e75f48,c96fdc6ba305a3a4a1fe5f3b14e3ba30bb9ba836..707f68a0f6a8dce48af4fc14681fa12533e15116
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
  
  #include "dsp_mainwindow.h"
  
 +#include "ext.h"
 +
  #include "list_account.h"
  #include "list_upcoming.h"
  #include "list_topspending.h"
  
  #include "dsp_account.h"
- #include "import.h"
- #include "imp_qif.h"
+ #include "ui-assist-import.h"
  #include "ui-assist-start.h"
  #include "ui-account.h"
+ #include "ui-currency.h"
  #include "ui-payee.h"
  #include "ui-category.h"
  #include "ui-archive.h"
@@@ -61,6 -59,7 +61,7 @@@
  /* Debug macros                                                             */
  /****************************************************************************/
  #define MYDEBUG 0
  #if MYDEBUG
  #define DB(x) (x);
  #else
@@@ -83,6 -82,7 +84,7 @@@ static void ui_mainwindow_action_proper
  static void ui_mainwindow_action_close(void);
  static void ui_mainwindow_action_quit(void);
  
+ static void ui_mainwindow_action_defcurrency(void);
  static void ui_mainwindow_action_defaccount(void);
  static void ui_mainwindow_action_defpayee(void);
  static void ui_mainwindow_action_defcategory(void);
@@@ -106,12 -106,11 +108,13 @@@ static void ui_mainwindow_action_budget
  static void ui_mainwindow_action_balance(void);
  static void ui_mainwindow_action_vehiclecost(void);
  
- static void ui_mainwindow_action_pluginprefs(void);
- static void ui_mainwindow_action_import(void);
+ static void ui_mainwindow_action_import(GtkAction *action);
  static void ui_mainwindow_action_export(void);
  static void ui_mainwindow_action_anonymize(void);
+ static void ui_mainwindow_action_file_statistics(void);
++static void ui_mainwindow_action_pluginprefs(void);
 +
  static void ui_mainwindow_action_help(void);
  void ui_mainwindow_action_help_welcome(void);
  static void ui_mainwindow_action_help_online(void);
@@@ -141,90 -140,101 +144,107 @@@ void ui_mainwindow_recent_add (struct h
  static void ui_mainwindow_scheduled_populate(GtkWidget *widget, gpointer user_data);
  void ui_mainwindow_scheduled_postall(GtkWidget *widget, gpointer user_data);
  
static void ui_mainwindow_showprefs(gint page);
void ui_mainwindow_recent_add (struct hbfile_data *data, const gchar *path);
  
++static void ui_mainwindow_showprefs(gint page);
 +
  extern gchar *CYA_ACC_TYPE[];
  
+ gchar *CYA_CATSUBCAT[] = { 
+       N_("Category"), 
+       N_("Subcategory"), 
+       NULL
+ };
  static GtkActionEntry entries[] = {
  
-   /* name, stock id, label */
+   /* name, icon-name, label */
  
-   { "FileMenu"     , NULL, N_("_File"), NULL, NULL, NULL },
-   { "EditMenu"     , NULL, N_("_Edit"), NULL, NULL, NULL },
-   { "ViewMenu"     , NULL, N_("_View"), NULL, NULL, NULL },
-   { "ManageMenu"   , NULL, N_("_Manage"), NULL, NULL, NULL },
-   { "TransactionMenu", NULL, N_("_Transactions"), NULL, NULL, NULL },
-   { "ReportMenu"   , NULL, N_("_Reports"), NULL, NULL, NULL  },
-   { "PluginMenu"   , NULL, N_("_Plugins"), NULL, NULL, NULL },
-   { "HelpMenu"     , NULL, N_("_Help"), NULL, NULL, NULL },
+   { "FileMenu"   , NULL, N_("_File"), NULL, NULL, NULL },
+   { "ImportMenu" , NULL, N_("_Import"), NULL, NULL, NULL },
+   { "EditMenu"   , NULL, N_("_Edit"), NULL, NULL, NULL },
+   { "ViewMenu"   , NULL, N_("_View"), NULL, NULL, NULL },
+   { "ManageMenu" , NULL, N_("_Manage"), NULL, NULL, NULL },
+   { "TxnMenu"    , NULL, N_("_Transactions"), NULL, NULL, NULL },
+   { "ReportMenu" , NULL, N_("_Reports"), NULL, NULL, NULL  },
+   { "ToolsMenu"  , NULL, N_("_Tools"), NULL, NULL, NULL },
++  { "PluginMenu" , NULL, N_("_Plugins"), NULL, NULL, NULL },
+   { "HelpMenu"   , NULL, N_("_Help"), NULL, NULL, NULL },
  
  //  { "Import"       , NULL, N_("Import") },
  //  { "Export"       , NULL, N_("Export to") },
-       /* name, stock id, label, accelerator, tooltip */
+       /* name, icon-name, label, accelerator, tooltip */
  
    /* FileMenu */
-   { "New"        , GTK_STOCK_NEW            , N_("_New")          , NULL, N_("Create a new file"),    G_CALLBACK (ui_mainwindow_action_new) },
-   { "Open"       , GTK_STOCK_OPEN           , N_("_Open...")      , NULL, N_("Open a file"),    G_CALLBACK (ui_mainwindow_action_open) },
-   { "Save"       , GTK_STOCK_SAVE           , N_("_Save")         , NULL, N_("Save the current file"),    G_CALLBACK (ui_mainwindow_action_save) },
-   { "SaveAs"     , GTK_STOCK_SAVE_AS        , N_("Save As...")    , "<shift><control>S", N_("Save the current file with a different name"),    G_CALLBACK (ui_mainwindow_action_saveas) },
-   { "Revert"     , GTK_STOCK_REVERT_TO_SAVED, N_("Revert")        , NULL, N_("Revert to a saved version of this file"),    G_CALLBACK (ui_mainwindow_action_revert) },
+   { "New"        , ICONNAME_NEW            , N_("_New")          , "<control>N", N_("Create a new file"),    G_CALLBACK (ui_mainwindow_action_new) },
+   { "Open"       , ICONNAME_OPEN           , N_("_Open...")      , "<control>O", N_("Open a file"),    G_CALLBACK (ui_mainwindow_action_open) },
+   { "Save"       , ICONNAME_SAVE           , N_("_Save")         , "<control>S", N_("Save the current file"),    G_CALLBACK (ui_mainwindow_action_save) },
+   { "SaveAs"     , ICONNAME_SAVE_AS        , N_("Save _As...")    , "<shift><control>S", N_("Save the current file with a different name"),    G_CALLBACK (ui_mainwindow_action_saveas) },
+   { "Revert"     , ICONNAME_REVERT         , N_("Revert")        , NULL, N_("Revert to a saved version of this file"),    G_CALLBACK (ui_mainwindow_action_revert) },
  
-   { "Properties" , GTK_STOCK_PROPERTIES     , N_("_Properties..."), NULL, N_("Configure the file"),    G_CALLBACK (ui_mainwindow_action_properties) },
-   { "Close"      , GTK_STOCK_CLOSE          , N_("_Close")        , NULL, N_("Close the current file"),    G_CALLBACK (ui_mainwindow_action_close) },
-   { "Quit"       , GTK_STOCK_QUIT           , N_("_Quit")         , NULL, N_("Quit homebank"),    G_CALLBACK (ui_mainwindow_action_quit) },
+   { "Properties" , ICONNAME_PROPERTIES     , N_("Properties..."), NULL, N_("Configure the file"),    G_CALLBACK (ui_mainwindow_action_properties) },
+   { "Close"      , ICONNAME_CLOSE          , N_("_Close")        , "<control>W", N_("Close the current file"),    G_CALLBACK (ui_mainwindow_action_close) },
+   { "Quit"       , ICONNAME_QUIT           , N_("_Quit")         , "<control>Q", N_("Quit HomeBank"),    G_CALLBACK (ui_mainwindow_action_quit) },
  
    /* Exchange */
-   { "FileImport" , "hb-file-import"         , N_("Import QIF/OFX/CSV...")     , NULL, N_("Open the import assistant"),    G_CALLBACK (ui_mainwindow_action_import) },
-   { "ExportQIF"  , "hb-file-export"         , N_("Export QIF...")     , NULL, N_("Open the export to QIF assistant"),    G_CALLBACK (ui_mainwindow_action_export) },
-   { "Anonymize"  , NULL                     , N_("Anonymize...")  , NULL, NULL,    G_CALLBACK (ui_mainwindow_action_anonymize) },
+   { "ImportQIF" , ICONNAME_HB_FILE_IMPORT  , N_("QIF file...")     , NULL, N_("Open the import assistant"),    G_CALLBACK (ui_mainwindow_action_import) },
+   { "ImportOFX" , ICONNAME_HB_FILE_IMPORT  , N_("OFX/QFX file...")     , NULL, N_("Open the import assistant"),    G_CALLBACK (ui_mainwindow_action_import) },
+   { "ImportCSV" , ICONNAME_HB_FILE_IMPORT  , N_("CSV file...")     , NULL, N_("Open the import assistant"),    G_CALLBACK (ui_mainwindow_action_import) },
+       
+   { "ExportQIF" , ICONNAME_HB_FILE_EXPORT  , N_("Export QIF file...")     , NULL, N_("Export all account in a QIF file"),    G_CALLBACK (ui_mainwindow_action_export) },
  
    /* EditMenu */
-   { "Preferences", GTK_STOCK_PREFERENCES, N_("Preferences..."), NULL,    N_("Configure homebank"),    G_CALLBACK (ui_mainwindow_action_preferences) },
+   { "Preferences", ICONNAME_PREFERENCES    , N_("Preferences..."), NULL,    N_("Configure HomeBank"),    G_CALLBACK (ui_mainwindow_action_preferences) },
  
    /* ManageMenu */
//  { "Currency"   , "hb-currency"  , N_("Currencies...") , NULL,    N_("Configure the currencies"), G_CALLBACK (ui_mainwindow_action_defcurrency) },
-   { "Account"    , "hb-account"   , N_("Acc_ounts...")  , NULL,    N_("Configure the accounts"), G_CALLBACK (ui_mainwindow_action_defaccount) },
-   { "Payee"      , "hb-payee"     , N_("_Payees...")    , NULL,    N_("Configure the payees"),    G_CALLBACK (ui_mainwindow_action_defpayee) },
-   { "Category"   , "hb-category"  , N_("Categories...") , NULL,    N_("Configure the categories"),    G_CALLBACK (ui_mainwindow_action_defcategory) },
-   { "Archive"    , "hb-archive"   , N_("Scheduled/Template...")  , NULL,    N_("Configure the scheduled/template transactions"),    G_CALLBACK (ui_mainwindow_action_defarchive) },
-   { "Budget"     , "hb-budget"    , N_("Budget...")     , NULL,    N_("Configure the budget"),    G_CALLBACK (ui_mainwindow_action_defbudget) },
-   { "Assign"     , "hb-assign"    , N_("Assignments..."), NULL,    N_("Configure the automatic assignments"),    G_CALLBACK (ui_mainwindow_action_defassign) },
-   /* TransactionMenu */
-   { "ShowOpe"    , HB_STOCK_OPE_SHOW, N_("Show...")             , NULL, N_("Shows selected account transactions"),    G_CALLBACK (ui_mainwindow_action_showtransactions) },
-   { "AddOpe"     , HB_STOCK_OPE_ADD , N_("Add...")              , NULL, N_("Add transaction"),    G_CALLBACK (ui_mainwindow_action_addtransactions) },
-   { "Scheduler"  , NULL             , N_("Set scheduler...")    , NULL, N_("Configure the transaction scheduler"),    G_CALLBACK (ui_mainwindow_action_properties) },
-   { "AddScheduled"  , NULL             , N_("Process scheduled..."), NULL, N_("Insert pending scheduled transactions"),    G_CALLBACK (ui_mainwindow_action_checkscheduled) },
  { "Currency"   , ICONNAME_HB_CURRENCY    , N_("Currencies...") , NULL,    N_("Configure the currencies"), G_CALLBACK (ui_mainwindow_action_defcurrency) },
+   { "Account"    , ICONNAME_HB_ACCOUNT     , N_("Acc_ounts...")  , NULL,    N_("Configure the accounts"), G_CALLBACK (ui_mainwindow_action_defaccount) },
+   { "Payee"      , ICONNAME_HB_PAYEE       , N_("_Payees...")    , NULL,    N_("Configure the payees"),    G_CALLBACK (ui_mainwindow_action_defpayee) },
+   { "Category"   , ICONNAME_HB_CATEGORY    , N_("Categories...") , NULL,    N_("Configure the categories"),    G_CALLBACK (ui_mainwindow_action_defcategory) },
+   { "Archive"    , ICONNAME_HB_ARCHIVE     , N_("Scheduled/Template...")  , NULL,    N_("Configure the scheduled/template transactions"),    G_CALLBACK (ui_mainwindow_action_defarchive) },
+   { "Budget"     , ICONNAME_HB_BUDGET      , N_("Budget...")     , NULL,    N_("Configure the budget"),    G_CALLBACK (ui_mainwindow_action_defbudget) },
+   { "Assign"     , ICONNAME_HB_ASSIGN      , N_("Assignments..."), NULL,    N_("Configure the automatic assignments"),    G_CALLBACK (ui_mainwindow_action_defassign) },
+   /* TxnMenu */
+   { "ShowOpe"     , ICONNAME_HB_OPE_SHOW   , N_("Show...")             , NULL, N_("Shows selected account transactions"),    G_CALLBACK (ui_mainwindow_action_showtransactions) },
+   { "AddOpe"      , ICONNAME_HB_OPE_ADD    , N_("Add...")              , NULL, N_("Add transactions"),    G_CALLBACK (ui_mainwindow_action_addtransactions) },
+   { "Scheduler"   , NULL                   , N_("Set scheduler...")    , NULL, N_("Configure the transaction scheduler"),    G_CALLBACK (ui_mainwindow_action_properties) },
+   { "AddScheduled", NULL                   , N_("Post scheduled"), NULL, N_("Post pending scheduled transactions"),    G_CALLBACK (ui_mainwindow_action_checkscheduled) },
  
    /* ReportMenu */
-   { "RStatistics" , HB_STOCK_REP_STATS , N_("_Statistics...") , NULL,    N_("Open the Statistics report"),    G_CALLBACK (ui_mainwindow_action_statistic) },
-   { "RTrendTime"   , HB_STOCK_REP_TIME , N_("_Trend Time...") , NULL,    N_("Open the Trend Time report"),    G_CALLBACK (ui_mainwindow_action_trendtime) },
-   { "RBudget"    , HB_STOCK_REP_BUDGET, N_("B_udget...")     , NULL,    N_("Open the Budget report"),    G_CALLBACK (ui_mainwindow_action_budget) },
-   { "RBalance"  , HB_STOCK_REP_BALANCE, N_("Balance...")  , NULL,    N_("Open the Balance report"),    G_CALLBACK (ui_mainwindow_action_balance) },
-   { "RVehiculeCost"    , HB_STOCK_REP_CAR   , N_("_Vehicle cost...")   , NULL,    N_("Open the Vehicle cost report"),    G_CALLBACK (ui_mainwindow_action_vehiclecost) },
+   { "RStatistics" , ICONNAME_HB_REP_STATS  , N_("_Statistics...") , NULL,    N_("Open the Statistics report"),    G_CALLBACK (ui_mainwindow_action_statistic) },
+   { "RTrendTime"  , ICONNAME_HB_REP_TIME   , N_("_Trend Time...") , NULL,    N_("Open the Trend Time report"),    G_CALLBACK (ui_mainwindow_action_trendtime) },
+   { "RBudget"     , ICONNAME_HB_REP_BUDGET , N_("B_udget...")     , NULL,    N_("Open the Budget report"),    G_CALLBACK (ui_mainwindow_action_budget) },
+   { "RBalance"    , ICONNAME_HB_REP_BALANCE, N_("Balance...")  , NULL,    N_("Open the Balance report"),    G_CALLBACK (ui_mainwindow_action_balance) },
+   { "RVehiculeCost", ICONNAME_HB_REP_CAR   , N_("_Vehicle cost...")   , NULL,    N_("Open the Vehicle cost report"),    G_CALLBACK (ui_mainwindow_action_vehiclecost) },
+   /* Tools */
+   { "Welcome"     , NULL              , N_("Show welcome dialog...")  , NULL, NULL, G_CALLBACK (ui_mainwindow_action_help_welcome) },
+   { "FileStats"   , NULL              , N_("File statistics...")  , NULL, NULL,    G_CALLBACK (ui_mainwindow_action_file_statistics) },
+   { "Anonymize"   , NULL              , N_("Anonymize...")  , NULL, NULL,    G_CALLBACK (ui_mainwindow_action_anonymize) },
+       
++  /* Plugins */
 +  { "PluginPreferences", "prf-plugins", N_("_Plugins..."), "<control>U", N_("Configure plugin preferences"), G_CALLBACK(ui_mainwindow_action_pluginprefs) },
 +
    /* HelpMenu */
-   { "Contents"   , GTK_STOCK_HELP    , N_("_Contents")                    , "F1", N_("Documentation about HomeBank"), G_CALLBACK (ui_mainwindow_action_help) },
-   { "Welcome"    , NULL              , N_("Show welcome dialog...")       , NULL, NULL                              , G_CALLBACK (ui_mainwindow_action_help_welcome) },
-   { "Online"     , "lpi-help"        , N_("Get Help Online...")           , NULL, N_("Connect to the LaunchPad website for online help"), G_CALLBACK (ui_mainwindow_action_help_online) },
-   { "Translate"  , "lpi-translate"   , N_("Translate this Application..."), NULL, N_("Connect to the LaunchPad website to help translate this application"), G_CALLBACK (ui_mainwindow_action_help_translate) },
-   { "Problem"    , "lpi-bug"         , N_("Report a Problem...")          , NULL, N_("Connect to the LaunchPad website to help fix problems"), G_CALLBACK (ui_mainwindow_action_help_problem) },
+   { "Contents"    , ICONNAME_HELP     , N_("_Contents")                    , "F1", N_("Documentation about HomeBank"), G_CALLBACK (ui_mainwindow_action_help) },
+   { "Online"      , "lpi-help"        , N_("Get Help Online...")           , NULL, N_("Connect to the LaunchPad website for online help"), G_CALLBACK (ui_mainwindow_action_help_online) },
+   { "Translate"   , "lpi-translate"   , N_("Translate this Application..."), NULL, N_("Connect to the LaunchPad website to help translate this application"), G_CALLBACK (ui_mainwindow_action_help_translate) },
+   { "Problem"     , "lpi-bug"         , N_("Report a Problem...")          , NULL, N_("Connect to the LaunchPad website to help fix problems"), G_CALLBACK (ui_mainwindow_action_help_problem) },
  
-   { "About"      , GTK_STOCK_ABOUT      , N_("_About")     , NULL, N_("About HomeBank")      ,G_CALLBACK (ui_mainwindow_action_about) },
+   { "About"       , ICONNAME_ABOUT      , N_("_About")     , NULL, N_("About HomeBank")      ,G_CALLBACK (ui_mainwindow_action_about) },
  
  };
  static guint n_entries = G_N_ELEMENTS (entries);
  
  
  static GtkToggleActionEntry toggle_entries[] = {
- /*  name         , stockid, label, accelerator, tooltip, callback, is_active */
+ /*  name         , icon-name, label, accelerator, tooltip, callback, is_active */
    { "Toolbar"    , NULL                 , N_("_Toolbar")  , NULL,    NULL,    G_CALLBACK (ui_mainwindow_action_toggle_toolbar), TRUE },
    { "Spending"   , NULL                 , N_("_Top spending") , NULL,    NULL,    G_CALLBACK (ui_mainwindow_action_toggle_topspending), TRUE },
    { "Upcoming"   , NULL                 , N_("_Scheduled list") , NULL,    NULL,    G_CALLBACK (ui_mainwindow_action_toggle_upcoming), TRUE },
-   { "AsMinor"    , NULL                 , N_("Minor currency"), "<control>M",    NULL,    G_CALLBACK (ui_mainwindow_action_toggle_minor), FALSE },
+   { "AsMinor"    , NULL                 , N_("Euro minor"), "<control>M",    NULL,    G_CALLBACK (ui_mainwindow_action_toggle_minor), FALSE },
  };
  
  static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
@@@ -242,14 -252,17 +262,17 @@@ static const gchar *ui_info 
  "      <menuitem action='SaveAs'/>"
  "      <menuitem action='Revert'/>"
  "        <separator/>"
- "      <menuitem action='FileImport'/>"
+ "      <menuitem action='Properties'/>"
+ "        <separator/>"
+ "        <menu action='ImportMenu'>"
+ "          <menuitem action='ImportQIF'/>"
+ "          <menuitem action='ImportOFX'/>"
+ "          <menuitem action='ImportCSV'/>"
+ "        </menu>"
  "      <menuitem action='ExportQIF'/>"
  //"        <separator/>"
  // print to come here
  "        <separator/>"
- "      <menuitem action='Properties'/>"
- "      <menuitem action='Anonymize'/>"
- "        <separator/>"
  "      <menuitem action='Close'/>"
  "      <menuitem action='Quit'/>"
  "    </menu>"
  "    </menu>"
  "    <menu action='ViewMenu'>"
  "      <menuitem action='Toolbar'/>"
+ "        <separator/>"
  "      <menuitem action='Spending'/>"
  "      <menuitem action='Upcoming'/>"
  "        <separator/>"
  "      <menuitem action='AsMinor'/>"
  "    </menu>"
  "    <menu action='ManageMenu'>"
- //"      <menuitem action='Currency'/>"
  "      <menuitem action='Account'/>"
  "      <menuitem action='Payee'/>"
  "      <menuitem action='Category'/>"
- "      <menuitem action='Assign'/>"
  "      <menuitem action='Archive'/>"
  "      <menuitem action='Budget'/>"
+ "      <menuitem action='Assign'/>"
+ "      <menuitem action='Currency'/>"
  "    </menu>"
- "    <menu action='TransactionMenu'>"
+ "    <menu action='TxnMenu'>"
  "      <menuitem action='ShowOpe'/>"
  "      <menuitem action='AddOpe'/>"
  "        <separator/>"
  "      <menuitem action='RBudget'/>"
  "      <menuitem action='RVehiculeCost'/>"
  "    </menu>"
+ "    <menu action='ToolsMenu'>"
+ "      <menuitem action='Welcome'/>"
+ "      <menuitem action='FileStats'/>"
+ "        <separator/>"
+ "      <menuitem action='Anonymize'/>"
+ "    </menu>"
 +"    <menu action='PluginMenu'>"
 +"      <separator/>"
 +"      <menuitem action='PluginPreferences'/>"
 +"      <separator/>"
 +"    </menu>"
  "    <menu action='HelpMenu'>"
  "      <menuitem action='Contents'/>"
  "        <separator/>"
- "      <menuitem action='Welcome'/>"
- "        <separator/>"
  "      <menuitem action='Online'/>"
  "      <menuitem action='Translate'/>"
  "      <menuitem action='Problem'/>"
  
  "  <toolbar  name='ToolBar'>"
  "    <toolitem action='New'/>"
+ //      here Open + recent is coded
  "    <toolitem action='Save'/>"
  "      <separator/>"
- //"    <toolitem action='Currency'/>"
  "    <toolitem action='Account'/>"
  "    <toolitem action='Payee'/>"
  "    <toolitem action='Category'/>"
- "    <toolitem action='Assign'/>"
  "    <toolitem action='Archive'/>"
  "    <toolitem action='Budget'/>"
+ "    <toolitem action='Assign'/>"
+ "    <toolitem action='Currency'/>"
  "      <separator/>"
  "    <toolitem action='ShowOpe'/>"
  "    <toolitem action='AddOpe'/>"
  "    <toolitem action='RBalance'/>"
  "    <toolitem action='RBudget'/>"
  "    <toolitem action='RVehiculeCost'/>"
 +"      <separator/>"
  "  </toolbar>"
  
  "</ui>";
  
  
  /* TODO: a bouger */
  
  
  void ui_mainwindow_revert(GtkWidget *widget, gpointer user_data)
  {
  //struct hbfile_data *data;
- GtkWidget *dialog;
  gchar *basename;
+ gchar *title;
+ gchar *secondtext;
  gint result;
  
        DB( g_print("\n[ui-mainwindow] revert\n") );
  
        //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
  
-               basename = g_path_get_basename(GLOBALS->xhb_filepath);
-               dialog = gtk_message_dialog_new
-               (
-                       GTK_WINDOW(GLOBALS->mainwindow),
-                       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
-                       GTK_MESSAGE_QUESTION,
-                       GTK_BUTTONS_NONE,
-                       _("Revert to the previously saved file of '%s'?"),
-                       basename
-               );
-               g_free(basename);
+       basename = g_path_get_basename(GLOBALS->xhb_filepath);
+       title = g_strdup_printf (
+               _("Revert unsaved changes to file '%s'?"), basename);
  
-               gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
-                       _("- Changes made to the file will be permanently lost\n"
-                       "- File will be restored to the last save (.xhb~)")
-                       );
+       secondtext = 
+               _("- Changes made to the file will be permanently lost\n"
+               "- File will be reloaded from the last save (.xhb~)");
  
-               gtk_dialog_add_buttons (GTK_DIALOG(dialog),
-                   GTK_STOCK_CANCEL, 0,
-                       GTK_STOCK_REVERT_TO_SAVED, 1,
-                       NULL);
+       result = ui_dialog_msg_confirm_alert(
+                       GTK_WINDOW(GLOBALS->mainwindow),
+                       title,
+                       secondtext,
+                       _("_Revert")
+               );
  
-         result = gtk_dialog_run( GTK_DIALOG( dialog ) );
-         gtk_widget_destroy( dialog );
+       g_free(title);
+       g_free(basename);
  
-       if( result == 1)
+       if( result == GTK_RESPONSE_OK )
        {
                DB( g_print(" - should revert\n") );
                
-               hbfile_change_filepath(hb_filename_new_with_extention(GLOBALS->xhb_filepath, "xhb~"));
+               hbfile_change_filepath(hb_util_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb~"));
                ui_mainwindow_open_internal(widget, NULL);
-               hbfile_change_filepath(hb_filename_new_with_extention(GLOBALS->xhb_filepath, "xhb"));
+               hbfile_change_filepath(hb_util_filename_new_with_extension(GLOBALS->xhb_filepath, "xhb"));
        }
  
  }
  
  static void
  activate_url (GtkAboutDialog *about,
              const gchar    *link,
  
  static void hbfile_about(void)
  {
- GtkWidget *about;
- gchar *pathfilename;
+ GtkWidget *dialog;
  GdkPixbuf *pixbuf;
+ gchar *pathfilename;
+ gchar *version;
  
    static const gchar *artists[] = {
      "Maxime DOYEN",
    static const gchar *authors[] = {
      "Lead developer:\n" \
      "Maxime DOYEN",
 -    "\nContributor:\n" \
 +    "\nContributors:\n" \
 +    "Charles MCGARVEY (Plugin system, Perl support)\n" \
      "Ga\xc3\xabtan LORIDANT (Maths formulas for charts)\n",
      NULL
    };
    };
  */
  
-       static const gchar license[] =
-               "This program is free software; you can redistribute it and/or modify\n"
-                 "it under the terms of the GNU General Public License as\n"
-                 "published by the Free Software Foundation; either version 2 of the\n"
-                 "License, or (at your option) any later version.\n\n"
-                 "This program is distributed in the hope that it will be useful,\n"
-                 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-                 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
-                 "GNU General Public License for more details.\n\n"
-                 "You should have received a copy of the GNU General Public License\n"
-                 "along with this program; if not, write to the Free Software\n"
-                 "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, "
-                 "MA 02110-1301, USA.";
+       static const gchar *copyright = "Copyright \xc2\xa9 1995-2016 - Maxime DOYEN";
  
-       static const gchar *copyright = "Copyright \xc2\xa9 1995-2014 - Maxime DOYEN";
  
  
-       pathfilename = g_build_filename(homebank_app_get_images_dir(), "splash.png", NULL);
-       pixbuf = gdk_pixbuf_new_from_file(pathfilename, NULL);
-       g_free(pathfilename);
+       version = g_strdup_printf (PACKAGE_VERSION "\n<small>Running against GTK+ %d.%d.%d</small>",
+                                                      gtk_get_major_version (),
+                                                      gtk_get_minor_version (),
+                                                      gtk_get_micro_version ());
+       
+       dialog = gtk_about_dialog_new();
  
-       about  = gtk_about_dialog_new();
-       gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG(about), g_get_application_name ());
-       gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(about), PACKAGE_VERSION);
-       gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(about), copyright);
-       gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(about), _("Free, easy, personal accounting for everyone."));
-       gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(about), license);
-       //gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(about), );
-       gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(about), "http://homebank.free.fr");
-       gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(about), "Visit the HomeBank website");
-       gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(about), authors);
-       gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(about), artists);
-       //gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(about), );
-       //gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(about), );
-       gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(about), "homebank");
-       gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(about), pixbuf);
+       gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(GLOBALS->mainwindow));
+       gtk_window_set_modal(GTK_WINDOW(dialog), TRUE);
        
-       /*
-       gtk_show_about_dialog(GTK_WINDOW(GLOBALS->mainwindow),
-               "name", g_get_application_name (),
-               "logo-icon-name", "homebank",
-               "logo"      , pixbuf,
-               "artists"       , artists,
-               "authors"       , authors,
-       //      "translator-credits"    , "trans",
-               "comments"      , _("Free, easy, personal accounting for everyone."),
-               "license"       , license,
-               "copyright"     , copyright,
-               "version"       , PACKAGE_VERSION,
-               "website"       , "http://homebank.free.fr",
-               "website-label", "Visit the HomeBank website",
-         NULL);
-       */
-       g_signal_connect (about, "activate-link", G_CALLBACK (activate_url), NULL);
+       gtk_about_dialog_set_program_name (GTK_ABOUT_DIALOG(dialog), g_get_application_name ());
+       gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), version);
+       gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), copyright);
+       gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), _("Free, easy, personal accounting for everyone"));
+       gtk_about_dialog_set_license_type (GTK_ABOUT_DIALOG(dialog), GTK_LICENSE_GPL_2_0);
+       
+       //gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(dialog), );
+       gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://homebank.free.fr");
+       gtk_about_dialog_set_website_label(GTK_ABOUT_DIALOG(dialog), "Visit the HomeBank website");
  
-       gtk_dialog_run (GTK_DIALOG (about));
+       gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "homebank");
  
-       gtk_widget_destroy (about);
+       pathfilename = g_build_filename(homebank_app_get_images_dir(), "splash.png", NULL);
+       pixbuf = gdk_pixbuf_new_from_file(pathfilename, NULL);
+       g_free(pathfilename);
  
-       g_object_unref (pixbuf);
- }
+       if( pixbuf )
+       {
+               gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), pixbuf);
+               g_object_unref (pixbuf);
+       }
+       
+       gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), authors);
+       gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(dialog), artists);
+       //gtk_about_dialog_set_documenters(GTK_ABOUT_DIALOG(dialog), );
+       //gtk_about_dialog_set_translator_credits(GTK_ABOUT_DIALOG(dialog), );
  
+       g_signal_connect (dialog, "activate-link", G_CALLBACK (activate_url), NULL);
  
+       gtk_dialog_run (GTK_DIALOG (dialog));
  
+       gtk_widget_destroy (dialog);
  
+       g_free(version);
+       
+ }
  
  
  /* hbfile action functions -------------------- */
@@@ -499,6 -491,11 +508,11 @@@ GtkWidget *widget = GLOBALS->mainwindow
                //clear all, and init GLOBALS->xhb_filepath to default
                ui_mainwindow_clear(widget, GINT_TO_POINTER(TRUE)); // GPOINTER_TO_INT(
                ui_mainwindow_update(widget, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
+               ui_start_assistant();
+               ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
+               ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
+               ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
        }
  }
  
@@@ -547,9 -544,12 +561,18 @@@ gboolean result
        //gtk_main_quit();
  }
  
+ static void ui_mainwindow_action_file_statistics(void)
+ {
+       ui_dialog_file_statistics();
+ }
  
  
++static void ui_mainwindow_action_pluginprefs(void)
++{
++      ui_mainwindow_showprefs(PREF_PLUGINS);
++}
++
 +
  static void ui_mainwindow_action_properties(void)
  {
        create_defhbfile_dialog();
  static void ui_mainwindow_action_anonymize(void)
  {
  gint result;
+ gchar *title;
+ gchar *secondtext;
+       title = _("Are you sure you want to anonymize the file?");
+       secondtext = 
+               _("Proceeding will anonymize any text, \n"
+               "like 'account x', 'payee y', 'memo z', ...");
  
-       result = ui_dialog_msg_question(
-               GTK_WINDOW(GLOBALS->mainwindow),
-               _("Anonymize the file ?"),
-               _("Proceeding will changes name/memo to anonymous datas,\n"
-               "please confirm.")
+       result = ui_dialog_msg_confirm_alert(
+                       GTK_WINDOW(GLOBALS->mainwindow),
+                       title,
+                       secondtext,
+                       _("_Anonymize")
                );
  
-       if( result == GTK_RESPONSE_NO )
+       if( result == GTK_RESPONSE_CANCEL )
                return; 
        
        hbfile_anonymize();
        ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
  }
  
- /*
  static void ui_mainwindow_action_defcurrency(void)
  {
-       //ui_cur_manage_dialog();
-       ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
+       ui_cur_manage_dialog();
+       ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_REFRESHALL));
  }
- */
  
  static void ui_mainwindow_action_defaccount(void)
  {
@@@ -608,7 -616,8 +639,8 @@@ static void ui_mainwindow_action_defcat
        ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE));
  }
  
- static void ui_mainwindow_action_defarchive(void)
+ static void ui_mainwindow_defarchive(Archive *arc)
  {
  struct hbfile_data *data;
  GtkTreeModel *model;
        model = gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc));
        gtk_list_store_clear (GTK_LIST_STORE(model));
  
-       ui_arc_manage_dialog();
+       ui_arc_manage_dialog(arc);
  
        ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
  
  }
  
  
+ static void ui_mainwindow_action_defarchive(void)
+ {
+       ui_mainwindow_defarchive(NULL);
+ }
  static void ui_mainwindow_action_defbudget(void)
  {
        ui_bud_manage_dialog();
@@@ -644,15 -659,10 +682,15 @@@ static void ui_mainwindow_action_defass
  
  
  static void ui_mainwindow_action_preferences(void)
 +{
 +      ui_mainwindow_showprefs(PREF_GENERAL);
 +}
 +
 +static void ui_mainwindow_showprefs(gint page)
  {
  struct hbfile_data *data = g_object_get_data(G_OBJECT(GLOBALS->mainwindow), "inst_data");
  
 -      defpref_dialog_new();
 +      defpref_dialog_new(page);
        if(!PREFS->euro_active)
        {
        GtkToggleAction *action = (GtkToggleAction *)gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/AsMinor");
@@@ -700,7 -710,7 +738,7 @@@ struct hbfile_data *data = g_object_get
  
        // top spending
        gtk_chart_show_minor(GTK_CHART(data->RE_pie), GLOBALS->minor);
-       hb_label_set_amount(GTK_LABEL(data->TX_topamount), data->toptotal, GLOBALS->minor);
+       hb_label_set_amount(GTK_LABEL(data->TX_topamount), data->toptotal, GLOBALS->kcur, GLOBALS->minor);
  
  }
  
@@@ -766,15 -776,25 +804,25 @@@ static void ui_mainwindow_action_vehicl
        repcost_window_new();
  }
  
- static void ui_mainwindow_action_pluginprefs(void)
+ static void ui_mainwindow_action_import(GtkAction *action)
  {
      ui_mainwindow_showprefs(PREF_PLUGINS);
- }
const gchar *name;
+ gint filetype = FILETYPE_UNKNOW;
  
- static void ui_mainwindow_action_import(void)
- {
-       ui_import_window_new();
+       name = gtk_action_get_name(action);
+       if( g_str_has_suffix (name, "QIF"))
+          filetype= FILETYPE_QIF;
+       else
+       if( g_str_has_suffix (name, "OFX"))
+          filetype= FILETYPE_OFX;
+       else
+       if( g_str_has_suffix (name, "CSV"))
+          filetype= FILETYPE_CSV_HB;
  
+       DB( g_print("action %s type=%d\n", name, filetype) );
+       ui_import_assistant_new(filetype);
  
  }
  
@@@ -837,35 -857,35 +885,35 @@@ static void ui_mainwindow_action_help_w
  
  void ui_mainwindow_action_help_welcome(void)
  {
- GtkWidget *dialog, *content;
+ GtkWidget *dialog, *content_area;
  GtkWidget *mainvbox, *widget, *label;
  
        dialog = gtk_dialog_new_with_buttons (_("Welcome to HomeBank"),
                        GTK_WINDOW(GLOBALS->mainwindow),
                        0,
-                       GTK_STOCK_CLOSE,
+                       _("_Close"),
                        GTK_RESPONSE_ACCEPT,
                        NULL);
  
-       content = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
+       content_area = gtk_dialog_get_content_area(GTK_DIALOG (dialog));
        
-       mainvbox = gtk_vbox_new (FALSE, 0);
-       gtk_box_pack_start (GTK_BOX (content), mainvbox, FALSE, FALSE, 0);
-       gtk_container_set_border_width (GTK_CONTAINER(mainvbox), HB_MAINBOX_SPACING);
+       mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+       gtk_box_pack_start (GTK_BOX (content_area), mainvbox, FALSE, FALSE, 0);
+       gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM);
  
        label = make_label (_("HomeBank"), 0, 0);
        gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
        gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
  
-       label = make_label (_("Free, easy, personal accounting for everyone."), 0, 0);
+       label = make_label (_("Free, easy, personal accounting for everyone"), 0, 0);
        gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
  
-       widget = gtk_hseparator_new();
-       gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0);
+       widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
+       gtk_box_pack_start (GTK_BOX (content_area), widget, FALSE, FALSE, 0);
  
-       mainvbox = gtk_vbox_new (FALSE, HB_MAINBOX_SPACING);
-       gtk_box_pack_start (GTK_BOX (content), mainvbox, TRUE, TRUE, 0);
-       gtk_container_set_border_width (GTK_CONTAINER(mainvbox), HB_MAINBOX_SPACING);
+       mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM);
+       gtk_box_pack_start (GTK_BOX (content_area), mainvbox, TRUE, TRUE, 0);
+       gtk_container_set_border_width (GTK_CONTAINER(mainvbox), SPACING_MEDIUM);
  
        label = make_label (_("What do you want to do:"), 0, 0);
        gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
        gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
        g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome1), dialog);
        
-       widget = gtk_button_new_with_mnemonic(_("Configure _Preferences"));
+       widget = gtk_button_new_with_mnemonic(_("Configure _preferences"));
        gtk_box_pack_start (GTK_BOX (mainvbox), widget, FALSE, FALSE, 0);
        g_signal_connect (widget, "clicked", G_CALLBACK (ui_mainwindow_action_help_welcome2), dialog);
        
@@@ -998,31 -1018,23 +1046,23 @@@ GList *lacc, *elt
  */
  void ui_mainwindow_clear(GtkWidget *widget, gpointer user_data)
  {
//struct hbfile_data *data;
+ struct hbfile_data *data;
  gboolean file_clear = GPOINTER_TO_INT(user_data);
  
        DB( g_print("\n[ui-mainwindow] clear\n") );
  
-       //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
  
        // Close opened account window
        // Clear TreeView
        ui_mainwindow_close_openbooks();
-       //gtk_tree_store_clear(GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc))));
-       //gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc))));
-       //gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top))));
+       gtk_tree_store_clear(GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_acc))));
+       gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_upc))));
+       gtk_list_store_clear(GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(data->LV_top))));
        
        hbfile_cleanup(file_clear);
        hbfile_setup(file_clear);
  
-       if(file_clear == TRUE)
-       {
-               ui_start_assistant();
-               ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
-               ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
-               ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
-       }
  }
  
  
@@@ -1035,7 -1047,7 +1075,7 @@@ struct hbfile_data *data
  GtkWidget *window;
  gint result = 1;
  guint32 date;
- gint account = 1, count;
+ gint account, count;
  
        DB( g_print("\n[ui-mainwindow] add transactions\n") );
  
  
        /* init the transaction */
        date = homebank_app_date_get_julian();
+       //todo: maybe think about set a default account here
+       account = 1;
        if(data->acc != NULL)
                account = data->acc->key;
  
-       window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD);
+       window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, FALSE);
        count = 0;
-       while(result == GTK_RESPONSE_ADD)
+       while(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ADDKEEP)
        {
        Transaction *ope;
  
                /* fill in the transaction */
-               ope = da_transaction_malloc();
-               ope->date    = date;
-               ope->kacc = account;
+               if( result == GTK_RESPONSE_ADD )
+               {
+                       ope = da_transaction_malloc();
+                       ope->date    = date;
+                       ope->kacc = account;
  
-               if( PREFS->heritdate == FALSE ) //fix: 318733
-                       ope->date = GLOBALS->today;
+                       if( PREFS->heritdate == FALSE ) //fix: 318733
+                               ope->date = GLOBALS->today;
+               }
+               // normally we can't be in addkeep without initialized ope with add
  
                deftransaction_set_transaction(window, ope);
  
                result = gtk_dialog_run (GTK_DIALOG (window));
  
-               DB( g_print(" -> dialog result is %d\n", result) );
+               DB( g_print(" - dialog result is %d\n", result) );
  
-               if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ACCEPT)
+               if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ADDKEEP || result == GTK_RESPONSE_ACCEPT)
                {
                        deftransaction_get(window, NULL);
                        transaction_add(ope, NULL, ope->kacc);
  
-                       DB( g_print(" -> added 1 transaction to %d\n", ope->kacc) );
+                       DB( g_print(" - added 1 transaction to %d\n", ope->kacc) );
  
                        ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
                        
                        count++;
-                       //store last date
+                       //todo: still usefull ? store last date
                        date = ope->date;
                }
  
-               da_transaction_free(ope);
-               ope = NULL;
+               if( result == GTK_RESPONSE_ADD )
+               {
+                       da_transaction_free(ope);
+                       ope = NULL;
+               }
  
        }
  
@@@ -1115,11 -1137,11 +1165,11 @@@ struct hbfile_data *data
  GtkTreeModel *model;
  GtkTreeIter  iter;
  GList *list;
- gint range;
+ gint type, range;
  guint n_result, i, n_items;
  GArray *garray;
  gdouble total, other;
//Account *acc;
+ Account *acc;
  
  #define MAX_TOPSPENDING 5
        
  
        data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
  
+       type = radio_get_active(GTK_CONTAINER(data->RA_type));
        range = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_range));
  
-       DB( g_print(" - range=%d\n", range) );
+       DB( g_print(" - type=%d, range=%d\n", type, range) );
        DB( g_print(" - pref range=%d\n", PREFS->date_range_wal) );
  
        if(range == FLT_RANGE_OTHER)
                return;
        
-       filter_preset_daterange_set(data->filter, range);
+       filter_preset_daterange_set(data->filter, range, 0);
        
        
        n_result = da_cat_get_max_key() + 1;
        if(garray)
        {
        struct tmptop zero = { .key=0, .value=0.0 };
+       GQueue *txn_queue;
                
                //DB( g_print(" - array length=%d\n", garray->len) );
  
  
                //DB( g_print("\n - end array length=%d\n", garray->len) );
  
+               //todo: not ideal, has ot force to get_acc for each txn below
+               txn_queue = hbfile_transaction_get_partial(data->filter->mindate, data->filter->maxdate);
                /* compute the results */
-               list = g_list_first(GLOBALS->ope_list);
+               list = g_queue_peek_head_link(txn_queue);
                while (list != NULL)
                {
                Transaction *ope = list->data;
-               Account *acc;
-                       //debug
                        //DB( g_print(" - eval txn: '%s', cat=%d ==> flt-test=%d\n", ope->wording, ope->kcat, filter_test(data->filter, ope)) );
-                       acc = da_acc_get(ope->kacc);
-                       if(acc == NULL) goto next1;
-                       if((acc->flags & (AF_CLOSED|AF_NOREPORT))) goto next1;
-                       if(ope->paymode == PAYMODE_INTXFER) goto next1;
  
-                       if( !(ope->flags & OF_REMIND) )
+                       if( !(ope->paymode == PAYMODE_INTXFER) )
                        {
-                               if( (ope->date >= data->filter->mindate) && (ope->date <= data->filter->maxdate) )
-                               {
-                               guint32 pos = 0;
-                               gdouble trn_amount;
+                       guint32 pos = 0;
+                       gdouble trn_amount;
  
-                                       //trn_amount = to_base_amount(ope->amount, acc->kcur);
-                                       trn_amount = ope->amount;
+                               //todo: optimize here
+                               trn_amount = ope->amount;
+                               acc = da_acc_get(ope->kacc);
+                               if(acc)
+                                       trn_amount = hb_amount_base(ope->amount, acc->kcur);
  
-                                       if(  ope->flags & OF_SPLIT )
-                                       {
-                                       guint nbsplit = da_transaction_splits_count(ope);
-                                       Split *split;
-                                       struct tmptop *item;
-                                       
-                                               for(i=0;i<nbsplit;i++)
-                                               {
-                                                       split = ope->splits[i];
-                                                       Category *catentry = da_cat_get(split->kcat);
-                                                               if(catentry)
-                                                                       pos = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key;
-                                                       //trn_amount = to_base_amount(split->amount, acc->kcur);
-                                                       trn_amount = split->amount;
-                                                       //#1297054 if( trn_amount < 0 ) {
-                                                               item = &g_array_index (garray, struct tmptop, pos);
-                                                               item->key = pos;
-                                                               item->value += trn_amount;
-                                                               DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos)  );
-                                                       //}
-                                               }
-                                       }
-                                       else
+                               if(  ope->flags & OF_SPLIT )
+                               {
+                               guint nbsplit = da_splits_count(ope->splits);
+                               Split *split;
+                               struct tmptop *item;
+                               
+                                       for(i=0;i<nbsplit;i++)
                                        {
-                                       Category *catentry = da_cat_get(ope->kcat);
-                                       struct tmptop *item;
+                                               split = ope->splits[i];
+                                               pos = category_report_id(split->kcat, type);
  
-                                               if(catentry)
-                                                       pos = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key;
-                       
+                                               trn_amount = hb_amount_base(split->amount, acc->kcur);
+                                               //trn_amount = split->amount;
                                                //#1297054 if( trn_amount < 0 ) {
                                                        item = &g_array_index (garray, struct tmptop, pos);
                                                        item->key = pos;
                                                        item->value += trn_amount;
-                                                       DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos)  );
+                                                       //DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos)  );
                                                //}
                                        }
+                               }
+                               else
+                               {
+                               struct tmptop *item;
  
+                                       pos = category_report_id(ope->kcat, type);
+       
+                                       //#1297054 if( trn_amount < 0 ) {
+                                               item = &g_array_index (garray, struct tmptop, pos);
+                                               item->key = pos;
+                                               item->value += trn_amount;
+                                               //DB( g_print(" - stored %.2f to item %d\n", trn_amount, pos)  );
+                                       //}
                                }
                        }
- next1:
                        list = g_list_next(list);
                }
  
+               g_queue_free (txn_queue);
                
                // we need to sort this and limit before
                g_array_sort(garray, (GCompareFunc)tmptop_compare_func);
  
                        if(!item->value) continue;
  
-                       value = arrondi(item->value, 2);
+                       value = hb_amount_round(item->value, 2);
                        entry = da_cat_get(item->key);
                        if(entry == NULL) continue;
  
-                       name = entry->key == 0 ? _("(no category)") : entry->name;
+                       name = entry->key == 0 ? _("(no category)") : da_cat_get_fullname(entry);
  
                        // append test
                        gtk_list_store_append (GTK_LIST_STORE(model), &iter);
                g_object_unref(model);
                
                data->toptotal = total;
-               hb_label_set_amount(GTK_LABEL(data->TX_topamount), total, GLOBALS->minor);
+               hb_label_set_amount(GTK_LABEL(data->TX_topamount), total, GLOBALS->kcur, GLOBALS->minor);
  
                gtk_chart_set_color_scheme(GTK_CHART(data->RE_pie), PREFS->report_color_scheme);
-               gtk_chart_set_datas(GTK_CHART(data->RE_pie), model, LST_TOPSPEND_AMOUNT, NULL);
+               gtk_chart_set_currency(GTK_CHART(data->RE_pie), GLOBALS->kcur);
+               gtk_chart_set_datas(GTK_CHART(data->RE_pie), model, LST_TOPSPEND_AMOUNT, NULL, NULL);
                //gtk_chart_show_legend(GTK_CHART(data->RE_pie), FALSE);
  
          /* update info range text */
@@@ -1352,6 -1373,76 +1401,76 @@@ GtkTreeIter                    iter
  }
  
  
+ static void ui_mainwindow_scheduled_onRowActivated (GtkTreeView        *treeview,
+                        GtkTreePath        *path,
+                        GtkTreeViewColumn  *col,
+                        gpointer            userdata)
+ {
+ //struct hbfile_data *data;
+ Archive *arc;
+       DB( g_print ("\n[ui-mainwindow] A scheduled row has been double-clicked!\n") );
+       //data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(treeview, GTK_TYPE_WINDOW)), "inst_data");
+       arc = ui_mainwindow_scheduled_get_selected_item(treeview);
+       ui_mainwindow_defarchive(arc);
+ }
+ static void ui_mainwindow_scheduled_do_post(Archive *arc, gboolean doedit, gpointer user_data)
+ {
+ struct hbfile_data *data = user_data;
+ GtkWidget *window;
+ gint result;
+ Transaction *txn;
+       window =  create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD, TRUE);
+       /* fill in the transaction */
+       txn = da_transaction_malloc();
+       da_transaction_init_from_template(txn, arc);
+       txn->date = scheduled_get_postdate(arc, arc->nextdate);
+       deftransaction_set_transaction(window, txn);
+       result = gtk_dialog_run (GTK_DIALOG (window));
+       DB( g_print(" - dialog result is %d\n", result) );
+       if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ACCEPT)
+       {
+               deftransaction_get(window, NULL);
+               transaction_add(txn, NULL, txn->kacc);
+               GLOBALS->changes_count++;
+               scheduled_date_advance(arc);
+               DB( g_print(" - added 1 transaction to %d\n", txn->kacc) );
+       }
+       da_transaction_free(txn);
+       deftransaction_dispose(window, NULL);
+       gtk_widget_destroy (window);
+ }
+ static void ui_mainwindow_scheduled_editpost_cb(GtkWidget *widget, gpointer user_data)
+ {
+ struct hbfile_data *data = user_data;
+       Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
+       if( (arc != NULL) )
+       {
+               ui_mainwindow_scheduled_do_post(arc, TRUE, data);
+               ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE|UF_REFRESHALL));
+       }
+ }
  static void ui_mainwindow_scheduled_post_cb(GtkWidget *widget, gpointer user_data)
  {
  struct hbfile_data *data = user_data;
                        da_transaction_init_from_template(txn, arc);
                        txn->date = scheduled_get_postdate(arc, arc->nextdate);
                        transaction_add(txn, NULL, 0);
                        GLOBALS->changes_count++;
-               
                        scheduled_date_advance(arc);
  
                        da_transaction_free (txn);
                }
                else
                {
-               GtkWidget *window = create_deftransaction_window(GTK_WINDOW(data->window), TRANSACTION_EDIT_ADD);
-               gint result;
-                       Transaction *txn;
-                               /* fill in the transaction */
-                               txn = da_transaction_malloc();
-                               da_transaction_init_from_template(txn, arc);
-                               txn->date = scheduled_get_postdate(arc, arc->nextdate);
-                               deftransaction_set_transaction(window, txn);
-                               result = gtk_dialog_run (GTK_DIALOG (window));
-                               DB( g_print(" -> dialog result is %d\n", result) );
-                               if(result == GTK_RESPONSE_ADD || result == GTK_RESPONSE_ACCEPT)
-                               {
-                                       deftransaction_get(window, NULL);
-                                       transaction_add(txn, NULL, txn->kacc);
-                                       GLOBALS->changes_count++;
-               
-                                       scheduled_date_advance(arc);
-                                       DB( g_print(" -> added 1 transaction to %d\n", txn->kacc) );
-                               }
-                               da_transaction_free(txn);
-                       
-                               deftransaction_dispose(window, NULL);
-                               gtk_widget_destroy (window);
-               
+                       ui_mainwindow_scheduled_do_post(arc, FALSE, data);
                }
  
-               ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_REFRESHALL));
-               
+               ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE|UF_REFRESHALL));
        }
-       
  }
  
  
@@@ -1424,9 -1481,11 +1509,11 @@@ struct hbfile_data *data = user_data
        Archive *arc = ui_mainwindow_scheduled_get_selected_item(GTK_TREE_VIEW(data->LV_upc));
        if( (arc != NULL) && (arc->flags & OF_AUTO) )
        {
+               GLOBALS->changes_count++;
                scheduled_date_advance(arc);
  
                ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
+               ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_SENSITIVE));
        }
  }
  
@@@ -1449,13 -1508,15 +1536,15 @@@ struct hbfile_data *data
        {
                DB( g_print("archive is %s\n", arc->wording) );
                
-               gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), TRUE);
                gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_skip), TRUE);
+               gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), TRUE);
+               gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_editpost), TRUE);
        }
        else
        {
-               gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), FALSE);
                gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_skip), FALSE);
+               gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_post), FALSE);
+               gtk_widget_set_sensitive(GTK_WIDGET(data->BT_sched_editpost), FALSE);
        }
  
  }
@@@ -1547,6 -1608,8 +1636,8 @@@ GDate *date
        while (list != NULL)
        {
        Archive *arc = list->data;
+       Account *acc;
+       gdouble inc, exp;
        guint nbdays, nblate;
  
                if((arc->flags & OF_AUTO) ) //&& arc->kacc > 0)
                        
                        DB( g_print(" - append '%s' : %d\n", arc->wording, nbdays) );
  
+                       if(arc->flags & OF_INCOME)
+                       {
+                               inc = arc->amount;
+                               exp = 0.0;
+                       }
+                       else
+                       {
+                               exp = arc->amount;
+                               inc = 0.0;
+                       }
+                       /* insert normal txn */
+                       acc = da_acc_get(arc->kacc);
+                       if( acc)
+                       {
+                               totinc += hb_amount_base(inc, acc->kcur);
+                               totexp += hb_amount_base(exp, acc->kcur);
+                       }
                        gtk_list_store_append (GTK_LIST_STORE(model), &iter);
                        gtk_list_store_set (GTK_LIST_STORE(model), &iter,
                                  LST_DSPUPC_DATAS, arc,
+                                 LST_DSPUPC_ACCOUNT, acc,
                              LST_DSPUPC_WORDING, arc->wording,
-                             LST_DSPUPC_EXPENSE, !(arc->flags & OF_INCOME) ? arc->amount : 0.0,
-                             LST_DSPUPC_INCOME, (arc->flags & OF_INCOME) ? arc->amount :  0.0,
+                             LST_DSPUPC_EXPENSE, exp,
+                             LST_DSPUPC_INCOME, inc,
                                  LST_DSPUPC_REMAINING, nbdays,
                              LST_DSPUPC_NB_LATE, nblate,
                                  -1);
  
-                       //acc = da_acc_get(arc->kacc);
-                       //total += to_base_amount(arc->amount, acc->kcur);
-                       if(arc->flags & OF_INCOME)
-                               totinc += arc->amount;
-                       else
-                               totexp += arc->amount;
+                       /* insert internal xfer txn : 1378836 */
+                       if(arc->paymode == PAYMODE_INTXFER)
+                       {
+                               acc = da_acc_get(arc->kxferacc);
+                               if( acc)
+                               {
+                                       totinc += hb_amount_base(-inc, acc->kcur);
+                                       totexp += hb_amount_base(-exp, acc->kcur);
+                               }
+                               gtk_list_store_append (GTK_LIST_STORE(model), &iter);
+                               gtk_list_store_set (GTK_LIST_STORE(model), &iter,
+                                         LST_DSPUPC_DATAS, arc,
+                                         LST_DSPUPC_ACCOUNT, acc,
+                                         LST_DSPUPC_WORDING, arc->wording,
+                                         LST_DSPUPC_EXPENSE, -inc,
+                                         LST_DSPUPC_INCOME, -exp,
+                                         LST_DSPUPC_REMAINING, nbdays,
+                                         LST_DSPUPC_NB_LATE, nblate,
+                                         -1);
+                       }
  
                }
                list = g_list_next(list);
                gtk_list_store_append (GTK_LIST_STORE(model), &iter);
                gtk_list_store_set (GTK_LIST_STORE(model), &iter,
                          LST_DSPUPC_DATAS, NULL,
+                         LST_DSPUPC_ACCOUNT, NULL,
                          LST_DSPUPC_WORDING, _("Total"),
                          LST_DSPUPC_EXPENSE, totexp,
                      LST_DSPUPC_INCOME, totinc,
@@@ -1635,7 -1732,7 +1760,7 @@@ gint r
  
        data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
  
-       DB( g_print(" -> filename: '%s'\n", GLOBALS->xhb_filepath) );
+       DB( g_print(" - filename: '%s'\n", GLOBALS->xhb_filepath) );
  
        if( GLOBALS->xhb_filepath != NULL )
        {
                r = homebank_load_xml(GLOBALS->xhb_filepath);
                if( r == XML_OK )
                {
-                       DB( g_print(" -> file loaded ok : rcode=%d\n", r) );
+                       DB( g_print(" - file loaded ok : rcode=%d\n", r) );
                        
                        hbfile_file_hasbackup(GLOBALS->xhb_filepath);
                        
                        if(PREFS->appendscheduled)
                                scheduled_post_all_pending();
  
+                       if(PREFS->do_update_currency)
+                               ui_cur_manage_dialog_update_currencies(GTK_WINDOW(GLOBALS->mainwindow));
                        homebank_lastopenedfiles_save();
  
-                       //todo: remove this after computing done at xml read
+                       //todo: delete this after computing done at xml read
                        account_compute_balances();
  
                        ui_mainwindow_recent_add(data, GLOBALS->xhb_filepath);
-                       ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
-                       ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
-                       ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
                }
                else
                {
  
                }
  
+               ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
+               ui_mainwindow_scheduled_populate(GLOBALS->mainwindow, NULL);
+               ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
                ui_mainwindow_update(GLOBALS->mainwindow, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_VISUAL));
        }
  
@@@ -1716,10 -1816,9 +1844,9 @@@ gint r = XML_UNSET
        {
                if(ui_file_chooser_xhb(GTK_FILE_CHOOSER_ACTION_SAVE, &filename) == TRUE)
                {
-                       DB( g_print(" + should save as %s\n", GLOBALS->xhb_filepath) );
-                       hbfile_change_filepath(filename);
-                       homebank_backup_current_file(GLOBALS->xhb_filepath);
-                       homebank_file_ensure_xhb();
+                       DB( g_print(" + should save as '%s'\n", filename) );
+                       homebank_file_ensure_xhb(filename);
+                       homebank_backup_current_file();
                        r = homebank_save_xml(GLOBALS->xhb_filepath);
                        GLOBALS->hbfile_is_new = FALSE;
                }
        else
        {
                DB( g_print(" + should quick save %s\n", GLOBALS->xhb_filepath) );
-               homebank_backup_current_file(GLOBALS->xhb_filepath);
-               homebank_file_ensure_xhb();
+               homebank_file_ensure_xhb(NULL);
+               homebank_backup_current_file();
                r = homebank_save_xml(GLOBALS->xhb_filepath);
        }
  
        }
        else
        {
-       gchar *msg = _("I/O error for file %s.");
+       gchar *msg = _("I/O error for file '%s'.");
  
                ui_dialog_msg_infoerror(GTK_WINDOW(data->window), GTK_MESSAGE_ERROR,
                        _("File error"),
@@@ -1780,7 -1879,7 +1907,7 @@@ gdouble gtbank, gttoday, gtfuture
                //#1339572
                if( !(acc->flags & (AF_CLOSED|AF_NOSUMMARY)) )
                {
-                       DB( g_print(" -> insert %d:%s\n", acc->key, acc->name) );
+                       DB( g_print(" - insert %d:%s\n", acc->key, acc->name) );
  
                        if(typeacc[acc->type] == NULL)
                                typeacc[acc->type] = g_ptr_array_sized_new(da_acc_length ());
  
        gtbank = gttoday = gtfuture = 0;
  
-       DB( g_print(" -> populate listview\n") );
+       DB( g_print(" - populate listview\n") );
  
  
        /* then populate the listview */
                {
                        nbtype++;
                        //1: Header: Bank, Cash, ...
-                       DB( g_print(" -> append type '%s'\n", CYA_ACC_TYPE[i]) );
+                       DB( g_print(" - append type '%s'\n", CYA_ACC_TYPE[i]) );
  
                        gtk_tree_store_append (GTK_TREE_STORE(model), &iter1, NULL);
                        gtk_tree_store_set (GTK_TREE_STORE(model), &iter1,
                        {
                                acc = g_ptr_array_index(gpa, j);
  
-                               //if(acc->kcur == GLOBALS->kcur)
-                               //{
-                                       tbank += acc->bal_bank;
-                                       ttoday += acc->bal_today;
-                                       tfuture += acc->bal_future;
-                               /*}
-                               else
-                               {
-                                       tbank += to_base_amount(acc->bal_bank, acc->kcur);
-                                       ttoday += to_base_amount(acc->bal_today, acc->kcur);
-                                       tfuture += to_base_amount(acc->bal_future, acc->kcur);
-                               }*/
+                               //tbank += acc->bal_bank;
+                               //ttoday += acc->bal_today;
+                               //tfuture += acc->bal_future;
+                               tbank += hb_amount_base(acc->bal_bank, acc->kcur);
+                               ttoday += hb_amount_base(acc->bal_today, acc->kcur);
+                               tfuture += hb_amount_base(acc->bal_future, acc->kcur);
  
                                DB( g_print(" - insert '%s' :: %.2f %.2f %.2f\n", acc->name, acc->bal_bank, acc->bal_today, acc->bal_future) );
  
  
        gtk_tree_view_expand_all(GTK_TREE_VIEW(data->LV_acc));
  
-       DB( g_print(" -> free ressources\n") );
+       DB( g_print(" - free ressources\n") );
  
  
        /* free all temp stuff */
@@@ -1933,11 -2026,11 +2054,11 @@@ gint flags
        gchar *basename;
        gchar *changed;
  
-               DB( printf(" +  1: wintitle %x\n", (gint)data->wintitle) );
+               DB( g_print(" +  1: wintitle %x\n", (gint)data->wintitle) );
  
                basename = g_path_get_basename(GLOBALS->xhb_filepath);
  
-               DB( printf(" global changes: %d\n", GLOBALS->changes_count) );
+               DB( g_print(" global changes: %d\n", GLOBALS->changes_count) );
  
                g_free(data->wintitle);
  
        GtkTreePath             *path;
        gboolean        active,sensitive;
  
-               DB( printf(" +  2: disabled, opelist count\n") );
+               DB( g_print(" +  2: disabled, opelist count\n") );
  
                selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_acc));
  
  
                        if( depth > 1 )
                        {
-                               DB( printf(" depth is %d\n", depth) );
+                               DB( g_print(" depth is %d\n", depth) );
  
                                gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, LST_DSPACC_DATAS, &acc, -1);
                                data->acc = acc;
  
  
                // no change: disable save
-               DB( printf(" changes %d - new %d\n", GLOBALS->changes_count, GLOBALS->hbfile_is_new) );
+               DB( g_print(" changes %d - new %d\n", GLOBALS->changes_count, GLOBALS->hbfile_is_new) );
  
  
                sensitive = (GLOBALS->changes_count != 0 ) ? TRUE : FALSE;
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Account"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Payee"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Category"), sensitive);
-               //gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Assign"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Budget"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/EditMenu/Preferences"), sensitive);
  
  
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/FileMenu/Close"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Archive"), sensitive);
-               gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TransactionMenu/AddOpe"), sensitive);
-               gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TransactionMenu/ShowOpe"), sensitive);
+               gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddOpe"), sensitive);
+               gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowOpe"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RStatistics"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RTrendTime"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RBudget"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RBalance"), sensitive);
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ReportMenu/RVehiculeCost"), sensitive);
  
-       // empty category list: disable Budget & Budget report
+       // empty category list: disable Budget
                sensitive = da_cat_length() > 1 ? TRUE : FALSE;
                gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Budget"), sensitive);
  
+               //#1501129 no need to disable, P & C can be created from assign dialog
+               //sensitive = ((da_cat_length() > 1) || (da_pay_length() > 1)) ? TRUE : FALSE;
+               //gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/ManageMenu/Assign"), sensitive);
        // empty archive list: disable scheduled check
                sensitive = g_list_length(GLOBALS->arc_list) > 0 ? TRUE : FALSE;
  
-               gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TransactionMenu/AddScheduled"), sensitive);
+               gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/AddScheduled"), sensitive);
  
        // no active account: disable Edit, Over
                sensitive = (active == TRUE ) ? TRUE : FALSE;
                if(data->acc && data->acc->window != NULL)
                        sensitive = FALSE;
  
-               gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TransactionMenu/ShowOpe"), sensitive);
+               gtk_action_set_sensitive(gtk_ui_manager_get_action(data->manager, "/MenuBar/TxnMenu/ShowOpe"), sensitive);
  
        }
  
        /* update toolbar, list */
        if(flags & UF_VISUAL)
        {
-               DB( printf(" +  8: visual\n") );
+               DB( g_print(" +  8: visual\n") );
  
                if(PREFS->toolbar_style == 0)
                        gtk_toolbar_unset_style(GTK_TOOLBAR(data->toolbar));
                else
                        gtk_toolbar_set_style(GTK_TOOLBAR(data->toolbar), PREFS->toolbar_style-1);
  
-               gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (data->LV_acc), PREFS->rules_hint);
+               gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (data->LV_acc), PREFS->grid_lines);
                gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc));
  
-               DB( printf(" - show toolbar=%d\n", PREFS->wal_toolbar) );
+               gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (data->LV_upc), PREFS->grid_lines);
+               gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_upc));
+               DB( g_print(" - show toolbar=%d\n", PREFS->wal_toolbar) );
                if(PREFS->wal_toolbar)
                        gtk_widget_show(GTK_WIDGET(data->toolbar));
                else
                        gtk_widget_hide(GTK_WIDGET(data->toolbar));
  
  
-               DB( printf(" - show top_spending=%d\n", PREFS->wal_spending) );
+               DB( g_print(" - show top_spending=%d\n", PREFS->wal_spending) );
  
                gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_range), PREFS->date_range_wal);
  
  
  
                
-               DB( printf(" - show upcoming=%d\n", PREFS->wal_upcoming) );
+               DB( g_print(" - show upcoming=%d\n", PREFS->wal_upcoming) );
                if(PREFS->wal_upcoming)
                        gtk_widget_show(GTK_WIDGET(data->GR_upc));
                else
                        gtk_widget_hide(GTK_WIDGET(data->GR_upc));
  
-               DB( printf(" minor %d\n", PREFS->euro_active) );
+               DB( g_print(" minor %d\n", PREFS->euro_active) );
                gtk_action_set_visible(gtk_ui_manager_get_action(data->manager, "/MenuBar/ViewMenu/AsMinor"), PREFS->euro_active);
        }
  
        if(flags & UF_BALANCE)
        {
  
-               DB( printf(" +  4: balances\n") );
+               DB( g_print(" +  4: balances\n") );
  
                gtk_tree_view_columns_autosize (GTK_TREE_VIEW(data->LV_acc));
  
  
        if(flags & UF_REFRESHALL)
        {
-               DB( printf(" +  8: refreshall\n") );
+               DB( g_print(" +  8: refreshall\n") );
  
                ui_mainwindow_populate_accounts(GLOBALS->mainwindow, NULL);
                ui_mainwindow_populate_topspending(GLOBALS->mainwindow, NULL);
@@@ -2157,9 -2255,6 +2283,9 @@@ struct hbfile_data *data = user_data
  struct WinGeometry *wg;
  gboolean retval = FALSE;
  
 +      GValue widget_value = G_VALUE_INIT;
 +      ext_hook("main_window_disposal", EXT_OBJECT(&widget_value, widget), NULL);
 +
        DB( g_print("\n[ui-mainwindow] dispose\n") );
  
        //store position and size
@@@ -2271,7 -2366,7 +2397,7 @@@ void ui_mainwindow_recent_add (struct h
  
        DB( g_print("\n[ui-mainwindow] recent_add\n") );
  
-       DB( g_print(" - suffix xhb %d", g_str_has_suffix (path, ".xhb") ) );
+       DB( g_print(" - file has .xhb suffix = %d\n", g_str_has_suffix (path, ".xhb") ) );
  
        if( g_str_has_suffix (path, ".xhb") == FALSE )  //ignore reverted file
                return;
@@@ -2328,7 -2423,7 +2454,7 @@@ static void ui_mainwindow_drag_data_rec
                        guint info, guint time, GtkWindow *window)
  {
        gchar **uris, **str;
-       gchar *data;
+       gchar *newseldata;
        gint filetype, slen;
  
        if (info != TARGET_URI_LIST)
  
        /* On MS-Windows, it looks like `selection_data->data' is not NULL terminated. */
        slen = gtk_selection_data_get_length(selection_data);
-       data = g_new (gchar, slen + 1);
-       memcpy (data, gtk_selection_data_get_data(selection_data), slen);
-       data[slen] = 0;
+       newseldata = g_new (gchar, slen + 1);
+       memcpy (newseldata, gtk_selection_data_get_data(selection_data), slen);
+       newseldata[slen] = 0;
  
-       uris = g_uri_list_extract_uris (data);
+       uris = g_uri_list_extract_uris (newseldata);
  
        str = uris;
        //for (str = uris; *str; str++)
  
                        if( filetype == FILETYPE_HOMEBANK)
                        {
-                               hbfile_change_filepath(path);
+                               hbfile_change_filepath(g_strdup(path));
                                ui_mainwindow_open_internal(GTK_WIDGET(window), NULL);
                        }
                        else
                g_free (path);
        }
        g_strfreev (uris);
+       
+       g_free(newseldata);
  }
  
  
@@@ -2401,7 -2498,7 +2529,7 @@@ GtkRecentFilter *filter
                                        GTK_RECENT_SORT_MRU);
        //todo: add a user pref for this
        gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER (toolbar_recent_menu),
-                                       5);
+                                       10);
  
  
        //gtk_recent_chooser_set_show_icons (GTK_RECENT_CHOOSER (toolbar_recent_menu), FALSE);
@@@ -2451,8 -2548,8 +2579,8 @@@ GError *error = NULL
        action = gtk_action_group_get_action(action_group, "Open");
        g_object_set(action, "short_label", _("Open"), NULL);
  
-       action = gtk_action_group_get_action(action_group, "Save");
-       g_object_set(action, "is_important", TRUE, NULL);
+       //action = gtk_action_group_get_action(action_group, "Save");
+       //g_object_set(action, "is_important", TRUE, NULL);
  
        action = gtk_action_group_get_action(action_group, "Account");
        g_object_set(action, "short_label", _("Account"), NULL);
                g_error_free (error);
        }
  
+       //todo: this generate a warning
        data->menubar = gtk_ui_manager_get_widget (manager, "/MenuBar");
        gtk_box_pack_start (GTK_BOX (mainvbox),
                            data->menubar,
  
        /* recent files menu */
  
        data->recent_manager = gtk_recent_manager_get_default ();
  
        data->recent_menu = ui_mainwindow_create_recent_chooser_menu (data->recent_manager);
        gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), data->recent_menu);
  */
  
-       /* testing */
-               /* add the custom Open button to the toolbar */
-       GtkToolItem *open_button = gtk_menu_tool_button_new_from_stock (GTK_STOCK_OPEN);
-       gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button),
-                                      data->recent_menu);
+       /* test */
+       /* add the custom Open button to the toolbar */
+       GtkWidget *image = gtk_image_new_from_icon_name (ICONNAME_OPEN, GTK_ICON_SIZE_BUTTON);
  
-       gtk_tool_item_set_tooltip_text (open_button, _("Open a file"));
-       gtk_menu_tool_button_set_arrow_tooltip_text (GTK_MENU_TOOL_BUTTON (open_button),
-                                                    _("Open a recently used file"));
+       GtkToolItem *open_button = gtk_menu_tool_button_new(image, _("_Open"));
+       gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (open_button), data->recent_menu);
  
+       gtk_tool_item_set_tooltip_text (open_button, _("Open a file"));
+       gtk_menu_tool_button_set_arrow_tooltip_text (GTK_MENU_TOOL_BUTTON (open_button), _("Open a recently used file"));
  
        action = gtk_action_group_get_action (data->actions, "Open");
-       g_object_set (action,
-                     "short_label", _("Open"),
-                     NULL);
+       g_object_set (action, "short_label", _("Open"), NULL);
        //gtk_action_connect_proxy (action, GTK_WIDGET (open_button));
        gtk_activatable_set_related_action (GTK_ACTIVATABLE (open_button), action);
  
-       gtk_toolbar_insert (GTK_TOOLBAR (data->toolbar),
-                           open_button,
-                           1);
-       /* end testing */
+       gtk_toolbar_insert (GTK_TOOLBAR (data->toolbar), open_button, 1);
+       /* end test */
  
  }
  
  static GtkWidget *ui_mainwindow_create_youraccounts(struct hbfile_data *data)
  {
- GtkWidget *mainvbox, *align, *label, *widget, *sw;
+ GtkWidget *mainvbox, *label, *widget, *sw;
  
-       mainvbox = gtk_vbox_new (FALSE, 0);
+       mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
  
-       label = make_label(_("Your accounts"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_misc_set_padding (GTK_MISC(label), HB_BOX_SPACING, HB_BOX_SPACING/2);
+       label = make_label_group(_("Your accounts"));
+       gtk_widget_set_margin_top(GTK_WIDGET(label), SPACING_SMALL/2);
+       gtk_widget_set_margin_bottom(GTK_WIDGET(label), SPACING_SMALL/2);
+       gtk_widget_set_margin_start(GTK_WIDGET(label), SPACING_SMALL);
+       gtk_widget_set_margin_end(GTK_WIDGET(label), SPACING_SMALL);
      gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
  
-       align = gtk_alignment_new(0, 0, 1.0, 1.0);
-       // top, bottom, left, right
-       gtk_alignment_set_padding (GTK_ALIGNMENT(align), 0, HB_BOX_SPACING, 2*HB_BOX_SPACING, HB_BOX_SPACING);
-       gtk_box_pack_start (GTK_BOX (mainvbox), align, TRUE, TRUE, 0);
        sw = gtk_scrolled_window_new (NULL, NULL);
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-       gtk_container_add (GTK_CONTAINER (align), sw);
-       
+       //gtk_widget_set_margin_top(GTK_WIDGET(sw), 0);
+       gtk_widget_set_margin_bottom(GTK_WIDGET(sw), SPACING_SMALL);
+       gtk_widget_set_margin_start(GTK_WIDGET(sw), 2*SPACING_SMALL);
+       gtk_widget_set_margin_end(GTK_WIDGET(sw), SPACING_SMALL);
+       gtk_box_pack_start (GTK_BOX (mainvbox), sw, TRUE, TRUE, 0);
        widget = (GtkWidget *)create_list_account();
        data->LV_acc = widget;
        gtk_container_add (GTK_CONTAINER (sw), widget);
  static GtkWidget *ui_mainwindow_create_topspending(struct hbfile_data *data)
  {
  GtkWidget *mainvbox, *hbox, *vbox;
- GtkWidget *label, *align, *widget;
+ GtkWidget *label, *widget;
  
-               mainvbox = gtk_vbox_new (FALSE, 0);
-               data->GR_top = mainvbox;
+       mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+       data->GR_top = mainvbox;
  
-               label = make_label(_("Where your money goes"), 0.0, 0.5);
-               gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-               gtk_misc_set_padding (GTK_MISC(label), HB_BOX_SPACING, HB_BOX_SPACING/2);
-           gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
+       label = make_label_group(_("Where your money goes"));
+       gtk_widget_set_margin_top(GTK_WIDGET(label), SPACING_SMALL/2);
+       gtk_widget_set_margin_bottom(GTK_WIDGET(label), SPACING_SMALL/2);
+       gtk_widget_set_margin_start(GTK_WIDGET(label), SPACING_SMALL);
+       gtk_widget_set_margin_end(GTK_WIDGET(label), SPACING_SMALL);
+     gtk_box_pack_start (GTK_BOX (mainvbox), label, FALSE, FALSE, 0);
  
-               align = gtk_alignment_new(0, 0, 1.0, 1.0);
-               // top, bottom, left, right
-               gtk_alignment_set_padding (GTK_ALIGNMENT(align), 0, HB_BOX_SPACING, 2*HB_BOX_SPACING, HB_BOX_SPACING);
-               gtk_box_pack_start (GTK_BOX (mainvbox), align, TRUE, TRUE, 0);
  
-               vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
-               gtk_container_add (GTK_CONTAINER (align), vbox);
-               
-               /* total + date range */
-               hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING);
-               gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-               
-               label = make_label(_("Top 5 spending"), 0.0, 0.5);
-               gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-               
-               label = make_label(NULL, 0.0, 0.5);
-               data->TX_topamount = label;
-               gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_SMALL);
+       //gtk_widget_set_margin_top(GTK_WIDGET(vbox), 0);
+       gtk_widget_set_margin_bottom(GTK_WIDGET(vbox), SPACING_SMALL);
+       gtk_widget_set_margin_start(GTK_WIDGET(vbox), 2*SPACING_SMALL);
+       gtk_widget_set_margin_end(GTK_WIDGET(vbox), SPACING_SMALL);
+       gtk_box_pack_start (GTK_BOX (mainvbox), vbox, TRUE, TRUE, 0);
+       
+       /* total + date range */
+       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
+       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
        
-               data->CY_range = make_daterange(label, FALSE);
-               gtk_box_pack_end (GTK_BOX (hbox), data->CY_range, FALSE, FALSE, 0);
+       label = make_label(_("Top spending"), 0.0, 0.5);
+       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+       
+       label = make_label(NULL, 0.0, 0.5);
+       data->TX_topamount = label;
+       gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
  
-               /* pie + listview */
-               hbox = gtk_hbox_new (FALSE, 0);
-               gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
+       data->CY_range = make_daterange(label, FALSE);
+       gtk_box_pack_end (GTK_BOX (hbox), data->CY_range, FALSE, FALSE, 0);
  
-               widget = gtk_chart_new(CHART_TYPE_PIE);
-               data->RE_pie = widget;
-               gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.symbol);
-               gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
+       widget = make_radio(CYA_CATSUBCAT, TRUE, GTK_ORIENTATION_HORIZONTAL);
+       data->RA_type = widget;
+       gtk_box_pack_end (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
  
- /*
-               sw = gtk_scrolled_window_new (NULL, NULL);
-               gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
-               gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-               gtk_box_pack_start (GTK_BOX (hbox), sw, FALSE, FALSE, 0);
-               */
-               
-               widget = (GtkWidget *)create_list_topspending();
-               data->LV_top = widget;
+       /* pie + listview */
+       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
  
-               gtk_chart_show_legend(GTK_CHART(data->RE_pie), TRUE, TRUE);
+       widget = gtk_chart_new(CHART_TYPE_PIE);
+       data->RE_pie = widget;
+       gtk_chart_set_minor_prefs(GTK_CHART(widget), PREFS->euro_value, PREFS->minor_cur.symbol);
+       gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
+ /*
+       sw = gtk_scrolled_window_new (NULL, NULL);
+       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
+       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+       gtk_box_pack_start (GTK_BOX (hbox), sw, FALSE, FALSE, 0);
+       */
        
+       widget = (GtkWidget *)create_list_topspending();
+       data->LV_top = widget;
+       gtk_chart_show_legend(GTK_CHART(data->RE_pie), TRUE, TRUE);
  //            gtk_container_add (GTK_CONTAINER (sw), widget);
  
        return mainvbox;
  
  static GtkWidget *ui_mainwindow_scheduled_create(struct hbfile_data *data)
  {
- GtkWidget *mainvbox, *hbox, *vbox, *sw, *tbar;
- GtkWidget *label, *image, *align, *widget;
+ GtkWidget *mainvbox, *hbox, *vbox, *bbox, *sw, *tbar;
+ GtkWidget *label, *widget;
  GtkToolItem *toolitem;
        
-       mainvbox = gtk_vbox_new (FALSE, 0);
+       mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
        data->GR_upc = mainvbox;
  
-       hbox = gtk_hbox_new (FALSE, HB_BOX_SPACING);
+       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
      gtk_box_pack_start (GTK_BOX (mainvbox), hbox, FALSE, FALSE, 0);
  
-       label = make_label(_("Scheduled transactions"), 0.0, 0.5);
-       //gtk_label_set_angle(GTK_LABEL(label), 90.0);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_misc_set_padding (GTK_MISC(label), HB_BOX_SPACING, HB_BOX_SPACING/2);
+       label = make_label_group(_("Scheduled transactions"));
+       gtk_widget_set_margin_top(GTK_WIDGET(label), SPACING_SMALL/2);
+       gtk_widget_set_margin_bottom(GTK_WIDGET(label), SPACING_SMALL/2);
+       gtk_widget_set_margin_start(GTK_WIDGET(label), SPACING_SMALL);
+       gtk_widget_set_margin_end(GTK_WIDGET(label), SPACING_SMALL);
      gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  
        label = make_label(_("maximum post date"), 0.0, 0.7);
        gimp_label_set_attributes (GTK_LABEL (label), PANGO_ATTR_SCALE, PANGO_SCALE_SMALL, -1);
      gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
        
-       align = gtk_alignment_new(0, 0, 1.0, 1.0);
-       // top, bottom, left, right
-       gtk_alignment_set_padding (GTK_ALIGNMENT(align), 0, HB_BOX_SPACING, 2*HB_BOX_SPACING, HB_BOX_SPACING);
-       gtk_box_pack_start (GTK_BOX (mainvbox), align, TRUE, TRUE, 0);
-       vbox = gtk_vbox_new (FALSE, 0);
-       gtk_container_add (GTK_CONTAINER (align), vbox);
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+       //gtk_widget_set_margin_top(GTK_WIDGET(vbox), 0);
+       gtk_widget_set_margin_bottom(GTK_WIDGET(vbox), SPACING_SMALL);
+       gtk_widget_set_margin_start(GTK_WIDGET(vbox), 2*SPACING_SMALL);
+       gtk_widget_set_margin_end(GTK_WIDGET(vbox), SPACING_SMALL);
+       gtk_box_pack_start (GTK_BOX (mainvbox), vbox, TRUE, TRUE, 0);
  
        sw = gtk_scrolled_window_new (NULL, NULL);
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
        tbar = gtk_toolbar_new();
        gtk_toolbar_set_icon_size (GTK_TOOLBAR(tbar), GTK_ICON_SIZE_MENU);
        gtk_toolbar_set_style(GTK_TOOLBAR(tbar), GTK_TOOLBAR_ICONS);
+       gtk_style_context_add_class (gtk_widget_get_style_context (tbar), GTK_STYLE_CLASS_INLINE_TOOLBAR);
        gtk_box_pack_start (GTK_BOX (vbox), tbar, FALSE, FALSE, 0);
  
-       /*widget = gtk_tool_item_new ();
-       label = gtk_label_new("test");
-       gtk_container_add(GTK_CONTAINER(widget), label);
-       gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(widget), -1);*/
-       
-       image = gtk_image_new_from_icon_name ("media-skip-forward", GTK_ICON_SIZE_MENU);
+       bbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
+       toolitem = gtk_tool_item_new();
+       gtk_container_add (GTK_CONTAINER(toolitem), bbox);
+       gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
+       widget = gtk_button_new_with_label(_("Skip"));
+       data->BT_sched_skip = widget;
+       gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0);
+       widget = gtk_button_new_with_label(_("Edit & Post"));
+       data->BT_sched_editpost = widget;
+       gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0);
+       //TRANSLATORS: Posting a scheduled transaction is the action to materialize it into its target account.
+       //TRANSLATORS: Before that action the automated transaction occurrence is pending and not yet really existing.
+       widget = gtk_button_new_with_label (_("Post"));
+       data->BT_sched_post = widget;
+       gtk_box_pack_start (GTK_BOX (bbox), widget, FALSE, FALSE, 0);
+ /*    image = gtk_image_new_from_icon_name (ICONNAME_HB_SCHED_SKIP, GTK_ICON_SIZE_MENU);
        toolitem = gtk_tool_button_new(image, NULL);
        data->BT_sched_skip = toolitem;
        gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
        gtk_widget_set_tooltip_text(GTK_WIDGET(toolitem), _("Skip"));
  
-       image = gtk_image_new_from_icon_name ("media-playback-start", GTK_ICON_SIZE_MENU);
+       image = gtk_image_new_from_icon_name (ICONNAME_HB_SCHED_POST, GTK_ICON_SIZE_MENU);
        toolitem = gtk_tool_button_new(image, NULL);
        data->BT_sched_post = toolitem;
        gtk_toolbar_insert(GTK_TOOLBAR(tbar), GTK_TOOL_ITEM(toolitem), -1);
        gtk_widget_set_tooltip_text(GTK_WIDGET(toolitem), _("Post"));
+ */
  
        
        return mainvbox;
@@@ -2743,19 -2856,7 +2887,7 @@@ GtkAction *action
        data->window = window;
        GLOBALS->mainwindow = window;
  
-       //setup, init and show window
-       wg = &PREFS->wal_wg;
-       if(wg->s == 0)
-       {
-               gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
-               gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
-       }
-       else
-               gtk_window_maximize(GTK_WINDOW(window));
-       gtk_widget_show (window);
-       mainvbox = gtk_vbox_new (FALSE, 0);
+       mainvbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
        gtk_container_add (GTK_CONTAINER (window), mainvbox);
  
        ui_mainwindow_create_menu_bar_and_toolbar (data, mainvbox);
@@@ -2772,15 -2873,15 +2904,15 @@@ GtkWidget *bar, *label
  #endif
        
        /* Add the main area */
-       vbox = gtk_vbox_new (FALSE, 0);
-     //gtk_container_set_border_width (GTK_CONTAINER(vbox), HB_MAINBOX_SPACING);
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+     //gtk_container_set_border_width (GTK_CONTAINER(vbox), SPACING_MEDIUM);
      gtk_box_pack_start (GTK_BOX (mainvbox), vbox, TRUE, TRUE, 0);
  
-       vpaned = gtk_vpaned_new();
+       vpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
        data->vpaned = vpaned;
      gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
  
-               hpaned = gtk_hpaned_new();
+               hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
                data->hpaned = hpaned;
                gtk_paned_pack1 (GTK_PANED(vpaned), hpaned, FALSE, FALSE);
  
        if(PREFS->wal_vpaned > 0)
                gtk_paned_set_position(GTK_PANED(data->vpaned), PREFS->wal_vpaned);
  
+       //setup, init and show window
+       wg = &PREFS->wal_wg;
+       if(wg->s == 0)
+       {
+               gtk_window_move(GTK_WINDOW(window), wg->l, wg->t);
+               gtk_window_resize(GTK_WINDOW(window), wg->w, wg->h);
+       }
+       else
+               gtk_window_maximize(GTK_WINDOW(window));
        gtk_widget_show_all (window);
        
        //todo: move this elsewhere
        g_signal_connect (GTK_TREE_VIEW(data->LV_acc), "row-activated", G_CALLBACK (ui_mainwindow_onRowActivated), GINT_TO_POINTER(2));
  
        g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data->LV_upc)), "changed", G_CALLBACK (ui_mainwindow_scheduled_selection_cb), NULL);
-       g_signal_connect (G_OBJECT (data->BT_sched_post), "clicked", G_CALLBACK (ui_mainwindow_scheduled_post_cb), data);
+       g_signal_connect (GTK_TREE_VIEW(data->LV_upc), "row-activated", G_CALLBACK (ui_mainwindow_scheduled_onRowActivated), NULL);
        g_signal_connect (G_OBJECT (data->BT_sched_skip), "clicked", G_CALLBACK (ui_mainwindow_scheduled_skip_cb), data);
+       g_signal_connect (G_OBJECT (data->BT_sched_editpost), "clicked", G_CALLBACK (ui_mainwindow_scheduled_editpost_cb), data);
+       g_signal_connect (G_OBJECT (data->BT_sched_post), "clicked", G_CALLBACK (ui_mainwindow_scheduled_post_cb), data);
        
+       widget = radio_get_nth_widget(GTK_CONTAINER(data->RA_type), 1);
+       if(widget)
+               g_signal_connect (widget, "toggled", G_CALLBACK (ui_mainwindow_populate_topspending), &data);
        g_signal_connect (data->CY_range, "changed", G_CALLBACK (ui_mainwindow_populate_topspending), NULL);
  
  
  
        //gtk_action_group_set_sensitive(data->actions, FALSE);
  
        
-   return window;
+       return window;
  }
  
diff --combined src/ext-perl.xs
index 80020473e87e9c00516c8fbc0131e29a4097f02d,0000000000000000000000000000000000000000..5aa56b01df5480491909eb647b4d6ae6b48696b5
mode 100644,000000..100644
--- /dev/null
@@@ -1,1042 -1,0 +1,1043 @@@
-               GList* list = g_list_first(GLOBALS->ope_list);
-               for (; list; list = g_list_next(list)) {
-                       GValue val = G_VALUE_INIT;
-                       SV* sv = val_to_sv(EXT_TRANSACTION(&val, list->data));
-                       mXPUSHs(sv);
 +
 +#include <EXTERN.h>
 +#include <perl.h>
 +#include <XSUB.h>
 +
 +#include <string.h>
 +
 +#undef _
 +#include "homebank.h"
 +#include "ext.h"
 +#include "refcount.h"
 +
 +extern struct HomeBank *GLOBALS;
 +#include "dsp_mainwindow.h"
 +#include "dsp_account.h"
 +#include "ui-transaction.h"
 +
 +
 +static gint ext_perl_init(int* argc, char** argv[], char** env[]);
 +static void ext_perl_term(void);
 +static gboolean ext_perl_check_file(const gchar* plugin_filepath);
 +static GHashTable* ext_perl_read_plugin_metadata(const gchar* plugin_filepath);
 +static gint ext_perl_load_plugin(const gchar* plugin_filepath);
 +static void ext_perl_unload_plugin(const gchar* plugin_filepath);
 +static void ext_perl_execute_action(const gchar* plugin_filepath);
 +static void ext_perl_call_hook(const gchar* hook_id, GList* args);
 +
 +static SV* val_to_sv(GValue* val);
 +static GValue* sv_to_val(SV* sv);
 +
 +static gboolean gperl_value_from_sv(GValue* value, SV* sv);
 +static SV*      gperl_sv_from_value(const GValue* value, gboolean copy_boxed);
 +
 +
 +static inline GValue* EXT_SV(GValue* v, SV* sv, GType type)
 +{
 +      g_value_init(v, type);
 +      gperl_value_from_sv(v, sv);
 +      return v;
 +}
 +
 +
 +#define EXT_P2C_OBJECT(PKG, ARG, VAR, TYP)  \
 +if (sv_derived_from(ARG, PKG)) {            \
 +    IV iv = SvIV((SV*)SvRV(ARG));           \
 +    VAR = INT2PTR(TYP, iv);                 \
 +} else {                                    \
 +    croak(#VAR" is not of type "PKG);       \
 +}
 +
 +#define EXT_C2P_OBJECT(PKG, ARG, VAR)       \
 +sv_setref_pv(ARG, PKG, (void*)VAR)
 +
 +
 +static inline GPtrArray* SvGptrarray(const SV* sv)
 +{
 +      if (SvROK(sv)) {
 +              sv = MUTABLE_SV(SvRV(sv));
 +      }
 +      if (SvTYPE(sv) == SVt_PVAV) {
 +              AV* av = (AV*)sv;
 +              int i;
 +              int top = av_len(av);
 +              GPtrArray* array = g_ptr_array_new();
 +              for (i = 0; i <= top; ++i) {
 +                      SV** item = av_fetch(av, i, 0);
 +                      if (!item) continue;
 +                      g_ptr_array_add(array, sv_to_val(*item));
 +              }
 +              return array;
 +              // TODO- leaking
 +      } else {
 +              croak("var is not an array");
 +      }
 +}
 +
 +static inline SV* newSVgptrarray(const GPtrArray* a)
 +{
 +      if (a) {
 +              AV* av = newAV();
 +              int i;
 +              for (i = 0; i < a->len; ++i) {
 +                      GValue* item = g_ptr_array_index(a, i);
 +                      av_push(av, val_to_sv(item));
 +              }
 +              return newRV((SV*)av);
 +      }
 +      return &PL_sv_undef;
 +}
 +
 +
 +static inline GHashTable* SvGhashtable(const SV* sv)
 +{
 +      if (SvROK(sv)) {
 +              sv = MUTABLE_SV(SvRV(sv));
 +      }
 +      if (SvTYPE(sv) == SVt_PVHV) {
 +              HV* hv = (HV*)sv;
 +              hv_iterinit(hv);
 +              gchar* key;
 +              I32 len;
 +              SV* item;
 +              GHashTable* hash = g_hash_table_new(g_str_hash, g_str_equal);
 +              while ((item = hv_iternextsv(hv, &key, &len))) {
 +                      g_hash_table_insert(hash, key, sv_to_val(item));
 +              }
 +              return hash;
 +              // TODO- leaking
 +      } else {
 +              croak("var is not a hash");
 +      }
 +}
 +
 +static inline SV* newSVghashtable(GHashTable* h)
 +{
 +      if (h) {
 +              HV* hv = newHV();
 +              GHashTableIter it;
 +              g_hash_table_iter_init(&it, h);
 +              gchar* key = NULL;
 +              GValue* item = NULL;
 +              while (g_hash_table_iter_next(&it, (gpointer*)&key, (gpointer*)&item)) {
 +                      hv_store(hv, key, -g_utf8_strlen(key, -1), val_to_sv(item), 0);
 +              }
 +              return newRV((SV*)hv);
 +      }
 +      return &PL_sv_undef;
 +}
 +
 +
 +static inline gboolean SvGboolean(SV* sv)
 +{
 +      if (!sv) {
 +              return FALSE;
 +      }
 +      if (SvROK(sv)) {
 +              return !!SvIV(SvRV(sv));
 +      } else {
 +              return SvTRUE(sv);
 +      }
 +}
 +
 +static inline SV* newSVgboolean(gboolean b)
 +{
 +      return sv_setref_iv(newSV(0), "HomeBank::Boolean", !!b);
 +}
 +
 +
 +static inline gchar* SvGchar_ptr(SV* sv)
 +{
 +      return SvPVutf8_nolen(sv);
 +}
 +
 +static inline SV* newSVgchar_ptr(const gchar* str)
 +{
 +      if (!str) return &PL_sv_undef;
 +
 +      SV* sv = newSVpv(str, 0);
 +      SvUTF8_on(sv);
 +      return sv;
 +}
 +
 +
 +static inline GObject* SvGobject(const SV* sv)
 +{
 +      GObject* (*func)(const SV*) = ext_symbol_lookup("gperl_get_object");
 +      if (func) {
 +              return func(sv);
 +      }
 +      return NULL;
 +}
 +
 +static inline SV* newSVgobject(const GObject* o)
 +{
 +    SV* (*func)(const GObject*, gboolean) = ext_symbol_lookup("gperl_new_object");
 +    if (func) {
 +        return func(o, FALSE);
 +    }
 +      return &PL_sv_undef;
 +}
 +
 +
 +static PerlInterpreter* context = NULL;
 +
 +
 +static gint ext_perl_init(int* argc, char** argv[], char** env[])
 +{
 +      int ret = 0;
 +
 +      PERL_SYS_INIT3(argc, argv, env);
 +      context = perl_alloc();
 +      perl_construct(context);
 +
 +      PL_exit_flags |= PERL_EXIT_DESTRUCT_END;
 +      PL_origalen = 1;
 +      PL_perl_destruct_level = 1;
 +
 +      gchar* bootstrap = g_strdup_printf("-e"
 +              "use lib '%s';"
 +              "use HomeBank;"
 +              "HomeBank->bootstrap;",
 +              homebank_app_get_pkglib_dir());
 +      char *args[] = { "", bootstrap };
 +
 +      EXTERN_C void xs_init(pTHX);
 +      if (perl_parse(context, xs_init, 2, args, NULL) || perl_run(context)) {
 +              ext_perl_term();
 +              ret = -1;
 +      }
 +
 +      g_free(bootstrap);
 +      return ret;
 +}
 +
 +static void ext_perl_term(void)
 +{
 +      if (context) {
 +              perl_destruct(context);
 +              perl_free(context);
 +              context = NULL;
 +      }
 +      PERL_SYS_TERM();
 +}
 +
 +static gboolean ext_perl_check_file(const gchar* plugin_filepath)
 +{
 +      if (g_str_has_suffix(plugin_filepath, ".pl")) {
 +              return TRUE;
 +      }
 +      return FALSE;
 +}
 +
 +static GHashTable* ext_perl_read_plugin_metadata(const gchar* plugin_filepath)
 +{
 +      GHashTable* table = NULL;
 +
 +      if (!context) return NULL;
 +      PERL_SET_CONTEXT(context);
 +
 +      dSP;
 +      ENTER;
 +      SAVETMPS;
 +      PUSHMARK(SP);
 +      mXPUSHs(newSVgchar_ptr(plugin_filepath));
 +      PUTBACK;
 +
 +      int ret = call_pv("HomeBank::read_metadata", G_SCALAR | G_EVAL);
 +
 +      SPAGAIN;
 +
 +      if (ret == 1) {
 +              table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 +              SV* sv = POPs;
 +              if (SvROK(sv)) {
 +                      sv = MUTABLE_SV(SvRV(sv));
 +              }
 +              if (SvTYPE(sv) == SVt_PVHV) {
 +                      HV* hv = (HV*)sv;
 +                      hv_iterinit(hv);
 +                      gchar* key;
 +                      I32 len;
 +                      SV* item;
 +                      while ((item = hv_iternextsv(hv, &key, &len))) {
 +                              if (SvPOK(item)) {
 +                                      gchar* val = SvPVutf8_nolen(item);
 +                                      g_hash_table_insert(table, g_strdup(key), g_strdup(val));
 +                              }
 +                      }
 +              }
 +      }
 +
 +      PUTBACK;
 +      FREETMPS;
 +      LEAVE;
 +
 +      return table;
 +}
 +
 +static gint ext_perl_load_plugin(const gchar* plugin_filepath)
 +{
 +      if (!context) return -1;
 +      PERL_SET_CONTEXT(context);
 +
 +      dSP;
 +      ENTER;
 +      SAVETMPS;
 +      PUSHMARK(SP);
 +      mXPUSHs(newSVgchar_ptr(plugin_filepath));
 +      PUTBACK;
 +      call_pv("HomeBank::load_plugin", G_DISCARD | G_EVAL);
 +      SPAGAIN;
 +
 +      gint ret = 0;
 +      if (SvTRUE(ERRSV)) {
 +              g_printerr("%s", SvPV_nolen(ERRSV));
 +              ret = -1;
 +      }
 +
 +      PUTBACK;
 +      FREETMPS;
 +      LEAVE;
 +
 +      return ret;
 +}
 +
 +static void ext_perl_unload_plugin(const gchar* plugin_filepath)
 +{
 +      if (!context) return;
 +      PERL_SET_CONTEXT(context);
 +
 +      dSP;
 +      ENTER;
 +      SAVETMPS;
 +      PUSHMARK(SP);
 +      mXPUSHs(newSVgchar_ptr(plugin_filepath));
 +      PUTBACK;
 +      call_pv("HomeBank::unload_plugin", G_DISCARD | G_EVAL);
 +      SPAGAIN;
 +
 +      if (SvTRUE(ERRSV)) {
 +              g_printerr("%s", SvPV_nolen(ERRSV));
 +      }
 +
 +      PUTBACK;
 +      FREETMPS;
 +      LEAVE;
 +}
 +
 +static void ext_perl_execute_action(const gchar* plugin_filepath)
 +{
 +      if (!context) return;
 +      PERL_SET_CONTEXT(context);
 +
 +      dSP;
 +      ENTER;
 +      SAVETMPS;
 +      PUSHMARK(SP);
 +      mXPUSHs(newSVgchar_ptr(plugin_filepath));
 +      PUTBACK;
 +      call_pv("HomeBank::execute_action", G_DISCARD | G_EVAL);
 +      SPAGAIN;
 +
 +      if (SvTRUE(ERRSV)) {
 +              g_printerr("%s", SvPV_nolen(ERRSV));
 +      }
 +
 +      PUTBACK;
 +      FREETMPS;
 +      LEAVE;
 +}
 +
 +static void ext_perl_call_hook(const gchar* hook_id, GList* args)
 +{
 +      if (!context) return;
 +      PERL_SET_CONTEXT(context);
 +
 +      dSP;
 +      ENTER;
 +      SAVETMPS;
 +      PUSHMARK(SP);
 +      mXPUSHs(newSVgchar_ptr(hook_id));
 +
 +      GList *list = g_list_first(args);
 +      while (list) {
 +              GValue* val = list->data;
 +              XPUSHs(sv_2mortal(val_to_sv(val)));
 +              list = g_list_next(list);
 +      }
 +
 +      PUTBACK;
 +      call_pv("HomeBank::call_hook", G_ARRAY);
 +      SPAGAIN;
 +      POPi;
 +      PUTBACK;
 +      FREETMPS;
 +      LEAVE;
 +}
 +
 +
 +static SV* val_to_sv(GValue* val)
 +{
 +      if (!val || !G_IS_VALUE(val) || G_VALUE_TYPE(val) == G_TYPE_NONE) {
 +              return &PL_sv_undef;
 +      }
 +      if (G_VALUE_TYPE(val) == G_TYPE_BOOLEAN) {
 +              return newSVgboolean(g_value_get_boolean(val));
 +      }
 +      if (G_VALUE_TYPE(val) == G_TYPE_PTR_ARRAY) {
 +              return newSVgptrarray((GPtrArray*)g_value_get_boxed(val));
 +      }
 +      if (G_VALUE_TYPE(val) == G_TYPE_HASH_TABLE) {
 +              return newSVghashtable((GHashTable*)g_value_get_boxed(val));
 +      }
 +#define obj(CTYPE, _2, PART, GTYPE, _5)                         \
 +      if (G_VALUE_TYPE(val) == GTYPE) {                           \
 +              SV* sv = newSV(0);                                      \
 +              CTYPE* ptr = (CTYPE*)g_value_get_##PART(val);           \
 +              EXT_C2P_OBJECT("HomeBank::"#CTYPE, sv, rc_ref(ptr));    \
 +              return sv;                                              \
 +      }
 +#include "ext-value.h"
 +#undef obj
 +      return gperl_sv_from_value(val, FALSE);
 +}
 +
 +static GValue* sv_to_val(SV* sv)
 +{
 +      GValue* val = g_new0(GValue, 1);
 +
 +      if (SvUOK(sv)) return EXT_SV(val, sv, G_TYPE_UINT);
 +      if (SvIOK(sv)) return EXT_SV(val, sv, G_TYPE_INT);
 +      if (SvNOK(sv)) return EXT_SV(val, sv, G_TYPE_DOUBLE);
 +      if (SvPOK(sv)) return EXT_SV(val, sv, G_TYPE_STRING);
 +      if (sv_isobject(sv)) {
 +              if (sv_derived_from(sv, "HomeBank::Boolean")) {
 +                      return EXT_BOOLEAN(val, SvGboolean(sv));
 +              }
 +#define obj(CTYPE, NAME, _3, _4, _5)                                \
 +              if (sv_derived_from(sv, "HomeBank::"#CTYPE)) {              \
 +                      CTYPE* ptr;                                             \
 +                      EXT_P2C_OBJECT("HomeBank::"#CTYPE, sv, ptr, CTYPE*);    \
 +                      return EXT_##NAME(val, ptr);                            \
 +              }
 +#include "ext-value.h"
 +#undef obj
 +              return EXT_SV(val, sv, G_TYPE_OBJECT);
 +      }
 +      if (SvROK(sv)) {
 +              sv = SvRV(sv);
 +              switch (SvTYPE(sv)) {
 +                      case SVt_IV:
 +                              return EXT_BOOLEAN(val, SvGboolean(sv));
 +                      case SVt_PVAV:
 +                              return EXT_ARRAY(val, SvGptrarray(sv));
 +                      case SVt_PVHV:
 +                              return EXT_HASH_TABLE(val, SvGhashtable(sv));
 +                      default:
 +                              break;
 +              }
 +      }
 +      switch (SvTYPE(sv)) {
 +              case SVt_PVAV:
 +                      return EXT_ARRAY(val, SvGptrarray(sv));
 +              case SVt_PVHV:
 +                      return EXT_HASH_TABLE(val, SvGhashtable(sv));
 +              default:
 +                      break;
 +      }
 +
 +      g_free(val);
 +      return NULL;
 +}
 +
 +
 +static gboolean gperl_value_from_sv(GValue* value, SV* sv)
 +{
 +      gboolean (*func)(GValue*, SV*) = ext_symbol_lookup("gperl_value_from_sv");
 +      if (func) return func(value, sv);
 +
 +      GType type = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value));
 +      if (!SvOK(sv)) return TRUE;
 +      switch (type) {
 +              case G_TYPE_CHAR:
 +              {
 +                      gchar *tmp = SvGchar_ptr(sv);
 +                      g_value_set_schar(value, (gint8)(tmp ? tmp[0] : 0));
 +                      break;
 +              }
 +              case G_TYPE_UCHAR:
 +              {
 +                      char *tmp = SvPV_nolen(sv);
 +                      g_value_set_uchar(value, (guchar)(tmp ? tmp[0] : 0));
 +                      break;
 +              }
 +              case G_TYPE_BOOLEAN:
 +                      g_value_set_boolean(value, SvTRUE(sv));
 +                      break;
 +              case G_TYPE_INT:
 +                      g_value_set_int(value, SvIV(sv));
 +                      break;
 +              case G_TYPE_UINT:
 +                      g_value_set_uint(value, SvIV(sv));
 +                      break;
 +              case G_TYPE_LONG:
 +                      g_value_set_long(value, SvIV(sv));
 +                      break;
 +              case G_TYPE_ULONG:
 +                      g_value_set_ulong(value, SvIV(sv));
 +                      break;
 +              case G_TYPE_FLOAT:
 +                      g_value_set_float(value, (gfloat)SvNV(sv));
 +                      break;
 +              case G_TYPE_DOUBLE:
 +                      g_value_set_double(value, SvNV(sv));
 +                      break;
 +              case G_TYPE_STRING:
 +                      g_value_set_string(value, SvGchar_ptr(sv));
 +                      break;
 +      }
 +      return TRUE;
 +}
 +
 +static SV* gperl_sv_from_value(const GValue* value, gboolean copy_boxed)
 +{
 +      SV* (*func)(const GValue*, gboolean) = ext_symbol_lookup("gperl_sv_from_value");
 +      if (func) return func(value, copy_boxed);
 +
 +      GType type = G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value));
 +      switch (type) {
 +              case G_TYPE_CHAR:
 +                      return newSViv(g_value_get_schar(value));
 +              case G_TYPE_UCHAR:
 +                      return newSVuv(g_value_get_uchar(value));
 +              case G_TYPE_BOOLEAN:
 +                      return newSViv(g_value_get_boolean(value));
 +              case G_TYPE_INT:
 +                      return newSViv(g_value_get_int(value));
 +              case G_TYPE_UINT:
 +                      return newSVuv(g_value_get_uint(value));
 +              case G_TYPE_LONG:
 +                      return newSViv(g_value_get_long(value));
 +              case G_TYPE_ULONG:
 +                      return newSVuv(g_value_get_ulong(value));
 +              case G_TYPE_FLOAT:
 +                      return newSVnv(g_value_get_float(value));
 +              case G_TYPE_DOUBLE:
 +                      return newSVnv(g_value_get_double(value));
 +              case G_TYPE_STRING:
 +                      return newSVgchar_ptr(g_value_get_string(value));
 +      }
 +      return &PL_sv_undef;
 +}
 +
 +
 +static void _register(void) __attribute__((constructor));
 +static void _register()
 +{
 +      ext_register("perl",
 +                      ext_perl_init,
 +                      ext_perl_term,
 +                      ext_perl_check_file,
 +                      ext_perl_read_plugin_metadata,
 +                      ext_perl_load_plugin,
 +                      ext_perl_unload_plugin,
 +                      ext_perl_execute_action,
 +                      ext_perl_call_hook);
 +}
 +
 +
 +MODULE = HomeBank  PACKAGE = HomeBank
 +
 +PROTOTYPES: ENABLE
 +
 +const gchar*
 +version(void)
 +      CODE:
 +              RETVAL = VERSION;
 +      OUTPUT:
 +              RETVAL
 +
 +const gchar*
 +config_dir(void)
 +      CODE:
 +              RETVAL = homebank_app_get_config_dir();
 +      OUTPUT:
 +              RETVAL
 +
 +gboolean
 +has(const gchar* CLASS, ...)
 +      PREINIT:
 +              int i;
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              RETVAL = TRUE;
 +              for (i = 1; i < items; ++i) {
 +                      gchar* feature = SvGchar_ptr(ST(i));
 +                      if (!feature || !ext_has(feature)) {
 +                              RETVAL = FALSE;
 +                              break;
 +                      }
 +              }
 +      OUTPUT:
 +              RETVAL
 +
 +GObject*
 +main_window(void)
 +      CODE:
 +              RETVAL = G_OBJECT(GLOBALS->mainwindow);
 +      OUTPUT:
 +              RETVAL
 +
 +GObject*
 +main_ui_manager(void)
 +      PREINIT:
 +              struct hbfile_data *data;
 +      CODE:
 +              RETVAL = NULL;
 +              if (GLOBALS->mainwindow) {
 +                      data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(GLOBALS->mainwindow, GTK_TYPE_WINDOW)), "inst_data");
 +                      if (data) {
 +                              RETVAL = G_OBJECT(data->manager);
 +                      }
 +              }
 +      OUTPUT:
 +              RETVAL
 +
 +void
 +info(const gchar* CLASS, const gchar* title, const gchar* text)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              ext_run_modal(title, text, "info");
 +
 +void
 +warn(const gchar* CLASS, const gchar* title, const gchar* text)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              ext_run_modal(title, text, "warn");
 +
 +void
 +error(const gchar* CLASS, const gchar* title, const gchar* text)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              ext_run_modal(title, text, "error");
 +
 +void
 +hook(const gchar* CLASS, const gchar* hook_name, ...)
 +      PREINIT:
 +              int i;
 +              GList* list = NULL;
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              for (i = 2; i < items; ++i) {
 +                      SV* sv = ST(i);
 +                      GValue *val = sv_to_val(sv);
 +                      list = g_list_append(list, val);
 +              }
 +      CLEANUP:
 +              ext_vhook(hook_name, list);
 +              g_list_free(list);
 +              // TODO free all the things
 +
 +GObject*
 +open_prefs(const gchar* CLASS)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              RETVAL = G_OBJECT(defpref_dialog_new(PREF_GENERAL));
 +      OUTPUT:
 +              RETVAL
 +
 +
 +MODULE = HomeBank  PACKAGE = HomeBank::File
 +
 +const gchar*
 +owner(const gchar* CLASS, ...)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              if (1 < items) {
 +                      hbfile_change_owner(g_strdup(SvGchar_ptr(ST(1))));
 +              }
 +              RETVAL = GLOBALS->owner;
 +      OUTPUT:
 +              RETVAL
 +
 +void
 +transactions(const gchar* CLASS)
 +      PPCODE:
 +              PERL_UNUSED_ARG(CLASS);
- Account*
- clone(Account* SELF)
-       CODE:
-               RETVAL = da_acc_clone(SELF);
-               RETVAL->key = 0;
-       OUTPUT:
-               RETVAL
++
++              GList* acc_list = g_hash_table_get_values(GLOBALS->h_acc);
++              GList* acc_link = g_list_first(acc_list);
++              for (; acc_link; acc_link = g_list_next(acc_link)) {
++                      Account *acc = acc_link->data;
++
++                      GList* txn_link = g_queue_peek_head_link(acc->txn_queue);
++                      for (; txn_link; txn_link = g_list_next(txn_link)) {
++                              Transaction* txn = txn_link->data;
++
++                              GValue val = G_VALUE_INIT;
++                              SV* sv = val_to_sv(EXT_TRANSACTION(&val, txn));
++                              mXPUSHs(sv);
++                      }
 +              }
 +
++              g_list_free(acc_list);
++
 +void
 +anonymize(void)
 +      CODE:
 +              hbfile_anonymize();
 +
 +void
 +baz(const gchar* CLASS, Account* account)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              g_print("hello: %s\n", account->name);
 +
 +GPtrArray*
 +meh(const gchar* CLASS, GPtrArray* asdf)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              g_print("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW\n");
 +              if (asdf) {
 +                      ;
 +              } else {
 +                      g_print("the array is nil\n");
 +              }
 +              RETVAL = asdf;
 +      OUTPUT:
 +              RETVAL
 +      CLEANUP:
 +              g_ptr_array_unref(asdf);
 +
 +GHashTable*
 +foo(const gchar* CLASS, GHashTable* asdf)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              g_print("WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW\n");
 +              if (asdf) {
 +                      GHashTableIter it;
 +                      g_hash_table_iter_init(&it, asdf);
 +                      gchar* key = NULL;
 +                      GValue* item = NULL;
 +                      while (g_hash_table_iter_next(&it, (gpointer*)&key, (gpointer*)&item)) {
 +                              g_print("hash with key: %s\n", key);
 +                      }
 +              } else {
 +                      g_print("the hash is nil\n");
 +              }
 +              RETVAL = asdf;
 +      OUTPUT:
 +              RETVAL
 +      CLEANUP:
 +              g_hash_table_unref(asdf);
 +
 +
 +MODULE = HomeBank  PACKAGE = HomeBank::Account
 +
 +void
 +compute_balances(const gchar* CLASS)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              account_compute_balances();
 +
 +Account*
 +new(void)
 +      CODE:
 +              RETVAL = da_acc_malloc();
 +      OUTPUT:
 +              RETVAL
 +
-               GList* list = g_list_first(GLOBALS->ope_list);
 +void
 +DESTROY(Account* SELF)
 +      CODE:
 +              da_acc_free(SELF);
 +
 +Account*
 +get(const gchar* CLASS, guint key)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              RETVAL = rc_ref(da_acc_get(key));
 +      OUTPUT:
 +              RETVAL
 +
 +Account*
 +get_by_name(const gchar* CLASS, const gchar* name)
 +      CODE:
 +              PERL_UNUSED_ARG(CLASS);
 +              RETVAL = rc_ref(da_acc_get_by_name((gchar*)name));
 +      OUTPUT:
 +              RETVAL
 +
 +const gchar*
 +name(Account* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      account_rename(SELF, SvGchar_ptr(ST(1)));
 +              }
 +              RETVAL = SELF->name;
 +      OUTPUT:
 +              RETVAL
 +
 +const gchar*
 +number(Account* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      g_free(SELF->number);
 +                      SELF->number = g_strdup(SvGchar_ptr(ST(1)));
 +              }
 +              RETVAL = SELF->number;
 +      OUTPUT:
 +              RETVAL
 +
 +const gchar*
 +bankname(Account* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      g_free(SELF->bankname);
 +                      SELF->bankname = g_strdup(SvGchar_ptr(ST(1)));
 +              }
 +              RETVAL = SELF->bankname;
 +      OUTPUT:
 +              RETVAL
 +
 +gdouble
 +initial(Account* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      SELF->initial = SvNV(ST(1));
 +              }
 +              RETVAL = SELF->initial;
 +      OUTPUT:
 +              RETVAL
 +
 +gdouble
 +minimum(Account* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      SELF->minimum = SvNV(ST(1));
 +              }
 +              RETVAL = SELF->minimum;
 +      OUTPUT:
 +              RETVAL
 +
 +guint
 +cheque1(Account* SELF, ...)
 +      ALIAS:
 +              check1 = 1
 +      CODE:
 +              PERL_UNUSED_VAR(ix);
 +              if (1 < items) {
 +                      SELF->cheque1 = SvUV(ST(1));
 +              }
 +              RETVAL = SELF->cheque1;
 +      OUTPUT:
 +              RETVAL
 +
 +guint
 +cheque2(Account* SELF, ...)
 +      ALIAS:
 +              check2 = 1
 +      CODE:
 +              PERL_UNUSED_VAR(ix);
 +              if (1 < items) {
 +                      SELF->cheque2 = SvUV(ST(1));
 +              }
 +              RETVAL = SELF->cheque2;
 +      OUTPUT:
 +              RETVAL
 +
 +gdouble
 +balance(Account* SELF)
 +      ALIAS:
 +              bank_balance    = 1
 +              future_balance  = 2
 +      CODE:
 +              switch (ix) {
 +                      case 1:
 +                              RETVAL = SELF->bal_bank;
 +                              break;
 +                      case 2:
 +                              RETVAL = SELF->bal_future;
 +                              break;
 +                      default:
 +                              RETVAL = SELF->bal_today;
 +                              break;
 +              }
 +      OUTPUT:
 +              RETVAL
 +
 +gboolean
 +is_inserted(Account* SELF)
 +      CODE:
 +              RETVAL = da_acc_get(SELF->key) == SELF;
 +      OUTPUT:
 +              RETVAL
 +
 +gboolean
 +is_used(Account* SELF)
 +      CODE:
 +              RETVAL = account_is_used(SELF->key);
 +      OUTPUT:
 +              RETVAL
 +
 +gboolean
 +insert(Account* SELF)
 +      CODE:
 +              if (SELF->key == 0 || account_is_used(SELF->key))
 +                      RETVAL = da_acc_append(rc_ref(SELF));
 +              else
 +                      RETVAL = da_acc_insert(rc_ref(SELF));
 +      OUTPUT:
 +              RETVAL
 +
 +void
 +remove(Account* SELF)
 +      CODE:
 +              da_acc_remove(SELF->key);
 +
 +void
 +transactions(Account* SELF)
 +      PPCODE:
-                       if (txn->kacc == SELF->key) {
-                               GValue val = G_VALUE_INIT;
-                               SV* sv = val_to_sv(EXT_TRANSACTION(&val, txn));
-                               mXPUSHs(sv);
-                       }
++              GList* list = g_queue_peek_head_link(SELF->txn_queue);
 +              for (; list; list = g_list_next(list)) {
 +                      Transaction* txn = list->data;
-               RETVAL = G_OBJECT(create_deftransaction_window(NULL, TRANSACTION_EDIT_MODIFY));
++                      GValue val = G_VALUE_INIT;
++                      SV* sv = val_to_sv(EXT_TRANSACTION(&val, txn));
++                      mXPUSHs(sv);
 +              }
 +
 +GObject*
 +open(Account* SELF)
 +      CODE:
 +              RETVAL = G_OBJECT(register_panel_window_new(SELF->key, SELF));
 +      OUTPUT:
 +              RETVAL
 +
 +
 +MODULE = HomeBank  PACKAGE = HomeBank::Transaction
 +
 +Transaction*
 +new(void)
 +      CODE:
 +              RETVAL = da_transaction_malloc();
 +      OUTPUT:
 +              RETVAL
 +
 +void
 +DESTROY(Transaction* SELF)
 +      CODE:
 +              da_transaction_free(SELF);
 +
 +gdouble
 +amount(Transaction* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      SELF->amount = SvNV(ST(1));
 +              }
 +              RETVAL = SELF->amount;
 +      OUTPUT:
 +              RETVAL
 +
 +guint
 +account_num(Transaction* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      SELF->kacc = SvIV(ST(1));
 +              }
 +              RETVAL = SELF->kacc;
 +      OUTPUT:
 +              RETVAL
 +
 +guint
 +paired_account_num(Transaction* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      SELF->kxferacc = SvIV(ST(1));
 +              }
 +              RETVAL = SELF->kxferacc;
 +      OUTPUT:
 +              RETVAL
 +
 +void
 +date(Transaction* SELF, ...)
 +      PPCODE:
 +              if (1 < items) {
 +                      SELF->date = SvIV(ST(1));
 +              }
 +              if (GIMME_V == G_ARRAY) {
 +                      GDate* d = g_date_new_julian(SELF->date);
 +                      mXPUSHp("day", 3);
 +                      mXPUSHi(g_date_get_day(d));
 +                      mXPUSHp("month", 5);
 +                      mXPUSHi(g_date_get_month(d));
 +                      mXPUSHp("year", 4);
 +                      mXPUSHi(g_date_get_year(d));
 +                      g_date_free(d);
 +                      XSRETURN(6);
 +              } else {
 +                      XSRETURN_IV(SELF->date);
 +              }
 +
 +const gchar*
 +wording(Transaction* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      if (SELF->wording) g_free(SELF->wording);
 +                      SELF->wording = g_strdup(SvGchar_ptr(ST(1)));
 +              }
 +              RETVAL = SELF->wording ? SELF->wording : "";
 +      OUTPUT:
 +              RETVAL
 +
 +const gchar*
 +info(Transaction* SELF, ...)
 +      CODE:
 +              if (1 < items) {
 +                      if (SELF->info) g_free(SELF->info);
 +                      SELF->info = g_strdup(SvGchar_ptr(ST(1)));
 +              }
 +              RETVAL = SELF->info ? SELF->info : "";
 +      OUTPUT:
 +              RETVAL
 +
 +GObject*
 +open(Transaction* SELF)
 +      CODE:
-                       other = ui_dialog_transaction_xfer_select_child(list);
++              RETVAL = G_OBJECT(create_deftransaction_window(NULL, TRANSACTION_EDIT_MODIFY, FALSE));
 +              deftransaction_set_transaction(GTK_WIDGET(RETVAL), SELF);
 +      OUTPUT:
 +              RETVAL
 +
 +Transaction*
 +pair_with(Transaction* SELF, Transaction* other, ...)
 +      PREINIT:
 +              int i;
 +              GList* list = NULL;
 +      CODE:
 +              if (2 < items) {
 +                      list = g_list_append(list, other);
 +                      for (i = 2; i < items; ++i) {
 +                              Transaction* ptr = NULL;
 +                              SV* sv = ST(i);
 +                              EXT_P2C_OBJECT("HomeBank::Transaction", sv, ptr, Transaction*);
 +                              list = g_list_append(list, ptr);
 +                      }
++                      other = ui_dialog_transaction_xfer_select_child(SELF, list);
 +              }
 +              if (other) {
 +                      transaction_xfer_change_to_child(SELF, other);
 +                      SELF->paymode = PAYMODE_INTXFER;
 +              }
 +              RETVAL = other;
 +      OUTPUT:
 +              RETVAL
 +      CLEANUP:
 +              g_list_free(list);
 +
 +void
 +dump(Transaction* SELF)
 +      CODE:
 +              g_print("txn: %p (%s) at %u (%d/%d) flags:%d, paymode:%d, kpay:%d, kcat:%d", SELF,
 +                      SELF->wording, SELF->date, SELF->kacc, SELF->kxferacc, SELF->flags, SELF->paymode, SELF->kpay, SELF->kcat);
 +
diff --combined src/hb-account.c
index c3366e770167a414e02984c55bd8c19409f56847,56b5339c1da2dfdff03969fec48ed5d48dbd6e41..9064868c71257d88d5ef18a4e0d5f8cce2b6dd29
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
@@@ -20,9 -20,6 +20,9 @@@
  #include "homebank.h"
  #include "hb-account.h"
  
 +#include "ext.h"
 +#include "refcount.h"
 +
  /****************************************************************************/
  /* Debug macros                                                                                */
  /****************************************************************************/
  extern struct HomeBank *GLOBALS;
  
  
- Account *
- da_acc_clone(Account *src_item)
- {
- Account *new_item = rc_dup(src_item, sizeof(Account));
-       DB( g_print("da_acc_clone\n") );
-       if(new_item)
-       {
-               //duplicate the string
-               new_item->name          = g_strdup(src_item->name);
-               new_item->number        = g_strdup(src_item->number);
-               new_item->bankname      = g_strdup(src_item->bankname);
-       }
-       return new_item;
- }
  void
  da_acc_free(Account *item)
  {
        DB( g_print("da_acc_free\n") );
 -      if(item != NULL)
 +      if(rc_unref(item))
        {
                DB( g_print(" => %d, %s\n", item->key, item->name) );
  
                g_free(item->name);
                g_free(item->number);
                g_free(item->bankname);
 -              g_free(item);
+               g_free(item->notes);
+               
+               g_queue_free (item->txn_queue);
+               
 +              rc_free(item);
        }
  }
  
  Account *
  da_acc_malloc(void)
  {
+ Account *item;
        DB( g_print("da_acc_malloc\n") );
-       return rc_alloc(sizeof(Account));
 -      item = g_malloc0(sizeof(Account));
++      item = rc_alloc(sizeof(Account));
+       item->txn_queue = g_queue_new ();
+       return item;
  }
  
  
@@@ -140,9 -125,9 +128,9 @@@ da_acc_length(void
  /**
   * da_acc_remove:
   *
-  * remove an account from the GHashTable
+  * delete an account from the GHashTable
   *
-  * Return value: TRUE if the key was found and removed
+  * Return value: TRUE if the key was found and deleted
   *
   */
  gboolean
@@@ -172,9 -157,6 +160,9 @@@ guint32 *new_key
        *new_key = item->key;
        g_hash_table_insert(GLOBALS->h_acc, new_key, item);
  
 +      GValue item_val = G_VALUE_INIT;
 +      ext_hook("account_inserted", EXT_ACCOUNT(&item_val, item), NULL);
 +
        return TRUE;
  }
  
@@@ -210,10 -192,6 +198,10 @@@ guint32 *new_key
                        DB( g_print(" -> insert id: %d\n", *new_key) );
  
                        g_hash_table_insert(GLOBALS->h_acc, new_key, item);
 +
 +                      GValue item_val = G_VALUE_INIT;
 +                      ext_hook("account_inserted", EXT_ACCOUNT(&item_val, item), NULL);
 +
                        return TRUE;
                }
        }
@@@ -360,57 -338,68 +348,68 @@@ GList *list = g_hash_table_get_values(G
  gboolean
  account_is_used(guint32 key)
  {
+ Account *acc;
  GList *list;
+ GList *lst_acc, *lnk_acc;
+ GList *lnk_txn;
+ gboolean retval;
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
-       {
-       Transaction *entry = list->data;
-               if( key == entry->kacc || key == entry->kxferacc)
-                       return TRUE;
-               list = g_list_next(list);
-       }
+       retval = FALSE;
+       lst_acc = NULL;
  
-       list = g_list_first(GLOBALS->arc_list);
-       while (list != NULL)
+       acc = da_acc_get(key);
+       if( g_queue_get_length(acc->txn_queue) > 0 )
        {
-       Archive *entry = list->data;
-               if( key == entry->kacc || key == entry->kxferacc)
-                       return TRUE;
-               list = g_list_next(list);
+               retval = TRUE;
+               goto end;
        }
  
-       return FALSE;
- }
- void
- account_move(guint32 key1, guint32 key2)
- {
- GList *list;
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
        {
-       Transaction *entry = list->data;
-               if(entry->kacc == key1)
-                       entry->kacc = key2;
-               if(entry->kxferacc == key1)
-                       entry->kxferacc = key2;
-               list = g_list_next(list);
+       Account *acc = lnk_acc->data;
+       
+               if(acc->key != key)
+               {
+                       lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+                       while (lnk_txn != NULL)
+                       {
+                       Transaction *entry = lnk_txn->data;
+                       
+                               if( key == entry->kxferacc)
+                               {
+                                       retval = TRUE;
+                                       goto end;
+                               }
+                               lnk_txn = g_list_next(lnk_txn);
+                       }
+               }
+               lnk_acc = g_list_next(lnk_acc);
        }
  
        list = g_list_first(GLOBALS->arc_list);
        while (list != NULL)
        {
        Archive *entry = list->data;
-               if(entry->kacc == key1)
-                       entry->kacc = key2;
-               if(entry->kxferacc == key1)
-                       entry->kxferacc = key2;
+               if( key == entry->kacc || key == entry->kxferacc)
+               {
+                       retval = TRUE;
+                       goto end;
+               }
                list = g_list_next(list);
        }
+ end:
+       g_list_free(lst_acc);
+       return retval;
  }
  
  static gchar *
  account_get_stripname(gchar *name)
  {
@@@ -453,46 -442,62 +452,62 @@@ gchar *stripname = account_get_stripnam
        return FALSE;
  }
  
- /* when we change the currency of an account, we must ensure
-  * xfer transaction account will be set to same currency
+ /* 
+  * change the account currency
+  * change every txn to currency
+  * ensure dst xfer transaction account will be set to same currency
   */
-  /*
- void account_set_currency(Account *item, guint32 kcur)
+ void account_set_currency(Account *acc, guint32 kcur)
  {
  GList *list;
- Account *acc;
+ Account *dstacc;
+ gboolean *xfer_list;
+ guint32 maxkey, i;
  
-       if(item->kcur != kcur)
+       DB( g_print("\n[account] set currency\n") );
+       if(acc->kcur == kcur)
        {
-               item->kcur = kcur;
-       
-               list = g_list_first(GLOBALS->ope_list);
-               while (list != NULL)
+               DB( g_print(" - already ok, return\n") );
+               return;
+       }
+       DB( g_print(" - set for '%s'\n", acc->name)  );
+               
+       maxkey = da_acc_get_max_key () + 1;
+       xfer_list = g_malloc0(sizeof(gboolean) * maxkey );
+       DB( g_print(" - alloc for %d account\n", da_acc_length() ) );
+       list = g_queue_peek_head_link(acc->txn_queue);
+       while (list != NULL)
+       {
+       Transaction *txn = list->data;
+               txn->kcur = kcur;
+               if( (txn->paymode == PAYMODE_INTXFER) && (txn->kxferacc > 0) && (txn->kxfer > 0) )
                {
-               Transaction *entry = list->data;
-                       if(entry->paymode == PAYMODE_INTXFER)
-                       {
-                               if(entry->kacc == item->key)
-                               {
-                                       // change target account
-                                       acc = da_acc_get (entry->kxferacc);
-                                       acc->kcur = kcur;
-                               }
-                               if(entry->kxferacc == item->key)
-                               {
-                                       // change source account
-                                       acc = da_acc_get (entry->kacc);
-                                       acc->kcur = kcur;
-                               }
-                       }
-                       
-                       list = g_list_next(list);
+                       xfer_list[txn->kxferacc] = TRUE;
                }
+               list = g_list_next(list);
        }
+       acc->kcur = kcur;
+       DB( g_print(" - '%s'\n", acc->name) );
        
- }
- */
+       for(i=1;i<maxkey;i++)
+       {
+               DB( g_print(" - %d '%d'\n", i, xfer_list[i]) );
+               if( xfer_list[i] == TRUE )
+               {
+                       dstacc = da_acc_get(i);
+                       account_set_currency(dstacc, kcur);
+               }
+       }
+       g_free(xfer_list);
  
+ }
  
  
  /**
@@@ -505,7 -510,8 +520,8 @@@ static void account_balances_sub_intern
        if(trn->date <= GLOBALS->today)
                acc->bal_today -= trn->amount;
  
-       if(trn->flags & OF_VALID)
+       if(trn->status == TXN_STATUS_RECONCILED)
+       //if(trn->flags & OF_VALID)
                acc->bal_bank -= trn->amount;
  }
  
@@@ -519,7 -525,8 +535,8 @@@ static void account_balances_add_intern
        if(trn->date <= GLOBALS->today)
                acc->bal_today += trn->amount;
  
-       if(trn->flags & OF_VALID)
+       if(trn->status == TXN_STATUS_RECONCILED)
+       //if(trn->flags & OF_VALID)
                acc->bal_bank += trn->amount;
  }
  
   */
  gboolean account_balances_sub(Transaction *trn)
  {
-       if(!(trn->flags & OF_REMIND))
+       if(!(trn->status == TXN_STATUS_REMIND))
+       //if(!(trn->flags & OF_REMIND))
        {
                Account *acc = da_acc_get(trn->kacc);
                if(acc == NULL) return FALSE;
   */
  gboolean account_balances_add(Transaction *trn)
  {
-       if(!(trn->flags & OF_REMIND))
+       if(!(trn->status == TXN_STATUS_REMIND))
+       //if(!(trn->flags & OF_REMIND))
        {
                Account *acc = da_acc_get(trn->kacc);
                if(acc == NULL) return FALSE;
  }
  
  
+ //todo: optim called 2 times from dsp_mainwindow
  void account_compute_balances(void)
  {
- GList *lacc, *list;
- Account *acc;
- Transaction *trn;
+ GList *lst_acc, *lnk_acc;
+ GList *lnk_txn;
  
        DB( g_print("\naccount_compute_balances start\n") );
  
-       /* set initial amount */
-       lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
-       while (list != NULL)
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
        {
-               acc = list->data;
+       Account *acc = lnk_acc->data;
+       
+               /* set initial amount */
                acc->bal_bank = acc->initial;
                acc->bal_today = acc->initial;
                acc->bal_future = acc->initial;
-               list = g_list_next(list);
-       }
-       g_list_free(lacc);
-       /* compute every transaction */
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
-       {
-               trn = list->data;
-               if(!(trn->flags & OF_REMIND))
+               
+               /* add every txn */
+               lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+               while (lnk_txn != NULL)
                {
-                       account_balances_add(trn);
+                       account_balances_add_internal(acc, lnk_txn->data);
+                       lnk_txn = g_list_next(lnk_txn);
                }
-               list = g_list_next(list);
+               
+               lnk_acc = g_list_next(lnk_acc);
        }
+       g_list_free(lst_acc);
  
        DB( g_print("\naccount_compute_balances end\n") );
  
  }
  
  
+ void account_convert_euro(Account *acc)
+ {
+ GList *lnk_txn;
+       lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+       while (lnk_txn != NULL)
+       {
+       Transaction *txn = lnk_txn->data;
+       gdouble oldamount = txn->amount;
  
+               txn->amount = hb_amount_to_euro(oldamount);
+               DB( g_print("%10.6f => %10.6f, %s\n", oldamount, txn->amount, txn->wording) );
+               //todo: sync child xfer
+               lnk_txn = g_list_next(lnk_txn);
+       }
  
+       acc->initial = hb_amount_to_euro(acc->initial);
+       acc->warning = hb_amount_to_euro(acc->warning);
+       acc->minimum = hb_amount_to_euro(acc->minimum);
+ }
  
diff --combined src/hb-archive.c
index e3faf5d40101af4c8958df252789db54a2a3eb56,c552f85d60ec02b867a7b9e2fb01de3fa94e0b28..d815703fc5067af1b3d96dad8aad4d1509e70635
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
  
  #include "homebank.h"
  #include "hb-archive.h"
+ #include "hb-split.h"
  
 +#include "ext.h"
 +#include "refcount.h"
 +
  /****************************************************************************/
  /* Debug macros                                                             */
  /****************************************************************************/
@@@ -43,29 -41,35 +44,35 @@@ extern struct HomeBank *GLOBALS
  
  Archive *da_archive_malloc(void)
  {
 -      return g_malloc0(sizeof(Archive));
 +      return rc_alloc(sizeof(Archive));
  }
  
  Archive *da_archive_clone(Archive *src_item)
  {
 -Archive *new_item = g_memdup(src_item, sizeof(Archive));
 +Archive *new_item = rc_dup(src_item, sizeof(Archive));
  
        if(new_item)
        {
                //duplicate the string
                new_item->wording = g_strdup(src_item->wording);
+               
+               if( da_splits_clone(src_item->splits, new_item->splits) > 0)
+                       new_item->flags |= OF_SPLIT; //Flag that Splits are active
        }
        return new_item;
  }
  
  void da_archive_free(Archive *item)
  {
 -      if(item != NULL)
 +      if(rc_unref(item))
        {
                if(item->wording != NULL)
                        g_free(item->wording);
  
 -              g_free(item);
+               da_splits_free(item->splits);
+               //item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared            
+               
 +              rc_free(item);
        }
  }
  
@@@ -110,27 -114,31 +117,31 @@@ Payee *pay
        {
                g_warning("arc consistency: fixed invalid cat %d", item->kcat);
                item->kcat = 0;
+               GLOBALS->changes_count++;
        }
+       
+       split_cat_consistency(item->splits);
+       
        // check payee exists
        pay = da_pay_get(item->kpay);
        if(pay == NULL)
        {
                g_warning("arc consistency: fixed invalid pay %d", item->kpay);
                item->kpay = 0;
+               GLOBALS->changes_count++;
        }
  
        // reset dst acc for non xfer transaction
        if( item->paymode != PAYMODE_INTXFER )
                item->kxferacc = 0;
  
-       // remove automation if dst_acc not exists
+       // delete automation if dst_acc not exists
        if(item->paymode == PAYMODE_INTXFER)
        {
                acc = da_acc_get(item->kxferacc);
                if(acc == NULL)
                {
-                       item->flags &= ~(OF_AUTO);      //remove flag
+                       item->flags &= ~(OF_AUTO);      //delete flag
                }
        }
  
  
  /* = = = = = = = = = = = = = = = = = = = = */
  
+ Archive *da_archive_init_from_transaction(Archive *arc, Transaction *txn)
+ {
+       //fill it
+       arc->amount             = txn->amount;
+       arc->kacc               = txn->kacc;
+       arc->kxferacc   = txn->kxferacc;
+       arc->paymode            = txn->paymode;
+       arc->flags                      = txn->flags    & (OF_INCOME);
+       arc->status             = txn->status;
+       arc->kpay                       = txn->kpay;
+       arc->kcat               = txn->kcat;
+       if(txn->wording != NULL)
+               arc->wording            = g_strdup(txn->wording);
+       else
+               arc->wording            = g_strdup(_("(new archive)"));
+       if( da_splits_clone(txn->splits, arc->splits) > 0)
+               arc->flags |= OF_SPLIT; //Flag that Splits are active
+       
+       return arc;
+ }
  static guint32 _sched_date_get_next_post(Archive *arc, guint32 nextdate)
  {
  GDate *tmpdate;
  guint32 nextpostdate = nextdate;
-       
+       DB( g_print("\n[scheduled] _sched_date_get_next_post\n") );
        tmpdate = g_date_new_julian(nextpostdate);
        switch(arc->unit)
        {
        nextpostdate = g_date_get_julian(tmpdate);
        g_date_free(tmpdate);
        
-       /* check limit, update and maybe break */
-       if(arc->flags & OF_LIMIT)
-       {
-               arc->limit--;
-               if(arc->limit <= 0)
-               {
-                       arc->flags ^= (OF_LIMIT | OF_AUTO);     // invert flags
-                       nextpostdate = 0;
-               }
-       }
        return nextpostdate;
  }
  
@@@ -183,7 -207,7 +210,7 @@@ gboolean scheduled_is_postable(Archive 
  {
  gdouble value;
  
-       value = arrondi(arc->amount, 2);
+       value = hb_amount_round(arc->amount, 2);
        if( (arc->flags & OF_AUTO) && (arc->kacc > 0) && (value != 0.0) )
                return TRUE;
  
@@@ -198,6 -222,9 +225,9 @@@ GDateWeekday wday
  guint32 finalpostdate;
  gint shift;
  
+       DB( g_print("\n[scheduled] scheduled_get_postdate\n") );
        finalpostdate = postdate;
        
        tmpdate = g_date_new_julian(finalpostdate);
  }
  
  
+ guint32 scheduled_get_latepost_count(Archive *arc, guint32 jrefdate)
+ {
+ guint32 curdate = jrefdate - arc->nextdate;
+ guint32 nblate = 0;
  
+       /*
+       switch(arc->unit)
+       {
+               case AUTO_UNIT_DAY:
+                       nbpost = (curdate / arc->every);
+                       g_print("debug d: %d => %f\n", curdate, nbpost);
+                       break;
  
+               case AUTO_UNIT_WEEK:
+                       nbpost = (curdate / ( 7 * arc->every));
+                       g_print("debug w: %d => %f\n", curdate, nbpost);
+                       break;
  
- guint32 scheduled_get_latepost_count(Archive *arc, guint32 jrefdate)
- {
- guint32 nbpost = 0;
- guint32 curdate = arc->nextdate;
+               case AUTO_UNIT_MONTH:
+                       //approximate is sufficient
+                       nbpost = (curdate / (( 365.2425 / 12) * arc->every));
+                       g_print("debug m: %d => %f\n", curdate, nbpost);
+                       break;
+               case AUTO_UNIT_YEAR:
+                       //approximate is sufficient
+                       nbpost = (curdate / ( 365.2425 * arc->every));
+                       g_print("debug y: %d => %f\n", curdate, nbpost);
+                       break;
+       }
+       nblate = floor(nbpost);
+       if(arc->flags & OF_LIMIT)
+               nblate = MIN(nblate, arc->limit);
+       
+       nblate = MIN(nblate, 11);
+       */
        
+       // pre 5.1 way
+       curdate = arc->nextdate;
        while(curdate <= jrefdate)
        {
                curdate = _sched_date_get_next_post(arc, curdate);
-               nbpost++;
-               // break at 11 max (to display +10)
-               if(nbpost >= 11)
+               nblate++;
+               // break if over limit or at 11 max (to display +10)
+               if(nblate >= arc->limit || nblate >= 11)
                        break;
        }
  
-       return nbpost;
+       return nblate;
  }
  
  
  guint32 scheduled_date_advance(Archive *arc)
  {
        arc->nextdate = _sched_date_get_next_post(arc, arc->nextdate);
+       
+       //#1556289
+       /* check limit, update and maybe break */
+       if(arc->flags & OF_LIMIT)
+       {
+               arc->limit--;
+               if(arc->limit <= 0)
+               {
+                       arc->flags ^= (OF_LIMIT | OF_AUTO);     // invert flags
+                       arc->nextdate = 0;
+               }
+       }
+       
        return arc->nextdate;
  }
  
diff --combined src/hb-assign.c
index 8303436ea80d7a7e0ef0276e2a8a0d51ecb50eb0,93fd2da83854df61fbbc928bc082cf6ef194de93..951cf92563bb1c519cf6ef9fcb7fa70daa26dd0c
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
@@@ -20,9 -20,6 +20,9 @@@
  #include "homebank.h"
  #include "hb-assign.h"
  
 +#include "ext.h"
 +#include "refcount.h"
 +
  #define MYDEBUG 0
  
  #if MYDEBUG
@@@ -41,12 -38,12 +41,12 @@@ voi
  da_asg_free(Assign *item)
  {
        DB( g_print("da_asg_free\n") );
 -      if(item != NULL)
 +      if(rc_unref(item))
        {
-               DB( g_print(" => %d, %s\n", item->key, item->name) );
+               DB( g_print(" => %d, %s\n", item->key, item->text) );
  
-               g_free(item->name);
+               g_free(item->text);
 -              g_free(item);
 +              rc_free(item);
        }
  }
  
@@@ -55,7 -52,7 +55,7 @@@ Assign 
  da_asg_malloc(void)
  {
        DB( g_print("da_asg_malloc\n") );
 -      return g_malloc0(sizeof(Assign));
 +      return rc_alloc(sizeof(Assign));
  }
  
  
@@@ -83,9 -80,9 +83,9 @@@ static void da_asg_max_key_ghfunc(gpoin
  
  static gboolean da_asg_name_grfunc(gpointer key, Assign *item, gchar *name)
  {
-       if( name && item->name )
+       if( name && item->text )
        {
-               if(!strcasecmp(name, item->name))
+               if(!strcasecmp(name, item->text))
                        return TRUE;
        }
        return FALSE;
@@@ -105,9 -102,9 +105,9 @@@ da_asg_length(void
  /**
   * da_asg_remove:
   *
-  * remove an rul from the GHashTable
+  * delete an rul from the GHashTable
   *
-  * Return value: TRUE if the key was found and removed
+  * Return value: TRUE if the key was found and deleted
   *
   */
  gboolean
@@@ -157,12 -154,12 +157,12 @@@ guint32 *new_key
  
        DB( g_print("da_asg_append\n") );
  
-       DB( g_print(" -> try append: %s\n", item->name) );
+       DB( g_print(" -> try append: %s\n", item->text) );
  
-       if( item->name != NULL )
+       if( item->text != NULL )
        {
                /* ensure no duplicate */
-               existitem = da_asg_get_by_name( item->name );
+               existitem = da_asg_get_by_name( item->text );
                if( existitem == NULL )
                {
                        new_key = g_new0(guint32, 1);
                }
        }
  
-       DB( g_print(" -> %s already exist: %d\n", item->name, item->key) );
+       DB( g_print(" -> %s already exist: %d\n", item->text, item->key) );
  
        return FALSE;
  }
@@@ -266,7 -263,7 +266,7 @@@ da_asg_debug_list_ghfunc(gpointer key, 
  guint32 *id = key;
  Assign *item = value;
  
-       DB( g_print(" %d :: %s\n", *id, item->name) );
+       DB( g_print(" %d :: %s\n", *id, item->text) );
  
  }
  
diff --combined src/hb-category.c
index 3dad28b5ea092b960ae44b44e3398dae8ffc7080,ce14b3c035b329b176c6cc00cfa4b56f52d627ea..781598a472b20788a32f77a82ce6f94c00640075
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
@@@ -20,9 -20,6 +20,9 @@@
  #include "homebank.h"
  #include "hb-category.h"
  
 +#include "ext.h"
 +#include "refcount.h"
 +
  
  /****************************************************************************/
  /* Debug macros                                                                                */
@@@ -43,7 -40,7 +43,7 @@@ extern struct HomeBank *GLOBALS
  Category *
  da_cat_clone(Category *src_item)
  {
 -Category *new_item = g_memdup(src_item, sizeof(Category));
 +Category *new_item = rc_dup(src_item, sizeof(Category));
  
        DB( g_print("da_cat_clone\n") );
        if(new_item)
@@@ -59,12 -56,12 +59,12 @@@ voi
  da_cat_free(Category *item)
  {
        DB( g_print("da_cat_free\n") );
 -      if(item != NULL)
 +      if(rc_unref(item))
        {
                DB( g_print(" => %d, %s\n", item->key, item->name) );
  
                g_free(item->name);
 -              g_free(item);
 +              rc_free(item);
        }
  }
  
@@@ -73,7 -70,7 +73,7 @@@ Category 
  da_cat_malloc(void)
  {
        DB( g_print("da_cat_malloc\n") );
 -      return g_malloc0(sizeof(Category));
 +      return rc_alloc(sizeof(Category));
  }
  
  
@@@ -120,7 -117,7 +120,7 @@@ da_cat_length(void
   *
   * GRFunc to get the max id
   *
-  * Return value: TRUE if the key/value must be removed
+  * Return value: TRUE if the key/value must be deleted
   *
   */
  static gboolean
@@@ -136,9 -133,9 +136,9 @@@ da_cat_remove_grfunc(gpointer key, Cate
  /**
   * da_cat_remove:
   *
-  * remove a category from the GHashTable
+  * delete a category from the GHashTable
   *
-  * Return value: TRUE if the key was found and removed
+  * Return value: TRUE if the key was found and deleted
   *
   */
  guint
@@@ -259,7 -256,7 +259,7 @@@ da_cat_get_fullname(Category *cat
  {
  Category *parent;
  
-       if( cat->parent == 0)
+       if( cat->parent == 0 )
                return g_strdup(cat->name);
        else
        {
@@@ -539,12 -536,30 +539,30 @@@ void da_cat_consistency(Category *item
  {
  gboolean isIncome;
  
+       if((item->flags & GF_SUB) && item->key > 0)
+       {
+               //check for existing parent
+               if( da_cat_get(item->parent) == NULL )
+               {
+               Category *parent = da_cat_append_ifnew_by_fullname ("orphaned", FALSE);
+                       item->parent = parent->key;
+                       
+                       g_warning("category consistency: fixed missing parent %d", item->parent);
+               }
+       }
        // ensure type equal for categories and its children
        if(!(item->flags & GF_SUB) && item->key > 0)
        {
                isIncome = (item->flags & GF_INCOME) ? TRUE : FALSE;
-               category_change_type(item, isIncome);
+               if( category_change_type(item, isIncome) > 0 )
+               {
+                       g_warning("category consistency: fixed type for child");
+                       GLOBALS->changes_count++;
+               }
        }
+       
        g_strstrip(item->name);
  }
  
@@@ -582,88 -597,181 +600,181 @@@ da_cat_debug_list(void
  
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  
- gboolean
- category_is_used(guint32 key)
+ guint32 category_report_id(guint32 key, gboolean subcat)
  {
GList *lrul, *list;
- guint i, nbsplit;
Category *catentry = da_cat_get(key);
+ guint32 retval = 0;
  
-       list = g_list_first(GLOBALS->ope_list);
+       if(catentry)
+       {
+               if(subcat == FALSE)
+               {
+                       retval = (catentry->flags & GF_SUB) ? catentry->parent : catentry->key;
+               }
+               else
+               {
+                       retval = catentry->key;
+               }
+       }
+       return retval;
+ }
+ void 
+ category_delete_unused(void)
+ {
+ GList *lcat, *list;
+       
+       lcat = list = g_hash_table_get_values(GLOBALS->h_cat);
        while (list != NULL)
        {
-       Transaction *entry = list->data;
-               if( key == entry->kcat )
-                       return TRUE;
+       Category *entry = list->data;
+               if(entry->usage_count <= 0 && entry->key > 0)
+                       da_cat_remove (entry->key);
+               list = g_list_next(list);
+       }
+       g_list_free(lcat);
+ }
+ static void 
+ category_fill_usage_count(guint32 kcat)
+ {
+ Category *cat = da_cat_get (kcat);
+ Category *parent;
  
-               // check split category #1340142
-               nbsplit = da_transaction_splits_count(entry);
-               for(i=0;i<nbsplit;i++)
+       if(cat)
+       {
+               cat->usage_count++;
+               if( cat->parent > 0 )
                {
-               Split *split = entry->splits[i];
+                       parent = da_cat_get(cat->parent);
+                       if( parent )
+                       {
+                               parent->usage_count++;
+                       }
+               }
+       }
+ }
+ void
+ category_fill_usage(void)
+ {
+ GList *lcat;
+ GList *lst_acc, *lnk_acc;
+ GList *lnk_txn;
+ GList *lpay, *lrul, *list;
  
-                       if( key == split->kcat )
-                               return TRUE;
+       lcat = list = g_hash_table_get_values(GLOBALS->h_cat);
+       while (list != NULL)
+       {
+       Category *entry = list->data;
+               entry->usage_count = 0;
+               list = g_list_next(list);
+       }
+       g_list_free(lcat);
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
+       {
+       Account *acc = lnk_acc->data;
+               lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+               while (lnk_txn != NULL)
+               {
+               Transaction *txn = lnk_txn->data;
+                       category_fill_usage_count(txn->kcat);           
+                       lnk_txn = g_list_next(lnk_txn);
                }
+               lnk_acc = g_list_next(lnk_acc);
+       }
+       g_list_free(lst_acc);
+       lpay = list = g_hash_table_get_values(GLOBALS->h_pay);
+       while (list != NULL)
+       {
+       Payee *entry = list->data;
  
+               category_fill_usage_count(entry->kcat);
                list = g_list_next(list);
        }
+       g_list_free(lpay);
  
        list = g_list_first(GLOBALS->arc_list);
        while (list != NULL)
        {
        Archive *entry = list->data;
-               if( key == entry->kcat )
-                       return TRUE;
+               category_fill_usage_count(entry->kcat);
                list = g_list_next(list);
        }
  
-       //todo: add budget use here
-       
        lrul = list = g_hash_table_get_values(GLOBALS->h_rul);
        while (list != NULL)
        {
        Assign *entry = list->data;
  
-               if( key == entry->kcat)
-                       return TRUE;
+               category_fill_usage_count(entry->kcat);
                list = g_list_next(list);
        }
        g_list_free(lrul);
  
-       return FALSE;
  }
  
  void
  category_move(guint32 key1, guint32 key2)
  {
+ GList *lst_acc, *lnk_acc;
+ GList *lnk_txn;
  GList *lrul, *list;
  guint i, nbsplit;
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
        {
-       Transaction *entry = list->data;
-               if(entry->kcat == key1)
-               {
-                       entry->kcat = key2;
-                       entry->flags |= OF_CHANGED;
-               }
+       Account *acc = lnk_acc->data;
  
-               // move split category #1340142
-               nbsplit = da_transaction_splits_count(entry);
-               for(i=0;i<nbsplit;i++)
+               lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+               while (lnk_txn != NULL)
                {
-               Split *split = entry->splits[i];
+               Transaction *txn = lnk_txn->data;
+               
+                       if(txn->kcat == key1)
+                       {
+                               txn->kcat = key2;
+                               txn->flags |= OF_CHANGED;
+                       }
  
-                       if( split->kcat == key1 )
+                       // move split category #1340142
+                       nbsplit = da_splits_count(txn->splits);
+                       for(i=0;i<nbsplit;i++)
                        {
-                               split->kcat = key2;
-                               entry->flags |= OF_CHANGED;
+                       Split *split = txn->splits[i];
+                               if( split->kcat == key1 )
+                               {
+                                       split->kcat = key2;
+                                       txn->flags |= OF_CHANGED;
+                               }
                        }
-               }
  
-               list = g_list_next(list);
+                       lnk_txn = g_list_next(lnk_txn);
+               }
+               
+               lnk_acc = g_list_next(lnk_acc);
        }
+       g_list_free(lst_acc);
  
        list = g_list_first(GLOBALS->arc_list);
        while (list != NULL)
@@@ -868,7 -976,7 +979,7 @@@ const gchar *encoding
  
                                        if( g_strv_length (str_array) != 3 )
                                        {
-                                               *error = _("invalid csv format");
+                                               *error = _("invalid CSV format");
                                                retval = FALSE;
                                                DB( g_print(" + error %s\n", *error) );
                                        }
@@@ -984,13 -1092,31 +1095,31 @@@ GList *lcat, *list
        return retval;
  }
  
+ gint category_type_get(Category *item)
+ {
+       if( (item->flags & (GF_INCOME)) )
+               return 1;
+       return -1;
+ }
+ static gint category_change_type_eval(Category *item, gboolean isIncome)
+ {
+       if( (item->flags & (GF_INCOME)) && !isIncome )
+               return 1;
+       return 0;
+ }
  
  gint category_change_type(Category *item, gboolean isIncome)
  {
- gint changes = 1;
+ gint changes = 0;
  GList *lcat, *list;
  
-       item->flags &= ~(GF_INCOME);    //remove flag
+       changes += category_change_type_eval(item, isIncome);
+       
+       item->flags &= ~(GF_INCOME);    //delete flag
        if(isIncome == TRUE)
                item->flags |= GF_INCOME;
  
  
                if(child->parent == item->key)
                {
-                       child->flags &= ~(GF_INCOME);   //remove flag
+                       changes += category_change_type_eval(child, isIncome);
+                       child->flags &= ~(GF_INCOME);   //delete flag
                        if(isIncome == TRUE)
                                child->flags |= GF_INCOME;
-                       changes++;
                }
                list = g_list_next(list);
        }
diff --combined src/hb-payee.c
index 6a51cc7c2563267772ba6853633341a5e55efda6,5992a4d0e544d98b264bfac12462e54bb1a67868..419bdeae643eb9307af790eccf53cb39de089fe3
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
@@@ -20,9 -20,6 +20,9 @@@
  #include "homebank.h"
  #include "hb-payee.h"
  
 +#include "ext.h"
 +#include "refcount.h"
 +
  
  /****************************************************************************/
  /* Debug macros                                                                                */
@@@ -44,12 -41,12 +44,12 @@@ voi
  da_pay_free(Payee *item)
  {
        DB( g_print("da_pay_free\n") );
 -      if(item != NULL)
 +      if(rc_unref(item))
        {
                DB( g_print(" => %d, %s\n", item->key, item->name) );
  
                g_free(item->name);
 -              g_free(item);
 +              rc_free(item);
        }
  }
  
@@@ -58,7 -55,7 +58,7 @@@ Payee 
  da_pay_malloc(void)
  {
        DB( g_print("da_pay_malloc\n") );
 -      return g_malloc0(sizeof(Payee));
 +      return rc_alloc(sizeof(Payee));
  }
  
  
@@@ -140,9 -137,9 +140,9 @@@ guint32 *new_key
  /**
   * da_pay_remove:
   *
-  * remove an payee from the GHashTable
+  * delete an payee from the GHashTable
   *
-  * Return value: TRUE if the key was found and removed
+  * Return value: TRUE if the key was found and deleted
   *
   */
  gboolean
@@@ -305,33 -302,75 +305,75 @@@ da_pay_debug_list(void
  #endif
  
  
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  
+ void 
+ payee_delete_unused(void)
+ {
+ GList *lpay, *list;
+       
+       lpay = list = g_hash_table_get_values(GLOBALS->h_pay);
+       while (list != NULL)
+       {
+       Payee *entry = list->data;
  
+               if(entry->usage_count <= 0 && entry->key > 0)
+                       da_pay_remove (entry->key);
+               list = g_list_next(list);
+       }
+       g_list_free(lpay);
+ }
  
  
- gboolean
- payee_is_used(guint32 key)
+ void 
+ payee_fill_usage(void)
  {
+ GList *lpay;
+ GList *lst_acc, *lnk_acc;
+ GList *lnk_txn;
  GList *lrul, *list;
  
-       list = g_list_first(GLOBALS->ope_list);
+       lpay = list = g_hash_table_get_values(GLOBALS->h_pay);
        while (list != NULL)
        {
-       Transaction *entry = list->data;
-               if( key == entry->kpay )
-                       return TRUE;
+       Payee *entry = list->data;
+               entry->usage_count = 0;
                list = g_list_next(list);
        }
+       g_list_free(lpay);
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
+       {
+       Account *acc = lnk_acc->data;
+               lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+               while (lnk_txn != NULL)
+               {
+               Transaction *txn = lnk_txn->data;
+               Payee *pay = da_pay_get (txn->kpay);
+                       
+                       if(pay)
+                               pay->usage_count++;
+                       lnk_txn = g_list_next(lnk_txn);
+               }
+               lnk_acc = g_list_next(lnk_acc);
+       }
+       g_list_free(lst_acc);
  
        list = g_list_first(GLOBALS->arc_list);
        while (list != NULL)
        {
        Archive *entry = list->data;
-               if( key == entry->kpay )
-                       return TRUE;
+       Payee *pay = da_pay_get (entry->kpay);
+               
+               if(pay)
+                       pay->usage_count++;
                list = g_list_next(list);
        }
  
        while (list != NULL)
        {
        Assign *entry = list->data;
+       Payee *pay = da_pay_get (entry->kpay);
+               if(pay)
+                       pay->usage_count++;
  
-               if( key == entry->kpay)
-                       return TRUE;
                list = g_list_next(list);
        }
        g_list_free(lrul);
  
-       return FALSE;
  }
  
  void
  payee_move(guint32 key1, guint32 key2)
  {
+ GList *lst_acc, *lnk_acc;
+ GList *lnk_txn;
  GList *lrul, *list;
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
        {
-       Transaction *entry = list->data;
-               if(entry->kpay == key1)
+       Account *acc = lnk_acc->data;
+               lnk_txn = g_queue_peek_head_link(acc->txn_queue);
+               while (lnk_txn != NULL)
                {
-                       entry->kpay = key2;
-                       entry->flags |= OF_CHANGED;
+               Transaction *txn = lnk_txn->data;
+       
+                       if(txn->kpay == key1)
+                       {
+                               txn->kpay = key2;
+                               txn->flags |= OF_CHANGED;
+                       }
+                       lnk_txn = g_list_next(lnk_txn);
                }
-               list = g_list_next(list);
+               lnk_acc = g_list_next(lnk_acc);
        }
+       g_list_free(lst_acc);
  
        list = g_list_first(GLOBALS->arc_list);
        while (list != NULL)
diff --combined src/hb-preferences.c
index e7695bc5f83877af411c5ce15dc1bf7d42a67199,5bf8234c19728dc2399425531d57afbcfa317751..d257ca7c3dcc7035f0713b8d0ed155ad90c9f552
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
@@@ -17,7 -17,9 +17,9 @@@
   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  #include "homebank.h"
  #include "hb-preferences.h"
  #include "hb-filter.h"
  #include "gtk-chart-colors.h"
  extern struct HomeBank *GLOBALS;
  extern struct Preferences *PREFS;
  
+ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
+ static void homebank_pref_init_monetary(void)
+ {
+       DB( g_print("\n[system] get currency code\n") );
+       
+ #ifdef G_OS_UNIX
+       struct lconv *lc = localeconv();
+       g_stpcpy (PREFS->IntCurrSymbol, lc->int_curr_symbol);
+       g_strstrip(PREFS->IntCurrSymbol);
+       DB( g_print("- stored '%s' from linux system\n", PREFS->IntCurrSymbol) );
+ #else
+       #ifdef G_OS_WIN32
+     #define BUFFER_SIZE 512
+     char buffer[BUFFER_SIZE];
+     //LPWSTR wcBuffer = buffer;
+     LPSTR wcBuffer = buffer;
+     int iResult;
+       //https://msdn.microsoft.com/en-us/library/windows/desktop/dd464799%28v=vs.85%29.aspx
+       //LOCALE_SINTLSYMBOL
+       iResult = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SINTLSYMBOL, wcBuffer, BUFFER_SIZE);
+     if(iResult > 0)
+     {
+         DB( g_print("LOCALE_SINTLSYMBOL='%s'\n", buffer) );
+               g_stpcpy (PREFS->IntCurrSymbol, buffer);
+               g_strstrip(PREFS->IntCurrSymbol);
+               DB( g_print("- stored '%s' from windows system\n", PREFS->IntCurrSymbol) );
+     }
+       #else
+       g_stpcpy (PREFS->IntCurrSymbol, "USD");
+       DB( g_print("- stored '%s' as default\n", PREFS->IntCurrSymbol) );
+       
+       #endif
+       
+ #endif
+       
+ }
  
+ /*
  static void homebank_pref_init_monetary(void)
  {
        DB( g_print("\n[preferences] monetary\n") );
@@@ -53,6 -104,8 +104,8 @@@ struct lconv *lc = localeconv()
  
        DB( g_print("\n[preferences] monetary unix\n") );
  
+       DB( g_print("int_curr_symbol '%s'\n", lc->int_curr_symbol) );
+       
        DB( g_print("mon_decimal_point is utf8: %d\n", g_utf8_validate(lc->mon_decimal_point, -1, NULL)) );
        DB( g_print("mon_decimal_point '%s'\n", lc->mon_decimal_point) );
        DB( g_print("mon_decimal_point %x %x %x %x\n", lc->mon_decimal_point[0], lc->mon_decimal_point[1], lc->mon_decimal_point[2], lc->mon_decimal_point[3]) );
  
        DB( g_print("n_cs_precedes '%d'\n", lc->n_cs_precedes) );
  
-       /* ok assign */
+       //PREFS->base_cur.iso_code = g_strdup(g_strstrip(lc->int_curr_symbol));
  
        if( lc->p_cs_precedes || lc->n_cs_precedes )
        {
                PREFS->base_cur.symbol = g_strdup(lc->currency_symbol);
-               PREFS->base_cur.is_prefix = TRUE;
+               PREFS->base_cur.sym_prefix = TRUE;
                DB( g_print("locale mon cs is a prefix\n") );
        }
        else
        {
                PREFS->base_cur.symbol = g_strdup(lc->currency_symbol);
-               PREFS->base_cur.is_prefix = FALSE;
+               PREFS->base_cur.sym_prefix = FALSE;
        }
  
        PREFS->base_cur.decimal_char  = g_strdup(lc->mon_decimal_point);
  
  #else
        #ifdef G_OS_WIN32
-       //todo: to be really set by a win32 specialist from the registry...
      #define BUFFER_SIZE 512
      char buffer[BUFFER_SIZE];
      //LPWSTR wcBuffer = buffer;
      int iResult;
      gsize toto;
  
+       //https://msdn.microsoft.com/en-us/library/windows/desktop/dd464799%28v=vs.85%29.aspx
+       //LOCALE_SINTLSYMBOL
+       
      //see g_locale_to_utf8 here
        iResult = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SCURRENCY, wcBuffer, BUFFER_SIZE);
      if(iResult > 0)
          PREFS->base_cur.symbol = g_locale_to_utf8(buffer, -1, NULL, &toto, NULL);
      }
  
+       // LOCALE_ICURRENCY
+       //PREFS->base_cur.sym_prefix =
+       
        iResult = GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, wcBuffer, BUFFER_SIZE);
      if(iResult > 0)
      {
          PREFS->base_cur.grouping_char = g_locale_to_utf8(buffer, -1, NULL, &toto, NULL);
      }
  
+       // LOCALE_ICURRDIGITS
        PREFS->base_cur.frac_digits   = 2;
  
        #else
  
-       PREFS->base_cur.prefix_symbol = NULL; //g_strdup("");
-       PREFS->base_cur.suffix_symbol = NULL; //g_strdup("");
+       PREFS->base_cur.iso_code      = g_strdup("USD");
+       PREFS->base_cur.symbol        = NULL; //g_strdup("");
+       PREFS->base_cur.sym_prefix    = FALSE;
        PREFS->base_cur.decimal_char  = g_strdup(".");
        PREFS->base_cur.grouping_char = NULL; //g_strdup("");
        PREFS->base_cur.frac_digits   = 2;
  #endif
  
  }
+ */
  
  
  
@@@ -164,57 -227,6 +227,6 @@@ static void homebank_pref_init_wingeome
  }
  
  
- /*
- ** create the format string for monetary strfmon (major/minor)
- */
- static void _homebank_pref_createformat(void)
- {
- struct CurrencyFmt *cur;
-       DB( g_print("\n[preferences] pref create format\n") );
- /*
-       if(PREFS->base_cur.grouping_char != NULL)
-               g_snprintf(GLOBALS->fmt_maj_number, 15, "%%^.%dn", PREFS->base_cur.frac_digits);
-       else
-               g_snprintf(GLOBALS->fmt_maj_number, 15, "%%.%dn", PREFS->base_cur.frac_digits);
-       DB( g_print("+ major is: '%s'\n", GLOBALS->fmt_maj_number) );
-       if(PREFS->minor_cur.grouping_char != NULL)
-               g_snprintf(GLOBALS->fmt_min_number, 15, "%s %%!^.%dn %s",
-                       PREFS->minor_cur.prefix_symbol,
-                       PREFS->minor_cur.frac_digits,
-                       PREFS->minor_cur.suffix_symbol
-                       );
-       else
-               g_snprintf(GLOBALS->fmt_min_number, 15, "%s %%!.%dn %s",
-                       PREFS->minor_cur.prefix_symbol,
-                       PREFS->minor_cur.frac_digits,
-                       PREFS->minor_cur.suffix_symbol
-                       );
-       DB( g_print("+ minor is: '%s'\n", GLOBALS->fmt_min_number) );
- */
-       /* base mon format */
-       cur = &PREFS->base_cur;
-       g_snprintf(cur->format , 8-1, "%%.%df", cur->frac_digits);
-       g_snprintf(cur->monfmt, 32-1, (cur->is_prefix) ? "%s %%s" : "%%s %s", cur->symbol);
-       DB( g_print(" - format: '%s'\n", cur->format) );
-       DB( g_print(" - monfmt: '%s'\n", cur->monfmt) );
-       /* minor mon format */
-       cur = &PREFS->minor_cur;
-       g_snprintf(cur->format , 8-1, "%%.%df", cur->frac_digits);
-       g_snprintf(cur->monfmt, 32-1, (cur->is_prefix) ? "%s %%s" : "%%s %s", cur->symbol);
-       DB( g_print(" - format: '%s'\n", cur->format) );
-       DB( g_print(" - monfmt: '%s'\n", cur->monfmt) );
- }
  //vehicle_unit_100
  //vehicle_unit_distbyvol
  //=> used for column title
@@@ -230,27 -242,30 +242,30 @@@ static void _homebank_pref_init_measure
        // unit is miles
        else
        {
-               PREFS->vehicle_unit_dist = "%d m.";
-               PREFS->vehicle_unit_100  = "100 miles";
+               PREFS->vehicle_unit_dist = "%d mi.";
+               PREFS->vehicle_unit_100  = "100 mi.";
        }
  
        // unit is Liters
        if(!PREFS->vehicle_unit_isgal)
        {
-               PREFS->vehicle_unit_vol  = "%.2f L";
+               //TRANSLATORS: format a liter number with l/L as abbreviation
+               PREFS->vehicle_unit_vol  = _("%.2f l");
                if(!PREFS->vehicle_unit_ismile)
-                       PREFS->vehicle_unit_distbyvol  = "km/L";
+                       //TRANSLATORS: kilometer per liter
+                       PREFS->vehicle_unit_distbyvol  = _("km/l");
                else
-                       PREFS->vehicle_unit_distbyvol  = "miles/gal";
+                       //TRANSLATORS: miles per liter
+                       PREFS->vehicle_unit_distbyvol  = _("mi./l");
        }
        // unit is gallon
        else
        {
-               PREFS->vehicle_unit_vol  = "%.2f gal";
+               PREFS->vehicle_unit_vol  = "%.2f gal.";
                if(!PREFS->vehicle_unit_ismile)
-                       PREFS->vehicle_unit_distbyvol  = "km/gal";
+                       PREFS->vehicle_unit_distbyvol  = "km/gal.";
                else
-                       PREFS->vehicle_unit_distbyvol  = "miles/gal";
+                       PREFS->vehicle_unit_distbyvol  = "mi./gal.";
        }
  
  }
@@@ -274,17 -289,11 +289,14 @@@ void homebank_pref_free(void
  
        g_free(PREFS->language);
  
-       g_free(PREFS->base_cur.symbol);
-       g_free(PREFS->base_cur.decimal_char);
-       g_free(PREFS->base_cur.grouping_char);
  
        g_free(PREFS->minor_cur.symbol);
        g_free(PREFS->minor_cur.decimal_char);
        g_free(PREFS->minor_cur.grouping_char);
  
 +      g_strfreev(PREFS->ext_path);
 +      g_list_free_full(PREFS->ext_whitelist, g_free);
 +
        memset(PREFS, 0, sizeof(struct Preferences));
  }
  
@@@ -309,16 -318,18 +321,18 @@@ gint i
        PREFS->showsplash = TRUE;
        PREFS->loadlast = TRUE;
        PREFS->appendscheduled = FALSE;
+       PREFS->do_update_currency = FALSE;
  
        PREFS->heritdate = FALSE;
        PREFS->hidereconciled = FALSE;
+       PREFS->showremind = TRUE;
  
        PREFS->toolbar_style = 4;       //text beside icons
        PREFS->custom_colors = TRUE;
        PREFS->color_exp  = g_strdup(DEFAULT_EXP_COLOR);
        PREFS->color_inc  = g_strdup(DEFAULT_INC_COLOR);
        PREFS->color_warn = g_strdup(DEFAULT_WARN_COLOR);
-       PREFS->rules_hint = FALSE;
+       PREFS->grid_lines = GTK_TREE_VIEW_GRID_LINES_NONE;
  
        /* fiscal year */
        PREFS->fisc_year_day = 1;
        homebank_pref_init_wingeometry(&PREFS->bud_wg, 0, 0, 800, 494);
        homebank_pref_init_wingeometry(&PREFS->cst_wg, 0, 0, 800, 494);
  
+       homebank_pref_init_wingeometry(&PREFS->txn_wg, 0, 0, -1, -1);
        homebank_pref_init_monetary();
  
        PREFS->wal_toolbar = TRUE;
        PREFS->lst_ope_columns[i++] = LST_DSPOPE_PAYEE;
        PREFS->lst_ope_columns[i++] = LST_DSPOPE_CATEGORY;
        PREFS->lst_ope_columns[i++] = LST_DSPOPE_TAGS;
+       PREFS->lst_ope_columns[i++] = LST_DSPOPE_CLR;
        PREFS->lst_ope_columns[i++] = -LST_DSPOPE_AMOUNT;
        PREFS->lst_ope_columns[i++] = LST_DSPOPE_EXPENSE;
        PREFS->lst_ope_columns[i++] = LST_DSPOPE_INCOME;
        PREFS->lst_ope_sort_id    = LST_DSPOPE_DATE;
        PREFS->lst_ope_sort_order = GTK_SORT_ASCENDING;
  
+       for( i=0;i<NUM_LST_DSPOPE;i++)
+               PREFS->lst_ope_col_size[i] = -1;
  
        //PREFS->base_cur.nbdecimal = 2;
        //PREFS->base_cur.separator = TRUE;
  
        PREFS->date_range_wal = FLT_RANGE_LASTMONTH;
        PREFS->date_range_txn = FLT_RANGE_LAST12MONTHS;
+       PREFS->date_future_nbdays = 0;
        PREFS->date_range_rep = FLT_RANGE_THISYEAR;
  
+       //import/export
+       PREFS->dtex_nointro = TRUE;
+       //PREFS->dtex_datefmt
+       PREFS->dtex_ofxname = 1;
+       PREFS->dtex_ofxmemo = 2;
+       PREFS->dtex_qifmemo = TRUE;
+       PREFS->dtex_qifswap = FALSE;
  
        //todo: add intelligence here
        PREFS->euro_active  = FALSE;
  
        PREFS->euro_country = 0;
        PREFS->euro_value   = 1.0;
+       
+       da_cur_initformat(&PREFS->minor_cur);
+       
        //PREFS->euro_nbdec   = 2;
        //PREFS->euro_thsep   = TRUE;
        //PREFS->euro_symbol    = g_strdup("??");
        PREFS->budg_showdetail = FALSE;
        PREFS->report_color_scheme = CHART_COLMAP_HOMEBANK;
  
-       PREFS->chart_legend = FALSE;
+       //PREFS->chart_legend = FALSE;
  
        PREFS->vehicle_unit_ismile = FALSE;
        PREFS->vehicle_unit_isgal  = FALSE;
  
-       _homebank_pref_createformat();
 +      gchar** plugin_path = g_new0(gchar**, 4);
 +      i = 0;
 +      const gchar* env = g_getenv("HOMEBANK_PLUGINS");
 +      if (env) {
 +              if (g_path_is_absolute(env)) {
 +                      plugin_path[i++] = g_strdup(env);
 +              } else {
 +                      gchar* cur = g_get_current_dir();
 +                      plugin_path[i++] = g_build_filename(cur, env, NULL);
 +                      g_free(cur);
 +              }
 +      }
 +      plugin_path[i++] = g_build_filename(homebank_app_get_config_dir(), "plugins", NULL);
 +      plugin_path[i++] = g_build_filename(homebank_app_get_pkglib_dir(), "plugins", NULL);
 +      PREFS->ext_path = plugin_path;
 +      PREFS->ext_whitelist = NULL;
 +
        _homebank_pref_init_measurement_units();
  
  }
@@@ -449,6 -458,9 +478,9 @@@ static void homebank_pref_get_wingeomet
        }
  }
  
  static void homebank_pref_get_boolean(
        GKeyFile *key_file,
      const gchar *group_name,
@@@ -548,18 -560,18 +580,18 @@@ gchar *string
  }
  
  
- static void homebank_pref_currfmt_convert(struct CurrencyFmt *cur, gchar *prefix, gchar *suffix)
+ static void homebank_pref_currfmt_convert(Currency *cur, gchar *prefix, gchar *suffix)
  {
  
        if( (prefix != NULL) && (strlen(prefix) > 0) )
        {
                cur->symbol = g_strdup(prefix);
-               cur->is_prefix = TRUE;
+               cur->sym_prefix = TRUE;
        }
        else if( (suffix != NULL) )
        {
                cur->symbol = g_strdup(suffix);
-               cur->is_prefix = FALSE;
+               cur->sym_prefix = FALSE;
        }
  }
  
@@@ -632,7 -644,16 +664,16 @@@ GError *error = NULL
                                        homebank_pref_get_string(keyfile, group, "ColorInc" , &PREFS->color_inc);
                                        homebank_pref_get_string(keyfile, group, "ColorWarn", &PREFS->color_warn);
  
-                                       homebank_pref_get_boolean(keyfile, group, "RulesHint", &PREFS->rules_hint);
+                                       if( version <= 500 )
+                                       {
+                                       gboolean rules_hint;
+                                               homebank_pref_get_boolean(keyfile, group, "RulesHint", &rules_hint);
+                                               if( rules_hint == TRUE )
+                                                       PREFS->grid_lines = GTK_TREE_VIEW_GRID_LINES_HORIZONTAL;
+                                       }
+                                       else
+                                               homebank_pref_get_short(keyfile, group, "GridLines", &PREFS->grid_lines);
                                }
  
                                DB( g_print(" - color exp: %s\n", PREFS->color_exp) );
                                homebank_pref_get_boolean(keyfile, group, "ShowSplash", &PREFS->showsplash);
                                homebank_pref_get_boolean(keyfile, group, "LoadLast", &PREFS->loadlast);
                                homebank_pref_get_boolean(keyfile, group, "AppendScheduled", &PREFS->appendscheduled);
+                               homebank_pref_get_boolean(keyfile, group, "UpdateCurrency", &PREFS->do_update_currency);        
  
                                homebank_pref_get_boolean(keyfile, group, "HeritDate", &PREFS->heritdate);
                                homebank_pref_get_boolean(keyfile, group, "HideReconciled", &PREFS->hidereconciled);
+                               homebank_pref_get_boolean(keyfile, group, "ShowRemind", &PREFS->showremind);
  
                                if( g_key_file_has_key(keyfile, group, "ColumnsOpe", NULL) )
                                {
                                gboolean *bsrc;
-                               gint *src, i;
+                               gint *src, i, j;
                                gsize length;
  
                                        if(version <= 2)        //retrieve old 0.1 or 0.2 visibility boolean
                                                                        DB( g_print(" - upgrade from v7\n") );
                                                                        DB( g_print(" - copying column order from pref file\n") );
                                                                        memcpy(PREFS->lst_ope_columns, src, length*sizeof(gint));
+                                                                       //append balance column
                                                                        PREFS->lst_ope_columns[10] = LST_DSPOPE_BALANCE;
                                                                }
                                                        }
  
+                                                       if(version < 500)
+                                                       {
+                                                               if( length == NUM_LST_DSPOPE-2 )        //1 less column before v4.5.1
+                                                               {
+                                                                       DB( g_print(" - upgrade prior v5.0\n") );
+                                                                       DB( g_print(" - copying column order from pref file\n") );
+                                                                       gboolean added = FALSE;
+                                                                       for(i=0,j=0; i<NUM_LST_DSPOPE-1 ; i++)
+                                                                       {
+                                                                               if( added == FALSE &&
+                                                                                   (ABS(src[i]) == LST_DSPOPE_AMOUNT ||
+                                                                                   ABS(src[i]) == LST_DSPOPE_EXPENSE ||
+                                                                                   ABS(src[i]) == LST_DSPOPE_INCOME) )
+                                                                               {
+                                                                                       PREFS->lst_ope_columns[j++] = LST_DSPOPE_CLR;
+                                                                                       added = TRUE;
+                                                                               }
+                                                                               PREFS->lst_ope_columns[j++] = src[i];
+                                                                       }
+                                                               }
+                                                       }
                                                }
  
                                                g_free(src);
  
                                }
  
+                               if( g_key_file_has_key(keyfile, group, "ColumnsOpeWidth", NULL) )
+                               {
+                               gint *src;
+                               gsize length;
+                                       src = g_key_file_get_integer_list(keyfile, group, "ColumnsOpeWidth", &length, &error);
+                                       DB( g_print(" - length %d (max=%d)\n", length, NUM_LST_DSPOPE) );
+                                       if( length == NUM_LST_DSPOPE-1 )
+                                       {
+                                               DB( g_print(" - copying column width from pref file\n") );
+                                               memcpy(PREFS->lst_ope_col_size, src, length*sizeof(gint));
+                                       }
+                               }
+                       
                                homebank_pref_get_integer(keyfile, group, "OpeSortId", &PREFS->lst_ope_sort_id);
                                homebank_pref_get_integer(keyfile, group, "OpeSortOrder", &PREFS->lst_ope_sort_order);
  
                                homebank_pref_get_wingeometry(keyfile, group, "Ove", &PREFS->ove_wg);
                                homebank_pref_get_wingeometry(keyfile, group, "Bud", &PREFS->bud_wg);
                                homebank_pref_get_wingeometry(keyfile, group, "Car", &PREFS->cst_wg);
+                               homebank_pref_get_wingeometry(keyfile, group, "Txn", &PREFS->txn_wg);
                                if(version <= 7)        //set maximize to 0
                                {
                                        PREFS->wal_wg.s = 0;
                                        PREFS->acc_wg.s = 0;
+                                       PREFS->txn_wg.s = 0;
                                        PREFS->sta_wg.s = 0;
                                        PREFS->tme_wg.s = 0;
                                        PREFS->ove_wg.s = 0;
  
                                homebank_pref_get_string(keyfile, group, "DateFmt", &PREFS->date_format);
  
-                               if(version <= 1)
-                               {
-                                       //retrieve old 0.1 preferences
-                                       homebank_pref_get_short(keyfile, group, "NumNbDec", &PREFS->base_cur.frac_digits);
-                                       //PREFS->base_cur.separator = g_key_file_get_boolean (keyfile, group, "NumSep", NULL);
-                               }
-                               else
-                               {
-                                       if(version < 460)
-                                       {
-                                       gchar *prefix = NULL;
-                                       gchar *suffix = NULL;
-                                               homebank_pref_get_string(keyfile, group, "PreSymbol", &prefix);
-                                               homebank_pref_get_string(keyfile, group, "SufSymbol", &suffix);
-                                               homebank_pref_currfmt_convert(&PREFS->base_cur, prefix, suffix);
-                                               g_free(prefix);
-                                               g_free(suffix);
-                                       }
-                                       else
-                                       {
-                                               homebank_pref_get_string(keyfile, group, "Symbol", &PREFS->base_cur.symbol);
-                                               homebank_pref_get_boolean(keyfile, group, "IsPrefix", &PREFS->base_cur.is_prefix);
-                                       }
-                                       homebank_pref_get_string(keyfile, group, "DecChar"  , &PREFS->base_cur.decimal_char);
-                                       homebank_pref_get_string(keyfile, group, "GroupChar", &PREFS->base_cur.grouping_char);
-                                       homebank_pref_get_short(keyfile, group, "FracDigits", &PREFS->base_cur.frac_digits);
-                                       //fix 378992/421228
-                                       if( PREFS->base_cur.frac_digits > MAX_FRAC_DIGIT )
-                                               PREFS->base_cur.frac_digits = MAX_FRAC_DIGIT;
-                               }
                                if(version < 460)
                                {
                                gboolean useimperial;
  
                                homebank_pref_get_integer(keyfile, group, "DateRangeWal", &PREFS->date_range_wal);
                                homebank_pref_get_integer(keyfile, group, "DateRangeTxn", &PREFS->date_range_txn);
+                               homebank_pref_get_integer(keyfile, group, "DateFutureNbDays", &PREFS->date_future_nbdays);
                                homebank_pref_get_integer(keyfile, group, "DateRangeRep", &PREFS->date_range_rep);
  
                                if(version <= 7)
                                        else
                                        {
                                                homebank_pref_get_string(keyfile, group, "Symbol", &PREFS->minor_cur.symbol);
-                                               homebank_pref_get_boolean(keyfile, group, "IsPrefix", &PREFS->minor_cur.is_prefix);
+                                               homebank_pref_get_boolean(keyfile, group, "IsPrefix", &PREFS->minor_cur.sym_prefix);
                                        }
                                        homebank_pref_get_string(keyfile, group, "DecChar"  , &PREFS->minor_cur.decimal_char);
                                        homebank_pref_get_string(keyfile, group, "GroupChar", &PREFS->minor_cur.grouping_char);
                                        if( PREFS->minor_cur.frac_digits > MAX_FRAC_DIGIT )
                                                PREFS->minor_cur.frac_digits = MAX_FRAC_DIGIT;
  
+                                       da_cur_initformat(&PREFS->minor_cur);
                                }
  
                        //PREFS->euro_symbol = g_locale_to_utf8(tmpstr, -1, NULL, NULL, NULL);
  
                                DB( g_print(" -> ** Exchange\n") );
  
+                               //homebank_pref_get_boolean(keyfile, group, "DoIntro", &PREFS->dtex_nointro);
                                homebank_pref_get_integer(keyfile, group, "DateFmt", &PREFS->dtex_datefmt);
+                               homebank_pref_get_integer(keyfile, group, "OfxName", &PREFS->dtex_ofxname);
                                homebank_pref_get_integer(keyfile, group, "OfxMemo", &PREFS->dtex_ofxmemo);
+                               homebank_pref_get_boolean(keyfile, group, "QifMemo", &PREFS->dtex_qifmemo);
+                               homebank_pref_get_boolean(keyfile, group, "QifSwap", &PREFS->dtex_qifswap);
  
  
                        //group = "Chart";
                        //PREFS->chart_legend = g_key_file_get_boolean (keyfile, group, "Legend", NULL);
  
  
 +                      group = "Plugins";
 +                      {
 +                              DB( g_print(" -> ** Plugins\n") );
 +
 +                              gchar** strv = g_key_file_get_string_list(keyfile, group, "Path", NULL, NULL);
 +                              if (strv) {
 +                                      g_strfreev(PREFS->ext_path);
 +                                      PREFS->ext_path = strv;
 +                              }
 +
 +                              strv = g_key_file_get_string_list(keyfile, group, "Whitelist", NULL, NULL);
 +                              if (strv) {
 +                                      gchar** it;
 +                                      for (it = strv; it && *it; ++it) {
 +                                              PREFS->ext_whitelist = g_list_append(PREFS->ext_whitelist, g_strdup(*it));
 +                                      }
 +                                      g_strfreev(strv);
 +                              }
 +                      }
 +
 +
                        /*
                        #if MYDEBUG == 1
                        gsize length;
                g_free(filename);
                g_key_file_free (keyfile);
  
-               _homebank_pref_createformat();
                _homebank_pref_init_measurement_units();
        }
  
@@@ -976,8 -993,7 +1034,7 @@@ gsize length
                g_key_file_set_string (keyfile, group, "ColorInc" , PREFS->color_inc);
                g_key_file_set_string (keyfile, group, "ColorWarn", PREFS->color_warn);
  
-               g_key_file_set_boolean (keyfile, group, "RulesHint", PREFS->rules_hint);
+               g_key_file_set_integer (keyfile, group, "GridLines", PREFS->grid_lines);
  
                homebank_pref_set_string  (keyfile, group, "WalletPath"   , PREFS->path_hbfile);
                homebank_pref_set_string  (keyfile, group, "ImportPath"   , PREFS->path_import);
                g_key_file_set_boolean (keyfile, group, "ShowSplash", PREFS->showsplash);
                g_key_file_set_boolean (keyfile, group, "LoadLast", PREFS->loadlast);
                g_key_file_set_boolean (keyfile, group, "AppendScheduled", PREFS->appendscheduled);
+               g_key_file_set_boolean (keyfile, group, "UpdateCurrency", PREFS->do_update_currency);
  
                g_key_file_set_boolean (keyfile, group, "HeritDate", PREFS->heritdate);
                g_key_file_set_boolean (keyfile, group, "HideReconciled", PREFS->hidereconciled);
+               g_key_file_set_boolean (keyfile, group, "ShowRemind", PREFS->showremind);
  
                g_key_file_set_integer_list(keyfile, group, "ColumnsOpe", PREFS->lst_ope_columns, NUM_LST_DSPOPE-1);
+               g_key_file_set_integer_list(keyfile, group, "ColumnsOpeWidth", PREFS->lst_ope_col_size, NUM_LST_DSPOPE-1);
                g_key_file_set_integer     (keyfile, group, "OpeSortId" , PREFS->lst_ope_sort_id);
                g_key_file_set_integer     (keyfile, group, "OpeSortOrder" , PREFS->lst_ope_sort_order);
  
                g_key_file_set_integer_list(keyfile, group, "Bud", (gint *)&PREFS->bud_wg, 5);
                g_key_file_set_integer_list(keyfile, group, "Car", (gint *)&PREFS->cst_wg, 5);
  
+               g_key_file_set_integer_list(keyfile, group, "Txn", (gint *)&PREFS->txn_wg, 5);
                g_key_file_set_integer (keyfile, group, "WalVPaned" , PREFS->wal_vpaned);
                g_key_file_set_integer (keyfile, group, "WalHPaned" , PREFS->wal_hpaned);
                g_key_file_set_boolean (keyfile, group, "WalToolbar", PREFS->wal_toolbar);
                group = "Format";
                homebank_pref_set_string  (keyfile, group, "DateFmt"   , PREFS->date_format);
  
-               homebank_pref_set_string  (keyfile, group, "Symbol" , PREFS->base_cur.symbol);
-               g_key_file_set_boolean    (keyfile, group, "IsPrefix" , PREFS->base_cur.is_prefix);
-               homebank_pref_set_string  (keyfile, group, "DecChar"   , PREFS->base_cur.decimal_char);
-               homebank_pref_set_string  (keyfile, group, "GroupChar" , PREFS->base_cur.grouping_char);
-               g_key_file_set_integer (keyfile, group, "FracDigits", PREFS->base_cur.frac_digits);
                //g_key_file_set_boolean (keyfile, group, "UKUnits" , PREFS->imperial_unit);
                g_key_file_set_boolean (keyfile, group, "UnitIsMile" , PREFS->vehicle_unit_ismile);
                g_key_file_set_boolean (keyfile, group, "UnitIsGal" , PREFS->vehicle_unit_isgal);
                group = "Filter";
                g_key_file_set_integer (keyfile, group, "DateRangeWal", PREFS->date_range_wal);
                g_key_file_set_integer (keyfile, group, "DateRangeTxn", PREFS->date_range_txn);
+               g_key_file_set_integer (keyfile, group, "DateFutureNbdays", PREFS->date_future_nbdays);
                g_key_file_set_integer (keyfile, group, "DateRangeRep", PREFS->date_range_rep);
  
                DB( g_print(" -> ** euro\n") );
                        g_ascii_dtostr(ratestr, 63, PREFS->euro_value);
                        homebank_pref_set_string  (keyfile, group, "ChangeRate", ratestr);
                        homebank_pref_set_string  (keyfile, group, "Symbol" , PREFS->minor_cur.symbol);
-                       g_key_file_set_boolean    (keyfile, group, "IsPrefix" , PREFS->minor_cur.is_prefix);
+                       g_key_file_set_boolean    (keyfile, group, "IsPrefix" , PREFS->minor_cur.sym_prefix);
                        homebank_pref_set_string  (keyfile, group, "DecChar"   , PREFS->minor_cur.decimal_char);
                        homebank_pref_set_string  (keyfile, group, "GroupChar" , PREFS->minor_cur.grouping_char);
                        g_key_file_set_integer (keyfile, group, "FracDigits", PREFS->minor_cur.frac_digits);
  
  
                group = "Exchange";
+               //g_key_file_set_boolean (keyfile, group, "DoIntro", PREFS->dtex_nointro);
                g_key_file_set_integer (keyfile, group, "DateFmt", PREFS->dtex_datefmt);
+               g_key_file_set_integer (keyfile, group, "OfxName", PREFS->dtex_ofxname);
                g_key_file_set_integer (keyfile, group, "OfxMemo", PREFS->dtex_ofxmemo);
+               g_key_file_set_boolean (keyfile, group, "QifMemo", PREFS->dtex_qifmemo);
+               g_key_file_set_boolean (keyfile, group, "QifSwap", PREFS->dtex_qifswap);
  
                //group = "Chart";
                //g_key_file_set_boolean (keyfile, group, "Legend", PREFS->chart_legend);
  
 +              group = "Plugins";
 +              {
 +                      g_key_file_set_string_list(keyfile, group, "Path", (const gchar* const*)PREFS->ext_path, g_strv_length(PREFS->ext_path));
 +
 +                      gsize len = g_list_length(PREFS->ext_whitelist);
 +                      gchar** strv = g_new0(gchar*, len + 1);
 +                      guint i;
 +
 +                      for (i = 0; i < len; ++i) {
 +                              strv[i] = g_list_nth_data(PREFS->ext_whitelist, i);
 +                      }
 +                      g_key_file_set_string_list(keyfile, group, "Whitelist", (const gchar* const*)strv, len);
 +                      g_free(strv);
 +              }
 +
                //g_key_file_set_string  (keyfile, group, "", PREFS->);
                //g_key_file_set_boolean (keyfile, group, "", PREFS->);
                //g_key_file_set_integer (keyfile, group, "", PREFS->);
                g_key_file_free (keyfile);
        }
  
-       _homebank_pref_createformat();
        _homebank_pref_init_measurement_units();
  
        return retval;
diff --combined src/hb-preferences.h
index ae8d259a36184001e0f69ae0da3d8ea7d6bb3f5d,a9ac1e77ae4330c2fe4b05195a06683774b437fc..4b1cc72fcd2123ead2075c365917e4e7ce505aa5
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
@@@ -20,6 -20,8 +20,8 @@@
  #ifndef __HB_PREFERENCES_H__
  #define __HB_PREFERENCES_H__
  
+ #include "hb-currency.h"
  #define DEFAULT_FORMAT_DATE                   "%x"
  
  #define MAX_FRAC_DIGIT                6
  /*
  ** Preference datas
  */
- struct CurrencyFmt
- {
-       //gchar         *prefix_symbol;         /* max symbol is 3 digits in unicode */
-       //gchar         *suffix_symbol;         /* but mostly is 1 digit, and most are prefix ~100  */
-       gchar       *symbol;
-       gboolean        is_prefix;
-       gchar           *decimal_char;  
-       gchar           *grouping_char; 
-       gshort          frac_digits;
-       gchar           format[8];                      /* hold decimal format: '%.xf' */
-       gchar           monfmt[32];                     /* hold monetary format: 'prefix %s suffix' */ 
- };
  
  struct WinGeometry
  {
@@@ -67,82 -57,67 +57,67 @@@ struct Preference
        gboolean        showsplash;
        gboolean        loadlast;
        gboolean        appendscheduled;
-       gchar      *language;
-       
-       gchar           *path_hbfile;
-       gchar           *path_import;
-       gchar           *path_export;
-       gboolean        heritdate;
-       gboolean        hidereconciled;
-       gint            date_range_wal;
-       gint            date_range_txn;
-       gint            date_range_rep;
+       gboolean        do_update_currency;
        gshort          fisc_year_day;
        gshort          fisc_year_month;
-       
+       gint            date_range_wal;
+       gchar           *path_hbfile;
        //interface
+       gchar           *language;
        gshort          toolbar_style;
+       //gboolean      rules_hint;
+       gshort          grid_lines;
        gboolean        custom_colors;
        gchar           *color_exp;
        gchar           *color_inc;
        gchar           *color_warn;
-       gboolean        rules_hint;
+       //transactions
+       gint            date_range_txn;
+       gint            date_future_nbdays;
+       gboolean        hidereconciled;
+       gboolean    showremind;
+       gboolean        heritdate;
+       gint            lst_ope_columns[NUM_LST_DSPOPE+1];
+       gint            lst_ope_col_size[NUM_LST_DSPOPE+1];
+       gint            lst_ope_sort_id;        // -- implicit --
+       gint            lst_ope_sort_order; // -- implicit --
  
        //display format
        gchar           *date_format;
+       gchar       IntCurrSymbol[8];
+       gboolean        vehicle_unit_ismile;    // true if unit is mile, default Km
+       gboolean        vehicle_unit_isgal;             // true if unit is gallon, default Liter
  
-       struct  CurrencyFmt base_cur;
-       //gshort        num_nbdecimal;
-       //gboolean      num_separator;
-       //gboolean      imperial_unit;
-       //help system
-       //gboolean      show_tooltips;
-       //gboolean      show_help_button;
-       //gboolean      show_tipofday;
-       //gchar         *path_navigator;
-       //currency
-       //gchar         *curr_default;
-       
-       //euro zone
-       gboolean        euro_active;
-       gint            euro_country;
-       gdouble         euro_value;
-       struct  CurrencyFmt minor_cur;
-       //gshort        euro_nbdec;
-       //gboolean      euro_thsep;
-       //gchar         *euro_symbol;
+       //data exchange options
+       gboolean        dtex_nointro;
+       gint            dtex_datefmt;
+       gint            dtex_ofxname;
+       gint            dtex_ofxmemo;
+       gboolean        dtex_qifmemo;
+       gboolean        dtex_qifswap;
+       gchar           *path_import;
+       gchar           *path_export;
  
        //report options
+       gint            date_range_rep;
+       gint            report_color_scheme;
        gboolean        stat_byamount;
        gboolean        stat_showrate;
        gboolean        stat_showdetail;
        gboolean        budg_showdetail;
-       gint            report_color_scheme;
  
-       //data exchange options
-       gint            dtex_ofxmemo;
-       gint            dtex_datefmt;
+       //euro zone
+       gboolean        euro_active;
+       gint            euro_country;
+       gdouble         euro_value;
+       Currency        minor_cur;
  
        //chart options
-       gboolean        chart_legend;
-       
-       /* internal : not saved*/
-       gint    lst_ope_columns[NUM_LST_DSPOPE+1];
-       gint    lst_ope_sort_id;
-       gint    lst_ope_sort_order;
+       //gboolean      chart_legend;
  
-       /* windows size an position */
+       /* windows/dialogs size an position */
        struct WinGeometry      wal_wg;
        struct WinGeometry      acc_wg;
        struct WinGeometry      sta_wg;
        struct WinGeometry      bud_wg;
        struct WinGeometry      cst_wg;
  
+       struct WinGeometry      txn_wg;
        gboolean        wal_toolbar;
        gboolean        wal_spending;
        gboolean        wal_upcoming;
        gint            wal_hpaned;
  
        //vehiclecost units (mile/gal or km/liters)
-       gboolean        vehicle_unit_ismile;    // true is unit is mile, default Km
-       gboolean        vehicle_unit_isgal;             // true is unit is gallon, default Liter
        
        gchar      *vehicle_unit_dist;
        gchar      *vehicle_unit_vol;
        gchar      *vehicle_unit_100;
        gchar      *vehicle_unit_distbyvol;
  
 +      // plugins
 +      gchar** ext_path;
 +      GList* ext_whitelist;
 +
  };
  
  
diff --combined src/hb-tag.c
index c8353a489d0916c616c4929c81db437ba2d97d1c,bf4ba696add250e67a8e119719b45ea5f030ff1b..42412c944b9a248f4bd9b08949959f8f9e9acbf3
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
@@@ -20,9 -20,6 +20,9 @@@
  #include "homebank.h"
  #include "hb-tag.h"
  
 +#include "ext.h"
 +#include "refcount.h"
 +
  #define MYDEBUG 0
  
  #if MYDEBUG
@@@ -40,12 -37,12 +40,12 @@@ extern struct HomeBank *GLOBALS
  void da_tag_free(Tag *item)
  {
        DB( g_print("da_tag_free\n") );
 -      if(item != NULL)
 +      if(rc_unref(item))
        {
                DB( g_print(" => %d, %s\n", item->key, item->name) );
  
                g_free(item->name);
 -              g_free(item);
 +              rc_free(item);
        }
  }
  
@@@ -53,7 -50,7 +53,7 @@@
  Tag *da_tag_malloc(void)
  {
        DB( g_print("da_tag_malloc\n") );
 -      return g_malloc0(sizeof(Tag));
 +      return rc_alloc(sizeof(Tag));
  }
  
  
@@@ -100,9 -97,9 +100,9 @@@ guint da_tag_length(void
  /**
   * da_tag_remove:
   *
-  * remove an tag from the GHashTable
+  * delete an tag from the GHashTable
   *
-  * Return value: TRUE if the key was found and removed
+  * Return value: TRUE if the key was found and deleted
   *
   */
  gboolean da_tag_remove(guint32 key)
diff --combined src/hb-transaction.c
index 1d6699871a85d174156d7e893b3d8ee2fe1be5de,2758da6d04404bc1d78e0788fab1c939059bcfb4..17fbad5dda73d181bab1c45845f4b9d200dcb3b1
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
  
  #include "hb-transaction.h"
  #include "hb-tag.h"
+ #include "hb-split.h"
  
 +#include "ext.h"
 +#include "refcount.h"
 +
  /****************************************************************************/
- /* Debug macros                                                                                */
+ /* Debug macros                                                                                                       */
  /****************************************************************************/
  #define MYDEBUG 0
  
@@@ -41,131 -39,6 +42,6 @@@ extern struct HomeBank *GLOBALS
  extern struct Preferences *PREFS;
  
  
- /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
- static void da_split_free(Split *item)
- {
-       if(item != NULL)
-       {
-               if(item->memo != NULL)
-                       g_free(item->memo);
-               g_free(item);
-       }
- }
- static Split *da_split_malloc(void)
- {
-       return g_malloc0(sizeof(Split));
- }
- Split *da_split_new(guint32 kcat, gdouble amount, gchar       *memo)
- {
- Split *split = da_split_malloc();
-       split->kcat = kcat;
-       split->amount = amount;
-       split->memo = g_strdup(memo);
-       return split;
- }
- static Split *da_split_clone(Split *src_split)
- {
- Split *new_split = g_memdup(src_split, sizeof(Split));
-       DB( g_print("da_split_clone\n") );
-       if(new_split)
-       {
-               //duplicate the string
-               new_split->memo = g_strdup(src_split->memo);
-               DB( g_print(" clone %p -> %p\n", src_split, new_split) );
-       }
-       return new_split;
- }
- /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
- guint da_transaction_splits_count(Transaction *txn)
- {
- guint i, count = 0;
-       for(i=0;i<TXN_MAX_SPLIT;i++)
-       {
-               if(txn->splits[i] == NULL)
-                       break;
-               count++;
-       }
-       return count;
- }
- void da_transaction_splits_free(Transaction *txn)
- {
- guint count, i=0;
-       count = da_transaction_splits_count(txn);
-       if(count == 0)
-               return;
-       
-       DB( g_print("da_transaction_splits_free\n") );
-       for(;i<=count;i++)
-       {
-               DB( g_print("- freeing %d :: %p\n", i, txn->splits[i]) );
-               
-               da_split_free(txn->splits[i]);
-               txn->splits[i] = NULL;
-       }
-       //remove the flag
-       txn->flags &= ~(OF_SPLIT);
- }
- void da_transaction_splits_append(Transaction *txn, Split *split)
- {
- guint count = da_transaction_splits_count(txn);
-       DB( g_print("da_transaction_splits_append\n") );
-       DB( g_print("- split[%d] at %p for ope %p\n", count, split, txn) );
-       txn->flags |= OF_SPLIT;
-       txn->splits[count] = split;
-       txn->splits[count + 1] = NULL;
-       
-       DB( g_print("- %d splits\n", da_transaction_splits_count(txn)) );
- }
- void da_transaction_splits_clone(Transaction *stxn, Transaction *dtxn)
- {
- gint i, count;
-       DB( g_print("da_transaction_splits_clone\n") );
-       
-       count = da_transaction_splits_count(stxn);
-       for(i=0;i<count;i++)
-       {
-               dtxn->splits[i] = da_split_clone(stxn->splits[i]);
-       }       
-       if(count > 0)
-               dtxn->flags |= OF_SPLIT;
-       
-       DB( g_print(" clone %p -> %p, %d splits\n", stxn, dtxn, count) );
- }
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  
  void
@@@ -190,7 -63,8 +66,8 @@@ da_transaction_clean(Transaction *item
                        item->tags = NULL;
                }
  
-               da_transaction_splits_free(item);
+               da_splits_free(item->splits);
+               item->flags &= ~(OF_SPLIT); //Flag that Splits are cleared
  
                if(item->same != NULL)
                {
  void
  da_transaction_free(Transaction *item)
  {
 -      if(item != NULL)
 +      if(rc_unref(item))
        {
                da_transaction_clean(item);
 -              g_free(item);
 +              rc_free(item);
        }
  }
  
  Transaction *
  da_transaction_malloc(void)
  {
 -      return g_malloc0(sizeof(Transaction));
 +      return rc_alloc(sizeof(Transaction));
  }
  
  
  Transaction *da_transaction_copy(Transaction *src_txn, Transaction *dst_txn)
  {
- guint count;
        DB( g_print("da_transaction_copy\n") );
  
        da_transaction_clean (dst_txn);
        dst_txn->info = g_strdup(src_txn->info);
  
        //duplicate tags
-       dst_txn->tags = NULL;
-       count = transaction_tags_count(src_txn);
-       if(count > 0)
-               dst_txn->tags = g_memdup(src_txn->tags, count*sizeof(guint32));
+       transaction_tags_clone(src_txn, dst_txn);
  
-       da_transaction_splits_clone(src_txn, dst_txn);
+       if (da_splits_clone(src_txn->splits, dst_txn->splits) > 0)
+               dst_txn->flags |= OF_SPLIT; //Flag that Splits are active
  
        return dst_txn;
  }
  Transaction *da_transaction_init_from_template(Transaction *txn, Archive *arc)
  {
        //txn->date             = 0;
-       txn->amount             = arc->amount;
-       txn->kacc               = arc->kacc;
+       txn->amount     = arc->amount;
+       //#1258344 keep the current account if tpl is empty
+       if(arc->kacc)
+               txn->kacc       = arc->kacc;
        txn->paymode    = arc->paymode;
        txn->flags              = arc->flags | OF_ADDED;
+       txn->status             = arc->status;
        txn->kpay               = arc->kpay;
        txn->kcat               = arc->kcat;
        txn->kxferacc   = arc->kxferacc;
        txn->wording    = g_strdup(arc->wording);
        txn->info               = NULL;
+       if( da_splits_clone(arc->splits, txn->splits) > 0)
+               txn->flags |= OF_SPLIT; //Flag that Splits are active
  
        return txn;
  }
  
  Transaction *da_transaction_clone(Transaction *src_item)
  {
 -Transaction *new_item = g_memdup(src_item, sizeof(Transaction));
 +Transaction *new_item = rc_dup(src_item, sizeof(Transaction));
- guint count;
  
        DB( g_print("da_transaction_clone\n") );
  
                new_item->info = g_strdup(src_item->info);
  
                //duplicate tags
-               new_item->tags = NULL;
-               count = transaction_tags_count(src_item);
-               if(count > 0)
-                       new_item->tags = g_memdup(src_item->tags, count*sizeof(guint32));
-               da_transaction_splits_clone(src_item, new_item);
+               transaction_tags_clone(src_item, new_item);
+               
+               if( da_splits_clone(src_item->splits, new_item->splits) > 0)
+                       new_item->flags |= OF_SPLIT; //Flag that Splits are active
  
        }
        return new_item;
  }
  
  GList *
  da_transaction_new(void)
  {
  }
  
  
- void da_transaction_destroy(GList *list)
+ guint
+ da_transaction_length(void)
+ {
+ GList *lst_acc, *lnk_acc;
+ guint count = 0;
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
+       {
+       Account *acc = lnk_acc->data;
+       
+               count += g_queue_get_length (acc->txn_queue);
+               lnk_acc = g_list_next(lnk_acc);
+       }
+       g_list_free(lst_acc);
+       return count;
+ }
+ static void da_transaction_queue_free_ghfunc(Transaction *item, gpointer data)
+ {
+       da_transaction_free (item);
+ }
+ void da_transaction_destroy(void)
  {
- GList *tmplist = g_list_first(list);
+ GList *lacc, *list;
  
-       while (tmplist != NULL)
+       lacc = g_hash_table_get_values(GLOBALS->h_acc);
+       list = g_list_first(lacc);
+       while (list != NULL)
        {
-       Transaction *item = tmplist->data;
-               da_transaction_free(item);
-               tmplist = g_list_next(tmplist);
+       Account *acc = list->data;
+               g_queue_foreach(acc->txn_queue, (GFunc)da_transaction_queue_free_ghfunc, NULL);
+               list = g_list_next(list);
        }
-       g_list_free(list);
+       g_list_free(lacc);
+ }
+ static gint da_transaction_compare_datafunc(Transaction *a, Transaction *b, gpointer data)
+ {
+       return ((gint)a->date - b->date);
+ }
+ void da_transaction_queue_sort(GQueue *queue)
+ {
+       g_queue_sort(queue, (GCompareDataFunc)da_transaction_compare_datafunc, NULL);
  }
  
  
@@@ -334,24 -248,28 +251,28 @@@ static void da_transaction_insert_memo(
  }
  
  
  gboolean da_transaction_insert_sorted(Transaction *newitem)
  {
- GList *tmplist = g_list_first(GLOBALS->ope_list);
+ Account *acc;
+ GList *lnk_txn;
  
-       // find the breaking date
-       while (tmplist != NULL)
+       acc = da_acc_get(newitem->kacc);
+       if(!acc) 
+               return FALSE;
+       
+       lnk_txn = g_queue_peek_tail_link(acc->txn_queue);
+       while (lnk_txn != NULL)
        {
-       Transaction *item = tmplist->data;
+       Transaction *item = lnk_txn->data;
  
-               if(item->date > newitem->date)
+               if(item->date <= newitem->date)
                        break;
-               tmplist = g_list_next(tmplist);
+               
+               lnk_txn = g_list_previous(lnk_txn);
        }
  
-       // here we're at the insert point, let's insert our new txn just before
-       GLOBALS->ope_list = g_list_insert_before(GLOBALS->ope_list, tmplist, newitem);
+       // we're at insert point, insert after txn
+       g_queue_insert_after(acc->txn_queue, lnk_txn, newitem);
  
        da_transaction_insert_memo(newitem);
        return TRUE;
  // nota: this is called only when loading xml file
  gboolean da_transaction_prepend(Transaction *item)
  {
-       GLOBALS->ope_list = g_list_prepend(GLOBALS->ope_list, item);
+ Account *acc;
+       acc = da_acc_get(item->kacc);
+       if(acc)
+               item->kcur = acc->kcur;
+       g_queue_push_tail(acc->txn_queue, item);
        da_transaction_insert_memo(item);
        return TRUE;
  }
  
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  
- guint32
static guint32
  da_transaction_get_max_kxfer(void)
  {
guint32 max_key = 0;
GList *lst_acc, *lnk_acc;
  GList *list;
Transaction *item;
guint32 max_key = 0;
  
        DB( g_print("da_transaction_get_max_kxfer\n") );
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
        {
-               item = list->data;
-               if( item->paymode == PAYMODE_INTXFER)
+       Account *acc = lnk_acc->data;
+               list = g_queue_peek_head_link(acc->txn_queue);
+               while (list != NULL)
                {
-                       if( item->kxfer > max_key)
-                               max_key = item->kxfer;
+               Transaction *item = list->data;
+                       if( item->paymode == PAYMODE_INTXFER )
+                       {
+                               max_key = MAX(max_key, item->kxfer);
+                       }
+                       list = g_list_next(list);
                }
-               list = g_list_next(list);
+               
+               lnk_acc = g_list_next(lnk_acc);
        }
+       g_list_free(lst_acc);
  
        DB( g_print(" max_key : %d \n", max_key) );
  
        return max_key;
  }
  
  static void da_transaction_goto_orphan(Transaction *txn)
  {
  const gchar *oatn = "orphaned transactions";
@@@ -417,7 -350,10 +353,10 @@@ void da_transaction_consistency(Transac
  Account *acc;
  Category *cat;
  Payee *pay;
- guint i, nbsplit;
+ gint nbsplit;
+       // ensure date is between range
+       item->date = CLAMP(item->date, HB_MINDATE, HB_MAXDATE);
  
        // check account exists
        acc = da_acc_get(item->kacc);
        {
                g_warning("txn consistency: fixed invalid acc %d", item->kacc);
                da_transaction_goto_orphan(item);
+               GLOBALS->changes_count++;
        }
  
        // check category exists
        {
                g_warning("txn consistency: fixed invalid cat %d", item->kcat);
                item->kcat = 0;
+               GLOBALS->changes_count++;
        }
  
        // check split category #1340142
-       nbsplit = da_transaction_splits_count(item);
-       for(i=0;i<nbsplit;i++)
+       split_cat_consistency(item->splits);
+       //# 1416624 empty category when split
+       nbsplit = da_splits_count(item->splits);
+       if(nbsplit > 0 && item->kcat > 0)
        {
-       Split *split = item->splits[i];
-               cat = da_cat_get(split->kcat);
-               if(cat == NULL)
-               {
-                       g_warning("txn consistency: fixed invalid split cat %d", split->kcat);
-                       split->kcat = 0;
-               }
+               g_warning("txn consistency: fixed invalid cat on split txn");
+               item->kcat = 0;
+               GLOBALS->changes_count++;
        }
        
        // check payee exists
        {
                g_warning("txn consistency: fixed invalid pay %d", item->kpay);
                item->kpay = 0;
+               GLOBALS->changes_count++;
        }
  
        // reset dst acc for non xfer transaction
        if( item->paymode != PAYMODE_INTXFER )
                item->kxferacc = 0;
  
+       //#1628678 tags for internal xfer should be checked as well
        //#1295877 ensure income flag is correctly set
        item->flags &= ~(OF_INCOME);
        if( item->amount > 0)
                item->flags |= (OF_INCOME);
  
        //#1308745 ensure remind flag unset if reconciled
-       if( item->flags & OF_VALID )
-               item->flags &= ~(OF_REMIND);
+       //useless since 5.0
+       //if( item->flags & OF_VALID )
+       //      item->flags &= ~(OF_REMIND);
  
  }
  
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  /* new transfer functions */
  
Transaction *transaction_strong_get_child_transfer(Transaction *src)
static void transaction_xfer_create_child(Transaction *ope)
  {
GList *list;
      DB( g_print("\n[transaction] transaction_strong_get_child_transfer\n") );
Transaction *child;
+ Account *acc;
gchar swap;
  
-       DB( g_print(" - search: %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->kacc, src->kxferacc) );
+       DB( g_print("\n[transaction] transaction_xfer_create_child\n") );
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
+       if( ope->kxferacc > 0 )
        {
-               Transaction *item = list->data;
-               //#1252230
-               //if( item->paymode == PAYMODE_INTXFER && item->kacc == src->kxferacc && item->kxfer == src->kxfer )
-               if( item->paymode == PAYMODE_INTXFER && item->kxfer == src->kxfer && item != src )
+               child = da_transaction_clone(ope);
+               ope->flags |= OF_CHANGED;
+               child->flags |= OF_ADDED;
+               child->amount = -child->amount;
+               child->flags ^= (OF_INCOME);    // invert flag
+               //#1268026
+               child->status = TXN_STATUS_NONE;
+               //child->flags &= ~(OF_VALID);  // delete reconcile state
+               swap = child->kacc;
+               child->kacc = child->kxferacc;
+               child->kxferacc = swap;
+               /* update acc flags */
+               acc = da_acc_get( child->kacc );
+               if(acc != NULL)
                {
-                       DB( g_print(" - found : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->kacc, item->kxferacc) );
-                       return item;
+                       acc->flags |= AF_ADDED;
+                       //strong link
+                       guint maxkey = da_transaction_get_max_kxfer();
+                       DB( g_print(" + maxkey is %d\n", maxkey) );
+                       ope->kxfer = maxkey+1;
+                       child->kxfer = maxkey+1;
+                       DB( g_print(" + strong link to %d\n", ope->kxfer) );
+                       DB( g_print(" + add transfer, %p\n", child) );
+                       da_transaction_insert_sorted(child);
+                       account_balances_add (child);
++                      GValue txn_value = G_VALUE_INIT;
++                      ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value, child), NULL);
++
                }
-               list = g_list_next(list);
        }
-       DB( g_print(" - not found...\n") );
-       return NULL;
  }
  
  
- /*
-  * this function retrieve into a glist the potential child transfer
-  * for the source transaction
-  */
- GList *transaction_match_get_child_transfer(Transaction *src)
+ //todo: add strong control and extend to payee, maybe memo ?
+ static gboolean transaction_xfer_child_might(Transaction *stxn, Transaction *dtxn, gint daygap)
  {
- GList *list;
- GList *match = NULL;
+ gboolean retval = FALSE;
  
-       DB( g_print("\n[transaction] transaction_match_get_child_transfer\n") );
+       if(stxn == dtxn)
+               return FALSE;
  
-       //DB( g_print(" - search : %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->account, src->kxferacc) );
+       /*g_print("test\n");
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
-       {
-               Transaction *item = list->data;
-               if( src->date == item->date &&
-                   src->kxferacc == item->kacc &&
-                   ABS(src->amount) == ABS(item->amount) &&
-                   item->kxfer == 0)
-               {
-                       //DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) );
+       g_print(" %d %d %d %f %d\n", 
+               stxn->kcur, stxn->date, stxn->kacc, ABS(stxn->amount), stxn->kxfer );
  
-                       match = g_list_append(match, item);
-               }
-               list = g_list_next(list);
-       }
  
-       DB( g_print(" - found : %d\n", g_list_length(match)) );
+       g_print(" %d %d %d %f %d\n", 
+               dtxn->kcur, dtxn->date, dtxn->kacc, ABS(dtxn->amount), dtxn->kxfer );
+       */
  
-       return match;
+       if( stxn->kcur == dtxn->kcur &&
+           stxn->date == dtxn->date &&
+           //v5.1 make no sense: stxn->kxferacc == dtxn->kacc &&
+           stxn->kacc != dtxn->kacc &&
+           ABS(stxn->amount) == ABS(dtxn->amount) &&
+           dtxn->kxfer == 0)
+       {
+               retval = TRUE;
+       }
+       //g_print(" return %d\n", retval);
+       return retval;
  }
  
  
void transaction_xfer_search_or_add_child(Transaction *ope, GtkWidget *treeview)
static GList *transaction_xfer_child_might_list_get(Transaction *ope)
  {
- GList *matchlist = transaction_match_get_child_transfer(ope);
+ GList *lst_acc, *lnk_acc;
+ GList *list, *matchlist = NULL;
+       DB( g_print("\n[transaction]xfer_get_potential_child\n") );
  
- guint count = g_list_length(matchlist);
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
+       {
+       Account *acc = lnk_acc->data;
  
+               if( !(acc->flags & AF_CLOSED) && (acc->key != ope->kacc) )
+               {
+                       list = g_queue_peek_tail_link(acc->txn_queue);
+                       while (list != NULL)
+                       {
+                       Transaction *item = list->data;
+       
+                               // no need to go higher than src txn date
+                               if(item->date < ope->date)
+                                       break;
+               
+                               if( transaction_xfer_child_might(ope, item, 0) == TRUE )
+                               {
+                                       //DB( g_print(" - match : %d %s %f %d=>%d\n", item->date, item->wording, item->amount, item->account, item->kxferacc) );
+                                       matchlist = g_list_append(matchlist, item);
+                               }
+                               list = g_list_previous(list);
+                       }
+               }
+               
+               lnk_acc = g_list_next(lnk_acc);
+       }
+       g_list_free(lst_acc);
+       return matchlist;
+ }
+ void transaction_xfer_search_or_add_child(GtkWindow *parentwindow, Transaction *ope, gboolean manual)
+ {
+ GList *matchlist;
+ gint count;
  
        DB( g_print("\n[transaction] transaction_xfer_search_or_add_child\n") );
  
+       matchlist = transaction_xfer_child_might_list_get(ope);
+       count = g_list_length(matchlist);
        DB( g_print(" - found result is %d, switching\n", count) );
  
        switch(count)
        {
                case 0:         //we should create the child
-                       transaction_xfer_create_child(ope, treeview);
+                       transaction_xfer_create_child(ope);
                        break;
  
                //todo: maybe with just 1 match the user must choose ?
  
                default:        //the user must choose himself
                {
-               Transaction *child;
+       Transaction *child;
  
-                       child = ui_dialog_transaction_xfer_select_child(matchlist);
-                       if(child == NULL)
-                               transaction_xfer_create_child(ope, treeview);
-                       else
-                               transaction_xfer_change_to_child(ope, child);
-                       break;
+                       child = ui_dialog_transaction_xfer_select_child(ope, matchlist);
+               if(child == NULL)
+                       transaction_xfer_create_child(ope);
+               else
+                       transaction_xfer_change_to_child(ope, child);
                }
        }
  
        g_list_free(matchlist);
  }
  
  
- void transaction_xfer_create_child(Transaction *ope, GtkWidget *treeview)
+ Transaction *transaction_xfer_child_strong_get(Transaction *src)
  {
- Transaction *child;
- Account *acc;
- gchar swap;
+ Account *dstacc;
+ GList *list;
  
-       DB( g_print("\n[transaction] transaction_xfer_create_child\n") );
+       DB( g_print("\n[transaction] transaction_xfer_child_strong_get\n") );
  
-       if( ope->kxferacc > 0 )
-       {
-               child = da_transaction_clone(ope);
+       dstacc = da_acc_get(src->kxferacc);
+       if( !dstacc || src->kxfer <= 0 )
+               return NULL;
  
-               child->amount = -child->amount;
-               child->flags ^= (OF_INCOME);    // invert flag
-               child->flags &= ~(OF_REMIND);   // remove flag
-               //#1268026
-               child->flags &= ~(OF_VALID);    // remove reconcile state
-               
+       DB( g_print(" - search: %d %s %f %d=>%d - %d\n", src->date, src->wording, src->amount, src->kacc, src->kxferacc, src->kxfer) );
  
-               swap = child->kacc;
-               child->kacc = child->kxferacc;
-               child->kxferacc = swap;
+       list = g_queue_peek_tail_link(dstacc->txn_queue);
+       while (list != NULL)
+       {
+       Transaction *item = list->data;
  
-               /* update acc flags */
-               acc = da_acc_get( child->kacc );
-               if(acc != NULL)
+               //#1252230
+               //if( item->paymode == PAYMODE_INTXFER 
+               //      && item->kacc == src->kxferacc
+               //      && item->kxfer == src->kxfer )
+               if( item->paymode == PAYMODE_INTXFER 
+                && item->kxfer == src->kxfer 
+                && item != src )
                {
-                       acc->flags |= AF_ADDED;
-                       //strong link
-                       guint maxkey = da_transaction_get_max_kxfer();
-                       DB( g_print(" + maxkey is %d\n", maxkey) );
-                       ope->kxfer = maxkey+1;
-                       child->kxfer = maxkey+1;
-                       DB( g_print(" + strong link to %d\n", ope->kxfer) );
-                       DB( g_print(" + add transfer, %p\n", child) );
-                       da_transaction_insert_sorted(child);
-                       account_balances_add (child);
-                       if(treeview != NULL)
-                               transaction_add_treeview(child, treeview, ope->kacc);
-                       GValue txn_value = G_VALUE_INIT;
-                       ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value, child), NULL);
+                       DB( g_print(" - found : %d %s %f %d=>%d - %d\n", item->date, item->wording, item->amount, item->kacc, item->kxferacc, src->kxfer) );
+                       return item;
                }
+               list = g_list_previous(list);
        }
+       
+       DB( g_print(" - not found...\n") );
+       return NULL;
  }
  
  
  void transaction_xfer_change_to_child(Transaction *ope, Transaction *child)
  {
- Account *acc;
+ Account *dstacc;
  
        DB( g_print("\n[transaction] transaction_xfer_change_to_child\n") );
  
+       if(ope->kcur != child->kcur)
+               return;
+       ope->flags |= OF_CHANGED;
+       child->flags |= OF_CHANGED;
        child->paymode = PAYMODE_INTXFER;
  
        ope->kxferacc = child->kacc;
        child->kxferacc = ope->kacc;
  
        /* update acc flags */
-       acc = da_acc_get( child->kacc);
-       if(acc != NULL)
-               acc->flags |= AF_CHANGED;
+       dstacc = da_acc_get( child->kacc);
+       if(dstacc != NULL)
+               dstacc->flags |= AF_CHANGED;
  
        //strong link
        guint maxkey = da_transaction_get_max_kxfer();
@@@ -697,45 -689,58 +695,58 @@@ void transaction_xfer_sync_child(Transa
  
        account_balances_add (child);
        
-       //todo: synchronise tags here also ?
+       //synchronise tags since 5.1
+       if(child->tags)
+               g_free(child->tags);
+       transaction_tags_clone (s_txn, child);
  
  }
  
  
- void transaction_xfer_delete_child(Transaction *src)
+ void transaction_xfer_remove_child(Transaction *src)
  {
  Transaction *dst;
  
-       DB( g_print("\n[transaction] transaction_xfer_delete_child\n") );
+       DB( g_print("\n[transaction] transaction_xfer_remove_child\n") );
  
-       dst = transaction_strong_get_child_transfer( src );
+       dst = transaction_xfer_child_strong_get( src );
  
        DB( g_print(" -> return is %s, %p\n", dst->wording, dst) );
  
        if( dst != NULL )
        {
+       Account *acc = da_acc_get(dst->kacc);
                DB( g_print("deleting...") );
                src->kxfer = 0;
                src->kxferacc = 0;
                account_balances_sub(dst);
-               GLOBALS->ope_list = g_list_remove(GLOBALS->ope_list, dst);
+               g_queue_remove(acc->txn_queue, dst);
+               da_transaction_free (dst);
        }
  }
  
  
+ // still useful for upgrade from < file v0.6 (hb v4.4 kxfer)
  Transaction *transaction_old_get_child_transfer(Transaction *src)
  {
+ Account *acc;
  GList *list;
- Transaction *item;
  
        DB( g_print("\n[transaction] transaction_get_child_transfer\n") );
  
        //DB( g_print(" search: %d %s %f %d=>%d\n", src->date, src->wording, src->amount, src->account, src->kxferacc) );
+       acc = da_acc_get(src->kxferacc);
  
-       list = g_list_first(GLOBALS->ope_list);
+       list = g_queue_peek_head_link(acc->txn_queue);
        while (list != NULL)
        {
-               item = list->data;
+       Transaction *item = list->data;
+               // no need to go higher than src txn date
+               if(item->date > src->date)
+                       break;
                if( item->paymode == PAYMODE_INTXFER)
                {
                        if( src->date == item->date &&
  }
  
  
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  
  
@@@ -773,13 -776,16 +782,16 @@@ Account *acc
        acc = da_acc_get(ope->kacc);
        if(acc == NULL) return;
  
+       ope->kcur = acc->kcur;
+       
        if(ope->paymode == PAYMODE_INTXFER)
        {
                acc = da_acc_get(ope->kxferacc);
                if(acc == NULL) return;
                
-               // remove any splits
-               da_transaction_splits_free(ope);
+               // delete any splits
+               da_splits_free(ope->splits);
+               ope->flags &= ~(OF_SPLIT); //Flag that Splits are cleared
        }
  
        //allocate a new entry and copy from our edited structure
  
                if(newope->paymode == PAYMODE_INTXFER)
                {
-                       transaction_xfer_search_or_add_child(newope, treeview);
+                       transaction_xfer_search_or_add_child(NULL, newope, FALSE);
                }
 +
 +              GValue txn_value = G_VALUE_INIT;
 +              ext_hook("transaction_inserted", EXT_TRANSACTION(&txn_value, newope), NULL);
        }
  }
  
  
  void transaction_add_treeview(Transaction *ope, GtkWidget *treeview, guint32 accnum)
  {
  GtkTreeModel *model;
@@@ -873,7 -874,33 +883,33 @@@ GtkTreeIter  iter
  }
  
  
+ gboolean transaction_acc_move(Transaction *txn, guint32 okacc, guint32 nkacc)
+ {
+ Account *oacc, *nacc;
+       oacc = da_acc_get(okacc);
+       nacc = da_acc_get(nkacc);
+       if( oacc && nacc )
+       {
+               if( g_queue_remove(oacc->txn_queue, txn) )
+               {
+                       g_queue_push_tail(nacc->txn_queue, txn);
+                       txn->kacc = nacc->key;
+                       txn->kcur = nacc->kcur;
+                       nacc->flags |= AF_CHANGED;
+                       return TRUE;
+               }
+               else
+                       //ensure to keep txn into current account
+                       txn->kacc = okacc;
+       }
+       return FALSE;
+ }
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  static gboolean misc_text_match(gchar *text, gchar *searchtext, gboolean exact)
  {
  gboolean match = FALSE;
        return match;
  }
  
+ static gboolean misc_regex_match(gchar *text, gchar *searchtext, gboolean exact)
+ {
+ gboolean match = FALSE;
+       if(text == NULL)
+               return FALSE;
+       
+       DB( g_print("match RE %s in %s\n", searchtext, text) );
+       if( searchtext != NULL )
+       {
+               match = g_regex_match_simple(searchtext, text, ((exact == TRUE)?0:G_REGEX_CASELESS) | G_REGEX_OPTIMIZE, G_REGEX_MATCH_NOTEMPTY );
+               if (match == TRUE) { DB( g_print(" found pattern '%s'\n", searchtext) ); }
+       }
+       return match;
+ }
  
  static Assign *transaction_auto_assign_eval_txn(GList *l_rul, Transaction *txn)
  {
@@@ -931,8 -974,17 +983,17 @@@ GList *list
                        if(pay)
                                text = pay->name;
                }
-               if( misc_text_match(text, rul->name, rul->flags & ASGF_EXACT))
-                       rule = rul;
+               
+               if( !(rul->flags & ASGF_REGEX) )
+               {
+                       if( misc_text_match(text, rul->text, rul->flags & ASGF_EXACT) )
+                               rule = rul;
+               }
+               else
+               {
+                       if( misc_regex_match(text, rul->text, rul->flags & ASGF_EXACT) )
+                               rule = rul;
+               }
  
                list = g_list_next(list);
        }
@@@ -955,8 -1007,16 +1016,16 @@@ GList *list
  
                if( rul->field == 0 )   //memo
                {
-                       if( misc_text_match(text, rul->name, rul->flags & ASGF_EXACT))
-                               rule = rul;
+                       if( !(rul->flags & ASGF_REGEX) )
+                       {
+                               if( misc_text_match(text, rul->text, rul->flags & ASGF_EXACT) )
+                                       rule = rul;
+                       }
+                       else
+                       {
+                               if( misc_regex_match(text, rul->text, rul->flags & ASGF_EXACT) )
+                                       rule = rul;
+                       }
                }
                list = g_list_next(list);
        }
  }
  
  
- gint transaction_auto_assign(GList *ope_list, guint32 key)
+ gint transaction_auto_assign(GList *ope_list, guint32 kacc)
  {
  GList *l_ope;
  GList *l_rul;
@@@ -973,73 -1033,79 +1042,79 @@@ gint changes = 0
  
        DB( g_print("\n[transaction] transaction_auto_assign\n") );
  
-       l_ope = g_list_first(ope_list);
        l_rul = g_hash_table_get_values(GLOBALS->h_rul);
  
+       l_ope = g_list_first(ope_list);
        while (l_ope != NULL)
        {
        Transaction *ope = l_ope->data;
+       gboolean changed = FALSE; 
  
                DB( g_print("- eval ope '%s' : acc=%d, pay=%d, cat=%d\n", ope->wording, ope->kacc, ope->kpay, ope->kcat) );
  
-               //#1215521: added key == 0
-               if( (key == ope->kacc || key == 0) )
+               //#1215521: added kacc == 0
+               if( (kacc == ope->kacc || kacc == 0) )
                {
                Assign *rul;
  
-                       if( !(ope->flags & OF_SPLIT) && (ope->kpay == 0 || ope->kcat == 0) )
+                       rul = transaction_auto_assign_eval_txn(l_rul, ope);
+                       if( rul != NULL )
                        {
-                               rul = transaction_auto_assign_eval_txn(l_rul, ope);
-                               if( rul != NULL )
+                               if( (ope->kpay == 0 && (rul->flags & ASGF_DOPAY)) || (rul->flags & ASGF_OVWPAY) )
+                               {
+                                       if(ope->kpay != rul->kpay) { changed = TRUE; }
+                                       ope->kpay = rul->kpay;
+                               }
+                               if( !(ope->flags & OF_SPLIT) )
                                {
-                                       if( ope->kpay == 0 && (rul->flags & ASGF_DOPAY) )
+                                       if( (ope->kcat == 0 && (rul->flags & ASGF_DOCAT)) || (rul->flags & ASGF_OVWCAT) )
                                        {
-                                               ope->kpay = rul->kpay;
-                                               ope->flags |= OF_CHANGED;
-                                               changes++;
+                                               if(ope->kcat != rul->kcat) { changed = TRUE; }
+                                               ope->kcat = rul->kcat;
                                        }
-                                       if( ope->kcat == 0 && (rul->flags & ASGF_DOCAT) )
+                               }
+                               if( (ope->paymode == 0 && (rul->flags & ASGF_DOMOD)) || (rul->flags & ASGF_OVWMOD) )
+                               {
+                                       //ugly hack - don't allow modify intxfer
+                                       if(ope->paymode != PAYMODE_INTXFER && rul->paymode != PAYMODE_INTXFER) 
                                        {
-                                               ope->kcat = rul->kcat;
-                                               ope->flags |= OF_CHANGED;
-                                               changes++;
+                                               if(ope->paymode != rul->paymode) { changed = TRUE; }
+                                               ope->paymode = rul->paymode;
                                        }
-                                       
                                }
                        }
-                       else if( ope->flags & OF_SPLIT )
+                       if( ope->flags & OF_SPLIT )
                        {
-                       guint i, nbsplit = da_transaction_splits_count(ope);
-                       Split *split;
-                       gboolean split_change = FALSE;
+                       guint i, nbsplit = da_splits_count(ope->splits);
  
                                for(i=0;i<nbsplit;i++)
                                {
-                                       split = ope->splits[i];
+                               Split *split = ope->splits[i];
+                                       
                                        DB( g_print("- eval split '%s'\n", split->memo) );
  
-                                       if(split->kcat == 0)
+                                       rul = transaction_auto_assign_eval(l_rul, split->memo);
+                                       if( rul != NULL )
                                        {
-                                               rul = transaction_auto_assign_eval(l_rul, split->memo);
-                                               if( rul != NULL )
+                                               //#1501144: check if user wants to set category in rule
+                                               if( (split->kcat == 0 || (rul->flags & ASGF_OVWCAT)) && (rul->flags & ASGF_DOCAT) )
                                                {
-                                                       if( split->kcat == 0 && rul->kcat > 0 )
-                                                       {
-                                                               split->kcat = rul->kcat;
-                                                               ope->flags |= OF_CHANGED;
-                                                               split_change = TRUE;
-                                                       }
+                                                       if(split->kcat != rul->kcat) { changed = TRUE; }
+                                                       split->kcat = rul->kcat;
                                                }
                                        }
                                }
+                       }
  
-                               if(split_change == TRUE)
-                                       changes++;
+                       if(changed == TRUE)
+                       {
+                               ope->flags |= OF_CHANGED;
+                               changes++;
                        }
-                       
                }
  
                l_ope = g_list_next(l_ope);
@@@ -1060,6 -1126,8 +1135,8 @@@ transaction_tags_count(Transaction *ope
  guint count = 0;
  guint32 *ptr = ope->tags;
  
+       DB( g_print("(transaction_tags_count)\n") );
+       
        if( ope->tags == NULL )
                return 0;
  
  }
  
  
- guint transaction_splits_parse(Transaction *ope, gchar *cats, gchar *amounts, gchar *memos)
+ void transaction_tags_clone(Transaction *src_txn, Transaction *dst_txn)
  {
- gchar **cat_a, **amt_a, **mem_a;
- guint count, i;
- guint32 kcat;
- gdouble amount;
- Split *split;
-       DB( g_print(" split parse %s :: %s :: %s\n", cats, amounts, memos) );
-       cat_a = g_strsplit (cats, "||", 0);
-       amt_a = g_strsplit (amounts, "||", 0);
-       mem_a = g_strsplit (memos, "||", 0);
+ guint count;
  
-       count = g_strv_length(amt_a);
-       if( (count == g_strv_length(cat_a)) && (count == g_strv_length(mem_a)) )
-       {
-               for(i=0;i<count;i++)
-               {
-                       kcat = atoi(cat_a[i]);
-                       amount = g_ascii_strtod(amt_a[i], NULL);
-                       split = da_split_new(kcat, amount, mem_a[i]);
-                       da_transaction_splits_append (ope, split);
-               }
-               
-               ope->flags |= OF_SPLIT;
-       }
-       else
+       dst_txn->tags = NULL;
+       count = transaction_tags_count(src_txn);
+       if(count > 0)
        {
-               g_warning("invalid split parse");
+               //1501962: we must also copy the final 0
+               dst_txn->tags = g_memdup(src_txn->tags, (count+1)*sizeof(guint32));
        }
-       g_strfreev (mem_a);
-       g_strfreev (amt_a);
-       g_strfreev (cat_a);
-       return count;
  }
  
- guint transaction_splits_tostring(Transaction *ope, gchar **cats, gchar **amounts, gchar **memos)
- {
- guint count, i;
- Split *split;
- char buf[G_ASCII_DTOSTR_BUF_SIZE];
- GString *cat_a = g_string_new (NULL);
- GString *amt_a = g_string_new (NULL);
- GString *mem_a = g_string_new (NULL);
-       count = da_transaction_splits_count(ope);
-       for(i=0;i<count;i++)
-       {
-               split = ope->splits[i];
-               g_string_append_printf (cat_a, "%d", split->kcat);
-               g_string_append(amt_a, g_ascii_dtostr (buf, sizeof (buf), split->amount) );
-               g_string_append(mem_a, split->memo);
-               if((i+1) < count)
-               {
-                       g_string_append(cat_a, "||");
-                       g_string_append(amt_a, "||");
-                       g_string_append(mem_a, "||");
-               }               
-       }       
-       *cats = g_string_free(cat_a, FALSE);
-       *amounts = g_string_free(amt_a, FALSE);
-       *memos = g_string_free(mem_a, FALSE);
-       
-       return count;
- }
  guint
  transaction_tags_parse(Transaction *ope, const gchar *tagstring)
  {
@@@ -1153,7 -1158,7 +1167,7 @@@ gchar **str_array
  guint count, i;
  Tag *tag;
  
-       DB( g_print("(transaction_set_tags)\n") );
+       DB( g_print("(transaction_tags_parse)\n") );
  
        DB( g_print(" - tagstring='%s'\n", tagstring) );
  
  
                        ope->tags[i] = tag->key;
                }
+               ope->tags[i] = 0;
        }
  
        //hex_dump(ope->tags, sizeof(guint32*)*count+1);
@@@ -1206,7 -1212,7 +1221,7 @@@ gchar **str_array
  gchar *tagstring;
  Tag *tag;
  
-       DB( g_print("transaction_get_tagstring\n") );
+       DB( g_print("transaction_tags_tostring\n") );
  
        DB( g_print(" -> tags at=%p\n", ope->tags) );
  
diff --combined src/hb-xml.c
index 9db1e3014744c1f69aaddddcae19eebeee4c6665,2338e581857133d5402597ec6a0a280fc62ced50..68768faf5449f7d30bf2ddfb6ec9f2270796ec0a
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
  #include "hb-transaction.h"
  #include "hb-xml.h"
  
 +#include "ext.h"
 +
+ #include "ui-dialogs.h"
  /****************************************************************************/
  /* Debug macros                                                             */
  /****************************************************************************/
  extern struct HomeBank *GLOBALS;
  extern struct Preferences *PREFS;
  
- typedef struct _ParseContext ParseContext;
- struct _ParseContext
- {
-       gdouble version;
  
- };
+ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  
- static void homebank_upgrade_to_v02(void);
- static void homebank_upgrade_to_v03(void);
- static void homebank_upgrade_to_v04(void);
- static void homebank_upgrade_to_v05(void);
- static void homebank_upgrade_lower_v06(void);
- static void homebank_upgrade_to_v06(void);
- static void homebank_upgrade_to_v07(void);
- static void homebank_upgrade_to_v08(void);
  
- static void
- start_element_handler (GMarkupParseContext *context,
-                      const gchar         *element_name,
-                      const gchar        **attribute_names,
-                      const gchar        **attribute_values,
-                      gpointer             user_data,
-                      GError             **error)
+ // v0.1 to v0.2 : we must change account reference by making a +1 to its index references
+ static void homebank_upgrade_to_v02(void)
  {
- ParseContext *ctx = user_data;
- //GtkUIManager *self = ctx->self;
- gint i, j;
+ GList *lst_acc, *lnk_acc;
+ GList *list;
+ GHashTable *h_old_acc;
+       
  
-       //DB( g_print("** start element: %s\n", element_name) );
+       DB( g_print("\n[hb-xml] homebank_upgrade_to_v02\n") );
  
-       switch(element_name[0])
+       //keep old hashtable with us
+       h_old_acc = GLOBALS->h_acc;
+       da_acc_new();
+       lst_acc = g_hash_table_get_values(h_old_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
        {
-               //get file version
-               /*
-               case 'h':
-               {
-                       if(!strcmp (element_name, "homebank"))
-                       {
-                            if(!strcmp (attribute_names[0], "v" ))
-                            {
-                                       version = g_ascii_strtod(attribute_values[0], NULL);
-                               DB( g_print(" version %f\n", version) );
-                            }
+       Account *acc = lnk_acc->data;
  
-                       }
-               }
-               */
+               acc->key++;
+               acc->pos++;
+               da_acc_insert (acc);
  
-               case 'a':
+               list = g_queue_peek_head_link(acc->txn_queue);
+               while (list != NULL)
                {
-                       if(!strcmp (element_name, "account"))
-                       {
-                       Account *entry = da_acc_malloc();
+               Transaction *entry = list->data;
+                       entry->kacc++;
+                       entry->kxferacc++;
+                       list = g_list_next(list);
+               }
+               lnk_acc = g_list_next(lnk_acc);
+       }
+       g_list_free(lst_acc);
  
-                               for (i = 0; attribute_names[i] != NULL; i++)
-                               {
-                                       //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
-                                            if(!strcmp (attribute_names[i], "key"     )) { entry->key   = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "flags"   )) { entry->flags = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "pos"     )) { entry->pos   = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "type"    )) { entry->type = atoi(attribute_values[i]); }
-                                       //else if(!strcmp (attribute_names[i], "curr"    )) { entry->kcur = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "name"    )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->name = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "number"  )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->number = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "bankname")) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->bankname = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "initial" )) { entry->initial = g_ascii_strtod(attribute_values[i], NULL); }
-                                       else if(!strcmp (attribute_names[i], "minimum" )) { entry->minimum = g_ascii_strtod(attribute_values[i], NULL); }
-                                       else if(!strcmp (attribute_names[i], "cheque1" )) { entry->cheque1 = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "cheque2" )) { entry->cheque2 = atoi(attribute_values[i]); }
+       //we loose some small memory here
+       g_hash_table_steal_all(h_old_acc);
  
-                               }
+       list = g_list_first(GLOBALS->arc_list);
+       while (list != NULL)
+       {
+       Archive *entry = list->data;
+               entry->kacc++;
+               entry->kxferacc++;
+               list = g_list_next(list);
+       }
+ }
  
-                               //version upgrade: type was added in 0.2
-                               //todo: for stock account
-                               /*
-                               if(version <= 0.1)
-                               {
-                                       entry->type = ACC_TYPE_BANK;
-                                       DB( g_print(" acctype forced to BANK\n") );
-                               }
-                       */
+ // v0.2 to v0.3 : we must assume categories exists : bugs 303886, 303738
+ static void homebank_upgrade_to_v03(void)
+ {
+ GList *lst_acc, *lnk_acc;
+ GList *list;
  
-                               DB( g_print(" version %f\n", ctx->version) );
+       DB( g_print("\n[hb-xml] homebank_upgrade_to_v03\n") );
  
-                               //upgrade to v0.2 file
-                               // we must change account reference by making a +1 to its index references
-                               if( ctx->version == 0.1 )
-                               {
-                                       entry->key++;
-                                       entry->pos = entry->key;
-                               }
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
+       {
+       Account *acc = lnk_acc->data;
  
-                               //all attribute loaded: append
-                               da_acc_insert(entry);
-                       }
+               list = g_queue_peek_head_link(acc->txn_queue);
+               while (list != NULL)
+               {
+               Transaction *entry = list->data;
  
-                       //assign
-                       else if(!strcmp (element_name, "asg"))
-                       {
-                       Assign *entry = da_asg_malloc();
-                       gint exact = 0;
+                       da_transaction_consistency(entry);
+                       list = g_list_next(list);
+               }
+               lnk_acc = g_list_next(lnk_acc);
+       }
+       g_list_free(lst_acc);
  
-                               for (i = 0; attribute_names[i] != NULL; i++)
-                               {
-                                       //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
-                                            if(!strcmp (attribute_names[i], "key"     )) { entry->key   = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "flags"   )) { entry->flags = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "field"   )) { entry->field = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "name"    )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->name = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "payee"   )) { entry->kpay = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "category")) { entry->kcat = atoi(attribute_values[i]); }
-                                       //else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
-                                       // prior v08
-                                       else if(!strcmp (attribute_names[i], "exact" )) { exact = atoi(attribute_values[i]); }
-                               }
  
-                               /* in v08 exact moved to flag */
-                               if( ctx->version <= 0.7)
-                               {
-                                       entry->flags = (ASGF_DOCAT|ASGF_DOPAY);
-                                       if( exact > 0 )
-                                          entry->flags |= ASGF_EXACT;
-                               }
+       list = g_list_first(GLOBALS->arc_list);
+       while (list != NULL)
+       {
+       Archive *entry = list->data;
  
-                               //all attribute loaded: append
-                               da_asg_append(entry);
+               da_archive_consistency(entry);
+               list = g_list_next(list);
+       }
+ }
  
-                       }
+ static void homebank_upgrade_to_v04(void)
+ {
+       DB( g_print("\n[hb-xml] homebank_upgrade_to_v04\n") );
  
-               }
-               break;
+       GLOBALS->arc_list = da_archive_sort(GLOBALS->arc_list);
+ }
  
-               case 'p':
-               {
-                       if(!strcmp (element_name, "pay"))
-                       {
-                       Payee *entry = da_pay_malloc();
  
-                               for (i = 0; attribute_names[i] != NULL; i++)
-                               {
-                                       //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
+ // v0.4 to v0.5 :
+ // we must assume kxferacc exists in archives for internal xfer : bug 528923
+ // if not, delete automation from the archive
+ static void homebank_upgrade_to_v05(void)
+ {
+ GList *list;
  
-                                            if(!strcmp (attribute_names[i], "key"  )) { entry->key = atoi(attribute_values[i]); }
-                                       //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
-                               }
+       DB( g_print("\n[hb-xml] homebank_upgrade_to_v05\n") );
  
-                               //all attribute loaded: append
-                               da_pay_insert(entry);
+       list = g_list_first(GLOBALS->arc_list);
+       while (list != NULL)
+       {
+       Archive *entry = list->data;
  
-                       }
-                       else if(!strcmp (element_name, "properties"))
-                       {
-                               for (i = 0; attribute_names[i] != NULL; i++)
-                               {
-                                            if(!strcmp (attribute_names[i], "title"       )) { g_free(GLOBALS->owner); GLOBALS->owner = g_strdup(attribute_values[i]); }
-                                       //else if(!strcmp (attribute_names[i], "curr"        )) { GLOBALS->kcur = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "car_category")) { GLOBALS->vehicle_category = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "auto_smode"  )) { GLOBALS->auto_smode = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "auto_weekday")) { GLOBALS->auto_weekday = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "auto_nbdays" )) { GLOBALS->auto_nbdays = atoi(attribute_values[i]); }
-                               }
-                       }
-               }
-               break;
+               da_archive_consistency(entry);
+               list = g_list_next(list);
+       }
+ }
  
-               case 'c':
-               {
-                       if(!strcmp (element_name, "cat"))
-                       {
-                       Category *entry = da_cat_malloc();
-                       gboolean budget;
  
-                               for (i = 0; attribute_names[i] != NULL; i++)
-                               {
-                                       //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
+ // v0.5 to v0.6 : we must change kxferacc to 0 on non Xfer transactions
+ //#677351
+ static void homebank_upgrade_to_v06(void)
+ {
+ GList *lst_acc, *lnk_acc;
+ GList *list;
  
-                                            if(!strcmp (attribute_names[i], "key"   )) { entry->key = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "parent")) { entry->parent = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "name"  )) { entry->name = g_strdup(attribute_values[i]); }
+       DB( g_print("\n[hb-xml] homebank_upgrade_to_v06\n") );
  
-                                       budget = FALSE;
-                                       for(j=0;j<=12;j++)
-                                       {
-                                       gchar *tmpname;
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
+       {
+       Account *acc = lnk_acc->data;
  
-                                               tmpname = g_strdup_printf ("b%d", j);
-                                               if(!(strcmp (attribute_names[i], tmpname))) { entry->budget[j] = g_ascii_strtod(attribute_values[i], NULL); }
-                                               g_free(tmpname);
+               list = g_queue_peek_head_link(acc->txn_queue);
+               while (list != NULL)
+               {
+               Transaction *entry = list->data;
+                       da_transaction_consistency(entry);
+                       list = g_list_next(list);
+               }
+               lnk_acc = g_list_next(lnk_acc);
+       }
+       g_list_free(lst_acc);
  
-                                               if(entry->budget[j]) budget = TRUE;
-                                       }
-                                       if(budget == TRUE)
-                                               entry->flags |= GF_BUDGET;
  
-                               }
+       list = g_list_first(GLOBALS->arc_list);
+       while (list != NULL)
+       {
+       Archive *entry = list->data;
+               da_archive_consistency(entry);
+               list = g_list_next(list);
+       }
+ }
  
-                               //all attribute loaded: append
-                               da_cat_insert( entry);
-                       }
- /*                    else if(!strcmp (element_name, "cur"))
-                       {
-                       Currency *entry = da_cur_malloc ();
  
-                               for (i = 0; attribute_names[i] != NULL; i++)
-                               {
-                                       //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
-                                                if(!strcmp (attribute_names[i], "key"    )) { entry->key = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "name"  )) { entry->name = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "iso"   )) { entry->iso_code = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "symb"  )) { entry->symbol = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "syprf" )) { entry->sym_prefix = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "dchar" )) { entry->decimal_char = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "gchar" )) { entry->grouping_char = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "frac"  )) { entry->frac_digits = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "rate"  )) { entry->rate = g_ascii_strtod(attribute_values[i], NULL); }
-                                       else if(!strcmp (attribute_names[i], "mdate ")) { entry->mdate = atoi(attribute_values[i]); }
+ // v0.7 AF_BUDGET deleted instead of AF_NOBUDGET
+ static void homebank_upgrade_to_v07(void)
+ {
+ GList *lacc, *list;
  
-                               }
+       DB( g_print("\n[hb-xml] homebank_upgrade_to_v07\n") );
  
-                               //all attribute loaded: append
-                               da_cur_insert (entry);
-                       }
-                       */
-               }
-               break;
+       lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
+       while (list != NULL)
+       {
+       Account *acc = list->data;
  
-               case 't':
+               if( acc->flags & AF_OLDBUDGET ) // budget include
                {
-                       if(!strcmp (element_name, "tags"))
-                       {
-                       Tag *entry = da_tag_malloc();
-                               for (i = 0; attribute_names[i] != NULL; i++)
-                               {
-                                       //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
-                                            if(!strcmp (attribute_names[i], "key"  )) { entry->key = atoi(attribute_values[i]); }
-                                       //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
-                               }
-                               //all attribute loaded: append
-                               da_tag_insert(entry);
-                       }
+                       acc->flags &= ~(AF_OLDBUDGET);
                }
-               case 'f':
+               else
                {
-                       if(!strcmp (element_name, "fav"))
-                       {
-                       Archive *entry = da_archive_malloc();
+                       acc->flags |= AF_NOBUDGET;
+               }
  
-                               for (i = 0; attribute_names[i] != NULL; i++)
-                               {
-                                       //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
-                                            if(!strcmp (attribute_names[i], "amount"     )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); }
-                                       else if(!strcmp (attribute_names[i], "account"    )) { entry->kacc = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "paymode"    )) { entry->paymode = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "flags"      )) { entry->flags = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "payee"      )) { entry->kpay = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "category"   )) { entry->kcat = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "wording"    )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "nextdate"   )) { entry->nextdate = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "every"      )) { entry->every = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "unit"       )) { entry->unit = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "limit"      )) { entry->limit = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "weekend"    )) { entry->weekend = atoi(attribute_values[i]); }
+               list = g_list_next(list);
+       }
+       g_list_free(lacc);
  
                              }
+ }
  
-                               //all attribute loaded: append
-                               GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, entry);
+ static void homebank_upgrade_to_v08(void)
+ {
+ GList *lst_acc, *lnk_acc;
+ GList *list;
  
-                       }
-               }
-               break;
+       DB( g_print("\n[hb-xml] homebank_upgrade_to_v08\n") );
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
+       {
+       Account *acc = lnk_acc->data;
  
-               /*
-               case 'r':
+               list = g_queue_peek_head_link(acc->txn_queue);
+               while (list != NULL)
                {
+               Transaction *entry = list->data;
+                       da_transaction_consistency(entry);
+                       list = g_list_next(list);
                }
-               break;
-               */
+               lnk_acc = g_list_next(lnk_acc);
+       }
+       g_list_free(lst_acc);
  
-               case 'o':
-               {
-                       if(!strcmp (element_name, "ope"))
-                       {
-                       Transaction *entry = da_transaction_malloc();
-                       gchar *scat = NULL;
-                       gchar *samt = NULL;
-                       gchar *smem = NULL;
-                       gboolean split = FALSE;
  
-                               for (i = 0; attribute_names[i] != NULL; i++)
-                               {
-                                       //DB( g_print(" att=%s val=%s\n", attribute_names[i], attribute_values[i]) );
-                                            if(!strcmp (attribute_names[i], "date"       )) { entry->date = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "amount"     )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); }
-                                       else if(!strcmp (attribute_names[i], "account"    )) { entry->kacc = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "paymode"    )) { entry->paymode = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "flags"      )) { entry->flags = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "payee"      )) { entry->kpay = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "category"   )) { entry->kcat = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "wording"    )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "info"       )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->info = g_strdup(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "tags"       ))
-                                       {
-                                               if(attribute_values[i] != NULL && strlen(attribute_values[i]) > 0 && strcmp(attribute_values[i],"(null)") != 0 )
-                                               {
-                                                       transaction_tags_parse(entry, attribute_values[i]);
-                                               }
-                                       }
-                                       else if(!strcmp (attribute_names[i], "kxfer"    )) { entry->kxfer = atoi(attribute_values[i]); }
-                                       else if(!strcmp (attribute_names[i], "scat"     )) { scat = (gchar *)attribute_values[i]; split = TRUE; }
-                                       else if(!strcmp (attribute_names[i], "samt"     )) { samt = (gchar *)attribute_values[i]; split = TRUE; }
-                                       else if(!strcmp (attribute_names[i], "smem"     )) { smem = (gchar *)attribute_values[i]; split = TRUE; }
-                               }
+ }
  
-                               //bugfix 303886
-                               //if(entry->kcat < 0)
-                               //      entry->kcat = 0;
  
                              if(split == TRUE)
                              {
                                      transaction_splits_parse(entry, scat, samt, smem);
-                               }
static void homebank_upgrade_to_v10(void)
+ {
GList *lst_acc, *lnk_acc;
+ GList *list;
  
-                               //all attribute loaded: append
-                               // we use prepend here, the list will be reversed later for perf reason
-                               da_transaction_prepend(entry);
-                       }
-               }
-               break;
+       DB( g_print("\n[hb-xml] homebank_upgrade_to_v10\n") );
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
+       {
+       Account *acc = lnk_acc->data;
+       
+               list = g_queue_peek_head_link(acc->txn_queue);
+               while (list != NULL)
+               {
+               Transaction *entry = list->data;
  
+                       entry->status = TXN_STATUS_NONE;
+                       if(entry->flags & OF_OLDVALID)
+                               entry->status = TXN_STATUS_RECONCILED;
+                       else 
+                               if(entry->flags & OF_OLDREMIND)
+                                       entry->status = TXN_STATUS_REMIND;
  
+                       //remove those flags
+                       entry->flags &= ~(OF_OLDVALID|OF_OLDREMIND);
  
+                       list = g_list_next(list);
+               }
+               lnk_acc = g_list_next(lnk_acc);
        }
+       g_list_free(lst_acc);
  
  }
  
- /*
- static void
- end_element_handler (GMarkupParseContext *context,
-                    const gchar         *element_name,
-                    gpointer             user_data,
-                    GError             **error)
- {
-   ParseContext *ctx = user_data;
-       //DB( g_print("-- end element: %s\n", element_name) );
  
- }
- */
+ static void homebank_upgrade_to_v11(void)
+ {
+ GList *list;
  
- static GMarkupParser hb_parser = {
-   start_element_handler,
-   NULL,       //end_element_handler,
-   NULL, //text_handler,
-   NULL,
-   NULL  //cleanup
- };
+       DB( g_print("\n[hb-xml] homebank_upgrade_to_v11\n") );
  
- /*
- ** XML load homebank file: hbfile
- */
- gint homebank_load_xml(gchar *filename)
- {
- gint retval;
- gchar *buffer;
- gsize length;
- GError *error = NULL;
- ParseContext ctx = { 0 };
- GMarkupParseContext *context;
- gboolean rc;
+       list = g_list_first(GLOBALS->arc_list);
+       while (list != NULL)
+       {
+       Archive *entry = list->data;
  
-       DB( g_print("\n[hb-xml] homebank_load_xml\n") );
+               entry->status = TXN_STATUS_NONE;
+               if(entry->flags & OF_OLDVALID)
+                       entry->status = TXN_STATUS_RECONCILED;
+               else 
+                       if(entry->flags & OF_OLDREMIND)
+                               entry->status = TXN_STATUS_REMIND;
  
-       GValue filename_val = G_VALUE_INIT;
-       ext_hook("load_file", EXT_STRING(&filename_val, filename), NULL);
+               //remove those flags
+               entry->flags &= ~(OF_OLDVALID|OF_OLDREMIND);
  
-       retval = XML_OK;
-       if (!g_file_get_contents (filename, &buffer, &length, &error))
-       {
-               //g_message ("%s", error->message);
-               retval = XML_IO_ERROR;
-               g_error_free (error);
+               list = g_list_next(list);
        }
-       else
-       {
-       gchar *v_buffer;
-       gdouble version;
  
-               /* v3.4 add :: prevent load of future file version */
-               v_buffer = g_strstr_len(buffer, 50, "<homebank v=");
-               if( v_buffer == NULL )
-                       return XML_FILE_ERROR;
+ }
  
-               DB( g_print("- id line: --(%.50s)\n\n", v_buffer) );
  
-               version = g_ascii_strtod(v_buffer+13, NULL);    /* a little hacky, but works ! */
-               if( version == 0.0 )
-                       version = 0.1;
+ // v0.6 to v0.7 : assign a default currency
+ static void homebank_upgrade_to_v12(void)
+ {
+       // set a base currency to the hbfile if not
+       DB( g_print("GLOBALS->kcur %d\n", GLOBALS->kcur) );
  
-               ctx.version = version;
+       ui_dialog_upgrade_choose_currency();
+ }
  
-               if( version > FILE_VERSION )
-               {
-                       DB( g_print("- failed: version %f is not supported (max is %f)\n", version, FILE_VERSION) );
-                       return XML_VERSION_ERROR;
-               }
-               else
-               {
-                       DB( g_print("- ok : version=%.1f\n", version) );
  
-                       /* 1st: validate the file is well in utf-8 */
-                       DB( g_print("- ensure UTF-8\n") );
-                       buffer = homebank_utf8_ensure(buffer);
  
-                       /* then process the buffer */
-                       #if MYDEBUG == 1
-                               GTimer *t = g_timer_new();
-                               g_print("- start parse\n");
-                       #endif
-                       context = g_markup_parse_context_new (&hb_parser, 0, &ctx, NULL);
+ // lower v0.6 : we must assume categories/payee exists
+ // and strong link to xfer
+ // #632496
+ static void homebank_upgrade_lower_v06(void)
+ {
+ GList *lst_acc, *lnk_acc;
+ Category *cat;
+ Payee *pay;
+ GList *lrul, *list;
  
-                       error = NULL;
-                       rc = g_markup_parse_context_parse (context, buffer, length, &error);
+       DB( g_print("\n[hb-xml] homebank_upgrade_lower_v06\n") );
  
-                       if( error )
-                               g_print("failed: %s\n", error->message);
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
+       {
+       Account *acc = lnk_acc->data;
+       
+               list = g_queue_peek_head_link(acc->txn_queue);
+               while (list != NULL)
+               {
+               Transaction *entry = list->data;
  
-                       if( rc == FALSE )
+                       //also strong link internal xfer
+                       if(entry->paymode == PAYMODE_INTXFER && entry->kxfer == 0)
                        {
-                               error = NULL;
-                               g_markup_parse_context_end_parse(context, &error);
-                               if( error )
-                                       g_print("failed: %s\n", error->message);
+                       Transaction *child = transaction_old_get_child_transfer(entry);
+                               if(child != NULL)
+                               {
+                                       transaction_xfer_change_to_child(entry, child);
+                               }
                        }
  
-                       g_markup_parse_context_free (context);
-                       g_free (buffer);
-                       //reverse the glist (see g_list append idiom to perf for reason
-                       // we use prepend and then reverse
-                       GLOBALS->ope_list = g_list_reverse(GLOBALS->ope_list);
+                       da_transaction_consistency(entry);
                        
-                       DB( g_print("- end parse : %f sec\n", g_timer_elapsed(t, NULL)) );
-                       DB( g_timer_destroy (t) );
+                       list = g_list_next(list);
+               }
+               lnk_acc = g_list_next(lnk_acc);
+       }
+       g_list_free(lst_acc);
  
-                       /* file upgrade / bugfix */
-                       if( version <= 0.1 )
-                               homebank_upgrade_to_v02();
-                       if( version <= 0.2 )
-                               homebank_upgrade_to_v03();
-                       if( version <= 0.3 )
-                               homebank_upgrade_to_v04();
-                       if( version <= 0.4 )
-                               homebank_upgrade_to_v05();
-                       if( version <= 0.5 )
-                       {
-                               homebank_upgrade_to_v06();
-                               homebank_upgrade_lower_v06();
-                       }
-                       if( version <= 0.6 )
-                       {
-                               homebank_upgrade_to_v07();
-                               hbfile_sanity_check();
-                       }
-                       if( version <= 0.7 )
-                               homebank_upgrade_to_v08();
-                       if( version <= 0.8 )
-                               hbfile_sanity_check();
  
-                       // next ?
-                       
+       lrul = list = g_hash_table_get_values(GLOBALS->h_rul);
+       while (list != NULL)
+       {
+       Assign *entry = list->data;
+               cat = da_cat_get(entry->kcat);
+               if(cat == NULL)
+               {
+                       DB( g_print(" !! fixing cat for rul: %d is unknow\n", entry->kcat) );
+                       entry->kcat = 0;
                }
-       }
  
-       return retval;
+               pay = da_pay_get(entry->kpay);
+               if(pay == NULL)
+               {
+                       DB( g_print(" !! fixing pay for rul: %d is unknow\n", entry->kpay) );
+                       entry->kpay = 0;
+               }
+               list = g_list_next(list);
+       }
+       g_list_free(lrul);
  }
  
  
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  
- // v0.1 to v0.2 : we must change account reference by making a +1 to its index references
- static void homebank_upgrade_to_v02(void)
+ static void homebank_load_xml_acc(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
  {
- GList *list;
+ Account *entry = da_acc_malloc();
+ gint i;
  
-       DB( g_print("\n[hb-xml] homebank_upgrade_to_v02\n") );
+       for (i = 0; attribute_names[i] != NULL; i++)
+       {
+               //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
+                    if(!strcmp (attribute_names[i], "key"     )) { entry->key   = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "flags"   )) { entry->flags = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "pos"     )) { entry->pos   = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "type"    )) { entry->type = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "curr"    )) { entry->kcur = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "name"    )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->name = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "number"  )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->number = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "bankname")) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->bankname = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "initial" )) { entry->initial = g_ascii_strtod(attribute_values[i], NULL); }
+               else if(!strcmp (attribute_names[i], "minimum" )) { entry->minimum = g_ascii_strtod(attribute_values[i], NULL); }
+               else if(!strcmp (attribute_names[i], "cheque1" )) { entry->cheque1 = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "cheque2" )) { entry->cheque2 = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "notes"   )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->notes = g_strdup(attribute_values[i]); }
+       }
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
+       //all attribute loaded: append
+       da_acc_insert(entry);
+ }
+ static void homebank_load_xml_asg(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
+ {
+ Assign *entry = da_asg_malloc();
+ gint exact = 0;
+ gint i;
+       for (i = 0; attribute_names[i] != NULL; i++)
        {
-       Transaction *entry = list->data;
-               entry->kacc++;
-               entry->kxferacc++;
-               list = g_list_next(list);
+               //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
+                    if(!strcmp (attribute_names[i], "key"     )) { entry->key   = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "flags"   )) { entry->flags = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "field"   )) { entry->field = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "name"    )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->text = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "payee"   )) { entry->kpay = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "category")) { entry->kcat = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
+               // prior v08
+               else if(!strcmp (attribute_names[i], "exact" )) { exact = atoi(attribute_values[i]); }
        }
  
-       list = g_list_first(GLOBALS->arc_list);
-       while (list != NULL)
+       /* in v08 exact moved to flag */
+       if( ctx->file_version <= 0.7)
        {
-       Archive *entry = list->data;
-               entry->kacc++;
-               entry->kxferacc++;
-               list = g_list_next(list);
+               entry->flags = (ASGF_DOCAT|ASGF_DOPAY);
+               if( exact > 0 )
+                  entry->flags |= ASGF_EXACT;
        }
+       //all attribute loaded: append
+       da_asg_append(entry);
  }
  
- // v0.2 to v0.3 : we must assume categories exists : bugs 303886, 303738
- static void homebank_upgrade_to_v03(void)
+ static void homebank_load_xml_pay(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
  {
- GList *list;
+ Payee *entry = da_pay_malloc();
+ gint i;
  
-       DB( g_print("\n[hb-xml] homebank_upgrade_to_v03\n") );
-       
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
+       for (i = 0; attribute_names[i] != NULL; i++)
        {
-       Transaction *entry = list->data;
+               //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
  
-               da_transaction_consistency(entry);
-               list = g_list_next(list);
+                        if(!strcmp (attribute_names[i], "key"  )) { entry->key = atoi(attribute_values[i]); }
+               //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "category")) { entry->kcat = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "paymode" )) { entry->paymode = atoi(attribute_values[i]); }
        }
  
-       list = g_list_first(GLOBALS->arc_list);
-       while (list != NULL)
-       {
-       Archive *entry = list->data;
+       //all attribute loaded: append
+       da_pay_insert(entry);
+ }
  
-               da_archive_consistency(entry);
-               list = g_list_next(list);
+ static void homebank_load_xml_prop(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
+ {
+ gint i;
+       for (i = 0; attribute_names[i] != NULL; i++)
+       {
+                    if(!strcmp (attribute_names[i], "title"       )) { g_free(GLOBALS->owner); GLOBALS->owner = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "curr"        )) { GLOBALS->kcur = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "car_category")) { GLOBALS->vehicle_category = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "auto_smode"  )) { GLOBALS->auto_smode = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "auto_weekday")) { GLOBALS->auto_weekday = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "auto_nbdays" )) { GLOBALS->auto_nbdays = atoi(attribute_values[i]); }
        }
  }
  
- static void homebank_upgrade_to_v04(void)
+ static void homebank_load_xml_cat(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
  {
-       DB( g_print("\n[hb-xml] homebank_upgrade_to_v04\n") );
+ Category *entry = da_cat_malloc();
+ gboolean budget;
+ gint i, j;
  
-       GLOBALS->arc_list = da_archive_sort(GLOBALS->arc_list);
+       for (i = 0; attribute_names[i] != NULL; i++)
+       {
+               //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
+                    if(!strcmp (attribute_names[i], "key"   )) { entry->key = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "parent")) { entry->parent = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "flags" )) { entry->flags = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "name"  )) { entry->name = g_strdup(attribute_values[i]); }
+               budget = FALSE;
+               for(j=0;j<=12;j++)
+               {
+               gchar *tmpname;
+                       tmpname = g_strdup_printf ("b%d", j);
+                       if(!(strcmp (attribute_names[i], tmpname))) { entry->budget[j] = g_ascii_strtod(attribute_values[i], NULL); }
+                       g_free(tmpname);
+                       if(entry->budget[j]) budget = TRUE;
+               }
+               if(budget == TRUE)
+                       entry->flags |= GF_BUDGET;
+       }
+       //all attribute loaded: append
+       da_cat_insert( entry);
  }
  
  
- // v0.4 to v0.5 :
- // we must assume kxferacc exists in archives for internal xfer : bug 528923
- // if not, remove automation from the archive
- static void homebank_upgrade_to_v05(void)
+ static void homebank_load_xml_cur(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
  {
- GList *list;
+ Currency *entry = da_cur_malloc ();
+ gint i;
  
-       DB( g_print("\n[hb-xml] homebank_upgrade_to_v05\n") );
+       for (i = 0; attribute_names[i] != NULL; i++)
+       {
+               //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
+                        if(!strcmp (attribute_names[i], "key"    )) { entry->key = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "name"  )) { entry->name = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "iso"   )) { entry->iso_code = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "symb"  )) { entry->symbol = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "syprf" )) { entry->sym_prefix = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "dchar" )) { entry->decimal_char = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "gchar" )) { entry->grouping_char = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "frac"  )) { entry->frac_digits = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "rate"  )) { entry->rate = g_ascii_strtod(attribute_values[i], NULL); }
+               else if(!strcmp (attribute_names[i], "mdate ")) { entry->mdate = atoi(attribute_values[i]); }
  
-       list = g_list_first(GLOBALS->arc_list);
-       while (list != NULL)
+       }
+       //all attribute loaded: append
+       da_cur_insert (entry);
+ }
+ static void homebank_load_xml_tag(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
+ {
+ Tag *entry = da_tag_malloc();
+ gint i;
+       for (i = 0; attribute_names[i] != NULL; i++)
        {
-       Archive *entry = list->data;
+               //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
  
-               da_archive_consistency(entry);
-               list = g_list_next(list);
+                    if(!strcmp (attribute_names[i], "key"  )) { entry->key = atoi(attribute_values[i]); }
+               //else if(!strcmp (attribute_names[i], "flags")) { entry->flags = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "name" )) { entry->name = g_strdup(attribute_values[i]); }
        }
+       //all attribute loaded: append
+       da_tag_insert(entry);
  }
  
  
- // v0.5 to v0.6 : we must change kxferacc to 0 on non Xfer transactions
- //#677351
- static void homebank_upgrade_to_v06(void)
+ static void homebank_load_xml_fav(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
  {
- GList *list;
+ Archive *entry = da_archive_malloc();
+ gchar *scat = NULL;
+ gchar *samt = NULL;
+ gchar *smem = NULL;
+ gboolean split = FALSE;
+ gint i;
+       for (i = 0; attribute_names[i] != NULL; i++)
+       {
+               //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
+                    if(!strcmp (attribute_names[i], "amount"     )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); }
+               else if(!strcmp (attribute_names[i], "account"    )) { entry->kacc = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "paymode"    )) { entry->paymode = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "st"         )) { entry->status = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "flags"      )) { entry->flags = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "payee"      )) { entry->kpay = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "category"   )) { entry->kcat = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "wording"    )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "nextdate"   )) { entry->nextdate = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "every"      )) { entry->every = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "unit"       )) { entry->unit = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "limit"      )) { entry->limit = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "weekend"    )) { entry->weekend = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "scat"       )) { scat = (gchar *)attribute_values[i]; split = TRUE; }
+               else if(!strcmp (attribute_names[i], "samt"       )) { samt = (gchar *)attribute_values[i]; split = TRUE; }
+               else if(!strcmp (attribute_names[i], "smem"       )) { smem = (gchar *)attribute_values[i]; split = TRUE; }
  
-       DB( g_print("\n[hb-xml] homebank_upgrade_to_v06\n") );
+       }
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
+       if(split == TRUE)
        {
-       Transaction *entry = list->data;
-               da_transaction_consistency(entry);
-               list = g_list_next(list);
+               if (da_splits_parse(entry->splits, scat, samt, smem) > 0)
+               {
+                       entry->flags |= OF_SPLIT; //Flag that Splits are active
+               }
        }
  
-       list = g_list_first(GLOBALS->arc_list);
-       while (list != NULL)
+       //all attribute loaded: append
+       GLOBALS->arc_list = g_list_append(GLOBALS->arc_list, entry);
+ }
+ static void homebank_load_xml_ope(ParseContext *ctx, const gchar **attribute_names, const gchar **attribute_values)
+ {
+ Transaction *entry = da_transaction_malloc();
+ gchar *scat = NULL;
+ gchar *samt = NULL;
+ gchar *smem = NULL;
+ gboolean split = FALSE;
+ gint i;
+       for (i = 0; attribute_names[i] != NULL; i++)
        {
-       Archive *entry = list->data;
-               da_archive_consistency(entry);
-               list = g_list_next(list);
+               //DB( g_print(" att='%s' val='%s'\n", attribute_names[i], attribute_values[i]) );
+                    if(!strcmp (attribute_names[i], "date"       )) { entry->date = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "amount"     )) { entry->amount = g_ascii_strtod(attribute_values[i], NULL); }
+               else if(!strcmp (attribute_names[i], "account"    )) { entry->kacc = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "dst_account")) { entry->kxferacc = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "paymode"    )) { entry->paymode = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "st"         )) { entry->status = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "flags"      )) { entry->flags = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "payee"      )) { entry->kpay = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "category"   )) { entry->kcat = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "wording"    )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->wording = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "info"       )) { if(strcmp(attribute_values[i],"(null)") && attribute_values[i] != NULL) entry->info = g_strdup(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "tags"       ))
+               {
+                       if(attribute_values[i] != NULL && strlen(attribute_values[i]) > 0 && strcmp(attribute_values[i],"(null)") != 0 )
+                       {
+                               transaction_tags_parse(entry, attribute_values[i]);
+                       }
+               }
+               else if(!strcmp (attribute_names[i], "kxfer"    )) { entry->kxfer = atoi(attribute_values[i]); }
+               else if(!strcmp (attribute_names[i], "scat"     )) { scat = (gchar *)attribute_values[i]; split = TRUE; }
+               else if(!strcmp (attribute_names[i], "samt"     )) { samt = (gchar *)attribute_values[i]; split = TRUE; }
+               else if(!strcmp (attribute_names[i], "smem"     )) { smem = (gchar *)attribute_values[i]; split = TRUE; }
+       }
+       //bugfix 303886
+       //if(entry->kcat < 0)
+       //      entry->kcat = 0;
+       if(split == TRUE)
+       {
+               if (da_splits_parse(entry->splits, scat, samt, smem) > 0)
+               {
+                       entry->flags |= OF_SPLIT; //Flag that Splits are active
+               }
        }
+       
+       //all attribute loaded: append
+       // we use prepend here, the list will be reversed later for perf reason
+       da_transaction_prepend(entry);
  }
  
  
- // v0.7 AF_BUDGET removed instead of AF_NOBUDGET
- static void homebank_upgrade_to_v07(void)
+ static void
+ start_element_handler (GMarkupParseContext *context,
+                      const gchar         *element_name,
+                      const gchar        **attribute_names,
+                      const gchar        **attribute_values,
+                      gpointer             user_data,
+                      GError             **error)
  {
- GList *lacc, *list;
+ ParseContext *ctx = user_data;
+ //GtkUIManager *self = ctx->self;
  
-       DB( g_print("\n[hb-xml] homebank_upgrade_to_v07\n") );
+       //DB( g_print("** start element: %s\n", element_name) );
  
-       lacc = list = g_hash_table_get_values(GLOBALS->h_acc);
-       while (list != NULL)
+       switch(element_name[0])
        {
-       Account *acc = list->data;
+               case 'a':
+               {
+                       if(!strcmp (element_name, "account"))   //account
+                       {
+                               homebank_load_xml_acc(ctx, attribute_names, attribute_values);
+                       }
+                       else if(!strcmp (element_name, "asg"))  //assign
+                       {
+                               homebank_load_xml_asg(ctx, attribute_names, attribute_values);
+                       }
+               }
+               break;
  
-               if( acc->flags & AF_OLDBUDGET ) // budget include
+               case 'p':
                {
-                       acc->flags &= ~(AF_OLDBUDGET);
+                       if(!strcmp (element_name, "pay"))
+                       {
+                               homebank_load_xml_pay(ctx, attribute_names, attribute_values);
+                       }
+                       else if(!strcmp (element_name, "properties"))
+                       {
+                               homebank_load_xml_prop(ctx, attribute_names, attribute_values);
+                       }
                }
-               else
+               break;
+               case 'c':
                {
-                       acc->flags |= AF_NOBUDGET;
+                       if(!strcmp (element_name, "cat"))
+                       {
+                               homebank_load_xml_cat(ctx, attribute_names, attribute_values);
+                       }
+                       else if(!strcmp (element_name, "cur"))
+                       {
+                               homebank_load_xml_cur(ctx, attribute_names, attribute_values);
+                       }
                }
+               break;
  
-               list = g_list_next(list);
+               case 't':
+               {
+                       if(!strcmp (element_name, "tags"))
+                       {
+                               homebank_load_xml_tag(ctx, attribute_names, attribute_values);
+                       }
+               }
+               case 'f':
+               {
+                       if(!strcmp (element_name, "fav"))
+                       {
+                               homebank_load_xml_fav(ctx, attribute_names, attribute_values);
+                       }
+               }
+               break;
+               case 'o':
+               {
+                       if(!strcmp (element_name, "ope"))
+                       {
+                               homebank_load_xml_ope(ctx, attribute_names, attribute_values);
+                       }
+               }
+               break;
        }
-       g_list_free(lacc);
+ }
+ /*
+ static void
+ end_element_handler (GMarkupParseContext *context,
+                    const gchar         *element_name,
+                    gpointer             user_data,
+                    GError             **error)
+ {
+   ParseContext *ctx = user_data;
+       //DB( g_print("-- end element: %s\n", element_name) );
  
  }
+ */
  
- static void homebank_upgrade_to_v08(void)
+ static GMarkupParser hb_parser = {
+       start_element_handler,
+       NULL,   //end_element_handler,
+       NULL, //text_handler,
+       NULL,
+       NULL  //cleanup
+ };
+ static gboolean hb_xml_get_version(ParseContext *ctx, gchar *buffer)
  {
GList *list;
gchar *v_buffer;
  
-       DB( g_print("\n[hb-xml] homebank_upgrade_to_v08\n") );
+       ctx->file_version = 0.0;
+       ctx->data_version = 0;
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
-       {
-       Transaction *entry = list->data;
-               da_transaction_consistency(entry);
-               list = g_list_next(list);
-       }
+       /* v3.4 add :: prevent load of future file version */
+       v_buffer = g_strstr_len(buffer, 50, "<homebank v=");
+       if( v_buffer == NULL )
+               return FALSE;
+       DB( g_print("- id line: --(%.50s)\n\n", v_buffer) );
  
+       ctx->file_version = g_ascii_strtod(v_buffer+13, NULL);  /* a little hacky, but works ! */
+       if( ctx->file_version == 0.0 ) 
+               ctx->file_version = 0.1;
+       else if( ctx->file_version == 5.0 ) //was a mistake
+               ctx->file_version = 1.0;
  
+       v_buffer = g_strstr_len(buffer+13, 50, "d=");
+       if( v_buffer )
+       {
+               DB( g_print(" d=%s)\n\n", v_buffer) );
+       
+               ctx->data_version = atoi(v_buffer+3);
+       }
+       return TRUE;
  }
  
  
- // v0.6 to v0.7 : assign a default currency
  /*
- static void homebank_upgrade_to_v08(void)
+ ** XML load homebank file: hbfile
+ */
+ gint homebank_load_xml(gchar *filename)
  {
+ gint retval;
+ gchar *buffer;
+ gsize length;
+ GError *error = NULL;
+ ParseContext ctx;
+ GMarkupParseContext *context;
+ gboolean rc;
+       DB( g_print("\n[hb-xml] homebank_load_xml\n") );
++      GValue filename_val = G_VALUE_INIT;
++      ext_hook("load_file", EXT_STRING(&filename_val, filename), NULL);
++
+       retval = XML_OK;
+       if (!g_file_get_contents (filename, &buffer, &length, &error))
+       {
+               //g_message ("%s", error->message);
+               retval = XML_IO_ERROR;
+               g_error_free (error);
+       }
+       else
+       {
+               if( hb_xml_get_version(&ctx, buffer) == FALSE )
+               {
+                       return XML_FILE_ERROR;
+               }
  
-       // set a base currency to the hbfile if not
-       g_print("GLOBALS->kcur %d\n", GLOBALS->kcur);
+               if( ctx.file_version > FILE_VERSION )
+               {
+                       DB( g_print("- failed: version %f is not supported (max is %f)\n", ctx.file_version, FILE_VERSION) );
+                       return XML_VERSION_ERROR;
+               }
+               else
+               {
+                       DB( g_print("- file ok : v=%.1f data_v=%06d\n", ctx.file_version, ctx.data_version) );
  
-       if(GLOBALS->kcur == 0)
-       {
-       //struct iso4217format *choice = ui_cur_select_dialog_new(GLOBALS->mainwindow);
-       struct iso4217format *curfmt =  iso4217format_get(PREFS->curr_default);
+                       /* 1st: validate the file is well in utf-8 */
+                       DB( g_print("- ensure UTF-8\n") );
+                       buffer = homebank_utf8_ensure(buffer);
  
-               if(curfmt == NULL)
-                       curfmt = iso4217format_get_en_us();
-               
-               
-               Currency *item = currency_add_from_user(curfmt);
+                       /* then process the buffer */
+                       #if MYDEBUG == 1
+                               GTimer *t = g_timer_new();
+                               g_print("- start parse\n");
+                       #endif
  
-                       GLOBALS->kcur = item->key;
+                       context = g_markup_parse_context_new (&hb_parser, 0, &ctx, NULL);
  
-                       g_print("GLOBALS->kcur %d\n", GLOBALS->kcur);
+                       error = NULL;
+                       rc = g_markup_parse_context_parse (context, buffer, length, &error);
  
-                       // set every accounts to base currecny
-                       GList *list = g_hash_table_get_values(GLOBALS->h_acc);
-                       while (list != NULL)
-                       {
-                       Account *acc;
-                               acc = list->data;
+                       if( error )
+                               g_print("failed: %s\n", error->message);
  
-                               acc->kcur = item->key;
+                       if( rc == FALSE )
+                       {
+                               error = NULL;
+                               g_markup_parse_context_end_parse(context, &error);
  
-                               list = g_list_next(list);
+                               if( error )
+                                       g_print("failed: %s\n", error->message);
                        }
-                       g_list_free(list);
-               
-       }
- }
- */
- // lower v0.6 : we must assume categories/payee exists
- // and strong link to xfer
- // #632496
- static void homebank_upgrade_lower_v06(void)
- {
- Category *cat;
- Payee *pay;
- GList *lrul, *list;
  
-       DB( g_print("\n[hb-xml] homebank_upgrade_lower_v06\n") );
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
-       {
-       Transaction *entry = list->data;
+                       g_markup_parse_context_free (context);
+                       g_free (buffer);
  
-               da_transaction_consistency(entry);
+                       DB( g_print("- end parse : %f sec\n", g_timer_elapsed(t, NULL)) );
+                       DB( g_timer_destroy (t) );
  
-               //also strong link internal xfer
-               if(entry->paymode == PAYMODE_INTXFER)
-               {
-               Transaction *child = transaction_old_get_child_transfer(entry);
-                       if(child != NULL)
+                       /* file upgrade / bugfix */
+                       if( ctx.file_version <= 0.1 )
+                               homebank_upgrade_to_v02();
+                       if( ctx.file_version <= 0.2 )
+                               homebank_upgrade_to_v03();
+                       if( ctx.file_version <= 0.3 )
+                               homebank_upgrade_to_v04();
+                       if( ctx.file_version <= 0.4 )
+                               homebank_upgrade_to_v05();
+                       if( ctx.file_version <= 0.5 )
                        {
-                               transaction_xfer_change_to_child(entry, child);
+                               homebank_upgrade_to_v06();
+                               homebank_upgrade_lower_v06();
+                       }
+                       if( ctx.file_version <= 0.6 )
+                       {
+                               homebank_upgrade_to_v07();
+                               hbfile_sanity_check();
+                       }
+                       if( ctx.file_version <= 0.7 )   // <= 4.5
+                       {       
+                               homebank_upgrade_to_v08();
+                       }
+                       if( ctx.file_version <= 0.8 )   // <= 4.6
+                       {
+                               hbfile_sanity_check();
+                       }
+                       if( ctx.file_version <= 0.9 )   // <= 4.6.3
+                       {
+                               hbfile_sanity_check();
+                               homebank_upgrade_to_v10();
+                       }
+                       if( ctx.file_version <= 1.0 )   // <= 5.0.0 
+                       {
+                               hbfile_sanity_check();
+                               homebank_upgrade_to_v11();
+                       }
+                       //starting 5.0.4 data upgrade is done without changing file_version
+                       if( ctx.data_version < 050005 ) // <= 5.0.5 
+                       {
+                               hbfile_sanity_check();
+                       }
+                       if( ctx.file_version <= 1.1 )   // <= 5.1.0 
+                       {
+                               hbfile_sanity_check();
+                               homebank_upgrade_to_v12();
                        }
-               }
-               list = g_list_next(list);
-       }
-       lrul = list = g_hash_table_get_values(GLOBALS->h_rul);
-       while (list != NULL)
-       {
-       Assign *entry = list->data;
-               cat = da_cat_get(entry->kcat);
-               if(cat == NULL)
-               {
-                       DB( g_print(" !! fixing cat for rul: %d is unknow\n", entry->kcat) );
-                       entry->kcat = 0;
-               }
  
-               pay = da_pay_get(entry->kpay);
-               if(pay == NULL)
-               {
-                       DB( g_print(" !! fixing pay for rul: %d is unknow\n", entry->kpay) );
-                       entry->kpay = 0;
+                       // next ?
+                       
                }
-               list = g_list_next(list);
        }
-       g_list_free(lrul);
  
+       return retval;
  }
  
  
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  
  /*
@@@ -806,6 -965,79 +970,79 @@@ static void hb_xml_append_txt(GString *
        }
  }
  
+ static void
+ append_escaped_text (GString     *str,
+                      const gchar *text,
+                      gssize       length)
+ {
+   const gchar *p;
+   const gchar *end;
+   gunichar c;
+   p = text;
+   end = text + length;
+   while (p < end)
+     {
+       const gchar *next;
+       next = g_utf8_next_char (p);
+       switch (*p)
+         {
+         case '&':
+           g_string_append (str, "&amp;");
+           break;
+         case '<':
+           g_string_append (str, "&lt;");
+           break;
+         case '>':
+           g_string_append (str, "&gt;");
+           break;
+         case '\'':
+           g_string_append (str, "&apos;");
+           break;
+         case '"':
+           g_string_append (str, "&quot;");
+           break;
+         default:
+           c = g_utf8_get_char (p);
+           if ((0x1 <= c && c <= 0x8) ||
+               (0xa <= c && c  <= 0xd) ||      //chnaged here from b<->c to a<->d
+               (0xe <= c && c <= 0x1f) ||
+               (0x7f <= c && c <= 0x84) ||
+               (0x86 <= c && c <= 0x9f))
+             g_string_append_printf (str, "&#x%x;", c);
+           else
+             g_string_append_len (str, p, next - p);
+           break;
+         }
+       p = next;
+     }
+ }
+ // we override g_markup_escape_text from glib to encode \n (LF) & \r (CR)
+ static void hb_xml_append_txt_crlf(GString *gstring, gchar *attrname, gchar *value)
+ {
+       if(value != NULL && *value != 0)
+       {
+       gssize length;
+       GString *escaped;
+               
+               //gchar *escaped = g_markup_escape_text(value, -1);
+               length = strlen (value);
+               escaped = g_string_sized_new (length);
+               append_escaped_text (escaped, value, length);
+               g_string_append_printf(gstring, "%s=\"%s\" ", attrname, escaped->str);
+               g_string_free (escaped, TRUE);
+       }
+ }
  static void hb_xml_append_int0(GString *gstring, gchar *attrname, guint32 value)
  {
        g_string_append_printf(gstring, "%s=\"%d\" ", attrname, value);
@@@ -829,13 -1061,18 +1066,18 @@@ char buf[G_ASCII_DTOSTR_BUF_SIZE]
  }
  
  
+ /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
  /*
  ** XML properties save
  */
- static void homebank_save_xml_prop(GIOChannel *io)
+ static gint homebank_save_xml_prop(GIOChannel *io)
  {
  gchar *title;
  GString *node;
+ gint retval = XML_OK;
+ GError *error = NULL;
  
        title = GLOBALS->owner == NULL ? "" : GLOBALS->owner;
  
        g_string_assign(node, "<properties ");
        
        hb_xml_append_txt(node, "title", title);
+       hb_xml_append_int(node, "curr", GLOBALS->kcur);
        hb_xml_append_int(node, "car_category", GLOBALS->vehicle_category);
        hb_xml_append_int0(node, "auto_smode", GLOBALS->auto_smode);
        hb_xml_append_int(node, "auto_weekday", GLOBALS->auto_weekday);
  
        g_string_append(node, "/>\n");
  
-       g_io_channel_write_chars(io, node->str, -1, NULL, NULL);
+       error = NULL;
+       g_io_channel_write_chars(io, node->str, -1, NULL, &error);
+       if(error)
+       {
+               retval = XML_IO_ERROR;
+               g_error_free(error);
+       }
  
        g_string_free(node, TRUE);
+       return retval;
  }
  
  
  /*
  ** XML currency save
  */
- /*
- static void homebank_save_xml_cur(GIOChannel *io)
+ static gint homebank_save_xml_cur(GIOChannel *io)
  {
  GList *list;
  gchar *tmpstr;
  char buf1[G_ASCII_DTOSTR_BUF_SIZE];
+ gint retval = XML_OK;
  
        list = g_hash_table_get_values(GLOBALS->h_cur);
        while (list != NULL)
        {
        Currency *item = list->data;
  
-               if(item->key != 0)
-               {
-                       tmpstr = g_markup_printf_escaped(
-                           "<cur key=\"%d\" iso=\"%s\" name=\"%s\" symb=\"%s\" syprf=\"%d\" dchar=\"%s\" gchar=\"%s\" frac=\"%d\" rate=\"%s\" mdate=\"%d\" />\n",
-                               item->key,
-                               item->iso_code,
-                           item->name,
-                           item->symbol,
-                           item->sym_prefix,
-                           item->decimal_char,
-                           item->grouping_char,
-                           item->frac_digits,
-                           g_ascii_dtostr (buf1, sizeof (buf1), item->rate),
-                           item->mdate
-                       );
-                       g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL);
-                       g_free(tmpstr);
+               tmpstr = g_markup_printf_escaped(
+                   "<cur key=\"%d\" iso=\"%s\" name=\"%s\" symb=\"%s\" syprf=\"%d\" dchar=\"%s\" gchar=\"%s\" frac=\"%d\" rate=\"%s\" mdate=\"%d\" />\n",
+                       item->key,
+                       item->iso_code,
+                   item->name,
+                   item->symbol,
+                   item->sym_prefix,
+                   item->decimal_char,
+                   item->grouping_char,
+                   item->frac_digits,
+                   g_ascii_dtostr (buf1, sizeof (buf1), item->rate),
+                   item->mdate
+               );
+               g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL);
+               g_free(tmpstr);
  
-               }
                list = g_list_next(list);
        }
        g_list_free(list);
+       return retval;
  }
- */
  
  
  /*
  ** XML account save
  */
- static void homebank_save_xml_acc(GIOChannel *io)
+ static gint homebank_save_xml_acc(GIOChannel *io)
  {
  GList *lacc, *list;
  GString *node;
+ gint retval = XML_OK;
+ GError *error = NULL;
  
        node = g_string_sized_new(255);
  
        {
        Account *item = list->data;
  
-               item->flags &= ~(AF_ADDED|AF_CHANGED);  //remove flag
+               item->flags &= ~(AF_ADDED|AF_CHANGED);  //delete flag
  
                g_string_assign(node, "<account ");
                
                hb_xml_append_int(node, "flags", item->flags);
                hb_xml_append_int(node, "pos", item->pos);
                hb_xml_append_int(node, "type", item->type);
-               //hb_xml_append_int(node, "curr", item->kcur);
+               hb_xml_append_int(node, "curr", item->kcur);
                hb_xml_append_txt(node, "name", item->name);
                hb_xml_append_txt(node, "number", item->number);
                hb_xml_append_txt(node, "bankname", item->bankname);
                hb_xml_append_amt(node, "initial", item->initial);
                hb_xml_append_amt(node, "minimum", item->minimum);
                hb_xml_append_int(node, "cheque1", item->cheque1);
                hb_xml_append_int(node, "cheque2", item->cheque2);
+               hb_xml_append_txt_crlf(node, "notes", item->notes);
  
                g_string_append(node, "/>\n");
  
-               g_io_channel_write_chars(io, node->str, -1, NULL, NULL);
+               error = NULL;
+               g_io_channel_write_chars(io, node->str, -1, NULL, &error);
+               if(error)
+               {
+                       retval = XML_IO_ERROR;
+                       g_error_free(error);
+               }
                list = g_list_next(list);
        }
        g_list_free(lacc);
        g_string_free(node, TRUE);
+       return retval;
  }
  
  /*
  ** XML payee save
  */
- static void homebank_save_xml_pay(GIOChannel *io)
+ static gint homebank_save_xml_pay(GIOChannel *io)
  {
  GList *lpay, *list;
- gchar *tmpstr;
+ GString *node;
+ gint retval = XML_OK;
+ GError *error = NULL;
+       node = g_string_sized_new(255);
  
        lpay = list = payee_glist_sorted(0);
        while (list != NULL)
  
                if(item->key != 0)
                {
-                       tmpstr = g_markup_printf_escaped("<pay key=\"%d\" name=\"%s\"/>\n",
-                               item->key,
-                               item->name
-                       );
+                       g_string_assign(node, "<pay ");
  
-                       g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL);
-                       g_free(tmpstr);
+                       hb_xml_append_int(node, "key", item->key);
+                       hb_xml_append_txt(node, "name", item->name);
+                       hb_xml_append_int(node, "category", item->kcat);
+                       hb_xml_append_int(node, "paymode" , item->paymode);
+                       g_string_append(node, "/>\n");
+                       error = NULL;
+                       g_io_channel_write_chars(io, node->str, -1, NULL, &error);
+                       if(error)
+                       {
+                               retval = XML_IO_ERROR;
+                               g_error_free(error);
+                       }
  
                }
                list = g_list_next(list);
        }
        g_list_free(lpay);
+       g_string_free(node, TRUE);
+       return retval;
  }
  
  /*
  ** XML category save
  */
- static void homebank_save_xml_cat(GIOChannel *io)
+ static gint homebank_save_xml_cat(GIOChannel *io)
  {
  GList *lcat, *list;
  GString *node;
  char buf[G_ASCII_DTOSTR_BUF_SIZE];
  guint i;
+ gint retval = XML_OK;
+ GError *error = NULL;
  
        node = g_string_sized_new(255);
  
                        }
  
                        g_string_append(node, "/>\n");
-                       g_io_channel_write_chars(io, node->str, -1, NULL, NULL);
+                       
+                       error = NULL;
+                       g_io_channel_write_chars(io, node->str, -1, NULL, &error);
+                       if(error)
+                       {
+                               retval = XML_IO_ERROR;
+                               g_error_free(error);
+                       }
  
                }
                list = g_list_next(list);
        }
        g_list_free(lcat);
        g_string_free(node, TRUE);
+       return retval;
  }
  
  /*
  ** XML tag save
  */
- static void homebank_save_xml_tag(GIOChannel *io)
+ static gint homebank_save_xml_tag(GIOChannel *io)
  {
  GList *ltag, *list;
  gchar *tmpstr;
+ gint retval = XML_OK;
+ GError *error = NULL;
  
        ltag = list = tag_glist_sorted(0);
        while (list != NULL)
  
                if(item->key != 0)
                {
-                       tmpstr = g_markup_printf_escaped("<tag key=\"%d\" name=\"%s\" />\n",
+                       tmpstr = g_markup_printf_escaped("<tag key=\"%d\" name=\"%s\"/>\n",
                                item->key,
                                item->name
                        );
  
-                       g_io_channel_write_chars(io, tmpstr, -1, NULL, NULL);
+                       error = NULL;
+                       g_io_channel_write_chars(io, tmpstr, -1, NULL, &error);
                        g_free(tmpstr);
+                       
+                       if(error)
+                       {
+                               retval = XML_IO_ERROR;
+                               g_error_free(error);
+                       }
                }
                list = g_list_next(list);
        }
        g_list_free(ltag);
+       return retval;
  }
  
  
  /*
  ** XML assign save
  */
- static void homebank_save_xml_asg(GIOChannel *io)
+ static gint homebank_save_xml_asg(GIOChannel *io)
  {
  GList *lasg, *list;
  GString *node;
+ gint retval = XML_OK;
+ GError *error = NULL;
  
        node = g_string_sized_new(255);
        
                hb_xml_append_int(node, "key"     , item->key);
                hb_xml_append_int(node, "flags"   , item->flags);
                hb_xml_append_int(node, "field"   , item->field);
-               hb_xml_append_txt(node, "name"    , item->name);        
+               hb_xml_append_txt(node, "name"    , item->text);        
                hb_xml_append_int(node, "payee"   , item->kpay);
                hb_xml_append_int(node, "category", item->kcat);
-               //hb_xml_append_int(node, "paymode" , item->paymode);
+               hb_xml_append_int(node, "paymode" , item->paymode);
  
                g_string_append(node, "/>\n");
                
-               g_io_channel_write_chars(io, node->str, -1, NULL, NULL);
+               error = NULL;
+               g_io_channel_write_chars(io, node->str, -1, NULL, &error);
+               if(error)
+               {
+                       retval = XML_IO_ERROR;
+                       g_error_free(error);
+               }
  
                list = g_list_next(list);
        }
        g_list_free(lasg);
        g_string_free(node, TRUE);
+       return retval;
  }
  
  
  /*
  ** XML archive save
  */
- static void homebank_save_xml_arc(GIOChannel *io)
+ static gint homebank_save_xml_arc(GIOChannel *io)
  {
  GList *list;
  GString *node;
+ gint retval = XML_OK;
+ GError *error = NULL;
  
        node = g_string_sized_new(255);
  
                hb_xml_append_int(node, "account", item->kacc);
                hb_xml_append_int(node, "dst_account", item->kxferacc);
                hb_xml_append_int(node, "paymode", item->paymode);
+               hb_xml_append_int(node, "st", item->status);
                hb_xml_append_int(node, "flags", item->flags);
                hb_xml_append_int(node, "payee", item->kpay);
                hb_xml_append_int(node, "category", item->kcat);
                hb_xml_append_int(node, "limit", item->limit);
                hb_xml_append_int(node, "weekend", item->weekend);
  
+               if(da_splits_count(item->splits) > 0)
+               {
+                       gchar *cats, *amounts, *memos;
+               
+                       da_splits_tostring(item->splits, &cats, &amounts, &memos);
+                       g_string_append_printf(node, "scat=\"%s\" ", cats);
+                       g_string_append_printf(node, "samt=\"%s\" ", amounts);
+                       //fix #1173910
+                       gchar *escaped = g_markup_escape_text(memos, -1);
+                       g_string_append_printf(node, "smem=\"%s\" ", escaped);
+                       g_free(escaped);
+                       g_free(cats);
+                       g_free(amounts);
+                       g_free(memos);
+               }
                g_string_append(node, "/>\n");
  
-               g_io_channel_write_chars(io, node->str, -1, NULL, NULL);
+               error = NULL;
+               g_io_channel_write_chars(io, node->str, -1, NULL, &error);
+               if(error)
+               {
+                       retval = XML_IO_ERROR;
+                       g_error_free(error);
+               }
                list = g_list_next(list);
        }
        g_string_free(node, TRUE);
+       return retval;
  }
  
  
  /*
  ** XML transaction save
  */
- static void homebank_save_xml_ope(GIOChannel *io)
+ static gint homebank_save_xml_ope(GIOChannel *io)
  {
+ GList *lst_acc, *lnk_acc;
  GList *list;
  GString *node;
  gchar *tagstr;
+ gint retval = XML_OK;
+ GError *error = NULL;
  
        node = g_string_sized_new(255);
  
-       list = g_list_first(GLOBALS->ope_list);
-       while (list != NULL)
+       lst_acc = g_hash_table_get_values(GLOBALS->h_acc);
+       lnk_acc = g_list_first(lst_acc);
+       while (lnk_acc != NULL)
        {
-       Transaction *item = list->data;
+       Account *acc = lnk_acc->data;
  
-               item->flags &= ~(OF_AUTO|OF_ADDED|OF_CHANGED);  //remove flag
-               tagstr = transaction_tags_tostring(item);
+               list = g_queue_peek_head_link(acc->txn_queue);
+               while (list != NULL)
+               {
+               Transaction *item = list->data;
  
-               g_string_assign(node, "<ope ");
-               
-               hb_xml_append_int(node, "date", item->date);
-               hb_xml_append_amt(node, "amount", item->amount);
-               hb_xml_append_int(node, "account", item->kacc);
-               hb_xml_append_int(node, "dst_account", item->kxferacc);
-               hb_xml_append_int(node, "paymode", item->paymode);
-               hb_xml_append_int(node, "flags", item->flags);
-               hb_xml_append_int(node, "payee", item->kpay);
-               hb_xml_append_int(node, "category", item->kcat);
-               hb_xml_append_txt(node, "wording", item->wording);      
-               hb_xml_append_txt(node, "info", item->info);    
-               hb_xml_append_txt(node, "tags", tagstr);        
-               hb_xml_append_int(node, "kxfer", item->kxfer);
+                       item->flags &= ~(OF_AUTO|OF_ADDED|OF_CHANGED);  //delete flag
+                       tagstr = transaction_tags_tostring(item);
  
-               if(da_transaction_splits_count(item) > 0)
+                       g_string_assign(node, "<ope ");
+               
+                       hb_xml_append_int(node, "date", item->date);
+                       hb_xml_append_amt(node, "amount", item->amount);
+                       hb_xml_append_int(node, "account", item->kacc);
+                       hb_xml_append_int(node, "dst_account", item->kxferacc);
+                       hb_xml_append_int(node, "paymode", item->paymode);
+                       hb_xml_append_int(node, "st", item->status);
+                       hb_xml_append_int(node, "flags", item->flags);
+                       hb_xml_append_int(node, "payee", item->kpay);
+                       hb_xml_append_int(node, "category", item->kcat);
+                       hb_xml_append_txt(node, "wording", item->wording);      
+                       hb_xml_append_txt(node, "info", item->info);    
+                       hb_xml_append_txt(node, "tags", tagstr);        
+                       hb_xml_append_int(node, "kxfer", item->kxfer);
+               if(da_splits_count(item->splits) > 0)
                {
-               gchar *cats, *amounts, *memos;
+                       gchar *cats, *amounts, *memos;
                
-                       transaction_splits_tostring(item, &cats, &amounts, &memos);
-                       g_string_append_printf(node, "scat=\"%s\" ", cats);
-                       g_string_append_printf(node, "samt=\"%s\" ", amounts);
-                       //fix #1173910
-                       gchar *escaped = g_markup_escape_text(memos, -1);
-                       g_string_append_printf(node, "smem=\"%s\" ", escaped);
-                       g_free(escaped);
+                               da_splits_tostring(item->splits, &cats, &amounts, &memos);
+                               g_string_append_printf(node, "scat=\"%s\" ", cats);
+                               g_string_append_printf(node, "samt=\"%s\" ", amounts);
+                               //fix #1173910
+                               gchar *escaped = g_markup_escape_text(memos, -1);
+                               g_string_append_printf(node, "smem=\"%s\" ", escaped);
+                               g_free(escaped);
+                               g_free(cats);
+                               g_free(amounts);
+                               g_free(memos);
+                       }
  
-                       g_free(cats);
-                       g_free(amounts);
-                       g_free(memos);
-               }
+                       g_string_append(node, "/>\n");
  
-               g_string_append(node, "/>\n");
+                       g_free(tagstr);
+               
+                       error = NULL;
+                       g_io_channel_write_chars(io, node->str, -1, NULL, &error);
+               
+                       if(error)
+                       {
+                               retval = XML_IO_ERROR;
+                               g_error_free(error);
+                       }
  
-               g_free(tagstr);
-               g_io_channel_write_chars(io, node->str, -1, NULL, NULL);
-               list = g_list_next(list);
+                       list = g_list_next(list);
+               }
+               
+               lnk_acc = g_list_next(lnk_acc);
        }
+       g_list_free(lst_acc);
        g_string_free(node, TRUE);
+       return retval;
  }
  
  /*
@@@ -1190,33 -1545,36 +1550,39 @@@ GIOChannel *io
  char buf1[G_ASCII_DTOSTR_BUF_SIZE];
  gchar *outstr;
  gint retval = XML_OK;
+ GError *error = NULL;
  
-       io = g_io_channel_new_file(filename, "w", NULL);
 +      GValue filename_val = G_VALUE_INIT;
 +      ext_hook("save_file", EXT_STRING(&filename_val, filename), NULL);
 +
+       io = g_io_channel_new_file(filename, "w", &error);
        if(io == NULL)
        {
                g_message("file error on: %s", filename);
                retval = XML_IO_ERROR;
+               
+               if(error)
+                       g_print("failed: %s\n", error->message);
+               
+               g_error_free(error);
        }
        else
        {
                g_io_channel_write_chars(io, "<?xml version=\"1.0\"?>\n", -1, NULL, NULL);
  
-               outstr = g_strdup_printf("<homebank v=\"%s\">\n", g_ascii_dtostr (buf1, sizeof (buf1), FILE_VERSION));
+               outstr = g_strdup_printf("<homebank v=\"%s\" d=\"%06d\">\n", g_ascii_dtostr (buf1, sizeof (buf1), FILE_VERSION), HB_VERSION_NUM);
                g_io_channel_write_chars(io, outstr, -1, NULL, NULL);
                g_free(outstr);
  
-               homebank_save_xml_prop(io);
-               //homebank_save_xml_cur(io);
-               homebank_save_xml_acc(io);
-               homebank_save_xml_pay(io);
-               homebank_save_xml_cat(io);
-               homebank_save_xml_tag(io);
-               homebank_save_xml_asg(io);
-               homebank_save_xml_arc(io);
-               homebank_save_xml_ope(io);
+               retval = homebank_save_xml_prop(io);
+               retval = homebank_save_xml_cur(io);
+               retval = homebank_save_xml_acc(io);
+               retval = homebank_save_xml_pay(io);
+               retval = homebank_save_xml_cat(io);
+               retval = homebank_save_xml_tag(io);
+               retval = homebank_save_xml_asg(io);
+               retval = homebank_save_xml_arc(io);
+               retval = homebank_save_xml_ope(io);
  
                g_io_channel_write_chars(io, "</homebank>\n", -1, NULL, NULL);
  
diff --combined src/homebank.c
index 106b8ecb90e5e7d97dcb0a521aad1aa48c6f8229,421d0eff7a45fe62367dad4fc9493503a1e43af9..c8a6895798d91f36b977e92ff1762ac864238533
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
   */
  
  #include "homebank.h"
 +#include "ext.h"
  
  #include "dsp_mainwindow.h"
  #include "hb-preferences.h"
  #include "language.h"
  
  #ifdef G_OS_WIN32
  #include <windows.h>
  #endif
@@@ -53,7 -54,6 +55,7 @@@ static gchar *pixmaps_dir  = NULL
  static gchar *locale_dir   = NULL;
  static gchar *help_dir     = NULL;
  static gchar *datas_dir    = NULL;
 +static gchar *pkglib_dir   = NULL;
  
  
  //#define MARKUP_STRING "<span size='small'>%s</span>"
@@@ -157,25 -157,26 +159,26 @@@ static gint csvtype[7] = 
                                        /* is it csv homebank ? */
                                        else
                                        {
-                                       gboolean hbcsv;
+                                       gchar **str_array;
+                                       gboolean isvalid = FALSE;
  
-                                               hbcsv = hb_string_csv_valid(tmpstr, 8, csvtype);
+                                               hb_string_strip_crlf(tmpstr);
+                                               str_array = hb_csv_row_get(tmpstr, ";", 8);
+                                               isvalid = hb_csv_row_valid(str_array, 8, csvtype);
  
-                                               DB( g_print(" hbcsv %d\n", hbcsv) );
+                                               DB( g_print(" hbcsv %d\n", isvalid) );
  
-                                               if( hbcsv == TRUE  )
+                                               if( isvalid == TRUE  )
                                                {
                                                        DB( g_print(" type is CSV homebank\n") );
                                                        retval = FILETYPE_CSV_HB;
                                                }
  
+                                               g_strfreev (str_array);
                                        }
                                        g_free(tmpstr);
                                }
                        }
                }
                g_io_channel_unref (io);
        }
  /* = = = = = = = = = = = = = = = = = = = = */
  
  
  /*
  ** ensure the filename ends with '.xhb'
  */
- void homebank_file_ensure_xhb(void)
+ void homebank_file_ensure_xhb(gchar *filename)
  {
- gchar *newfilepath;
-       
        DB( g_print("\n[homebank] file_ensure_xhb\n") );
-       newfilepath = hb_filename_new_with_extention(GLOBALS->xhb_filepath, "xhb");
-       hbfile_change_filepath(newfilepath);
-       DB( g_print("- out: %s\n", GLOBALS->xhb_filepath) );
+       filename = (filename == NULL) ? g_strdup(GLOBALS->xhb_filepath) : filename;
+       if( g_str_has_suffix (filename, ".xhb") == FALSE )
+       {
+       gchar *newfilename;
+       
+               newfilename = hb_util_filename_new_with_extension(filename, "xhb");
+               hbfile_change_filepath(newfilename);
+               DB( g_print(" - changed to: '%s'\n", GLOBALS->xhb_filepath) );
+       }
+       //#1460390
+       else
+       {
+               hbfile_change_filepath(filename);
+       }
  }
  
  
@@@ -218,51 -224,32 +226,32 @@@ gboolean retval = FALSE
                {
                        retval = TRUE;
                }
+               g_free(buffer);
        }
        return retval;
  }
  
  
- void homebank_backup_current_file(gchar *pathname)
+ void homebank_backup_current_file(void)
  {
- gchar *basename;
- gchar *dirname;
- gchar *filename;
- gchar *newname;
- gchar **str_array;
+ gchar *bakfilename;
  
        DB( g_print("\n[homebank] backup_current_file\n") );
  
-       basename = g_path_get_basename(pathname);
-       dirname  = g_path_get_dirname (pathname);
-       if( g_str_has_suffix(basename, ".xhb") )
+       bakfilename = hb_util_filename_new_with_extension (GLOBALS->xhb_filepath, "xhb~");
+       if( g_file_test(bakfilename, G_FILE_TEST_EXISTS) )
        {
-               str_array = g_strsplit(basename, ".", 0);
-               filename = g_strdup_printf("%s.xhb~", str_array[0]);
-               newname = g_build_filename(dirname, filename, NULL);
-               g_free(filename);
-               if( g_file_test(newname, G_FILE_TEST_EXISTS) )
-               {
-                       DB( g_print("- remove existing: %s\n", newname) );
-                       g_remove(newname);
-               }
-               DB( g_print("- copy %s => %s\n", pathname, newname) );
-               homebank_copy_file (pathname, newname);
-               //#512046
-               //retval = g_rename(pathname, newname);
+               DB( g_print(" - delete existing: '%s'\n", bakfilename) );
+               g_remove(bakfilename);
+       }
  
-               //DB( g_print("retval %d\n", retval) );
+       DB( g_print(" - copy '%s' => '%s'\n", GLOBALS->xhb_filepath, bakfilename) );
  
-               g_strfreev(str_array);
-               g_free(newname);
-       }
-       g_free(basename);
-       g_free(dirname);
+       //#512046 copy file not to broke potential links
+       //retval = g_rename(pathname, newname);
+       homebank_copy_file (GLOBALS->xhb_filepath, bakfilename);
+       
+       g_free(bakfilename);
  }
  
  /* = = = = = = = = = = = = = = = = = = = = */
@@@ -287,7 -274,7 +276,7 @@@ gchar *errmsg
        errmsg = g_win32_error_message(retval);
        DB( g_print ("%s\n", errmsg) );
        g_free(errmsg);
-       
        return FALSE;
  }
  
@@@ -357,25 -344,25 +346,25 @@@ gchar *group, *filename, *lastfilename
  
                filename = g_build_filename(homebank_app_get_config_dir(), "lastopenedfiles", NULL );
  
-               DB( g_print(" -> filename: %s\n", filename) );
+               DB( g_print(" - filename: %s\n", filename) );
  
                if(g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL))
                {
                        group = "HomeBank";
  
-             DB( g_print(" -> load keyfile ok\n") );
+             DB( g_print(" - load keyfile ok\n") );
  
                        if(g_key_file_has_key(keyfile, group, "LastOpenedFile", NULL))
                        {
-                 DB( g_print(" -> keyfile has key ok\n") );
+                 DB( g_print(" - keyfile has key ok\n") );
  
                                lastfilename = g_key_file_get_string  (keyfile, group, "LastOpenedFile", NULL);
  
-                               DB( g_print(" -> lastfile loaded: %s\n", lastfilename ) );
+                               DB( g_print(" - lastfile loaded: %s\n", lastfilename ) );
                                // #593082
                                if (g_file_test (lastfilename, G_FILE_TEST_EXISTS) != FALSE)
                                {
-                                       DB( g_print(" -> file exists\n") );
+                                       DB( g_print(" - file exists\n") );
  
                                        hbfile_change_filepath(lastfilename);
  
                g_key_file_free (keyfile);
        }
  
-       DB( g_print(" -> return: %d\n", retval) );
+       DB( g_print(" - return: %d\n", retval) );
  
        return retval;
  }
@@@ -407,10 -394,11 +396,11 @@@ gsize length
  
        if( GLOBALS->xhb_filepath != NULL )
        {
                keyfile = g_key_file_new();
                if(keyfile )
                {
+                       DB( g_print(" - saving '%s'\n", GLOBALS->xhb_filepath) );
                        group = "HomeBank";
                        g_key_file_set_string  (keyfile, group, "LastOpenedFile", GLOBALS->xhb_filepath);
  
  
  /* = = = = = = = = = = = = = = = = = = = = */
  /* Main homebank */
+ #ifdef G_OS_WIN32
+ static GtkCssProvider *provider;
  
+ static void
+ homebank_theme_changed (GtkSettings *settings, GParamSpec  *pspec, gpointer     data)
+ {
  
+       if (pspec == NULL || g_str_equal (pspec->name, "gtk-theme-name"))
+       {
+               gchar *theme;
+               GdkScreen *screen;
  
- static void free_list_pixbuf(void)
- {
- guint i;
+               g_object_get (settings, "gtk-theme-name", &theme, NULL);
+               screen = gdk_screen_get_default ();
  
-       DB( g_print("\n[homebank] free_list_pixbuf\n") );
+               DB( g_print("theme %s\n", theme) );
  
-       for(i=0;i<NUM_LST_PIXBUF;i++)
-       {
-               if(GLOBALS->lst_pixbuf[i] != NULL)
+               if (g_str_equal (theme, "gtk-win32"))
                {
-                       g_object_unref(GLOBALS->lst_pixbuf[i]);
-               }
-       }
- }
+                       if (provider == NULL)
+                       {
+                               gchar *filename;
  
- static void load_list_pixbuf(void)
- {
- GdkPixbuf *pixbuf;
- guint i;
- GtkWidget *cellview;
-       DB( g_print("\n[homebank] load_list_pixbuf\n") );
-       cellview = gtk_cell_view_new ();
-       /* list added (account/transaction list) */
-       pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_NEW, GTK_ICON_SIZE_MENU, NULL);
-       //g_object_unref(pixbuf);
-       GLOBALS->lst_pixbuf[LST_PIXBUF_ADD] = pixbuf;
-       /* list scheduled (archive list) */
-       pixbuf = gtk_widget_render_icon (cellview, HB_STOCK_OPE_AUTO, GTK_ICON_SIZE_MENU, NULL);
-       //g_object_unref(pixbuf);
-       GLOBALS->lst_pixbuf[LST_PIXBUF_AUTO] = pixbuf;
-       /* list edited (account/transaction list) */
-       pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU, NULL);
-       //g_object_unref(pixbuf);
-       GLOBALS->lst_pixbuf[LST_PIXBUF_EDIT] = pixbuf;
-       /* list remind (transaction list) */
-       pixbuf = gtk_widget_render_icon (cellview, HB_STOCK_OPE_REMIND, GTK_ICON_SIZE_MENU, NULL);
-       //g_object_unref(pixbuf);
-       GLOBALS->lst_pixbuf[LST_PIXBUF_REMIND] = pixbuf;
-       /* list reconciled (transaction list) */
-       pixbuf = gtk_widget_render_icon (cellview, HB_STOCK_OPE_VALID, GTK_ICON_SIZE_MENU, NULL);
-       //g_object_unref(pixbuf);
-       GLOBALS->lst_pixbuf[LST_PIXBUF_VALID] = pixbuf;
-       /* list warning (import transaction list) */
-       pixbuf = gtk_widget_render_icon (cellview, GTK_STOCK_DIALOG_WARNING, GTK_ICON_SIZE_MENU, NULL);
-       //g_object_unref(pixbuf);
-       GLOBALS->lst_pixbuf[LST_PIXBUF_WARNING] = pixbuf;
-       GLOBALS->lst_pixbuf_maxwidth = 0;
-       for(i=0;i<NUM_LST_PIXBUF;i++)
-       {
-               if( GLOBALS->lst_pixbuf[i] != NULL )
-                       GLOBALS->lst_pixbuf_maxwidth = MAX(GLOBALS->lst_pixbuf_maxwidth, gdk_pixbuf_get_width(GLOBALS->lst_pixbuf[i]) );
+                 filename = g_build_filename(homebank_app_get_datas_dir(), "homebank-gtk-win32.css", NULL );
+                 DB( g_print("tweak file %s\n", filename) );
  
-       }
+                 if( g_file_test(filename, G_FILE_TEST_EXISTS) )
+                 {
+                     provider = gtk_css_provider_new ();
+                     gtk_css_provider_load_from_path (provider, filename, NULL);
+                 }
+                 g_free (filename);
+                       }
  
-       DB( g_print(" -> pixbuf list maxwidth: %d\n", GLOBALS->lst_pixbuf_maxwidth) );
+             if(provider != NULL)
+             {
+                 DB( g_print(" assign provider %p to screen %p\n", provider, screen) );
  
-   gtk_widget_destroy (cellview);
+                 gtk_style_context_add_provider_for_screen (screen,
+                                        GTK_STYLE_PROVIDER (provider),
+                                        GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+             }
+               }
+               else if (provider != NULL)
+               {
+                       gtk_style_context_remove_provider_for_screen (screen,
+                                                                     GTK_STYLE_PROVIDER (provider));
+                       g_clear_object (&provider);
+               }
  
+               g_free (theme);
+       }
  }
  
  static void
- homebank_register_stock_icons()
+ homebank_setup_theme_extensions (void)
  {
-       DB( g_print("\n[homebank] register_stock_icons\n") );
+       GtkSettings *settings;
  
-       GtkIconFactory *factory;
-       GtkIconSet *icon_set;
-       GtkIconSource *icon_source;
-       guint i;
+       settings = gtk_settings_get_default ();
+       provider = NULL;
+       g_signal_connect (settings, "notify", G_CALLBACK (homebank_theme_changed), NULL);
+       homebank_theme_changed (settings, NULL, NULL);
+ }
+ #endif
  
-       const char *icon_theme_items[] =
-       {
-               "hb-file-import",
-               "hb-file-export"
-               "pm-none",
-               "pm-ccard",
-               "pm-check",
-               "pm-cash" ,
-               "pm-transfer",
-               "pm-intransfer",
-               "pm-dcard",
-               "pm-standingorder",
-               "pm-epayment",
-               "pm-deposit",
-               "pm-fifee",
-               "pm-directdebit",
-               "flt-inactive",
-               "flt-include",
-               "flt-exclude",
-               HB_STOCK_OPE_VALID,
-               HB_STOCK_OPE_REMIND,
-               HB_STOCK_OPE_AUTO,
-               "prf-general",
-               "prf-interface",
-               "prf-columns",
-               "prf-display",
-               "prf-euro",
-               "prf-report",
-               "prf-import",
-               "prf-plugins"
-       };
-       factory = gtk_icon_factory_new ();
-       for (i = 0; i < G_N_ELEMENTS (icon_theme_items); i++)
-       {
-               icon_source = gtk_icon_source_new ();
-               gtk_icon_source_set_icon_name (icon_source, icon_theme_items[i]);
  
-               icon_set = gtk_icon_set_new ();
-               gtk_icon_set_add_source (icon_set, icon_source);
-               gtk_icon_source_free (icon_source);
+ static void
+ homebank_icon_theme_setup()
+ {
+       DB( g_print("\n[homebank] icon_theme_setup\n") );
  
-               gtk_icon_factory_add (factory, icon_theme_items[i], icon_set);
-               gtk_icon_set_unref (icon_set);
-       }
+       GLOBALS->icontheme = gtk_icon_theme_get_default();
  
-       //gtk_stock_add_static (icon_theme_items, G_N_ELEMENTS (icon_theme_items));
+       DB( g_print(" - prepend theme search path: %s\n", homebank_app_get_pixmaps_dir()) );
+       gtk_icon_theme_prepend_search_path (GLOBALS->icontheme, homebank_app_get_pixmaps_dir());
+       //DB( g_print(" - append theme search path: %s\n", homebank_app_get_pixmaps_dir()) );
+       //gtk_icon_theme_append_search_path (GLOBALS->icontheme, homebank_app_get_pixmaps_dir());
  
-       gtk_icon_factory_add_default (factory);
-       g_object_unref (factory);
  
        #if MYDEBUG == 1
        GtkIconTheme *ic = gtk_icon_theme_get_default();
+       guint i;
        gchar **paths;
  
-               DB( g_print(" -> get default icon theme\n") );
-       
+               DB( g_print(" - get default icon theme\n") );
                gtk_icon_theme_get_search_path(ic, &paths, NULL);
                for(i=0;i<g_strv_length(paths);i++)
                {
-                       g_print("-> path %d: %s\n", i, paths[i]);
+                       g_print(" - path %d: %s\n", i, paths[i]);
                }
-       
                g_strfreev(paths);
  
        #endif
  
-       
  
-       DB( g_print(" -> adding theme search path: %s\n", homebank_app_get_pixmaps_dir()) );
-       gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), homebank_app_get_pixmaps_dir());
  }
  
- /*
- void homebank_window_set_icon_from_file(GtkWindow *window, gchar *filename)
- {
- gchar *pathfilename;
-       pathfilename = g_build_filename(homebank_app_get_pixmaps_dir(), filename, NULL);
-       gtk_window_set_icon_from_file(GTK_WINDOW (window), pathfilename, NULL);
-       g_free(pathfilename);
- }
- */
  
  const gchar *
  homebank_app_get_config_dir (void)
@@@ -638,12 -559,6 +561,12 @@@ homebank_app_get_datas_dir (void
        return datas_dir;
  }
  
 +const gchar *
 +homebank_app_get_pkglib_dir (void)
 +{
 +      return pkglib_dir;
 +}
 +
  
  /* build package paths at runtime */
  static void
@@@ -660,13 -575,12 +583,13 @@@ build_package_paths (void
        pixmaps_dir  = g_build_filename (prefix, "share", PACKAGE, "icons", NULL);
        help_dir     = g_build_filename (prefix, "share", PACKAGE, "help", NULL);
        datas_dir    = g_build_filename (prefix, "share", PACKAGE, "datas", NULL);
- #ifdef PORTABLE_APP
-       DB( g_print("- app is portable under windows\n") );
-       config_dir   = g_build_filename(prefix, "config", NULL);
- #else
-       config_dir   = g_build_filename(g_get_user_config_dir(), HB_DATA_PATH, NULL);
- #endif
 +      pkglib_dir   = g_build_filename (prefix, "lib", PACKAGE, NULL);
+       #ifdef PORTABLE_APP
+               DB( g_print(" - app is portable under windows\n") );
+               config_dir   = g_build_filename(prefix, "config", NULL);
+       #else
+               config_dir   = g_build_filename(g_get_user_config_dir(), HB_DATA_PATH, NULL);
+       #endif
        g_free (prefix);
  #else
        locale_dir   = g_build_filename (DATA_DIR, "locale", NULL);
        pixmaps_dir  = g_build_filename (DATA_DIR, PACKAGE, "icons", NULL);
        help_dir     = g_build_filename (DATA_DIR, PACKAGE, "help", NULL);
        datas_dir    = g_build_filename (DATA_DIR, PACKAGE, "datas", NULL);
-       config_dir   = g_build_filename (g_get_user_config_dir(), HB_DATA_PATH, NULL);
 +      pkglib_dir   = g_build_filename (PKGLIB_DIR, NULL);
+       config_dir   = g_build_filename(g_get_user_config_dir(), HB_DATA_PATH, NULL);
  
        //#870023 Ubuntu packages the help files in "/usr/share/doc/homebank-data/help/" for some strange reason
        if(! g_file_test(help_dir, (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
        }
  #endif
  
-       DB( g_print("- config_dir : %s\n", config_dir) );
-       DB( g_print("- images_dir : %s\n", images_dir) );
-       DB( g_print("- pixmaps_dir: %s\n", pixmaps_dir) );
-       DB( g_print("- locale_dir : %s\n", locale_dir) );
-       DB( g_print("- help_dir   : %s\n", help_dir) );
-       DB( g_print("- datas_dir  : %s\n", datas_dir) );
-       DB( g_print("- pkglib_dir : %s\n", pkglib_dir) );
+       DB( g_print(" - config_dir : %s\n", config_dir) );
+       DB( g_print(" - images_dir : %s\n", images_dir) );
+       DB( g_print(" - pixmaps_dir: %s\n", pixmaps_dir) );
+       DB( g_print(" - locale_dir : %s\n", locale_dir) );
+       DB( g_print(" - help_dir   : %s\n", help_dir) );
+       DB( g_print(" - datas_dir  : %s\n", datas_dir) );
++      DB( g_print(" - pkglib_dir : %s\n", pkglib_dir) );
  
  }
  
@@@ -726,7 -638,7 +649,7 @@@ gboolean retval = FALSE
        {
                if(g_file_set_contents(dstpath, buffer, length, NULL))
                {
-                       //g_print("sould remove %s\n", srcpath);
+                       //g_print("sould delete %s\n", srcpath);
                        g_remove(srcpath);
                        retval = TRUE;
                }
@@@ -752,47 -664,47 +675,47 @@@ gboolean exists
        /* check if <userdir>/.config exist */
  #ifndef G_OS_WIN32
        configdir = g_get_user_config_dir();
-       DB( g_print("- check '%s' exists\n", configdir) );
+       DB( g_print(" - check '%s' exists\n", configdir) );
        if(!g_file_test(configdir, G_FILE_TEST_IS_DIR))
        {
-               DB( g_print("- creating dir\n") );
+               DB( g_print(" - creating dir\n") );
                g_mkdir(configdir, 0755);
        }
  #endif
-       
        /* check for XDG .config/homebank */
        configdir = homebank_app_get_config_dir();
-       DB( g_print("- config_dir is: '%s'\n", configdir) );
+       DB( g_print(" - config_dir is: '%s'\n", configdir) );
        exists = g_file_test(configdir, G_FILE_TEST_IS_DIR);
        if(exists)
        {
                /* just update folder security */
-               DB( g_print("- chmod 0700\n") );
+               DB( g_print(" - chmod 0700\n") );
                g_chmod(configdir, 0700);
                GLOBALS->first_run = FALSE;
        }
        else
        {
                /* create the config dir */
-               DB( g_print("- create config_dir\n") );
+               DB( g_print(" - create config_dir\n") );
                g_mkdir(configdir, 0755);
                g_chmod(configdir, 0700);
  
                /* any old homedir configuration out there ? */
                homedir = g_build_filename(g_get_home_dir (), ".homebank", NULL );
-               DB(     g_print("- homedir is: '%s'\n", homedir) );
+               DB(     g_print(" - homedir is: '%s'\n", homedir) );
  
                exists = g_file_test(homedir, G_FILE_TEST_IS_DIR);
                if(exists)
                {
                gboolean f1, f2;
                        /* we must do the migration properly */
-                       DB( g_print("- migrate old 2 files\n") );
+                       DB( g_print(" - migrate old 2 files\n") );
                        f1 = homebank_check_app_dir_migrate_file(homedir, config_dir, "preferences");
                        f2 = homebank_check_app_dir_migrate_file(homedir, config_dir, "lastopenedfiles");
                        if(f1 && f2)
                        {
-                               DB( g_print("- removing old dir\n") );
+                               DB( g_print(" - removing old dir\n") );
                                g_rmdir(homedir);
                        }
                }
  static void homebank_cleanup()
  {
  
-       DB( g_print("\n\n[homebank] cleanup\n") );
+       DB( g_print("\n[homebank] cleanup\n") );
  
        //v3.4 save windows size/position
        homebank_pref_save();
  
-       free_list_pixbuf();
-       free_paymode_icons();
-       free_nainex_icons();
-       free_pref_icons();
        hbfile_cleanup(TRUE);
  
        /* free our global datas */
        g_free (pixmaps_dir);
        g_free (locale_dir);
        g_free (help_dir);
 +      g_free (pkglib_dir);
  
  }
  
@@@ -865,29 -771,28 +783,28 @@@ static gboolean homebank_setup(
  
        hbfile_setup(TRUE);
  
-       homebank_register_stock_icons();
+       homebank_icon_theme_setup();
  
-       load_list_pixbuf();
-       load_paymode_icons();
-       load_nainex_icons();
-       load_pref_icons();
+ #ifdef G_OS_WIN32
+       homebank_setup_theme_extensions();
+ #endif
  
        homebank_app_date_get_julian();
  
  
        #if MYDEBUG == 1
  
-       g_print("- user_name: %s\n", g_get_user_name ());
-       g_print("- real_name: %s\n", g_get_real_name ());
-       g_print("- user_cache_dir: %s\n", g_get_user_cache_dir());
-       g_print("- user_data_dir: %s\n", g_get_user_data_dir ());
-       g_print("- user_config_dir: %s\n", g_get_user_config_dir ());
-       //g_print("- system_data_dirs: %s\n", g_get_system_data_dirs ());
-       //g_print("- system_config_dirs: %s\n", g_get_system_config_dirs ());
+       g_print(" - user_name: %s\n", g_get_user_name ());
+       g_print(" - real_name: %s\n", g_get_real_name ());
+       g_print(" - user_cache_dir: %s\n", g_get_user_cache_dir());
+       g_print(" - user_data_dir: %s\n", g_get_user_data_dir ());
+       g_print(" - user_config_dir: %s\n", g_get_user_config_dir ());
+       //g_print(" - system_data_dirs: %s\n", g_get_system_data_dirs ());
+       //g_print(" - system_config_dirs: %s\n", g_get_system_config_dirs ());
  
-       g_print("- home_dir: %s\n", g_get_home_dir ());
-       g_print("- tmp_dir: %s\n", g_get_tmp_dir ());
-       g_print("- current_dir: %s\n", g_get_current_dir ());
+       g_print(" - home_dir: %s\n", g_get_home_dir ());
+       g_print(" - tmp_dir: %s\n", g_get_tmp_dir ());
+       g_print(" - current_dir: %s\n", g_get_current_dir ());
  
        #endif
  
@@@ -906,7 -811,7 +823,7 @@@ GtkWidget *frame, *vbox, *image
  //gchar *ver_string, *markup, *version;
  gchar *pathfilename;
  
-       DB( g_print("[homebank_construct_splash]\n") );
+       DB( g_print("\n[homebank_construct_splash]\n") );
  
        window = gtk_window_new(GTK_WINDOW_POPUP);      //TOPLEVEL DONT WORK
        gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_SPLASHSCREEN);
        gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
        gtk_container_add (GTK_CONTAINER (window), frame);
  
-       vbox = gtk_vbox_new (FALSE, 0);
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
        gtk_container_add (GTK_CONTAINER (frame), vbox);
  
        /*
@@@ -952,7 -857,7 +869,7 @@@ homebank_init_i18n (void
     */
  
        setlocale (LC_ALL, "");
-       
        bindtextdomain (GETTEXT_PACKAGE, homebank_app_get_locale_dir ());
  //#ifdef HAVE_BIND_TEXTDOMAIN_CODESET
        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  
        /*#ifdef G_OS_WIN32
        gchar *wl = g_win32_getlocale ();
-       DB( g_print(" -> win32 locale is '%s'\n", wl) );
+       DB( g_print(" - win32 locale is '%s'\n", wl) );
        g_free(wl);
        #endif*/
  
  
  
  int
 -main (int argc, char *argv[])
 +main (int argc, char *argv[], char *env[])
  {
  GOptionContext *option_context;
  GOptionGroup *option_group;
@@@ -1042,22 -947,6 +959,22 @@@ gboolean openlast
                /*  change the locale if a language is specified  */
                language_init (PREFS->language);
  
-               DB( g_print(" -> loading plugins\n") );
++              DB( g_print(" - loading plugins\n") );
 +              ext_init(&argc, &argv, &env);
 +
 +              GList* it;
 +              for (it = PREFS->ext_whitelist; it; it = g_list_next(it)) {
 +                      ext_load_plugin(it->data);
 +              }
 +
 +              gchar** plugins = ext_list_plugins();
 +              gchar** plugins_it;
 +              for (plugins_it = plugins; *plugins_it; ++plugins_it) {
 +                      gboolean loaded = ext_is_plugin_loaded(*plugins_it);
 +                      g_print("found plugin: %s, loaded: %d\n", *plugins_it, loaded);
 +              }
 +              g_strfreev(plugins);
 +
                if( PREFS->showsplash == TRUE )
                {
                        splash = homebank_construct_splash();
                                gtk_main_iteration ();
                }
  
-               /*
-               pathfilename = g_build_filename(homebank_app_get_pixmaps_dir(), "homebank.svg", NULL);
-               gtk_window_set_default_icon_from_file(pathfilename, NULL);
-               g_free(pathfilename);
-               */
                gtk_window_set_default_icon_name ("homebank");
  
-               DB( g_print(" -> creating window\n" ) );
+               DB( g_print(" - creating window\n" ) );
  
                mainwin = (GtkWidget *)create_hbfile_window (NULL);
  
 +              GValue mainwin_val = G_VALUE_INIT;
 +              ext_hook("create_main_window", EXT_OBJECT(&mainwin_val, mainwin), NULL);
 +
                if(mainwin)
                {
  
                                gtk_main_iteration ();
  
  
-                       DB( g_print(" -> open last file ?\n" ) );
+                       DB( g_print(" - open last file ?\n" ) );
  
                        // load a file ?
                        /* load 1st file specified on commandline */
                        {
                                if (g_file_test (files[0], G_FILE_TEST_EXISTS) != FALSE)
                                {
-                                       DB( g_print(" -> should load %s\n", files[0] ) );
+                                       DB( g_print(" - should load %s\n", files[0] ) );
                                        hbfile_change_filepath(g_strdup(files[0]));
                                        ui_mainwindow_open_internal(mainwin, NULL);
                                        openlast = FALSE;
                        }
  
  
-                       DB( g_print(" -> GLOBALS->xhb_filepath: '%s'\n", GLOBALS->xhb_filepath ) );
+                       DB( g_print(" - GLOBALS->xhb_filepath: '%s'\n", GLOBALS->xhb_filepath ) );
  
                        if( openlast )
                        {
                                        ui_mainwindow_open_internal(mainwin, NULL);
                        }
  
+                       /* -- hack to generate a big file -- */
                        /* update the mainwin display */
                        ui_mainwindow_update(mainwin, GINT_TO_POINTER(UF_TITLE+UF_SENSITIVE+UF_BALANCE+UF_VISUAL));
  
-               DB( g_print(" -> gtk_main()\n" ) );
 +                      ext_hook("enter_main_loop", NULL);
 +
+               DB( g_print(" - gtk_main()\n" ) );
                        gtk_main ();
 +
 +                      ext_hook("exit_main_loop", NULL);
                }
  
-               DB( g_print(" -> unloading plugins\n") );
++              DB( g_print(" - unloading plugins\n") );
 +              ext_term();
 +
        }
  
  
diff --combined src/homebank.h
index 9acc5fc8f9c5ef25a2379c73c6fab003a18a55f4,de661f83f0da4edfd02c9c08908397d7cd49e2b4..a89fc438f6de2b82843edab9979636779d5d32b9
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
@@@ -17,8 -17,8 +17,8 @@@
   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
- #ifndef __HOMEBANK_H__
- #define __HOMEBANK_H__
+ #ifndef _HOMEBANK_H_
+ #define _HOMEBANK_H_
  
  #ifdef HAVE_CONFIG_H
  #include <config.h>
@@@ -41,6 -41,7 +41,7 @@@
  #include "hb-preferences.h"
  
  #include "hb-transaction.h"
+ #include "hb-currency.h"
  #include "hb-account.h"
  #include "hb-archive.h"
  #include "hb-assign.h"
  #define gettext_noop(str) (str)
  #define N_(str) gettext_noop (str)
  
- /* = = = = = = = = */
  /* = = = = = = = = = = = = = = = = */
- /* = = = = = = = = = = = = = = = = = = = = = = = = */
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
  
- #define HB_UNSTABLE                   FALSE
- #define HB_VERSION                    "4.6.3"
- #define FILE_VERSION          0.9
- #define PREF_VERSION          460
+ #define HB_UNSTABLE           FALSE
+ #define HB_VERSION_MAJOR      5
+ #define HB_VERSION_MINOR      1
+ #define HB_VERSION_MICRO      2
+ #define HB_VERSION                    "5.1.2"
+ #define HB_VERSION_NUM        (HB_VERSION_MAJOR*10000) + (HB_VERSION_MINOR*100) + HB_VERSION_MICRO
+ #define FILE_VERSION          1.2
+ #define PREF_VERSION          512
  
  #if HB_UNSTABLE == FALSE
        #define PROGNAME                "HomeBank"
@@@ -82,6 -88,7 +88,7 @@@
        #define HB_DATA_PATH    "homebank_unstable"
  #endif
  
  #ifdef G_OS_WIN32
        #define GETTEXT_PACKAGE "homebank"
        #define LOCALE_DIR      "locale"
        #define ENABLE_NLS 1
  #endif
  
  /* container spacing */
- #define PHI 1.61803399
+ #define SPACING_TINY          3
+ #define SPACING_SMALL         6
+ #define SPACING_MEDIUM                12
+ #define SPACING_LARGE         18
  
- #define HB_MAINBOX_SPACING    12
- #define HB_BOX_SPACING                6
  
- #define HB_HSPACE_SPACING     18  /* used to separate dialog block */
- #define HB_TABROW_SPACING     6
- #define HB_TABCOL_SPACING     6
+ #define HB_MINDATE  693596      //01/01/1900
+ #define HB_MAXDATE  803533      //31/12/2200
  
  /* widget minimum width */
  #define HB_MINWIDTH_LIST      161
- #define HB_MINWIDTH_COMBO     80
+ #define HB_MINHEIGHT_LIST     260
+ #define HB_MINWIDTH_SEARCH    240
+ #define HB_MINWIDTH_COLUMN  48
  
  
- /* for transaction dialog */
- #define GTK_RESPONSE_ADD       1
+ /* miscellaneous */
+ #define PHI 1.61803399
  
+ /* official GTK_RESPONSE are negative */
+ #define GTK_RESPONSE_ADD               1
+ #define GTK_RESPONSE_ADDKEEP   2
  
- #define HB_NUMBER_SAMPLE      20457.99
+ #define HB_NUMBER_SAMPLE      1234567.89
  
  
- enum
typedef enum
  {
        FILETYPE_UNKNOW,
        FILETYPE_HOMEBANK,
        FILETYPE_OFX,
        FILETYPE_QIF,
        FILETYPE_CSV_HB,
      FILETYPE_AMIGA_HB,
//    FILETYPE_AMIGA_HB,
        NUM_FILETYPE
- };
+ } HbFileType;
  
- /*
- ** stock icons
- */
  
- /* Custom HomeBank named icons */
- #define HB_STOCK_ACCOUNT         "hb-account"
- #define HB_STOCK_ARCHIVE         "hb-archive"
- #define HB_STOCK_ASSIGN          "hb-assign"
- #define HB_STOCK_BUDGET          "hb-budget"
- #define HB_STOCK_CATEGORY        "hb-category"
- #define HB_STOCK_PAYEE           "hb-payee"
- #define HB_STOCK_FILTER          "hb-filter"
- #define HB_STOCK_OPE_ADD         "hb-ope-add"
- #define HB_STOCK_OPE_HERIT       "hb-ope-herit"
- #define HB_STOCK_OPE_EDIT        "hb-ope-edit"
- #define HB_STOCK_OPE_SHOW        "hb-ope-show"
- #define HB_STOCK_OPE_DELETE      "hb-ope-delete"
- #define HB_STOCK_OPE_VALID       "hb-ope-valid"
- #define HB_STOCK_OPE_REMIND      "hb-ope-remind"
- #define HB_STOCK_OPE_AUTO        "hb-ope-auto"
- #define HB_STOCK_REP_STATS       "hb-rep-stats"
- #define HB_STOCK_REP_TIME        "hb-rep-time"
- #define HB_STOCK_REP_BALANCE     "hb-rep-balance"
- #define HB_STOCK_REP_BUDGET      "hb-rep-budget"
- #define HB_STOCK_REP_CAR         "hb-rep-vehicle"
+ /* ---- icon size as defined into gtkiconfactory.c ---- */
+ /* GTK_ICON_SIZE_MENU 16
+  * GTK_ICON_SIZE_BUTTON 20
+  * GTK_ICON_SIZE_SMALL_TOOLBAR 18
+  * GTK_ICON_SIZE_LARGE_TOOLBAR 24 (default for toolbar)
+  * GTK_ICON_SIZE_DND 32
+  * GTK_ICON_SIZE_DIALOG 48
+  */
+ /* -------- named icons (Standard Icon Name) -------- */
+ #define ICONNAME_NEW                          "document-new"
+ #define ICONNAME_OPEN                         "document-open"
+ #define ICONNAME_SAVE                         "document-save"
+ #define ICONNAME_SAVE_AS                      "document-save-as"        //obsolete
+ #define ICONNAME_REVERT                           "document-revert"     //obsolete
+ #define ICONNAME_PRINT                                "document-print"                //unused
+ #define ICONNAME_PROPERTIES                   "document-properties"   //obsolete
+ #define ICONNAME_CLOSE                                "window-close"    //obsolete
+ #define ICONNAME_QUIT                         "application-exit"        //obsolete
+ #define ICONNAME_FIND                         "edit-find"
+ #define ICONNAME_CLEAR                                "edit-clear"
+ #define ICONNAME_WARNING                      "dialog-warning"
+ #define ICONNAME_ERROR                                "dialog-error"
+ #define ICONNAME_INFO                         "dialog-information"
+ #define ICONNAME_HELP                         "help-browser"    //obsolete
+ #define ICONNAME_ABOUT                                "help-about"      //obsolete
+ #define ICONNAME_PREFERENCES          "preferences-system"      //obsolete
+ #define ICONNAME_REFRESH                      "view-refresh"          
+ #define ICONNAME_FOLDER                               "folder-symbolic"
+ #define ICONNAME_LIST_ADD                     "list-add-symbolic"
+ #define ICONNAME_LIST_REMOVE          "list-remove-symbolic"
+ //#define ICONNAME_HB_SCHED_SKIP              "media-skip-forward"
+ //#define ICONNAME_HB_SCHED_POST              "media-playback-start"
+ // custom or gnome not found
+ #define ICONNAME_HB_BUTTON_MENU               "open-menu-symbolic"
+ #define ICONNAME_HB_TOGGLE_SIGN               "toggle-sign-symbolic"
+ /* -------- named icons (Custom to homebank) -------- */
+ #define ICONNAME_HB_CURRENCY          "hb-currency"
+ #define ICONNAME_HB_ACCOUNT         "hb-account"
+ #define ICONNAME_HB_ARCHIVE         "hb-archive"
+ #define ICONNAME_HB_ASSIGN          "hb-assign"
+ #define ICONNAME_HB_BUDGET          "hb-budget"
+ #define ICONNAME_HB_CATEGORY        "hb-category"
+ #define ICONNAME_HB_PAYEE           "hb-payee"
+ #define ICONNAME_HB_OPE_SHOW        "hb-ope-show"   //? "view-register
+ #define ICONNAME_HB_REP_STATS       "hb-rep-stats"
+ #define ICONNAME_HB_REP_TIME        "hb-rep-time"
+ #define ICONNAME_HB_REP_BALANCE     "hb-rep-balance"
+ #define ICONNAME_HB_REP_BUDGET      "hb-rep-budget"
+ #define ICONNAME_HB_REP_CAR         "hb-rep-vehicle"
+ #define ICONNAME_HB_VIEW_LIST     "hb-view-list"   //"view-list-text"
+ #define ICONNAME_HB_VIEW_BAR      "hb-view-bar"    //"view-chart-bar"
+ #define ICONNAME_HB_VIEW_COLUMN           "hb-view-column" //"view-chart-column"
+ #define ICONNAME_HB_VIEW_LINE     "hb-view-line"   //"view-chart-line"
+ #define ICONNAME_HB_VIEW_STACK            "hb-view-stack"  //"view-chart-stack"
+ #define ICONNAME_HB_VIEW_PIE      "hb-view-pie"    //"view-chart-pie"
+ #define ICONNAME_HB_VIEW_DONUT            "hb-view-donut"  //"view-chart-donut"
+ #define ICONNAME_HB_SHOW_LEGEND           "hb-legend"          //"view-legend"
+ #define ICONNAME_HB_SHOW_RATE     "hb-rate"       // obsolete ?
+ #define ICONNAME_HB_FILTER          "hb-filter"                //"edit-filter"
+ #define ICONNAME_HB_FILE_IMPORT               "hb-file-import"        //document-import
+ #define ICONNAME_HB_FILE_EXPORT               "hb-file-export"        //document-export
+ #define ICONNAME_HB_FILE_VALID                "hb-file-valid"
+ #define ICONNAME_HB_FILE_INVALID      "hb-file-invalid"
+ #define ICONNAME_HB_BUTTON_COLLAPSE   "btn-collapse"
+ #define ICONNAME_HB_BUTTON_EXPAND     "btn-expand"
+ #define ICONNAME_HB_BUTTON_SPLIT      "btn-split"
+ #define ICONNAME_HB_OPE_AUTO        "hb-ope-auto"   //? 
+ #define ICONNAME_HB_OPE_BUDGET      "hb-ope-budget" //? 
+ #define ICONNAME_HB_OPE_ADD         "hb-ope-add"      //? "edit-add"
+ #define ICONNAME_HB_OPE_HERIT       "hb-ope-herit"  //? "edit-clone"
+ #define ICONNAME_HB_OPE_EDIT        "hb-ope-edit"   //
+ #define ICONNAME_HB_OPE_MULTIEDIT   "hb-ope-multiedit"   //
+ #define ICONNAME_HB_OPE_DELETE      "hb-ope-delete" //? "edit-delete"
+ #define ICONNAME_CONVERT                      "hb-ope-convert"
+ #define ICONNAME_HB_ASSIGN_RUN      "hb-assign-run"
+ #define ICONNAME_HB_OPE_VALID       "hb-ope-valid"  // obsolete ?
+ #define ICONNAME_HB_OPE_CLEARED     "hb-ope-cleared"
+ #define ICONNAME_HB_OPE_RECONCILED  "hb-ope-reconciled"
+ #define ICONNAME_HB_OPE_REMIND      "hb-ope-remind"
  
  
  /*
  struct HomeBank
  {
        // hbfile storage
-       GHashTable      *h_cur;                 //currencies
-       GHashTable      *h_acc;                 //accounts
-       GHashTable      *h_pay;                 //payees
-       GHashTable      *h_cat;                 //categories
-       GHashTable      *h_tag;                 //tags
-       GHashTable      *h_rul;                 //assign rules
+       GHashTable              *h_cur;                 //currencies
+       GHashTable              *h_acc;                 //accounts
+       GHashTable              *h_pay;                 //payees
+       GHashTable              *h_cat;                 //categories
+       GHashTable              *h_tag;                 //tags
+       GHashTable              *h_rul;                 //assign rules
+       GHashTable              *h_memo;                //memo/description
  
-       GHashTable      *h_memo;                //memo/description
+       GList                   *arc_list;              //archives
  
-       GList           *arc_list;              //archives
-       GList           *ope_list;              //transactions
+       //#1419304 we keep the deleted txn to a stack trash
+       GTrashStack             *txn_stk;
  
        // hbfile (saved properties)
-       gchar           *owner;
-       gshort          auto_smode;
-       gshort          auto_weekday;
-       gshort          auto_nbdays;
+       gchar                   *owner;
+       gshort                  auto_smode;
+       gshort                  auto_weekday;
+       gshort                  auto_nbdays;
  
-       guint32         vehicle_category;
-       //guint32               kcur;                   // base currency
+       guint32                 vehicle_category;
+       guint32                 kcur;                   // base currency
  
        // hbfile (unsaved properties)
-       guint           changes_count;
-       gboolean        hbfile_is_new;
-       gchar           *xhb_filepath;
-       gboolean        xhb_hasbak;             //file has backup (*.xhb~) used for revert menu sensitivity
+       guint                   changes_count;
+       gboolean                hbfile_is_new;
+       gchar                   *xhb_filepath;
+       gboolean                xhb_hasbak;             //file has backup (*.xhb~) used for revert menu sensitivity
  
        // really global stuffs
-       gboolean        first_run;
-       guint32         today;                  //today's date
-       gint            define_off;             //>0 when a stat, account window is opened
-       gboolean        minor;
+       gboolean                first_run;
+       guint32                 today;                  //today's date
+       gint                    define_off;             //>0 when a stat, account window is opened
+       gboolean                minor;
  
-       GtkWidget       *mainwindow;    //should be global to access attached window data
-       GdkPixbuf       *lst_pixbuf[NUM_LST_PIXBUF];
-       gint            lst_pixbuf_maxwidth;
+       GtkWidget               *mainwindow;    //should be global to access attached window data
+       GtkIconTheme    *icontheme;
+       //GdkPixbuf             *lst_pixbuf[NUM_LST_PIXBUF];
+       //gint                  lst_pixbuf_maxwidth;
  
  };
  
  gint homebank_alienfile_recognize(gchar *filename);
  gchar *homebank_filepath_with_extention(gchar *path, gchar *extension);
  gchar *homebank_filename_without_extention(gchar *path);
- void homebank_file_ensure_xhb(void);
- void homebank_backup_current_file(gchar *pathname);
+ void homebank_file_ensure_xhb(gchar *filename);
+ void homebank_backup_current_file(void);
  gboolean homebank_util_url_show (const gchar *url);
  gboolean homebank_lastopenedfiles_load(void);
  gboolean homebank_lastopenedfiles_save(void);
@@@ -220,13 -305,11 +305,12 @@@ const gchar *homebank_app_get_pixmaps_d
  const gchar *homebank_app_get_locale_dir (void);
  const gchar *homebank_app_get_help_dir (void);
  const gchar *homebank_app_get_datas_dir (void);
 +const gchar *homebank_app_get_pkglib_dir (void);
  guint32 homebank_app_date_get_julian(void);
  
  /* - - - - obsolete things - - - - */
  
  /*
  typedef struct _budget                Budget;
  
  struct _budget
@@@ -254,7 -337,4 +338,4 @@@ struct _investmen
  };
  */
  
  #endif
diff --combined src/ui-pref.c
index 4cc1eebf66c78871d9fa8711977476b9312b8d27,5a63a4957422dbbe27c9dd6e85bd46d16bf152f7..fa7f906142dcf5722c66e625d3cc3e499ba4b2bc
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
  #include "dsp_mainwindow.h"
  #include "gtk-chart-colors.h"
  
 +#include "ext.h"
 +
+ #include "ui-currency.h"
  /****************************************************************************/
  /* Debug macros                                                             */
  /****************************************************************************/
@@@ -43,8 -44,7 +46,7 @@@ extern struct Preferences *PREFS
  
  
  enum {
-       LST_PREF_SMALLPIXBUF,
-       LST_PREF_ICON,
+       LST_PREF_ICONNAME,
        LST_PREF_NAME,
        LST_PREF_PAGE,
        LST_PREF_MAX
@@@ -60,17 -60,18 +62,15 @@@ enu
  
  enum
  {
 -      PREF_GENERAL,
 -      PREF_INTERFACE,
 -      PREF_COLUMNS,
 -      PREF_DISPLAY,
 -      PREF_IMPORT,
 -      PREF_REPORT,
 -      PREF_EURO,
 -      PREF_MAX
 +      EXT_COLUMN_ENABLED = 0,
 +      EXT_COLUMN_LABEL,
 +      EXT_COLUMN_TOOLTIP,
 +      EXT_COLUMN_PLUGIN_NAME,
 +      EXT_NUM_COLUMNS
  };
  
- GdkPixbuf *pref_pixbuf[PREF_MAX];
  
- static gchar *pref_pixname[PREF_MAX] = {
+ static gchar *pref_iconname[PREF_MAX] = {
  "prf-general",
  "prf-interface",
  "prf-columns",
@@@ -78,7 -79,6 +78,7 @@@
  "prf-import",
  "prf-report",
  "prf-euro",                   // to be renamed
 +"prf-plugins",
  //"prf_charts.svg"
  };
  
@@@ -89,8 -89,7 +89,8 @@@ N_("Transactions")
  N_("Display format"),
  N_("Import/Export"),
  N_("Report"),
 -N_("Euro minor")
 +N_("Euro minor"),
 +N_("Plugins")
  //
  };
  
@@@ -103,6 -102,15 +103,15 @@@ N_("Text beside icons")
  NULL
  };
  
+ static gchar *CYA_GRID_LINES[] = {
+ N_("None"),
+ N_("Horizontal"),
+ N_("Vertical"),
+ N_("Both"),
+ NULL
+ };
  gchar *CYA_TANGO_COLORS[] = {
  "----",
  N_("Tango light"),
@@@ -119,6 -127,7 +128,7 @@@ NUL
  };
  
  gchar *CYA_IMPORT_OFXNAME[] = {
+ N_("Ignore"),
  N_("Memo"),
  N_("Payee"),
  NULL
@@@ -128,6 -137,7 +138,7 @@@ gchar *CYA_IMPORT_OFXMEMO[] = 
  N_("Ignore"),
  N_("Append to Info"),
  N_("Append to Memo"),
+ N_("Append to Payee"),
  NULL
  };
  
@@@ -143,7 -153,7 +154,7 @@@ typedef struc
        //gchar         *prefix_symbol;         /* max symbol is 3 digits in unicode */
        //gchar         *suffix_symbol;         /* but mostly is 1 digit */
        gchar           *symbol;
-       gboolean        is_prefix;
+       gboolean        sym_prefix;
        gchar           *decimal_char;
        gchar           *grouping_char;
        gshort          frac_digits;
@@@ -177,24 -187,25 +188,25 @@@ static EuroParams euro_params[] 
  /* 2007 */
        { "SIT", "Slovenia"      , 239.640      , "tol" , TRUE , ",", ".", 2  },        //
  /* 2008 */
-       { "CYP", "Cyprus"        , 0.585274 , ""    , TRUE , ",", "" , 2  },    //
-       { "MTL", "Malta"         , 0.429300 , ""    , TRUE , ",", "" , 2  },    //
+       { "CYP", "Cyprus"        , 0.585274 , "£"   , TRUE , ",", "" , 2  },   //
+       { "MTL", "Malta"         , 0.429300 , "Lm"  , TRUE , ",", "" , 2  },    //
  /* 2009 */
        { "SKK", "Slovaquia"     , 30.12600 , "Sk"  , FALSE, ",", " ", 2  },    //
  /* 2011 */
        { "EEK", "Estonia"       , 15.6466  , "kr"  , FALSE, ",", " ", 2  },    //
  /* 2014 */
-       { "LVL", "Latvia"        , 0.702804 , "lat.", FALSE, ",", "" , 2  },    // 2014 target for euro earliest
-       
+       { "LVL", "Latvia"        , 0.702804 , "lat.", FALSE, ",", "" , 2  },    // jan. 2014
+ /* 2016 */
+       { "LTL", "Lithuania"     , 3.45280      , "Lt." , TRUE , ",", "" , 2  },        // jan. 2015
  /* future */
-       { "CZK", "Czech republic", 28.36        , "Kč"  , FALSE, ",", " ", 2  },       // non-fixé - 2015 earliest
-       { "HUF", "Hungary"       , 261.51       , "Ft"  , TRUE , ",", " ", 2  },        // non-fixé - No current target for euro
-       { "LTL", "Lithuania"     , 3.45280      , "Lt." , TRUE , ",", "" , 2  },        // 2014 target for euro earliest
-       { "PLN", "Poland"        , 0.25     , "zł"  , FALSE, ",", "" , 2  },   // non-fixé - No current target for euro
        { "BGN", "Bulgaria"      , 1.95583      , "лв." , TRUE , ",", " ", 2  },      // non-fixé - 2014 target for euro
+       { "HUF", "Hungary"       , 261.51       , "Ft"  , TRUE , ",", " ", 2  },        // non-fixé - No current target for euro
        { "RON", "Romania"       , 3.5155       , "Leu" , FALSE, ",", ".", 2  },        // non-fixé - 2015 target for euro earliest
+       { "CZK", "Czech republic", 28.36        , "Kč"  , FALSE, ",", " ", 2  },       // non-fixé - 2015 earliest
        { "HRK", "Croatia"       , 1.0000   , "kn"  , FALSE, "" , ".", 0  },    // non-fixé - 2015 target for euro earliest
-       
+       { "PLN", "Poland"        , 0.25     , "zł"  , FALSE, ",", "" , 2  },   // non-fixé - No current target for euro
  //    { "   ", ""    , 1.00000        , ""   , ""  , FALSE, ",", "", 2  },
        
  };
@@@ -205,7 -216,6 +217,7 @@@ GtkWidget *list_txn_colprefcreate(void)
  
  static void list_txn_colpref_get(GtkTreeView *treeview, gboolean *columns);
  
 +static void list_ext_colpref_get(GtkTreeView *treeview, GList **columns);
  
  
  
@@@ -537,57 -547,6 +549,6 @@@ const gchar *dirname
  
  }
  
- static gchar *ui_language_combobox_get_active_id(GtkComboBox *combobox)
- {
- GtkTreeModel *model;
- GtkTreeIter  iter;
- gchar *id = 0;
-       if( gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combobox), &iter) )
-       {
-               model = gtk_combo_box_get_model(GTK_COMBO_BOX(combobox));
-               gtk_tree_model_get (GTK_TREE_MODEL(model), &iter, 
-                                           0, &id,
-                                           -1);
-       }
-       return id;
- }
- static gint ui_language_combobox_set_active_id(GtkComboBox *combobox, gchar *id)
- {
- GtkTreeModel *model;
- GtkTreeIter  iter;
- gboolean valid;
- gchar *tmp_id;
- gint i;
-       model = gtk_combo_box_get_model(GTK_COMBO_BOX(combobox));
-       valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
-       i = 0;
-       while (valid)
-       {
-               gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
-                       0, &tmp_id,
-                       -1);
-               if( tmp_id != NULL)
-               {
-                       if( g_ascii_strncasecmp(id, tmp_id, -1) == 0 )
-                       {
-                               gtk_combo_box_set_active_iter(combobox, &iter);
-                               return i;
-                       }
-               }       
-               
-               valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
-               i++;
-       }
-       return i;
- }
  
  static GtkWidget *
  ui_language_combobox_new(GtkWidget *label)
@@@ -607,12 -566,13 +568,13 @@@ GtkCellRenderer *renderer
        gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combobox), renderer, TRUE);
        gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combobox), renderer, "text", 1, NULL);
  
+       gtk_combo_box_set_id_column( GTK_COMBO_BOX(combobox), 0);
+               
        g_object_unref(store);
  
        if(label)
                gtk_label_set_mnemonic_widget (GTK_LABEL(label), combobox);
  
-       //gtk_widget_set_size_request(comboboxentry, HB_MINWIDTH_COMBO, -1);
        ui_language_combobox_populate(combobox);
  
        gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 0);
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
  
  
  /*
  **
  */
@@@ -652,53 -609,6 +611,6 @@@ guint i
        return combobox;
  }
  
- /*
- static defpref_currency_display(GtkWidget *widget, gpointer user_data)
- {
- struct defpref_data *data;
- struct iso4217format *curfmt;
-       DB( g_print("\n[ui-pref] display default currency\n") );
-       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-       curfmt =  iso4217format_get(PREFS->curr_default);
-       if(curfmt != NULL)
-       {
-       gchar *name = g_strdup_printf("%s (%s)", curfmt->curr_iso_code, iso4217_get_name(curfmt->curr_iso_code));
-       
-               gtk_label_set_label (data->LB_default, name);
-               g_free(name);
-       }
- }
- static void defpref_currency_change(GtkWidget *widget, gpointer user_data)
- {
- struct defpref_data *data;
- struct iso4217format *curfmt;
-       DB( g_print("\n[ui-pref] chnage default currency\n") );
-       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-       curfmt = ui_cur_select_dialog_new(data->window);
-       DB( g_print("(cur) return  %s\n", curfmt) );
-       if( curfmt != NULL )
-       {
-               g_free(PREFS->curr_default);
-               PREFS->curr_default = g_strdup(curfmt->culture);
-               
-               defpref_currency_display(widget, NULL);
-       }
- }
- */
  
  static void defpref_pathselect(GtkWidget *widget, gpointer user_data)
  {
@@@ -777,91 -687,33 +689,33 @@@ GDate *date
  }
  
  
- /*
- ** update the number sample label
- */
- static void defpref_numberbase_sample(GtkWidget *widget, gpointer user_data)
- {
- struct defpref_data *data;
- struct CurrencyFmt cur;
- gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
- gchar  buf[128], *ptr;
-       DB( g_print("\n[ui-pref] number sample\n") );
-       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
-       cur.symbol = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_num_symbol));
-       cur.is_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_num_isprefix));
-       cur.decimal_char  = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_num_decimalchar));
-       cur.grouping_char = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_num_groupingchar));
-       cur.frac_digits   = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_num_fracdigits));
-       g_snprintf(cur.format, 8-1, "%%.%df", cur.frac_digits);
-       ptr = cur.monfmt;
-       if(cur.is_prefix)
-       {
-               ptr = g_stpcpy(ptr, cur.symbol);
-               ptr = g_stpcpy(ptr, " ");
-       }
-       ptr = g_stpcpy(ptr, "%s");
-       if(!cur.is_prefix)
-       {
-               ptr = g_stpcpy(ptr, " ");
-               ptr = g_stpcpy(ptr, cur.symbol);
-       }
-       
-       DB( g_print("fmt: %s\n", cur.format) );
-       DB( g_print("monfmt: %s\n", cur.monfmt) );
-       g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur.format, 12345.67);
-       
-       real_mystrfmon(buf, 127, formatd_buf, &cur);
-       gtk_label_set_text(GTK_LABEL(data->LB_numberbase), buf);
- }
  /*
  ** update the number sample label
  */
  static void defpref_numbereuro_sample(GtkWidget *widget, gpointer user_data)
  {
  struct defpref_data *data;
struct CurrencyFmt cur;
Currency cur;
  gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
- gchar  buf[128], *ptr;
+ gchar buf[128];
  
        DB( g_print("\n[ui-pref] number sample\n") );
  
        data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
  
        cur.symbol = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_euro_symbol));
-       cur.is_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix));
+       cur.sym_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix));
        cur.decimal_char  = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_euro_decimalchar));
        cur.grouping_char = (gchar *)gtk_entry_get_text(GTK_ENTRY(data->ST_euro_groupingchar));
        cur.frac_digits   = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_euro_fracdigits));
-       g_snprintf(cur.format, 8-1, "%%.%df", cur.frac_digits);
-       
-       ptr = cur.monfmt;
-       if(cur.is_prefix)
-       {
-               ptr = g_stpcpy(ptr, cur.symbol);
-               ptr = g_stpcpy(ptr, " ");
-       }
-       ptr = g_stpcpy(ptr, "%s");
-       if(!cur.is_prefix)
-       {
-               ptr = g_stpcpy(ptr, " ");
-               ptr = g_stpcpy(ptr, cur.symbol);
-       }
+       da_cur_initformat (&cur);
        
        DB( g_print("fmt: %s\n", cur.format) );
-       DB( g_print("monfmt: %s\n", cur.monfmt) );
-       
-       g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur.format, 12345.67);
-       
-       real_mystrfmon(buf, 127, formatd_buf, &cur);
+       g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur.format, HB_NUMBER_SAMPLE);
+       hb_str_formatd(buf, 127, formatd_buf, &cur, TRUE);
        gtk_label_set_text(GTK_LABEL(data->LB_numbereuro), buf);
  
  }
  static void defpref_eurotoggle(GtkWidget *widget, gpointer user_data)
  {
  struct defpref_data *data;
- gboolean bool;
+ gboolean sensitive;
  
        DB( g_print("\n[ui-pref] euro toggle\n") );
  
        data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
  
-       bool = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_enable));
+       sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_enable));
+       gtk_widget_set_sensitive(data->GRP_currency      , sensitive);
+       gtk_widget_set_sensitive(data->GRP_rate          , sensitive);
+       gtk_widget_set_sensitive(data->GRP_format        , sensitive);
+ }
  
  
+ /*
+ ** set euro value widget from a country
+ */
+ static void defpref_eurosetcurrency(GtkWidget *widget, gpointer user_data)
+ {
+ struct defpref_data *data;
+ EuroParams *euro = user_data;
+ gchar *buf;
+       
+       DB( g_print("\n[ui-pref] eurosetcurrency\n") );
  
-       gtk_widget_set_sensitive(data->CY_euro_preset   , bool);
-       gtk_widget_set_sensitive(data->ST_euro_country  , bool);
-       gtk_widget_set_sensitive(data->NB_euro_value    , bool);
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+       
+       buf = g_strdup_printf("%s - %s", euro->iso, euro->name);
  
-       gtk_widget_set_sensitive(data->ST_euro_symbol, bool);
-       gtk_widget_set_sensitive(data->CM_euro_isprefix, bool);
-       gtk_widget_set_sensitive(data->ST_euro_decimalchar, bool);
-       gtk_widget_set_sensitive(data->ST_euro_groupingchar, bool);     
-       gtk_widget_set_sensitive(data->NB_euro_fracdigits, bool);
-       gtk_widget_set_sensitive(data->LB_numbereuro, bool);
+       gtk_label_set_markup(GTK_LABEL(data->ST_euro_country), buf);
  
+       g_free(buf);
  }
  
  
@@@ -911,27 -775,45 +777,45 @@@ gint country
        data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
  
        country = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_euro_preset));
+       data->country = country;
  
-       gtk_label_set_text(GTK_LABEL(data->ST_euro_country), euro_params[country].name);
+       defpref_eurosetcurrency(widget, &euro_params[country]);
  
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_value), euro_params[country].value);
  
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_fracdigits), euro_params[country].frac_digits);
  
        gtk_entry_set_text(GTK_ENTRY(data->ST_euro_symbol)   , euro_params[country].symbol);
-       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix), euro_params[country].is_prefix);
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix), euro_params[country].sym_prefix);
        gtk_entry_set_text(GTK_ENTRY(data->ST_euro_decimalchar) , euro_params[country].decimal_char);
        gtk_entry_set_text(GTK_ENTRY(data->ST_euro_groupingchar), euro_params[country].grouping_char);
  
  }
  
+ static void defpref_colortoggle(GtkWidget *widget, gpointer user_data)
+ {
+ struct defpref_data *data;
+ gboolean sensitive;
+       DB( g_print("\n[ui-pref] color toggle\n") );
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+       sensitive = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_custom_colors));
+       gtk_widget_set_sensitive(data->GR_colors         , sensitive);
+ }
  /*
  ** set preset colors for amount display
  */
  static void defpref_colorpreset(GtkWidget *widget, gpointer user_data)
  {
  struct defpref_data *data;
- GdkColor color;
+ GdkRGBA rgba;
  gint preset;
  gchar *expcol, *inccol, *wrncol;
  
        }
  
  
-       gdk_color_parse(expcol, &color);
-       gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_exp_color), &color);
+       gdk_rgba_parse(&rgba, expcol);
+       gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_exp_color), &rgba);
  
-       gdk_color_parse(inccol, &color);
-       gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_inc_color), &color);
+       gdk_rgba_parse(&rgba, inccol);
+       gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_inc_color), &rgba);
  
-       gdk_color_parse(wrncol, &color);
-       gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_warn_color), &color);
+       gdk_rgba_parse(&rgba, wrncol);
+       gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_warn_color), &rgba);
  
  
  }
  
  
+ static void defpref_color_scheme_changed(GtkWidget *widget, gpointer user_data)
+ {
+ struct defpref_data *data;
+       DB( g_print("\n[ui-pref] color scheme chnaged\n") );
+       data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
+       gtk_widget_queue_draw (data->DA_colors);
+       
+ }
  
  
  /*
@@@ -999,24 -894,15 +896,15 @@@ guint   tmp
  /*
  ** set :: fill in widgets from PREFS structure
  */
- static void defpref_entry_set_text(GtkWidget *widget, gchar *text)
- {
-       DB( g_print(" set text to '%s'\n", text) );
-       if( text != NULL )
-       {
-               gtk_entry_set_text(GTK_ENTRY(widget), text);
-       }
- }
  
  static void defpref_set(struct defpref_data *data)
  {
- GdkColor color;
+ GdkRGBA rgba;
  
        DB( g_print("\n[ui-pref] set\n") );
  
        if(PREFS->language != NULL)
-               ui_language_combobox_set_active_id(GTK_COMBO_BOX(data->CY_language), PREFS->language);
+               gtk_combo_box_set_active_id(GTK_COMBO_BOX(data->CY_language), PREFS->language);
        else
                gtk_combo_box_set_active (GTK_COMBO_BOX(data->CY_language), 0);
  
  
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_custom_colors), PREFS->custom_colors);
  
-       gdk_color_parse(PREFS->color_exp, &color);
-       gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_exp_color), &color);
+       gdk_rgba_parse(&rgba, PREFS->color_exp);
+       gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_exp_color), &rgba);
  
-       gdk_color_parse(PREFS->color_inc, &color);
-       gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_inc_color), &color);
+       gdk_rgba_parse(&rgba, PREFS->color_inc);
+       gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_inc_color), &rgba);
  
-       gdk_color_parse(PREFS->color_warn, &color);
-       gtk_color_button_set_color(GTK_COLOR_BUTTON(data->CP_warn_color), &color);
+       gdk_rgba_parse(&rgba, PREFS->color_warn);
+       gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(data->CP_warn_color), &rgba);
  
-       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_ruleshint), PREFS->rules_hint);
+       //gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_ruleshint), PREFS->rules_hint);
+       gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_gridlines), PREFS->grid_lines);
  
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_fiscyearday), PREFS->fisc_year_day );
        gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_fiscyearmonth), PREFS->fisc_year_month - 1);
  
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_load_last), PREFS->loadlast);
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_append_scheduled), PREFS->appendscheduled);
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_do_update_currency), PREFS->do_update_currency);
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_show_splash), PREFS->showsplash);
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_herit_date), PREFS->heritdate);
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_hide_reconciled), PREFS->hidereconciled);
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_show_remind), PREFS->showremind);
  
        /* display */
        gtk_entry_set_text(GTK_ENTRY(data->ST_datefmt), PREFS->date_format);
  
-       defpref_entry_set_text(data->ST_num_symbol, PREFS->base_cur.symbol);
-       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_num_isprefix), PREFS->base_cur.is_prefix);
-       defpref_entry_set_text(data->ST_num_decimalchar, PREFS->base_cur.decimal_char);
-       defpref_entry_set_text(data->ST_num_groupingchar, PREFS->base_cur.grouping_char);
-       gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_num_fracdigits), PREFS->base_cur.frac_digits);
-       //gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_numnbdec), PREFS->num_nbdecimal);
-       //gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_numseparator), PREFS->num_separator);
-       //gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_imperial), PREFS->imperial_unit);
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_unitismile), PREFS->vehicle_unit_ismile);
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_unitisgal), PREFS->vehicle_unit_isgal);
  
        gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_daterange_wal), PREFS->date_range_wal);
        gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_daterange_txn), PREFS->date_range_txn);
+       gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->ST_datefuture_nbdays), PREFS->date_future_nbdays);
        gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_daterange_rep), PREFS->date_range_rep);
-       
        /* euro */
-       //defpref_currency_display(data->LB_default, NULL);
-       
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_enable), PREFS->euro_active);
        //gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_euro_preset), PREFS->euro_country);
-       gchar *buf;
-       buf = g_strdup_printf("%s", euro_params[PREFS->euro_country].name);
-       gtk_label_set_markup(GTK_LABEL(data->ST_euro_country), buf);
-       g_free(buf);
+       data->country = PREFS->euro_country;
+       defpref_eurosetcurrency(data->window, &euro_params[PREFS->euro_country]);
  
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_value), PREFS->euro_value);
  
-       defpref_entry_set_text(data->ST_euro_symbol, PREFS->minor_cur.symbol);
-       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix), PREFS->minor_cur.is_prefix);
-       defpref_entry_set_text(data->ST_euro_decimalchar, PREFS->minor_cur.decimal_char);
-       defpref_entry_set_text(data->ST_euro_groupingchar, PREFS->minor_cur.grouping_char);
+       ui_gtk_entry_set_text(data->ST_euro_symbol, PREFS->minor_cur.symbol);
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix), PREFS->minor_cur.sym_prefix);
+       ui_gtk_entry_set_text(data->ST_euro_decimalchar, PREFS->minor_cur.decimal_char);
+       ui_gtk_entry_set_text(data->ST_euro_groupingchar, PREFS->minor_cur.grouping_char);
        gtk_spin_button_set_value(GTK_SPIN_BUTTON(data->NB_euro_fracdigits), PREFS->minor_cur.frac_digits);
  
  
  
        /* import */
        gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_dtex_datefmt), PREFS->dtex_datefmt);
+       gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_dtex_ofxname), PREFS->dtex_ofxname);
        gtk_combo_box_set_active(GTK_COMBO_BOX(data->CY_dtex_ofxmemo), PREFS->dtex_ofxmemo);
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_dtex_qifmemo), PREFS->dtex_qifmemo);
+       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data->CM_dtex_qifswap), PREFS->dtex_qifswap);
  
  
  }
  ** get :: fill PREFS structure from widgets
  */
  
+ #define RGBA_TO_INT(x) (int)(x*255)
  
- static void defpref_entry_get_text(GtkWidget *widget, gchar **storage)
+ static gchar *gdk_rgba_to_hex(GdkRGBA *rgba)
  {
- const gchar *text;
-       DB( g_print("defpref_entry_get_text\n") );
-       DB( g_print(" storage is '%p' at '%p'\n", *storage, storage) );
-       /* free any previous string */
-       if( *storage != NULL )
-       {
-               DB( g_print(" storage was not null, freeing\n") );
-               g_free(*storage);
-       }
-       *storage = NULL;
-       text = gtk_entry_get_text(GTK_ENTRY(widget));
-       *storage = g_strdup(text);
-       DB( g_print(" storing %s at %p\n", *storage, storage) );
-       DB( g_print(" get text to '%s' '%s'\n", text, *storage) );
+       return g_strdup_printf("#%02x%02x%02x", RGBA_TO_INT(rgba->red), RGBA_TO_INT(rgba->green), RGBA_TO_INT(rgba->blue));
  }
  
  
  static void defpref_get(struct defpref_data *data)
  {
- GdkColor color;
+ GdkRGBA rgba;
  const gchar *lang;
  
        DB( g_print("\n[ui-pref] get\n") );
  
        g_free(PREFS->language);
        PREFS->language = NULL;
-       lang = ui_language_combobox_get_active_id(GTK_COMBO_BOX(data->CY_language));
+       lang = gtk_combo_box_get_active_id(GTK_COMBO_BOX(data->CY_language));
        if(lang != NULL)
        {
                PREFS->language = g_strdup(lang);
  
        PREFS->custom_colors = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_custom_colors));
  
-       gtk_color_button_get_color(GTK_COLOR_BUTTON(data->CP_exp_color), &color);
+       gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(data->CP_exp_color), &rgba);
        g_free(PREFS->color_exp);
-       PREFS->color_exp = gdk_color_to_string(&color);
+       PREFS->color_exp = gdk_rgba_to_hex(&rgba);
  
-       gtk_color_button_get_color(GTK_COLOR_BUTTON(data->CP_inc_color), &color);
+       gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(data->CP_inc_color), &rgba);
        g_free(PREFS->color_inc);
-       PREFS->color_inc = gdk_color_to_string(&color);
+       PREFS->color_inc = gdk_rgba_to_hex(&rgba);
  
-       gtk_color_button_get_color(GTK_COLOR_BUTTON(data->CP_warn_color), &color);
+       gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(data->CP_warn_color), &rgba);
        g_free(PREFS->color_warn);
-       PREFS->color_warn = gdk_color_to_string(&color);
+       PREFS->color_warn = gdk_rgba_to_hex(&rgba);
  
-       PREFS->rules_hint = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_ruleshint));
+       //PREFS->rules_hint = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_ruleshint));
+       PREFS->grid_lines = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_gridlines));
  
        PREFS->fisc_year_day = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_fiscyearday));
        PREFS->fisc_year_month = 1 + gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_fiscyearmonth));
        g_free(PREFS->path_hbfile);
        PREFS->path_hbfile = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_path_hbfile)));
  
-       defpref_entry_get_text(data->ST_path_import, &PREFS->path_import);
+       ui_gtk_entry_replace_text(data->ST_path_import, &PREFS->path_import);
  
-       defpref_entry_get_text(data->ST_path_export, &PREFS->path_export);
+       ui_gtk_entry_replace_text(data->ST_path_export, &PREFS->path_export);
  
        PREFS->loadlast  = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_load_last));
        PREFS->appendscheduled  = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_append_scheduled));
+       PREFS->do_update_currency  = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_do_update_currency));
+               
        PREFS->showsplash  = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_show_splash));
        PREFS->heritdate = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_herit_date));
        PREFS->hidereconciled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_hide_reconciled));
+       PREFS->showremind = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_show_remind));
  
        //g_free(PREFS->path_navigator);
        //PREFS->path_navigator = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_path_navigator)));
        g_free(PREFS->date_format);
        PREFS->date_format = g_strdup(gtk_entry_get_text(GTK_ENTRY(data->ST_datefmt)));
  
-       defpref_entry_get_text(data->ST_num_symbol, &PREFS->base_cur.symbol);
-       PREFS->base_cur.is_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_num_isprefix));
-       defpref_entry_get_text(data->ST_num_decimalchar, &PREFS->base_cur.decimal_char);
-       defpref_entry_get_text(data->ST_num_groupingchar, &PREFS->base_cur.grouping_char);
-       PREFS->base_cur.frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_num_fracdigits));
-       //PREFS->num_nbdecimal = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_numnbdec));
-       //PREFS->num_separator = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_numseparator));
-       //PREFS->imperial_unit = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_imperial));
        PREFS->vehicle_unit_ismile = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_unitismile));
        PREFS->vehicle_unit_isgal = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_unitisgal));
  
        PREFS->date_range_wal = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_daterange_wal));
        PREFS->date_range_txn = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_daterange_txn));
+       PREFS->date_future_nbdays  = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->ST_datefuture_nbdays));
        PREFS->date_range_rep = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_daterange_rep));
  
        PREFS->euro_active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_enable));
-       PREFS->euro_country = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_euro_preset));
+       PREFS->euro_country = data->country;
        PREFS->euro_value = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_euro_value));
        //strcpy(PREFS->euro_symbol, gtk_entry_get_text(GTK_ENTRY(data->ST_euro_symbol)));
        //PREFS->euro_nbdec = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_euro_nbdec));
        //PREFS->euro_thsep = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_thsep));
  
-       defpref_entry_get_text(data->ST_euro_symbol, &PREFS->minor_cur.symbol);
-       PREFS->minor_cur.is_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix));
-       
-       g_free(PREFS->minor_cur.decimal_char);
-       PREFS->minor_cur.decimal_char  = g_strdup( gtk_entry_get_text(GTK_ENTRY(data->ST_euro_decimalchar)) );
-       
-       g_free(PREFS->minor_cur.grouping_char);
-       PREFS->minor_cur.grouping_char = g_strdup( gtk_entry_get_text(GTK_ENTRY(data->ST_euro_groupingchar)) );
+       ui_gtk_entry_replace_text(data->ST_euro_symbol, &PREFS->minor_cur.symbol);
+       PREFS->minor_cur.sym_prefix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_euro_isprefix));
+       ui_gtk_entry_replace_text(data->ST_euro_decimalchar, &PREFS->minor_cur.decimal_char);
+       ui_gtk_entry_replace_text(data->ST_euro_groupingchar, &PREFS->minor_cur.grouping_char);
        PREFS->minor_cur.frac_digits = gtk_spin_button_get_value(GTK_SPIN_BUTTON(data->NB_euro_fracdigits));
  
        PREFS->stat_byamount   = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_stat_byamount));
  
        /* import */
        PREFS->dtex_datefmt = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_dtex_datefmt));
+       PREFS->dtex_ofxname = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_dtex_ofxname));
        PREFS->dtex_ofxmemo = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_dtex_ofxmemo));
+       PREFS->dtex_qifmemo = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_dtex_qifmemo));
+       PREFS->dtex_qifswap = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_dtex_qifswap));
  
        //PREFS->chart_legend = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(data->CM_chartlegend));
  
 +      list_ext_colpref_get(GTK_TREE_VIEW(data->PI_plugin_columns), &(PREFS->ext_whitelist));
  }
  
- /*
- GtkWidget *defpref_page_charts (struct defpref_data *data)
- {
- GtkWidget *container;
- GtkWidget *table, *label, *widget;
- gint row;
-       container = gtk_hbox_new(FALSE, 0);
-       table = gtk_table_new (2, 2, FALSE);
-       gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
-       gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
-       gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
-       gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
-       row = 0;
-       widget = gtk_check_button_new_with_mnemonic (_("Show legend"));
-       data->CM_chartlegend = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("Bar width:"), 1.0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_numeric(label, 8.0, 32.0);
-       //data->NB_numnbdec = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       return(container);
- }
- */
  
  static GtkWidget *defpref_page_import (struct defpref_data *data)
  {
- GtkWidget *container;
- GtkWidget *table, *hbox, *label, *widget;
- gint row;
-       container = gtk_vbox_new(FALSE, 0);
-       table = gtk_table_new (5, 3, FALSE);
-       //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
-       gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
-       gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
-       gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
-       row = 0;
-       label = make_label(_("Date options"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
-       row++;
-       label = make_label(_("Date order:"), 0, 0.5);
+ GtkWidget *content_grid, *group_grid, *hbox, *label, *widget;
+ gint crow, row;
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       crow = 0;
+       // group :: Date options
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Date options"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
+       label = make_label_widget(_("Date order:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_cycle(label, CYA_IMPORT_DATEORDER);
        data->CY_dtex_datefmt = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
  
-       row++;
-       label = make_label(_("OFX/QFX options"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+       // group :: OFX/QFX options
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("OFX/QFX options"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
+       label = make_label_widget(_("_Name field:"));
+       //----------------------------------------- l, r, t, b
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_cycle(label, CYA_IMPORT_OFXNAME);
+       data->CY_dtex_ofxname = widget;
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
        row++;
-       label = make_label(_("_Memo field:"), 0, 0.5);
+       label = make_label_widget(_("_Memo field:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_cycle(label, CYA_IMPORT_OFXMEMO);
        data->CY_dtex_ofxmemo = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("Files folder"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
-       row++;
-       label = make_label(_("_Import:"), 0, 0.5);
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+       // group :: QIF options
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("QIF options"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
+       label = make_label_widget(_("Memos:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = gtk_check_button_new_with_mnemonic (_("_Import"));
+       data->CM_dtex_qifmemo = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+       widget = gtk_check_button_new_with_mnemonic (_("_Swap with payees"));
+       data->CM_dtex_qifswap = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 3, row, 1, 1);
+       // group :: Files folder
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Files folder"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
+       label = make_label_widget(_("_Import:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
  
-       hbox = gtk_hbox_new(FALSE, 0);
-       gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0);
+       hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+       gtk_widget_set_hexpand (hbox, TRUE);
+       gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
  
        widget = make_string(label);
        data->ST_path_import = widget;
+       gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED);
        gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
  
-       widget = gtk_button_new_with_label("...");
+       //widget = gtk_button_new_with_label("...");
+       widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON);
        data->BT_path_import = widget;
        gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
  
        row++;
-       label = make_label(_("_Export:"), 0, 0.5);
+       label = make_label_widget(_("_Export:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
  
-       hbox = gtk_hbox_new(FALSE, 0);
-       gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0);
+       hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+       gtk_widget_set_hexpand (hbox, TRUE);
+       gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
  
        widget = make_string(label);
        data->ST_path_export = widget;
+       gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED);
        gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
  
-       widget = gtk_button_new_with_label("...");
+       //widget = gtk_button_new_with_label("...");
+       widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON);
        data->BT_path_export = widget;
        gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
  
-       return(container);
+       return content_grid;
  }
  
+ #define cube_dim 16
  
- static GtkWidget *defpref_page_reports (struct defpref_data *data)
+ static gboolean
+ draw_callback (GtkWidget *widget,
+                cairo_t   *cr,
+                gpointer   user_data)
  {
- GtkWidget *container;
- GtkWidget *table, *label, *widget;
- gint row;
+ struct defpref_data *data = user_data;
+ gint index;
+ GtkColorScheme scheme;
+ gint w, h;
+ gint i, x, y;
  
-       container = gtk_vbox_new(FALSE, 0);
+       index = gtk_combo_box_get_active(GTK_COMBO_BOX(data->CY_color_scheme));
  
-       table = gtk_table_new (5, 3, FALSE);
-       //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
-       gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
-       gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
+       colorscheme_init(&scheme, index);
+       
+       gtk_widget_get_size_request (widget, &w, &h);
+       x = y = 0;
+       for(i=0;i<scheme.nb_cols;i++)
+       {
+               cairo_user_set_rgbcol (cr, &scheme.colors[i]);
+               cairo_rectangle(cr, x, y, cube_dim, cube_dim);
+               cairo_fill(cr);
+               x += 1 + cube_dim;
+               if( i == 15 )
+               { x = 0; y = 1 + cube_dim; }
+       }
  
-       gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
+       return TRUE;
+ }
  
  
-       row = 0;
-       label = make_label(_("Initial filter"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
  
-       row++;
-       label = make_label(_("Date _range:"), 0, 0.5);
+ static GtkWidget *defpref_page_reports (struct defpref_data *data)
+ {
+ GtkWidget *content_grid, *group_grid, *label, *widget;
+ gint crow, row;
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       crow = 0;
+       // group :: Initial filter
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Initial filter"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
+       label = make_label_widget(_("Date _range:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_daterange(label, FALSE);
        data->CY_daterange_rep = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("Charts options"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
-       row++;
-       label = make_label(_("Color Scheme:"), 0, 0.5);
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+       // group ::Charts options
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Charts options"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
+       label = make_label_widget(_("Color scheme:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_cycle(label, (gchar **)chart_colors);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_cycle(label, chart_colors);
        data->CY_color_scheme = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
        row++;
-       label = make_label(_("Statistics options"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+       widget = gtk_drawing_area_new ();
+       data->DA_colors = widget;
+       gtk_widget_set_size_request (widget, (1+cube_dim)*16, (1+cube_dim)*2);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
-       row++;
+       g_signal_connect (data->DA_colors, "draw", G_CALLBACK (draw_callback), data);
+       // group :: Statistics options
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Statistics options"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
        widget = gtk_check_button_new_with_mnemonic (_("Show by _amount"));
        data->CM_stat_byamount = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
        row++;
        widget = gtk_check_button_new_with_mnemonic (_("Show _rate column"));
        data->CM_stat_showrate = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
        row++;
        widget = gtk_check_button_new_with_mnemonic (_("Show _details"));
        data->CM_stat_showdetail = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("Budget options"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
-       row++;
+       // group :: Budget options
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Budget options"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       
+       row = 1;
        widget = gtk_check_button_new_with_mnemonic (_("Show _details"));
        data->CM_budg_showdetail = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
-       return(container);
+       return content_grid;
  }
  
  
  static GtkWidget *defpref_page_euro (struct defpref_data *data)
  {
- GtkWidget *container;
- GtkWidget *table, *label, *widget;
- gint row;
-       container = gtk_vbox_new(FALSE, 0);
-       table = gtk_table_new (7, 3, FALSE);
-       //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
-       gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
-       gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
-       gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
-       row = 0;
- /*
-       label = make_label(_("Default currency"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
-       row++;
-       label = make_label(_("Code:"), 0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_label(NULL, 0.0, 0.0);
-       data->LB_default = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       widget = gtk_button_new_with_mnemonic (_("_Change"));
-       data->BT_default = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
-       row++;
- */
-       label = make_label(_("General"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+ GtkWidget *content_grid, *group_grid, *label, *widget, *expander;
+ gint crow, row;
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       crow = 0;
+       // group :: General
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("General"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
+       row=1;
        widget = gtk_check_button_new_with_mnemonic (_("_Enable"));
        data->CM_euro_enable = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
+       // group :: Currency
+     group_grid = gtk_grid_new ();
+       data->GRP_currency = group_grid;
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Currency"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 4, 1);
  
-       row++;
-       label = make_label(_("Fill from:"), 0, 0.5);
+       row=1;
+       widget = make_label(NULL, 0.0, 0.5);
+       data->ST_euro_country = widget;
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1);
+       //row++;
+       label = make_label_widget(_("_Preset:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 2, row, 1, 1);
        widget = make_euro_presets(label);
        data->CY_euro_preset = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("Country:"), 0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_label(NULL, 0.0, 0.0);
-       data->ST_euro_country = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_widget_set_margin_left (label, 2*SPACING_LARGE);
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 3, row, 1, 1);
  
-       row++;
-       label = make_label(_("Value:"), 0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_euro(label);
+       
+       // group :: Exchange rate
+     group_grid = gtk_grid_new ();
+       data->GRP_rate = group_grid;
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       label = make_label_group(_("Exchange rate"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       row=1;
+       label = make_label_widget("1 EUR _=");
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_exchange_rate(label);
        data->NB_euro_value = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+       // group :: Numbers format
+     group_grid = gtk_grid_new ();
+       data->GRP_format = group_grid;
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Format"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
-       label = make_label(_("Numbers format"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+       row = 1;
+       widget = make_label(NULL, 0, 0.0);
+       data->LB_numbereuro = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 1, 1);
  
        row++;
-       label = make_label(_("Symbol:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       expander = gtk_expander_new_with_mnemonic(_("_Customize"));
+       gtk_grid_attach (GTK_GRID (group_grid), expander, 1, row, 1, 1);
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_container_add (GTK_CONTAINER (expander), group_grid);
+       
+       row = 0;
+       label = make_label_widget(_("_Symbol:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_string_maxlength(label, 3);
        data->ST_euro_symbol = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
        row++;
-       widget = gtk_check_button_new_with_mnemonic (_("Is prefix"));
+       widget = gtk_check_button_new_with_mnemonic (_("Is pre_fix"));
        data->CM_euro_isprefix = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
        row++;
-       label = make_label(_("Decimal char:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       label = make_label_widget(_("_Decimal char:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_string_maxlength(label, 1);
        data->ST_euro_decimalchar = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("Grouping char:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_string_maxlength(label, 1);
-       data->ST_euro_groupingchar = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
        row++;
-       label = make_label(_("_Frac digits:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       label = make_label_widget(_("_Frac digits:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_numeric(label, 0.0, 6.0);
        data->NB_euro_fracdigits = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(NULL, 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_label(NULL, 0, 0.5);
-       data->LB_numbereuro = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
- /*
-       row++;
-       label = make_label(_("_Frac digits:"), 0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_numeric(label, 0.0, 6.0);
-       data->NB_euro_nbdec = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       widget = gtk_check_button_new_with_mnemonic (_("Thousand separator"));
-       data->CM_euro_thsep = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
        row++;
-       label = make_label(_("Symbol:"), 0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_string_maxlength(label, 8);
-       data->ST_euro_symbol = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
- */
+       label = make_label_widget(_("_Grouping char:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_string_maxlength(label, 1);
+       data->ST_euro_groupingchar = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
-       return(container);
+       return content_grid;
  }
  
  
- /*
- GtkWidget *defpref_page_help (struct defpref_data *data)
- {
- GtkWidget *container;
- GtkWidget *table, *label, *widget;
- gint row;
-       container = gtk_vbox_new(FALSE, 0);
-       table = gtk_table_new (2, 2, FALSE);
-       gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
-       gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
-       gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
-       gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
-       row = 0;
-       label = make_label(_("Web navigator"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
-       row++;
-       label = make_label("", 0.0, 0.5);
-       gtk_misc_set_padding (GTK_MISC (label), HB_BOX_SPACING, 0);
-       gtk_table_attach (GTK_TABLE (table), label, 0, 1, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       label = make_label(_("Web _navigator to use:"), 1.0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_string(label);
-       data->ST_path_navigator = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
-       return(container);
- }
- */
  static GtkWidget *defpref_page_display (struct defpref_data *data)
  {
- GtkWidget *container;
- GtkWidget *table, *label, *widget;
- gint row;
-       container = gtk_vbox_new(FALSE, 0);
+ GtkWidget *content_grid, *group_grid, *label, *widget, *expander;
+ gint crow, row;
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       crow = 0;
+       // group :: Date options
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Date"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       table = gtk_table_new (7, 3, FALSE);
-       //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
-       gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
-       gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
+       row = 1;
+       widget = make_label(NULL, 0, 0.5);
+       data->LB_date = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
-       gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
+       row++;
+       expander = gtk_expander_new_with_mnemonic(_("_Customize"));
+       gtk_grid_attach (GTK_GRID (group_grid), expander, 1, row, 1, 1);
  
-       row = 0;
-       label = make_label(_("Date options"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_container_add (GTK_CONTAINER (expander), group_grid);
  
-       row++;
-       label = make_label(_("_Date format:"), 0, 0.5);
+       row = 1;
+       label = make_label_widget(_("_Format:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_string(label);
        data->ST_datefmt = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+       widget = gtk_image_new_from_icon_name (ICONNAME_INFO, GTK_ICON_SIZE_BUTTON);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 3, row, 1, 1);
  
+       
        gtk_widget_set_tooltip_text(widget,
        _("%a locale's abbreviated weekday name.\n"
  "%A locale's full weekday name. \n"
  "%Y year with century as a decimal number. \n")
  );
  
-       row++;
-       label = make_label(NULL, 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_label(NULL, 0, 0.5);
-       data->LB_date = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("Numbers options"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
-       row++;
-       label = make_label(_("Symbol:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_string_maxlength(label, 3);
-       data->ST_num_symbol = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       widget = gtk_check_button_new_with_mnemonic (_("Is prefix"));
-       data->CM_num_isprefix = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("Decimal char:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_string_maxlength(label,1);
-       data->ST_num_decimalchar = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("Grouping char:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_string_maxlength(label, 1);
-       data->ST_num_groupingchar = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(_("_Frac digits:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       #if MYDEBUG
-               widget = make_numeric(label, 0.0, 15.0);
-       #else
-               widget = make_numeric(label, 0.0, 6.0);
-       #endif
-       data->NB_num_fracdigits = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       label = make_label(NULL, 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_label(NULL, 0, 0.5);
-       data->LB_numberbase = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       /* obsolete */
-       /*
-       row++;
-       label = make_label(_("_Frac digits:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       widget = make_numeric(label, 0.0, 6.0);
-       data->NB_numnbdec = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
-       widget = gtk_check_button_new_with_mnemonic (_("_Thousand separator"));
-       data->CM_numseparator = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       */
        row++;
-       label = make_label(_("Measurement units"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+       widget = make_label(NULL, 0.0, 0.5);
+       gtk_label_set_markup (GTK_LABEL(widget), "<small><a href=\"http://man7.org/linux/man-pages/man3/strftime.3.html\">online reference</a></small>");
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
-       /*row++;
-       widget = gtk_check_button_new_with_mnemonic (_("Use _Imperial units"));
-       data->CM_imperial = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);*/
+       // group :: Measurement units
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Measurement units"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
+       row = 1;
        widget = gtk_check_button_new_with_mnemonic (_("Use _miles for meter"));
        data->CM_unitismile = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
        row++;
-       widget = gtk_check_button_new_with_mnemonic (_("Use _galons for fuel"));
+       widget = gtk_check_button_new_with_mnemonic (_("Use _gallon for fuel"));
        data->CM_unitisgal = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
-       return(container);
+       return content_grid;
  }
  
  
  static GtkWidget *defpref_page_transactions (struct defpref_data *data)
  {
- GtkWidget *container;
- GtkWidget *table, *label, *sw, *widget;
- gint row;
-       container = gtk_vbox_new(FALSE, 0);
-       table = gtk_table_new (3, 3, FALSE);
-       //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
-       gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
-       gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
-       gtk_box_pack_start (GTK_BOX (container), table, TRUE, TRUE, 0);
-       row = 0;
-       label = make_label(_("Transaction window"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach (GTK_TABLE (table), label, 0, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+ GtkWidget *content_grid, *group_grid, *sw, *label, *widget;
+ gint crow, row;
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       crow = 0;
+       // group :: Transaction window
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Transaction window"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
-       label = make_label(_("Date _range:"), 0, 0.5);
+       row = 1;
+       label = make_label_widget(_("Date _range:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_daterange(label, FALSE);
        data->CY_daterange_txn = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
        row++;
-       widget = gtk_check_button_new_with_mnemonic (_("Hide reconciled transactions"));
-       data->CM_hide_reconciled = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       label = make_label_widget(_("_Show:"));
+       //----------------------------------------- l, r, t, b
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_numeric(NULL, 0, 366);
+       
+       data->ST_datefuture_nbdays = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
+       //TRANSLATORS: there is a spinner on the left of this label, and so you have 0....x days in advance the current date
+       label = make_label(_("days in advance the current date"), 0, 0.5);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 3, row, 1, 1);
  
        row++;
-       label = make_label(_("Multiple add"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach (GTK_TABLE (table), label, 0, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       widget = gtk_check_button_new_with_mnemonic (_("Hide reconciled transactions"));
+       data->CM_hide_reconciled = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 2, 1);
  
        row++;
+       widget = gtk_check_button_new_with_mnemonic (_("Always show remind transactions"));
+       data->CM_show_remind = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 2, 1);
+       // group :: Multiple add
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Multiple add"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       row = 1;
        widget = gtk_check_button_new_with_mnemonic (_("Keep the last date"));
        data->CM_herit_date = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
+       // group :: Column list
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Column list"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
-       label = make_label(_("Column list"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach (GTK_TABLE (table), label, 0, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       row++;
+       row = 1;
        sw = gtk_scrolled_window_new (NULL, NULL);
        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_ETCHED_IN);
        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
        widget = (GtkWidget *)list_txn_colprefcreate();
        data->LV_opecolumns = widget;
+       gtk_widget_set_size_request(data->LV_opecolumns, HB_MINWIDTH_LIST, -1);
        gtk_container_add (GTK_CONTAINER (sw), widget);
+       gtk_widget_set_vexpand (sw, TRUE);
+       gtk_grid_attach (GTK_GRID (group_grid), sw, 1, row, 2, 1);
        gtk_widget_set_tooltip_text(widget, _("Drag & drop to change the order"));
-       gtk_table_attach (GTK_TABLE (table), sw, 1, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0);
  
-       return(container);
+       return content_grid;
  }
  
  
  
  static GtkWidget *defpref_page_interface (struct defpref_data *data)
  {
- GtkWidget *container;
- GtkWidget *table, *hbox, *label, *widget;
- gint row;
-       container = gtk_vbox_new(FALSE, 0);
-       table = gtk_table_new (6, 3, FALSE);
-       //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
-       gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
-       gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
-       gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
-       row = 0;
-       label = make_label(_("Language"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+ GtkWidget *content_grid, *group_grid, *hbox, *label, *widget;
+ gint crow, row;
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       crow = 0;
+       // group :: General
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("General"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
-       label = make_label(_("_Language:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       row = 1;
+       label = make_label_widget(_("_Language:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = ui_language_combobox_new(label);
        data->CY_language = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
        
        row++;
-       label = make_label(_("General"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
-       row++;
-       label = make_label(_("_Toolbar:"), 0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       label = make_label_widget(_("_Toolbar:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_cycle(label, CYA_TOOLBAR_STYLE);
        data->CY_toolbar = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
-       /*
-       row++;
-       label = make_label(_("_Size:"), 0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       hbox = gtk_hbox_new(FALSE, HB_BOX_SPACING);
-       gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
-       widget = make_numeric(label, 16.0, 48.0);
-       data->NB_image_size = widget;
-       gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
-       label = make_label(_("pixels"), 0, 0.5);
-       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-       */
-       row++;
-       label = make_label(_("Treeview"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
  
        row++;
-       widget = gtk_check_button_new_with_mnemonic (_("Show rules hint"));
-       data->CM_ruleshint = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       //widget = gtk_check_button_new_with_mnemonic (_("Enable rows in alternating colors"));
+       //data->CM_ruleshint = widget;
+       label = make_label_widget(_("_Grid line:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       widget = make_cycle(label, CYA_GRID_LINES);
+       data->CY_gridlines = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
+       // group :: Amount colors
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Amount colors"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
-       label = make_label(_("Amount colors"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
-       row++;
+       row = 1;
        widget = gtk_check_button_new_with_mnemonic (_("Uses custom colors"));
        data->CM_custom_colors = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
+     group_grid = gtk_grid_new ();
+       data->GR_colors = group_grid;
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
  
        row++;
-       label = make_label(_("_Preset:"), 0, 0.5);
+       label = make_label_widget(_("_Preset:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_cycle(label, CYA_TANGO_COLORS);
        data->CY_colors = widget;
-       //gtk_table_attach_defaults (GTK_TABLE (table), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       //gtk_grid_attach (GTK_GRID (group_grid), data->CY_option[FILTER_DATE], 1, 2, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
        row++;
-       label = make_label(_("_Expense:"), 0, 0.5);
+       label = make_label_widget(_("_Expense:"));
        //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       hbox = gtk_hbox_new(FALSE, HB_BOX_SPACING);
-       gtk_table_attach_defaults (GTK_TABLE (table), hbox, 2, 3, row, row+1);
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
+       hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
+       gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
        
        widget = gtk_color_button_new ();
        data->CP_exp_color = widget;
        gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
        
-       label = make_label(_("_Income:"), 0, 0.5);
+       label = make_label_widget(_("_Income:"));
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  
        widget = gtk_color_button_new ();
        data->CP_inc_color = widget;
        gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
  
-       label = make_label(_("_Warning:"), 0, 0.5);
+       label = make_label_widget(_("_Warning:"));
        gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
  
        widget = gtk_color_button_new ();
        data->CP_warn_color = widget;
        gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
  
-       return(container);
+       return content_grid;
  }
  
  static GtkWidget *defpref_page_general (struct defpref_data *data)
  {
- GtkWidget *container;
- GtkWidget *table, *label, *widget, *hbox;
- gint row;
-       container = gtk_vbox_new(FALSE, 0);
-       table = gtk_table_new (4, 3, FALSE);
-       //gtk_container_set_border_width (GTK_CONTAINER (table), HB_BOX_SPACING);
-       gtk_table_set_row_spacings (GTK_TABLE (table), HB_TABROW_SPACING);
-       gtk_table_set_col_spacings (GTK_TABLE (table), HB_TABCOL_SPACING);
-       gtk_box_pack_start (GTK_BOX (container), table, FALSE, FALSE, 0);
-       row = 0;
-       label = make_label(_("Program start"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+ GtkWidget *content_grid, *group_grid, *hbox, *label, *widget;
+ gint crow, row;
+       content_grid = gtk_grid_new();
+       gtk_grid_set_row_spacing (GTK_GRID (content_grid), SPACING_LARGE);
+       gtk_orientable_set_orientation(GTK_ORIENTABLE(content_grid), GTK_ORIENTATION_VERTICAL);
+       crow = 0;
+       // group :: Program start
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Program start"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
+       row = 1;
        widget = gtk_check_button_new_with_mnemonic (_("Show splash screen"));
        data->CM_show_splash = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
        row++;
        widget = gtk_check_button_new_with_mnemonic (_("Load last opened file"));
        data->CM_load_last = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
        row++;
        widget = gtk_check_button_new_with_mnemonic (_("Post pending scheduled transactions"));
        data->CM_append_scheduled = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 1, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
        row++;
-       label = make_label(_("Fiscal year"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+       widget = gtk_check_button_new_with_mnemonic (_("Update currencies online"));
+       data->CM_do_update_currency = widget;
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 1, row, 2, 1);
  
-       row++;
+       // group :: Fiscal year
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       label = make_label_group(_("Fiscal year"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
+       row = 1;
        //TRANSLATORS: (fiscal year) starts on
-       label = make_label(_("Starts _on:"), 0.0, 0.5);
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       label = make_label_widget(_("Starts _on:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
  
-       hbox = gtk_hbox_new(FALSE, HB_BOX_SPACING);
-       gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_FILL|GTK_EXPAND), (GtkAttachOptions) (0), 0, 0);
+       hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
+       gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
        widget = make_numeric (label, 1, 28);
        data->NB_fiscyearday = widget;
        gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
        data->CY_fiscyearmonth = widget;
        gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
  
-       row++;
-       label = make_label(_("Main window reports"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+       // group :: Main window reports
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Main window reports"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
-       label = make_label(_("Date _range:"), 0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       row = 1;
+       label = make_label_widget(_("Date _range:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
        widget = make_daterange(label, FALSE);
        data->CY_daterange_wal = widget;
-       gtk_table_attach (GTK_TABLE (table), widget, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (0), 0, 0);
+       gtk_grid_attach (GTK_GRID (group_grid), widget, 2, row, 1, 1);
  
+       // group :: Files folder
+     group_grid = gtk_grid_new ();
+       gtk_grid_set_row_spacing (GTK_GRID (group_grid), SPACING_SMALL);
+       gtk_grid_set_column_spacing (GTK_GRID (group_grid), SPACING_MEDIUM);
+       gtk_grid_attach (GTK_GRID (content_grid), group_grid, 0, crow++, 1, 1);
+       
+       label = make_label_group(_("Files folder"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 0, 0, 3, 1);
  
-       row++;
-       label = make_label(_("Files folder"), 0.0, 0.5);
-       gimp_label_set_attributes(GTK_LABEL(label), PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD, -1);
-       gtk_table_attach_defaults (GTK_TABLE (table), label, 0, 3, row, row+1);
+       row = 1;
+       label = make_label_widget(_("_Default:"));
+       gtk_grid_attach (GTK_GRID (group_grid), label, 1, row, 1, 1);
  
-       row++;
-       label = make_label(_("_Default:"), 0, 0.5);
-       //----------------------------------------- l, r, t, b
-       gtk_table_attach (GTK_TABLE (table), label, 1, 2, row, row+1, (GtkAttachOptions) (GTK_FILL), (GtkAttachOptions) (0), 0, 0);
-       hbox = gtk_hbox_new(FALSE, 0);
-       gtk_table_attach (GTK_TABLE (table), hbox, 2, 3, row, row+1, (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), (GtkAttachOptions) (GTK_EXPAND|GTK_FILL), 0, 0);
+       hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
+       gtk_widget_set_hexpand (hbox, TRUE);
+       gtk_grid_attach (GTK_GRID (group_grid), hbox, 2, row, 1, 1);
  
        widget = make_string(label);
        data->ST_path_hbfile = widget;
+       gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET(widget)), GTK_STYLE_CLASS_LINKED);
        gtk_box_pack_start (GTK_BOX (hbox), widget, TRUE, TRUE, 0);
  
-       widget = gtk_button_new_with_label("...");
+       //widget = gtk_button_new_with_label("...");
+       widget = gtk_button_new_from_icon_name(ICONNAME_FOLDER, GTK_ICON_SIZE_BUTTON);
        data->BT_path_hbfile = widget;
        gtk_box_pack_start (GTK_BOX (hbox), widget, FALSE, FALSE, 0);
  
-       return(container);
+       return content_grid;
  }
  
 +
 +void plugin_execute_action(GtkTreeView* treeview, GtkTreePath* path, GtkTreeViewColumn* col, gpointer userdata);
 +
 +static void
 +toggle_plugin(GtkCellRendererToggle *cell, gchar* path_str, gpointer data)
 +{
 +      GtkTreeModel *model = (GtkTreeModel*)data;
 +      GtkTreeIter  iter;
 +      GtkTreePath *path = gtk_tree_path_new_from_string(path_str);
 +
 +      const gchar* plugin;
 +
 +      gtk_tree_model_get_iter(model, &iter, path);
 +      gtk_tree_model_get(model, &iter, EXT_COLUMN_PLUGIN_NAME, &plugin, -1);
 +
 +      gboolean enabled = ext_is_plugin_loaded(plugin);
 +      if (enabled) {
 +              ext_unload_plugin(plugin);
 +              enabled = FALSE;
 +      } else {
 +              enabled = (ext_load_plugin(plugin) == 0);
 +              if (!enabled) {
 +                      ext_run_modal(_("Plugin Error"), _("The plugin failed to load properly."), "error");
 +              }
 +      }
 +
 +      /* set new value */
 +      gtk_list_store_set(GTK_LIST_STORE (model), &iter, EXT_COLUMN_ENABLED, enabled, -1);
 +
 +      /* clean up */
 +      gtk_tree_path_free(path);
 +}
 +
 +
 +void plugin_execute_action(GtkTreeView* treeview, GtkTreePath* path, GtkTreeViewColumn* col, gpointer userdata)
 +{
 +      GtkTreeModel*   model = gtk_tree_view_get_model(treeview);
 +      GtkTreeIter     iter;
 +
 +      if (gtk_tree_model_get_iter(model, &iter, path)) {
 +              gchar* plugin_filename;
 +              gtk_tree_model_get(model, &iter, EXT_COLUMN_PLUGIN_NAME, &plugin_filename, -1);
 +              ext_execute_action(plugin_filename);
 +              g_free(plugin_filename);
 +      }
 +}
 +
 +static GtkWidget *defpref_page_plugins (struct defpref_data *data)
 +{
 +      GtkWidget *container;
 +      GtkListStore *store;
 +      GtkTreeIter it;
 +      GtkWidget* view;
 +
 +      container = gtk_vbox_new(FALSE, 0);
 +
 +      store = gtk_list_store_new(EXT_NUM_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
 +
 +      gchar** plugins = ext_list_plugins();
 +      gchar** plugins_it;
 +      for (plugins_it = plugins; *plugins_it; ++plugins_it) {
 +
 +              gboolean    enabled = ext_is_plugin_loaded(*plugins_it);
 +              GHashTable* metadata = ext_read_plugin_metadata(*plugins_it);
 +              if (!metadata) {
 +                      metadata = g_hash_table_new(g_str_hash, g_str_equal);
 +              }
 +
 +              gchar* tmp = NULL;
 +
 +              // NAME
 +              gchar* name = g_hash_table_lookup(metadata, "name");
 +              if (!name || *name == '\0') {
 +                      name = *plugins_it;
 +              }
 +              name = g_markup_escape_text(name, -1);
 +              gchar* label = g_strdup_printf("<b>%s</b>", name);
 +              gchar* tooltip = g_strdup_printf("<span size='x-large' weight='bold'>%s</span>", name);
 +              g_free(name);
 +
 +              // VERSION
 +              gchar* version = g_hash_table_lookup(metadata, "version");
 +              if (version) {
 +                      version = g_markup_escape_text(version, -1);
 +                      tmp = label;
 +                      label = g_strdup_printf("%s %s", tmp, version);
 +                      g_free(tmp);
 +                      tmp = tooltip;
 +                      tooltip = g_strdup_printf("%s %s", tmp, version);
 +                      g_free(tmp);
 +                      g_free(version);
 +              }
 +
 +              // ABSTRACT
 +              gchar* abstract = g_hash_table_lookup(metadata, "abstract");
 +              if (abstract) {
 +                      abstract = g_markup_escape_text(abstract, -1);
 +                      tmp = label;
 +                      label = g_strdup_printf("%s\n%s", tmp, abstract);
 +                      g_free(tmp);
 +                      g_free(abstract);
 +              }
 +
 +              // AUTHOR
 +              gchar* author = g_hash_table_lookup(metadata, "author");
 +              if (author) {
 +                      author = g_markup_escape_text(author, -1);
 +                      tmp = tooltip;
 +                      tooltip = g_strdup_printf("%s\n%s", tmp, author);
 +                      g_free(tmp);
 +                      g_free(author);
 +              }
 +
 +              // WEBSITE
 +              gchar* website = g_hash_table_lookup(metadata, "website");
 +              if (website) {
 +                      website = g_markup_escape_text(website, -1);
 +                      tmp = tooltip;
 +                      tooltip = g_strdup_printf("%s\n<b>%s:</b> %s", tmp, _("Website"), website);
 +                      g_free(tmp);
 +                      g_free(website);
 +              }
 +
 +              // FILEPATH
 +              tmp = ext_find_plugin(*plugins_it);
 +              gchar* full = g_markup_escape_text(tmp, -1);
 +              g_free(tmp);
 +              tmp = tooltip;
 +              tooltip = g_strdup_printf("%s\n<b>%s:</b> %s", tmp, _("File"), full);
 +              g_free(tmp);
 +              g_free(full);
 +
 +              g_hash_table_unref(metadata);
 +
 +              gtk_list_store_append(store, &it);
 +              gtk_list_store_set(store, &it,
 +                              EXT_COLUMN_ENABLED,     enabled,
 +                              EXT_COLUMN_LABEL,       label,
 +                              EXT_COLUMN_TOOLTIP,     tooltip,
 +                              EXT_COLUMN_PLUGIN_NAME, *plugins_it,
 +                              -1);
 +
 +              g_free(label);
 +              g_free(tooltip);
 +      }
 +      g_strfreev(plugins);
 +
 +      view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
 +      g_object_unref(store);
 +
 +      g_signal_connect(view, "row-activated", (GCallback)plugin_execute_action, NULL);
 +
 +      gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
 +      gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), TRUE);
 +      gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(view), EXT_COLUMN_TOOLTIP);
 +
 +
 +      GtkTreeViewColumn   *col;
 +      GtkCellRenderer     *renderer;
 +
 +
 +      col = gtk_tree_view_column_new();
 +      gtk_tree_view_column_set_title(col, _("Enabled"));
 +      gtk_tree_view_column_set_sort_column_id(col, EXT_COLUMN_ENABLED);
 +      gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
 +
 +      renderer = gtk_cell_renderer_toggle_new();
 +      gtk_tree_view_column_pack_start(col, renderer, TRUE);
 +      gtk_tree_view_column_add_attribute(col, renderer, "active", 0);
 +      g_signal_connect(renderer, "toggled", G_CALLBACK(toggle_plugin), store);
 +
 +      col = gtk_tree_view_column_new();
 +      gtk_tree_view_column_set_title(col, _("Plugin"));
 +      gtk_tree_view_column_set_sort_column_id(col, EXT_COLUMN_LABEL);
 +      gtk_tree_view_column_set_expand(col, TRUE);
 +      /*gtk_tree_view_column_set_sort_order(col, GTK_SORT_ASCENDING);*/
 +      gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
 +
 +      renderer = gtk_cell_renderer_text_new();
 +      g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
 +      gtk_tree_view_column_pack_start(col, renderer, TRUE);
 +      gtk_tree_view_column_add_attribute(col, renderer, "markup", EXT_COLUMN_LABEL);
 +
 +      data->PI_plugin_columns = view;
 +
 +      GtkWidget* sw = gtk_scrolled_window_new(NULL, NULL);
 +      gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
 +      gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
 +      gtk_container_add(GTK_CONTAINER(sw), view);
 +
 +      gtk_box_pack_start(GTK_BOX(container), sw, TRUE, TRUE, 0);
 +
 +      return(container);
 +}
 +
 +
  static void defpref_selection(GtkTreeSelection *treeselection, gpointer user_data)
  {
  struct defpref_data *data;
@@@ -2291,9 -1911,9 +2110,9 @@@ gint page
                gtk_label_set_text (GTK_LABEL (data->label), g_value_get_string (&val));
                g_value_unset (&val);
  
-               gtk_tree_model_get_value(model, &iter, LST_PREF_ICON, &val);
-               gtk_image_set_from_pixbuf (GTK_IMAGE (data->image),
-                              g_value_get_object (&val));
+               gtk_tree_model_get_value(model, &iter, LST_PREF_ICONNAME, &val);
+               //gtk_image_set_from_pixbuf (GTK_IMAGE (data->image), g_value_get_object (&val));
+               gtk_image_set_from_icon_name(GTK_IMAGE (data->image), g_value_get_string (&val), GTK_ICON_SIZE_DIALOG);
                g_value_unset (&val);
  
  
@@@ -2344,12 -1964,13 +2163,13 @@@ gint result
        data = g_object_get_data(G_OBJECT(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW)), "inst_data");
        DB( g_print("\n(defpref_clear) (data=%p)\n", data) );
  
-       result = ui_dialog_msg_question(
+       result = ui_dialog_msg_confirm_alert(
                GTK_WINDOW(data->window),
-               _("Clear every preferences ?"),
-               _("This will revert the preferences\nto its default values")
+               _("Reset all preferences"),
+               _("Do you really want to reset all\npreferences to default values?"),
+           _("Reset")
                );
-       if( result == GTK_RESPONSE_YES )
+       if( result == GTK_RESPONSE_OK )
        {
                homebank_pref_setdefault();
                defpref_set(data);
  
  
  // the window creation
 -GtkWidget *defpref_dialog_new (void)
 +GtkWidget *defpref_dialog_new (gint initial_selection)
  {
  struct defpref_data data;
  GtkWidget *window, *content, *mainvbox;
  GtkWidget *hbox, *vbox, *sw, *widget, *notebook, *page, *ebox, *image, *label;
  
        window = gtk_dialog_new_with_buttons (_("Preferences"),
                                GTK_WINDOW(GLOBALS->mainwindow),
                                0,
-                               GTK_STOCK_CANCEL,
+                               _("_Cancel"),
                                GTK_RESPONSE_REJECT,
-                               GTK_STOCK_OK,
+                               _("_OK"),
                                GTK_RESPONSE_ACCEPT,
                                NULL);
  
        //store our window private data
        g_object_set_data(G_OBJECT(window), "inst_data", (gpointer)&data);
  
-       gtk_window_set_icon_name(GTK_WINDOW (window), GTK_STOCK_PREFERENCES);
+       gtk_window_set_icon_name(GTK_WINDOW (window), ICONNAME_PREFERENCES);
  
-       content = gtk_dialog_get_content_area(GTK_DIALOG (window));
-       mainvbox = gtk_vbox_new (FALSE, 8);
+       content = gtk_dialog_get_content_area(GTK_DIALOG (window));                     // return a vbox
+       mainvbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM);
        gtk_box_pack_start (GTK_BOX (content), mainvbox, TRUE, TRUE, 0);
  
-       gtk_container_set_border_width(GTK_CONTAINER(mainvbox), 8);
+       gtk_container_set_border_width(GTK_CONTAINER(mainvbox), SPACING_MEDIUM);
  
-       hbox = gtk_hbox_new (FALSE, 8);
+       hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, SPACING_MEDIUM);
        gtk_box_pack_start (GTK_BOX (mainvbox), hbox, TRUE, TRUE, 0);
  
        //left part
-       vbox = gtk_vbox_new (FALSE, HB_BOX_SPACING);
+       vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, SPACING_SMALL);
        gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
        
        //list
        gtk_container_add (GTK_CONTAINER (sw), widget);
  
        // clear button
-       data.BT_clear = gtk_button_new_from_stock(GTK_STOCK_CLEAR);
+       data.BT_clear = gtk_button_new_with_mnemonic(_("_Reset"));
        gtk_box_pack_start (GTK_BOX (vbox), data.BT_clear, FALSE, TRUE, 0);
  
        
        //right part : notebook
-       vbox = gtk_vbox_new (FALSE, 12);
+       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, SPACING_MEDIUM);
        gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
        gtk_widget_show (vbox);
  
        ebox = gtk_event_box_new();
-       gtk_widget_set_state (ebox, GTK_STATE_SELECTED);
+       gtk_widget_set_name(ebox, "hbebox");
+       GtkStyleContext *context = gtk_widget_get_style_context (ebox);
+       #if GTK_MINOR_VERSION <= 18
+               gtk_style_context_add_class (context, GTK_STYLE_CLASS_LIST_ROW);
+               gtk_widget_set_state_flags(ebox, GTK_STATE_FLAG_SELECTED, TRUE);
+       #else
+       GtkCssProvider *provider;
+               provider = gtk_css_provider_new ();
+               gtk_css_provider_load_from_data (provider, 
+               "#hbebox { color: @theme_selected_fg_color; background-color: @theme_selected_bg_color; }"
+               , -1, NULL);
+               gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER(provider), G_MAXUINT);
+       
+       //      gtk_style_context_set_state(context, GTK_STATE_FLAG_SELECTED);
+       #endif
        gtk_box_pack_start (GTK_BOX (vbox), ebox, FALSE, TRUE, 0);
        gtk_widget_show (ebox);
  
-   hbox = gtk_hbox_new (FALSE, 6);
-   gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
-   gtk_container_add (GTK_CONTAINER (ebox), hbox);
-   gtk_widget_show (hbox);
-   label = gtk_label_new (NULL);
-   gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, SPACING_SMALL);
+       gtk_container_set_border_width (GTK_CONTAINER (hbox), SPACING_SMALL);
+       gtk_container_add (GTK_CONTAINER (ebox), hbox);
+       gtk_widget_show (hbox);
  
-   gimp_label_set_attributes (GTK_LABEL (label),
-                              PANGO_ATTR_SCALE,  PANGO_SCALE_LARGE,
+       label = gtk_label_new (NULL);
+       gtk_widget_set_margin_left(label, SPACING_MEDIUM);
+       gimp_label_set_attributes (GTK_LABEL (label),
+                              PANGO_ATTR_SCALE,  PANGO_SCALE_XX_LARGE,
                               PANGO_ATTR_WEIGHT, PANGO_WEIGHT_BOLD,
                               -1);
  
        page = defpref_page_euro(&data);
        gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL);
  
 +      //plugins
 +      page = defpref_page_plugins(&data);
 +      gtk_notebook_append_page (GTK_NOTEBOOK (notebook), page, NULL);
 +
  
        //todo:should move this
        gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(data.CM_euro_enable), PREFS->euro_active);
        g_signal_connect (data.BT_path_import, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(2));
        g_signal_connect (data.BT_path_export, "pressed", G_CALLBACK (defpref_pathselect), GINT_TO_POINTER(3));
  
+       g_signal_connect (data.CM_custom_colors, "toggled", G_CALLBACK (defpref_colortoggle), NULL);
      g_signal_connect (data.CY_colors, "changed", G_CALLBACK (defpref_colorpreset), NULL);
  
  
+       
        g_signal_connect (gtk_tree_view_get_selection(GTK_TREE_VIEW(data.LV_page)), "changed", G_CALLBACK (defpref_selection), notebook);
  
        g_signal_connect (data.CM_euro_enable, "toggled", G_CALLBACK (defpref_eurotoggle), NULL);
        //date
      g_signal_connect (data.ST_datefmt, "changed", G_CALLBACK (defpref_date_sample), NULL);
  
-       //base number
-     g_signal_connect (data.ST_num_symbol   , "changed", G_CALLBACK (defpref_numberbase_sample), NULL);
-       g_signal_connect (data.CM_num_isprefix, "toggled", G_CALLBACK (defpref_numberbase_sample), NULL);
-     g_signal_connect (data.ST_num_decimalchar, "changed", G_CALLBACK (defpref_numberbase_sample), NULL);
-     g_signal_connect (data.ST_num_groupingchar, "changed", G_CALLBACK (defpref_numberbase_sample), NULL);
-     g_signal_connect (data.NB_num_fracdigits, "value-changed", G_CALLBACK (defpref_numberbase_sample), NULL);
+       //report
+       g_signal_connect (data.CY_color_scheme, "changed", G_CALLBACK (defpref_color_scheme_changed), NULL);
  
        //euro number
      g_signal_connect (data.ST_euro_symbol   , "changed", G_CALLBACK (defpref_numbereuro_sample), NULL);
        //defhbfile_setup(&data);
        //defhbfile_update(data.LV_arc, NULL);
  
-       defpref_eurotoggle(window, NULL);
        defpref_set(&data);
  
+       defpref_colortoggle(window, NULL);
+       defpref_eurotoggle(window, NULL);
        gtk_window_resize(GTK_WINDOW(window), 640, 256);
  
  
        //select first row
 -      GtkTreePath *path = gtk_tree_path_new_first ();
 +      GtkTreePath *path = gtk_tree_path_new_from_indices(initial_selection, -1);
 +
  
        gtk_tree_selection_select_path (gtk_tree_view_get_selection(GTK_TREE_VIEW(data.LV_page)), path);
  
        gtk_tree_path_free(path);
  
        gtk_widget_show_all (window);
 +      gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), initial_selection);
  
        gint result;
        gchar *old_lang;
@@@ -2607,14 -2235,12 +2440,12 @@@ GtkWidget *view
  GtkCellRenderer    *renderer;
  GtkTreeViewColumn  *column;
  GtkTreeIter    iter;
- GtkWidget *cellview;
  gint i;
  
        /* create list store */
        store = gtk_list_store_new(
                LST_PREF_MAX,
-               GDK_TYPE_PIXBUF,
-               GDK_TYPE_PIXBUF,
+               G_TYPE_STRING,
                G_TYPE_STRING,
                G_TYPE_INT
                );
        view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
        g_object_unref(store);
  
-       //gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE);
        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW (view), FALSE);
        gtk_tree_selection_set_mode(gtk_tree_view_get_selection(GTK_TREE_VIEW(view)), GTK_SELECTION_SINGLE);
  
        /* column 1: icon */
        column = gtk_tree_view_column_new();
        renderer = gtk_cell_renderer_pixbuf_new ();
+       g_object_set(renderer, "stock-size", GTK_ICON_SIZE_DND, NULL);
        gtk_tree_view_column_pack_start(column, renderer, FALSE);
-       gtk_tree_view_column_set_attributes(column, renderer, "pixbuf", LST_PREF_SMALLPIXBUF, NULL);
+       gtk_tree_view_column_set_attributes(column, renderer, "icon-name", LST_PREF_ICONNAME, NULL);
  
        renderer = gtk_cell_renderer_text_new ();
        gtk_tree_view_column_pack_start(column, renderer, TRUE);
  
        gtk_tree_view_append_column (GTK_TREE_VIEW(view), column);
  
-       cellview = gtk_cell_view_new ();
        //populate our combobox model
        for(i=0;i<PREF_MAX;i++)
        {
-       GdkPixbuf *small_pixbuf = NULL;
                gtk_list_store_append(store, &iter);
  
-               /*
-               if( pref_pixbuf[i] )
-                       small_pixbuf = gdk_pixbuf_scale_simple (pref_pixbuf[i], 24, 24, GDK_INTERP_BILINEAR);
-               */
-               small_pixbuf = gtk_widget_render_icon (cellview, pref_pixname[i], GTK_ICON_SIZE_DND, NULL);
                gtk_list_store_set(store, &iter,
-                       LST_PREF_SMALLPIXBUF, small_pixbuf,
-                       LST_PREF_ICON, pref_pixbuf[i],
+                   LST_PREF_ICONNAME, pref_iconname[i],
                        LST_PREF_NAME, _(pref_name[i]),
                        LST_PREF_PAGE, i,
                        -1);
        }
  
-       gtk_widget_destroy (cellview);
        return(view);
  }
  
  
- void free_pref_icons(void)
- {
- guint i;
-       for(i=0;i<PREF_MAX;i++)
-       {
-               if(pref_pixbuf[i] != NULL)
-                       g_object_unref(pref_pixbuf[i]);
-       }
- }
- void load_pref_icons(void)
- {
- //GError *error = NULL;
- GtkWidget *cellview;
- guint i;
-       cellview = gtk_cell_view_new ();
-       for(i=0;i<PREF_MAX;i++)
-       {
-               pref_pixbuf[i] = gtk_widget_render_icon (cellview, pref_pixname[i], GTK_ICON_SIZE_DIALOG, NULL);
-       }
-       gtk_widget_destroy (cellview);
- }
  /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
  
  
- static gchar *list_txn_column_label[] = {
-       "----", //datas
-       "----", //status
-       "----", //date
-       N_("Info"    ),
-       N_("Payee"   ),
-       N_("Memo"    ),
-       N_("Amount"  ),
-       N_("Expense" ),
-       N_("Income"  ),
-       N_("Category"),
-       N_("Tags"    ),
-       N_("Balance" ),
-       NULL
- };
- //static gint n_ope_list_columns = G_N_ELEMENTS (ope_list_columns);
+ extern gchar *list_txn_column_label[];
  
  
  static void
@@@ -2823,7 -2389,7 +2594,7 @@@ gint i
                gtk_list_store_append (store, &iter);
                gtk_list_store_set (store, &iter,
                        COLUMN_VISIBLE, visible,
-                       COLUMN_NAME, list_txn_column_label[id],
+                       COLUMN_NAME, _(list_txn_column_label[id]),
                        COLUMN_ID  , id,
                        -1);
                
        return(view);
  }
  
 +
 +static void list_ext_colpref_get(GtkTreeView *treeview, GList **columns)
 +{
 +      GtkTreeModel *model;
 +      GtkTreeIter     iter;
 +
 +      g_list_free_full(*columns, g_free);
 +      *columns = NULL;
 +
 +      model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));
 +
 +      gboolean valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter);
 +      while (valid) {
 +              gboolean        enabled = FALSE;
 +              const gchar*    name;
 +
 +              gtk_tree_model_get(GTK_TREE_MODEL(model), &iter,
 +                      EXT_COLUMN_ENABLED,     &enabled,
 +                      EXT_COLUMN_PLUGIN_NAME, &name,
 +                      -1);
 +
 +              if (enabled) {
 +                      *columns = g_list_append(*columns, g_strdup(name));
 +              }
 +
 +              valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter);
 +      }
 +}
 +
diff --combined src/ui-pref.h
index 47c0b011f588182a312695beb09738f3a0e3411b,afd529ee817a9d64953e3f56e0c97635dbdc1340..1eb95f19d3c775a2730e81edc714ccc2e1589b4e
@@@ -1,5 -1,5 +1,5 @@@
  /*  HomeBank -- Free, easy, personal accounting for everyone.
-  *  Copyright (C) 1995-2014 Maxime DOYEN
+  *  Copyright (C) 1995-2016 Maxime DOYEN
   *
   *  This file is part of HomeBank.
   *
@@@ -34,12 -34,15 +34,15 @@@ struct defpref_dat
  
        GtkWidget       *CY_language;
        GtkWidget       *CY_toolbar;
+       GtkWidget   *GR_colors;
        GtkWidget       *CY_colors;
        GtkWidget       *CM_custom_colors;
        GtkWidget       *CP_exp_color;
        GtkWidget       *CP_inc_color;
        GtkWidget       *CP_warn_color;
-       GtkWidget       *CM_ruleshint;
+       //GtkWidget     *CM_ruleshint;
+       GtkWidget       *CY_gridlines;
  
        GtkWidget       *LV_opecolumns;
        GtkWidget       *BT_go_up;
        GtkWidget       *CM_load_last;
        GtkWidget       *CM_show_splash;
        GtkWidget       *CM_append_scheduled;
+       GtkWidget   *CM_do_update_currency;
        GtkWidget       *CM_herit_date;
        GtkWidget       *CM_hide_reconciled;
-       //GtkWidget     *ST_path_navigator;
+       GtkWidget       *CM_show_remind;
  
        GtkWidget       *ST_datefmt;
        GtkWidget       *LB_date;
  
-       GtkWidget       *ST_num_symbol;
-       GtkWidget   *CM_num_isprefix;
-       GtkWidget       *ST_num_decimalchar;    
-       GtkWidget       *ST_num_groupingchar;   
-       GtkWidget       *NB_num_fracdigits;
-       GtkWidget       *LB_numberbase;
-       //GtkWidget     *NB_numnbdec;
-       //GtkWidget     *CM_numseparator;
-       //GtkWidget     *CM_imperial;
        GtkWidget       *CM_unitismile;
        GtkWidget       *CM_unitisgal;
  
        GtkWidget       *CY_daterange_wal;
        GtkWidget       *CY_daterange_txn;
+       GtkWidget   *ST_datefuture_nbdays;
        GtkWidget       *CY_daterange_rep;
        
-       /* currencies 
+       /* currencies */
        GtkWidget       *LB_default;
-       GtkWidget       *BT_default; */
+       GtkWidget       *BT_default; 
        
        GtkWidget       *CM_euro_enable;
+       GtkWidget       *GRP_currency;
+       GtkWidget       *GRP_rate;
+       GtkWidget       *GRP_format;
+        
        GtkWidget       *CY_euro_preset;
        GtkWidget       *ST_euro_country;
        GtkWidget       *NB_euro_value;
        GtkWidget       *CM_budg_showdetail;
  
        GtkWidget       *CY_color_scheme;
+       GtkWidget   *DA_colors;
  
        GtkWidget       *CM_chartlegend;
  
        GtkWidget       *CY_dtex_datefmt;
+       GtkWidget       *CY_dtex_ofxname;
        GtkWidget       *CY_dtex_ofxmemo;
+       GtkWidget       *CM_dtex_qifmemo;
+       GtkWidget       *CM_dtex_qifswap;
+       gint            country;
  
-       PREF_COLUMNS,
-       PREF_DISPLAY,
-       PREF_IMPORT,
 +      GtkWidget       *PI_plugin_columns;
 +};
 +
 +enum
 +{
 +      PREF_GENERAL,
 +      PREF_INTERFACE,
-       PREF_EURO,
++      PREF_TRANSACTIONS,
++      PREF_DISPLAY_FORMAT,
++      PREF_IMPORT_EXPORT,
 +      PREF_REPORT,
++      PREF_EURO_MINOR,
 +      PREF_PLUGINS,
 +      PREF_MAX
  };
  
  
  void free_pref_icons(void);
  void load_pref_icons(void);
  
 -GtkWidget *defpref_dialog_new (void);
 +GtkWidget *defpref_dialog_new (gint initial_selection);
  
  #endif
index 0000000000000000000000000000000000000000,a70b789423b301b7454aba664066f1fc853a855b..f5ac1b75129045428bb726d2d9852f83be3d8b84
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,144 +1,145 @@@
+ ## Process this file with automake to produce Makefile.in
+ NULL =
+ public_icons_themes = \
+       hicolor \
+       $(NULL)
+ public_icons = \
+       $(NULL)
+ private_icons = \
+       hicolor_actions_16x16_btn-collapse.png \
+       hicolor_actions_16x16_btn-expand.png \
+       hicolor_status_16x16_btn-split.png \
+       hicolor_status_16x16_flt-exclude.png \
+       hicolor_status_16x16_flt-inactive.png \
+       hicolor_status_16x16_flt-include.png \
+       hicolor_actions_16x16_hb-ope-auto.png \
+       hicolor_actions_16x16_hb-ope-budget.png \
+       hicolor_actions_16x16_hb-ope-edit.png \
+       hicolor_actions_16x16_hb-ope-cleared.png \
+       hicolor_actions_16x16_hb-ope-remind.png \
+       hicolor_actions_16x16_hb-ope-reconciled.png \
+       hicolor_actions_24x24_hb-account.png \
+       hicolor_actions_24x24_hb-archive.png \
+       hicolor_actions_24x24_hb-assign.png \
+       hicolor_actions_24x24_hb-assign-run.png \
+       hicolor_actions_24x24_hb-budget.png \
+       hicolor_actions_24x24_hb-category.png \
+       hicolor_actions_24x24_hb-currency.png \
+       hicolor_actions_24x24_hb-file-export.png \
+       hicolor_actions_24x24_hb-file-import.png \
+       hicolor_actions_24x24_hb-file-valid.png \
+       hicolor_actions_24x24_hb-file-invalid.png \
+       hicolor_actions_24x24_hb-filter.png \
+       hicolor_actions_24x24_hb-legend.png \
+       hicolor_actions_24x24_hb-ope-add.png \
+       hicolor_actions_24x24_hb-ope-cleared.png \
+       hicolor_actions_24x24_hb-ope-delete.png \
+       hicolor_actions_24x24_hb-ope-edit.png \
+       hicolor_actions_24x24_hb-ope-herit.png \
+       hicolor_actions_24x24_hb-ope-multiedit.png \
+       hicolor_actions_24x24_hb-ope-reconciled.png \
+       hicolor_actions_24x24_hb-ope-convert.png \
+       hicolor_actions_24x24_hb-ope-show.png \
+       hicolor_actions_24x24_hb-payee.png \
+       hicolor_actions_24x24_hb-rate.png \
+       hicolor_actions_24x24_hb-rep-balance.png \
+       hicolor_actions_24x24_hb-rep-budget.png \
+       hicolor_actions_24x24_hb-rep-stats.png \
+       hicolor_actions_24x24_hb-rep-time.png \
+       hicolor_actions_24x24_hb-rep-vehicle.png \
+       hicolor_actions_24x24_hb-view-bar.png \
+       hicolor_actions_24x24_hb-view-column.png \
+       hicolor_actions_24x24_hb-view-donut.png \
+       hicolor_actions_24x24_hb-view-line.png \
+       hicolor_actions_24x24_hb-view-list.png \
+       hicolor_actions_24x24_hb-view-pie.png \
+       hicolor_actions_24x24_hb-view-stack.png \
+       hicolor_status_16x16_pm-none.png \
+       hicolor_status_16x16_pm-ccard.png \
+       hicolor_status_16x16_pm-dcard.png \
+       hicolor_status_16x16_pm-check.png \
+       hicolor_status_16x16_pm-cash.png \
+       hicolor_status_16x16_pm-transfer.png \
+       hicolor_status_16x16_pm-intransfer.png \
+       hicolor_status_16x16_pm-none.png \
+       hicolor_status_16x16_pm-standingorder.png \
+       hicolor_status_16x16_pm-epayment.png \
+       hicolor_status_16x16_pm-deposit.png \
+       hicolor_status_16x16_pm-fifee.png \
+       hicolor_status_16x16_pm-directdebit.png \
+       hicolor_status_48x48_prf-columns.png \
+       hicolor_status_48x48_prf-display.png \
+       hicolor_status_48x48_prf-euro.png \
+       hicolor_status_48x48_prf-general.png \
+       hicolor_status_48x48_prf-import.png \
+       hicolor_status_48x48_prf-interface.png \
+       hicolor_status_48x48_prf-report.png \
++      hicolor_status_48x48_prf-plugins.png \
+       hicolor_actions_scalable_toggle-sign-symbolic.svg \
+       $(NULL)
+ EXTRA_DIST = \
+       $(public_icons)         \
+       $(private_icons)        \
+       $(noinst_DATA)          \
+       $(NULL)
+ ###############################################################################
+ gtk_update_icon_cache = gtk-update-icon-cache -f -t
+ update-icon-cache:
+       @-if test -z "$(DESTDIR)"; then \
+               echo "Updating Gtk icon cache."; \
+               for theme in $(public_icons_themes); do \
+                       $(gtk_update_icon_cache) $(datadir)/icons/$$theme; \
+               done; \
+       else \
+               echo "*** Icon cache not updated.  After (un)install, run this:"; \
+               for theme in $(public_icons_themes); do \
+                       echo "***   $(gtk_update_icon_cache) $(datadir)/icons/$$theme"; \
+               done; \
+       fi
+ install-icons:
+       for icon in $(public_icons); do \
+               THEME=`echo $$icon | cut -d_ -f1`; \
+               CONTEXT=`echo $$icon | cut -d_ -f2`; \
+               SIZE=`echo $$icon | cut -d_ -f3`; \
+               ICONFILE=`echo $$icon | cut -d_ -f4`; \
+               mkdir -p $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT; \
+               $(INSTALL_DATA) $(srcdir)/$$icon $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \
+       done; \
+       for icon in $(private_icons); do \
+               THEME=`echo $$icon | cut -d_ -f1`; \
+               CONTEXT=`echo $$icon | cut -d_ -f2`; \
+               SIZE=`echo $$icon | cut -d_ -f3`; \
+               ICONFILE=`echo $$icon | cut -d_ -f4`; \
+               mkdir -p $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT; \
+               $(INSTALL_DATA) $(srcdir)/$$icon $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \
+       done
+ uninstall-icons:
+       -for icon in $(public_icons); do \
+               THEME=`echo $$icon | cut -d_ -f1`; \
+               CONTEXT=`echo $$icon | cut -d_ -f2`; \
+               SIZE=`echo $$icon | cut -d_ -f3`; \
+               ICONFILE=`echo $$icon | cut -d_ -f4`; \
+               rm -f $(DESTDIR)$(datadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \
+       done; \
+       for icon in $(private_icons); do \
+               THEME=`echo $$icon | cut -d_ -f1`; \
+               CONTEXT=`echo $$icon | cut -d_ -f2`; \
+               SIZE=`echo $$icon | cut -d_ -f3`; \
+               ICONFILE=`echo $$icon | cut -d_ -f4`; \
+               rm -f $(DESTDIR)$(pkgdatadir)/icons/$$THEME/$$SIZE/$$CONTEXT/$$ICONFILE; \
+       done
+ install-data-local: install-icons update-icon-cache
+ uninstall-local: uninstall-icons update-icon-cache
index 395001990fcc10752449c18a85eb3e55e3085618,0000000000000000000000000000000000000000..395001990fcc10752449c18a85eb3e55e3085618
mode 100644,000000..100644
Binary files differ
This page took 0.402726 seconds and 5 git commands to generate.