Author: Elmar Pruesse <elmar@pruesse.net>
Last-Update: Tue, 02 Sep 2014 15:15:06 +0200
Description:show progress while ARB is loading a database
 (needed as indicator/splash screen while ARB is launching)
Origin: upstream, http://bugs.arb-home.de/log/trunk?revs=12792-12793,12795

--- a/ARBDB/ad_load.cxx
+++ b/ARBDB/ad_load.cxx
@@ -17,6 +17,7 @@
 #include <arb_str.h>
 #include <arb_file.h>
 #include <arb_defs.h>
+#include <arb_progress.h>
 
 #include "gb_key.h"
 #include "gb_localdata.h"
@@ -655,12 +656,18 @@ static void DEBUG_DUMP_INDENTED(long dee
 #endif // DEBUG_READ
 // ----------------------------------------
 
-
-static long gb_read_bin_rek_V2(FILE *in, GBCONTAINER *gbc_dest, long nitems, long version, long reversed, long deep) {
+static long gb_read_bin_rek_V2(FILE *in, GBCONTAINER *gbc_dest, long nitems, long version, 
+                               long reversed, long deep, arb_progress& progress) {
     GB_MAIN_TYPE *Main = GB_MAIN(gbc_dest);
 
     DEBUG_DUMP_INDENTED(deep, GBS_global_string("Reading container with %li items", nitems));
 
+    progress.inc_to(ftell(in));
+    if (progress.aborted()) {
+        GB_export_error(progress.error_if_aborted());
+        return -1;
+    }
+
     gb_create_header_array(gbc_dest, (int)nitems);
     gb_header_list *header = GB_DATA_LIST_HEADER(gbc_dest->d);
     if (deep == 0 && GBCONTAINER_MAIN(gbc_dest)->allow_corrupt_file_recovery) {
@@ -849,7 +856,7 @@ static long gb_read_bin_rek_V2(FILE *in,
             case GB_DB: {
                 long size = gb_get_number(in);
                 // gbc->d.size  is automatically incremented
-                if (gb_read_bin_rek_V2(in, gbc, size, version, reversed, deep+1)) {
+                if (gb_read_bin_rek_V2(in, gbc, size, version, reversed, deep+1, progress)) {
                     if (!GBCONTAINER_MAIN(gbc_dest)->allow_corrupt_file_recovery) {
                         return -1;
                     }
@@ -922,7 +929,7 @@ inline bool read_keyword(const char *exp
     return as_expected;
 }
 
-static long gb_read_bin(FILE *in, GBCONTAINER *gbc, bool allowed_to_load_diff) {
+static long gb_read_bin(FILE *in, GBCONTAINER *gbc, bool allowed_to_load_diff, arb_progress& progress) {
     int   c = 1;
     long  i;
     long  error;
@@ -1153,7 +1160,7 @@ static long gb_read_bin(FILE *in, GBCONT
             if (Main->clock<=0) Main->clock++;
             // fall-through
         case 1: // master arb file
-            error = gb_read_bin_rek_V2(in, gbc, nodecnt, version, reversed, 0);
+            error = gb_read_bin_rek_V2(in, gbc, nodecnt, version, reversed, 0, progress);
             break;
         default:
             GB_internal_errorf("Sorry: This ARB Version does not support database format V%li", version);
@@ -1445,7 +1452,10 @@ static GBDATA *GB_login(const char *cpat
                 i = (input != stdin) ? gb_read_in_uint32(input, 0) : 0;
 
                 if (is_binary_db_id(i)) {
-                    i = gb_read_bin(input, gbc, false);     // read or map whole db
+                    {
+                        arb_progress progress("Loading database", GB_size_of_FILE(input));
+                        i = gb_read_bin(input, gbc, false, progress);     // read or map whole db
+                    }
                     gbc = Main->root_container;
                     fclose(input);
 
@@ -1486,7 +1496,10 @@ static GBDATA *GB_login(const char *cpat
                             }
                             i = gb_read_in_uint32(input, 0);
                             if (is_binary_db_id(i)) {
-                                err = gb_read_bin(input, gbc, true);
+                                {
+                                    arb_progress progress("Loading quicksave", GB_size_of_FILE(input) / 1024);
+                                    err = gb_read_bin(input, gbc, true, progress);
+                                }
                                 fclose (input);
 
                                 if (err) {
--- a/CORE/arb_progress.cxx
+++ b/CORE/arb_progress.cxx
@@ -22,6 +22,7 @@ struct null_counter: public arb_progress
 
     void inc() OVERRIDE {}
     void implicit_inc() OVERRIDE {}
+    void inc_to(int x) OVERRIDE {}
     void done() OVERRIDE {}
     void restart(int) OVERRIDE {}
     void force_update() OVERRIDE {}
@@ -142,6 +143,13 @@ public:
 
     void inc()          OVERRIDE { explicit_counter += 1; update_display_if_needed(); }
     void implicit_inc() OVERRIDE { implicit_counter += 1; update_display_if_needed(); }
+    void inc_to(int x) {
+        explicit_counter = std::max(explicit_counter, x);
+        if (maxcount) {
+            explicit_counter = std::min(explicit_counter, maxcount);
+        }
+        update_display_if_needed();
+    }
     
     void done() OVERRIDE {
         implicit_counter = explicit_counter = maxcount;
--- a/CORE/arb_progress.h
+++ b/CORE/arb_progress.h
@@ -44,6 +44,7 @@ public:
 
     virtual void inc()                              = 0;
     virtual void implicit_inc()                     = 0;
+    virtual void inc_to(int x)                      = 0;
     virtual void child_updates_gauge(double gauge)  = 0;
     virtual void done()                             = 0;
     virtual void force_update()                     = 0;
@@ -131,6 +132,7 @@ public:
     void force_update() { counter->force_update(); }
 
     void inc() { counter->inc(); }
+    void inc_to(int x) { counter->inc_to(x); }
     void done() { counter->done(); }
     void auto_subtitles(const char *prefix) { counter->auto_subtitles(prefix); }
 
@@ -244,6 +246,7 @@ public:
     const arb_progress& operator++() { inc(); return *this; } // ++progress
 
     void inc_by(int count) { arb_assert(count>0); while (count--) inc(); }
+    void inc_to(int x) { used->inc_to(x); }
 
     void sub_progress_skipped() { used->child_terminated(); }
 
