/* HomeBank -- Free, easy, personal accounting for everyone.
- * Copyright (C) 1995-2014 Maxime DOYEN
+ * Copyright (C) 1995-2019 Maxime DOYEN
*
* This file is part of HomeBank.
*
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+
+//nota: this file should be renamed hb-utils
+
#include "homebank.h"
#include "hb-misc.h"
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
-static gdouble fint(gdouble amount)
-{
-gdouble fi;
-
- modf(amount, &fi);
- return(fi);
-}
+static const double fac[9] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
-static unsigned dix_puissance_n(unsigned n)
+double hb_amount_round(const double x, unsigned int digits)
{
- unsigned i, retval = 1;
+ digits = MAX(digits, 8);
+ return floor((x * fac[digits]) + 0.5) / fac[digits];
+}
- for(i = 0; i < n; i++)
- retval *= 10;
- return retval;
-}
+// used to convert from national to euro currency
+// used in hb_account.c :: only when convert account to euro
+// round option is to 0.5 case so 1.32 is 1.3, but 1.35 is 1.4
-double arrondi(const double x, unsigned n)
+gdouble hb_amount_to_euro(gdouble amount)
{
- unsigned N = dix_puissance_n(n);
- return floor((x * N) + 0.5) / N;
+ return hb_amount_round((amount * PREFS->euro_value), PREFS->minor_cur.frac_digits);
}
-// new for v4.5
-/*
+/* new >5.1 currency fct
+*
* convert an amount in base currency
*
*/
-gdouble to_base_amount(gdouble value, guint32 kcur)
+gdouble hb_amount_base(gdouble value, guint32 kcur)
{
-/*
gdouble newvalue;
Currency *cur;
return value;
cur = da_cur_get(kcur);
- if(cur == NULL)
+ if(cur == NULL || cur->rate == 0.0)
return 0;
- newvalue = value * cur->rate;
- return newvalue;
-*/
- return value;
-}
-
-/* new currency fct
-static gint real_mystrfmoncurr(gchar *outstr, gint outlen, gchar *buf1, Currency *cur)
-{
-gint size = 0;
-gchar groupbuf[G_ASCII_DTOSTR_BUF_SIZE];
-gchar **str_array;
-guint i, length;
-gchar *monstr;
-
- str_array = g_strsplit(buf1, ".", 2);
- monstr = NULL;
-
- length = strlen(str_array[0]);
-
- if( cur->grouping_char == NULL || !strlen(cur->grouping_char) )
- {
- monstr = g_strjoinv(cur->decimal_char, str_array);
- }
- else
- {
- gchar *s = str_array[0];
- gchar *d = groupbuf;
-
- i = 0;
- // avoid the - for negative amount
- if( *s == '-')
- {
- *d++ = *s++;
- length--;
- }
-
- // do the grouping
- do
- {
- if( i!=0 && (length % 3) == 0 )
- {
- gchar *gc = cur->grouping_char;
-
- while( *gc )
- *d++ = *gc++;
- }
-
- *d++ = *s;
- length--;
- i++;
- }
- while (length && *s++ != '\0');
- *d = 0;
-
- monstr = g_strjoin(cur->decimal_char, groupbuf, str_array[1], NULL);
-
- }
-
- //debug
- //g_print("**\nmystrfmon %.2f\n 0=%s\n 1=%s\n [%d]\n", value, str_array[0], str_array[1], length );
- //g_print(" => %s :: %s\n", monstr, groupbuf);
-
- g_strfreev(str_array);
-
- // insert our formated number with symbol
- g_snprintf(outstr, outlen, cur->monfmt, monstr);
-
- g_free(monstr);
-
- return size;
+ newvalue = value / cur->rate;
+ return hb_amount_round(newvalue, cur->frac_digits);
}
Currency *cur = da_cur_get(kcur);
if(cur == NULL)
- g_stpcpy(outstr, "error");
+ g_stpcpy(outstr, "nan");
return cur;
}
-void hb_strfmon(gchar *outstr, gint outlen, gdouble value, guint32 kcur)
+gchar *hb_str_rate(gchar *outstr, gint outlen, gdouble rate)
{
-gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
-Currency *cur;
-gdouble monval;
-
- cur = hb_strfmon_check(outstr, kcur);
- if(cur != NULL)
+gint count, i;
+gchar *p;
+
+ count = g_snprintf(outstr, outlen, "%.6f", rate);
+ //remove trailing 0 and decimal point
+ p = &outstr[count-1];
+ for(i=count;i>0;i--)
{
- monval = arrondi(value, cur->frac_digits);
- g_ascii_formatd(formatd_buf, G_ASCII_DTOSTR_BUF_SIZE-1, cur->format, monval);
- real_mystrfmoncurr(outstr, outlen, formatd_buf, cur);
+ if(*p == '0')
+ *p = '\0';
+ else
+ break;
+ p--;
}
-}
+ if(*p == '.' || *p == ',')
+ *p = '\0';
+ return outstr;
+}
-void hb_strfmon_int(gchar *outstr, gint outlen, gdouble value, guint32 kcur)
+/* this function copy a number 99999.99 at s into d and count
+ * number of digits for integer part and decimal part
+ */
+static gchar * _strfnumcopycount(gchar *s, gchar *d, gchar *decchar, gint *plen, gint *pnbint, gint *pnbdec)
{
-gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
-Currency *cur;
-gdouble monval;
+gint len=0, nbint=0, nbdec=0;
- cur = hb_strfmon_check(outstr, kcur);
- if(cur != NULL)
- {
- monval = arrondi(value, cur->frac_digits);
- g_ascii_formatd(formatd_buf, sizeof (formatd_buf), "%0.f", monval);
- real_mystrfmoncurr(outstr, outlen, formatd_buf, cur);
+ // sign part
+ if(*s == '-') {
+ *d++ = *s++;
+ len++;
}
-}
-
-//todo: remove this
-// test for currecny choose dialog
-void mystrfmoncurrcurr(gchar *outstr, gint outlen, gdouble value, Currency *cur)
-{
-gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
-gdouble monval;
+ // integer part
+ while(*s != 0 && *s != '.') {
+ *d++ = *s++;
+ nbint++;
+ len++;
+ }
+ // decimal separator
+ if(*s == '.') {
+ d = g_stpcpy(d, decchar);
+ len++;
+ s++;
+ }
+ // decimal part
+ while(*s != 0) {
+ *d++ = *s++;
+ nbdec++;
+ len++;
+ }
+ // end string | fill external count
+ *d = 0;
+ *plen = len;
+ *pnbint = nbint;
+ *pnbdec = nbdec;
- monval = arrondi(value, cur->frac_digits);
- g_ascii_formatd(formatd_buf, G_ASCII_DTOSTR_BUF_SIZE-1, cur->format, monval);
- real_mystrfmoncurr(outstr, outlen, formatd_buf, cur);
+ return d;
}
-*/
-
-
-
-/* obsolete before currencies */
-gint real_mystrfmon(gchar *outstr, gint outlen, gchar *buf1, struct CurrencyFmt *cur)
+//todo: used only in ui_prefs.c
+gchar *hb_str_formatd(gchar *outstr, gint outlen, gchar *buf1, Currency *cur, gboolean showsymbol)
{
-gint size = 0;
-gchar groupbuf[G_ASCII_DTOSTR_BUF_SIZE];
-gchar **str_array;
-guint i, length;
-gchar *monstr;
+gint len, nbd, nbi;
+gchar *s, *d, *tmp;
- str_array = g_strsplit(buf1, ".", 2);
- monstr = NULL;
-
- length = strlen(str_array[0]);
-
- if( cur->grouping_char == NULL || !strlen(cur->grouping_char) )
+ d = tmp = outstr;
+ if(showsymbol && cur->sym_prefix)
{
- monstr = g_strjoinv(cur->decimal_char, str_array);
+ d = g_stpcpy (d, cur->symbol);
+ *d++ = ' ';
+ tmp = d;
}
- else
+
+ d = _strfnumcopycount(buf1, d, cur->decimal_char, &len, &nbi, &nbd);
+
+ if( cur->grouping_char != NULL && strlen(cur->grouping_char) > 0 )
{
- gchar *s = str_array[0];
- gchar *d = groupbuf;
+ gint i, grpcnt;
- i = 0;
- // avoid the - for negative amount
- if( *s == '-')
- {
+ s = buf1;
+ d = tmp;
+ if(*s == '-')
*d++ = *s++;
- length--;
- }
-
- // do the grouping
- do
+
+ grpcnt = 4 - nbi;
+ for(i=0;i<nbi;i++)
{
- if( i!=0 && (length % 3) == 0 )
+ *d++ = *s++;
+ if( !(grpcnt % 3) && i<(nbi-1))
{
- gchar *gc = cur->grouping_char;
-
- while( *gc )
- *d++ = *gc++;
+ d = g_stpcpy(d, cur->grouping_char);
}
-
- *d++ = *s;
- length--;
- i++;
+ grpcnt++;
}
- while (length && *s++ != '\0');
- *d = 0;
-
- monstr = g_strjoin(cur->decimal_char, groupbuf, str_array[1], NULL);
+ if(nbd > 0)
+ {
+ d = g_stpcpy(d, cur->decimal_char);
+ d = g_stpcpy(d, s+1);
+ }
+ *d = 0;
}
- //debug
- //g_print("**\nmystrfmon %.2f\n 0=%s\n 1=%s\n [%d]\n", value, str_array[0], str_array[1], length );
- //g_print(" => %s :: %s\n", monstr, groupbuf);
-
- g_strfreev(str_array);
-
- // insert our formated number with symbol
- g_snprintf(outstr, outlen, cur->monfmt, monstr);
+ if(showsymbol && !cur->sym_prefix)
+ {
+ *d++ = ' ';
+ d = g_stpcpy (d, cur->symbol);
+ }
- g_free(monstr);
+ *d = 0;
- return size;
+ return d;
}
-gint mystrfmon(gchar *outstr, gint outlen, gdouble value, gboolean minor)
+void hb_strfmon(gchar *outstr, gint outlen, gdouble value, guint32 kcur, gboolean minor)
{
-struct CurrencyFmt *cur;
-gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
+gchar formatd_buf[outlen];
+Currency *cur;
gdouble monval;
-gint size;
-
- cur = minor ? &PREFS->minor_cur : &PREFS->base_cur;
-
- monval = arrondi(value, cur->frac_digits);
- if(minor == TRUE)
+ if(minor == FALSE)
{
- monval = (value * PREFS->euro_value);
- monval += (monval > 0.0) ? 0.005 : -0.005;
- monval = (fint(monval * 100) / 100);
+ cur = hb_strfmon_check(outstr, kcur);
+ if(cur != NULL)
+ {
+ monval = hb_amount_round(value, cur->frac_digits);
+ g_ascii_formatd(formatd_buf, outlen, cur->format, monval);
+ hb_str_formatd(outstr, outlen, formatd_buf, cur, TRUE);
+ }
+ }
+ else
+ {
+ monval = hb_amount_base(value, kcur);
+ monval = hb_amount_to_euro(monval);
+ cur = &PREFS->minor_cur;
+ g_ascii_formatd(formatd_buf, outlen, cur->format, monval);
+ hb_str_formatd(outstr, outlen, formatd_buf, cur, TRUE);
}
- //DB( g_print("fmt = %s\n", cur->format) );
-
- g_ascii_formatd(formatd_buf, sizeof (formatd_buf), cur->format, monval);
-
- size = real_mystrfmon(outstr, outlen, formatd_buf, cur);
-
- return size;
}
-
-
-
-gint mystrfmon_int(gchar *outstr, gint outlen, gdouble value, gboolean minor)
+void hb_strfmon_int(gchar *outstr, gint outlen, gdouble value, guint32 kcur, gboolean minor)
{
-struct CurrencyFmt *cur;
-gchar formatd_buf[G_ASCII_DTOSTR_BUF_SIZE];
-gdouble monval = value;
-gint size;
-
- cur = minor ? &PREFS->minor_cur : &PREFS->base_cur;
+gchar formatd_buf[outlen];
+Currency *cur;
+gdouble monval;
- if(minor == TRUE)
+ if(minor == FALSE)
{
- monval = (value * PREFS->euro_value);
- monval += (monval > 0.0) ? 0.005 : -0.005;
- monval = (fint(monval * 100) / 100);
+ cur = hb_strfmon_check(outstr, kcur);
+ if(cur != NULL)
+ {
+ monval = hb_amount_round(value, cur->frac_digits);
+ g_ascii_formatd(formatd_buf, outlen, "%0.f", monval);
+ hb_str_formatd(outstr, outlen, formatd_buf, cur, TRUE);
+ }
+ }
+ else
+ {
+ monval = hb_amount_base(value, kcur);
+ monval = hb_amount_to_euro(monval);
+ cur = &PREFS->minor_cur;
+ g_ascii_formatd(formatd_buf, outlen, cur->format, monval);
+ hb_str_formatd(outstr, outlen, formatd_buf, cur, TRUE);
}
- g_ascii_formatd(formatd_buf, sizeof (formatd_buf), "%0.f", monval);
-
- size = real_mystrfmon(outstr, outlen, formatd_buf, cur);
-
- return size;
}
+void hb_strfnum(gchar *outstr, gint outlen, gdouble value, guint32 kcur, gboolean minor)
+{
+gchar formatd_buf[outlen];
+Currency *cur;
+gdouble monval;
+ if(minor == FALSE)
+ {
+ cur = hb_strfmon_check(outstr, kcur);
+ if(cur != NULL)
+ {
+ monval = hb_amount_round(value, cur->frac_digits);
+ g_ascii_formatd(formatd_buf, outlen, "%.2f", monval);
+ hb_str_formatd(outstr, outlen, formatd_buf, cur, TRUE);
+ }
+ }
+ else
+ {
+ cur = &PREFS->minor_cur;
+ monval = hb_amount_to_euro(value);
+ g_ascii_formatd(formatd_buf, outlen, "%.2f", monval);
+ hb_str_formatd(outstr, outlen, formatd_buf, cur, TRUE);
+ }
-/* end obsolete call */
+
+}
gchar *get_normal_color_amount(gdouble value)
gchar *color = NULL;
//fix: 400483
- value = arrondi(value, 2);
+ value = hb_amount_round(value, 2);
if(value != 0.0 && PREFS->custom_colors == TRUE)
{
gchar *color = NULL;
//fix: 400483
- value = arrondi(value, 2);
+ value = hb_amount_round(value, 2);
if(value != 0.0 && PREFS->custom_colors == TRUE)
{
color = (value > 0.0) ? PREFS->color_inc : PREFS->color_exp;
return color;
}
-void hb_label_set_amount(GtkLabel *label, gdouble value, gboolean minor)
+void hb_label_set_amount(GtkLabel *label, gdouble value, guint32 kcur, gboolean minor)
{
gchar strbuffer[G_ASCII_DTOSTR_BUF_SIZE];
- mystrfmon(strbuffer, G_ASCII_DTOSTR_BUF_SIZE-1, value, minor);
+ hb_strfmon(strbuffer, G_ASCII_DTOSTR_BUF_SIZE-1, value, kcur, minor);
gtk_label_set_text(GTK_LABEL(label), strbuffer);
}
/*
** format/color and set a label text with a amount value
*/
-void hb_label_set_colvalue(GtkLabel *label, gdouble value, gboolean minor)
+void hb_label_set_colvalue(GtkLabel *label, gdouble value, guint32 kcur, gboolean minor)
{
gchar strbuffer[G_ASCII_DTOSTR_BUF_SIZE];
gchar *markuptxt;
gchar *color = NULL;
- mystrfmon(strbuffer, G_ASCII_DTOSTR_BUF_SIZE-1, value, minor);
+ hb_strfmon(strbuffer, G_ASCII_DTOSTR_BUF_SIZE-1, value, kcur, minor);
if(value != 0.0 && PREFS->custom_colors == TRUE)
{
}
-/*
-void hb_label_set_colvaluecurr(GtkLabel *label, gdouble value, guint32 currkey)
-{
-gchar strbuffer[G_ASCII_DTOSTR_BUF_SIZE];
-gchar *markuptxt;
-gchar *color = NULL;
- hb_strfmon(strbuffer, G_ASCII_DTOSTR_BUF_SIZE-1, value, currkey);
- if(value != 0.0 && PREFS->custom_colors == TRUE)
- {
- color = get_normal_color_amount(value);
- if(color)
- {
- markuptxt = g_strdup_printf("<span color='%s'>%s</span>", color, strbuffer);
- gtk_label_set_markup(GTK_LABEL(label), markuptxt);
- g_free(markuptxt);
- return;
- }
- }
-
- gtk_label_set_text(GTK_LABEL(label), strbuffer);
-
-}
+/*
+** String utility
*/
-
-/*
-void get_range_minmax(guint32 refdate, gint range, guint32 *mindate, guint32 *maxdate)
+gint hb_string_compare(gchar *s1, gchar *s2)
{
-GDate *date;
-guint month, year, qnum;
-
- if(refdate > *maxdate)
- refdate = *maxdate;
-
- date = g_date_new_julian(refdate);
- month = g_date_get_month(date);
- year = g_date_get_year(date);
- qnum = ((month-1)/3)+1;
+gint retval = 0;
- DB( g_print("m=%d, y=%d, qnum=%d\n", month, year, qnum) );
+ if (s1 == NULL || s2 == NULL)
+ {
+ if (s1 == NULL && s2 == NULL)
+ goto end;
- switch( range )
- {
- case 0: // this month
- g_date_set_day(date, 1);
- *mindate = g_date_get_julian(date);
- g_date_add_days(date, g_date_get_days_in_month(month, year)-1);
- *maxdate = g_date_get_julian(date);
- break;
-
- case 1: // last month
- g_date_set_day(date, 1);
- g_date_subtract_months(date, 1);
- *mindate = g_date_get_julian(date);
- month = g_date_get_month(date);
- year = g_date_get_year(date);
- g_date_add_days(date, g_date_get_days_in_month(month, year)-1);
- *maxdate = g_date_get_julian(date);
- break;
+ retval = (s1 == NULL) ? -1 : 1;
+ }
+ else
+ {
+ retval = strcasecmp(s1, s2);
+ }
+end:
+ return retval;
+}
- case 2: // this quarter
- g_date_set_day(date, 1);
- g_date_set_month(date, (qnum-1)*3+1);
- *mindate = g_date_get_julian(date);
- g_date_add_months(date, 3);
- g_date_subtract_days(date, 1);
- *maxdate = g_date_get_julian(date);
- break;
-
- case 3: // last quarter
- g_date_set_day(date, 1);
- g_date_set_month(date, (qnum-1)*3+1);
- g_date_subtract_months(date, 3);
- *mindate = g_date_get_julian(date);
- g_date_add_months(date, 3);
- g_date_subtract_days(date, 1);
- *maxdate = g_date_get_julian(date);
- break;
-
- case 4: // this year
- g_date_set_dmy(date, 1, 1, year);
- *mindate = g_date_get_julian(date);
- g_date_set_dmy(date, 31, 12, year);
- *maxdate = g_date_get_julian(date);
- break;
-
- // separator
-
- case 6: // last 30 days
- *mindate = refdate - 30;
- *maxdate = refdate;
- break;
- case 7: // last 60 days
- *mindate = refdate - 60;
- *maxdate = refdate;
- break;
+gint hb_string_utf8_strstr(gchar *haystack, gchar *needle, gboolean exact)
+{
+gint retval = FALSE;
- case 8: // last 90 days
- *mindate = refdate - 90;
- *maxdate = refdate;
- break;
-
- case 9: // last 12 months
- g_date_subtract_months(date, 12);
- *mindate = g_date_get_julian(date);
- *maxdate = refdate;
- break;
+ if( exact )
+ {
+ if( g_strstr_len(haystack, -1, needle) != NULL )
+ {
+ DB( g_print(" found case '%s'\n", needle) );
+ retval = 1;
+ }
+ }
+ else
+ {
+ gchar *nchaystack = g_utf8_casefold(haystack, -1);
+ gchar *ncneedle = g_utf8_casefold(needle, -1);
+ if( g_strrstr(nchaystack, ncneedle) != NULL )
+ {
+ DB( g_print(" found nocase '%s'\n", ncneedle) );
+ retval = 1;
+ }
+ g_free(nchaystack);
+ g_free(ncneedle);
}
- g_date_free(date);
+ return retval;
}
-*/
-/*
-** String utility
-*/
+
+
/*
}
}
+
+void hb_string_replace_char(gchar c, gchar *str)
+{
+gchar *s = str;
+gchar *d = str;
+
+ if(str)
+ {
+ while( *s )
+ {
+ if( *s != c )
+ {
+ *d++ = *s;
+ }
+ s++;
+ }
+ *d = 0;
+ }
+}
+
+
+gchar *hb_string_copy_jsonpair(gchar *dst, gchar *str)
+{
+
+ while( *str!='\0' )
+ {
+ if( *str=='}' )
+ break;
+
+ if( *str==',' )
+ {
+ *dst = '\0';
+ return str + 1;
+ }
+
+ if( *str!='{' && *str!='\"' )
+ {
+ *dst++ = *str;
+ }
+ str++;
+ }
+ *dst = '\0';
+ return NULL;
+}
+
+
+void hb_string_inline(gchar *str)
+{
+gchar *s = str;
+gchar *d = str;
+
+ if(str)
+ {
+ while( *s )
+ {
+ if( !(*s==' ' || *s=='\t' || *s=='\n' || *s=='\r') )
+ {
+ *d++ = *s;
+ }
+ s++;
+ }
+ *d = 0;
+ }
+}
+
+
+/*void strip_extra_spaces(char* str) {
+ int i,x;
+ for(i=x=1; str[i]; ++i)
+ if(!isspace(str[i]) || (i>0 && !isspace(str[i-1])))
+ str[x++] = str[i];
+ str[x] = '\0';
+}*/
+
+
+
gchar*
hb_strdup_nobrackets (const gchar *str)
{
}
+/* if we found a . or , within last x digits it might be a dchar */
+static gchar hb_string_raw_amount_guess_dchar(const gchar *s, gint len, gshort digit)
+{
+gint nbc, nbd, i;
+gchar gdc='?';
+
+ DB( g_print(" digit=%d maxidx=%d\n", digit, len-digit-1) );
+
+ nbc = nbd = 0;
+ for(i=len-1;i>=0;i--)
+ {
+ DB( g_print(" [%2d] '%c' %d %d '%c'\n", i, s[i], nbc, nbd, gdc) );
+ //store rightmost ,. within digit-1
+ if( i>=(len-digit-1) )
+ {
+ if(s[i]=='.' || s[i]==',')
+ gdc=s[i];
+ }
+ if(s[i]=='.') nbd++;
+ else if(s[i]==',') nbc++;
+ }
+ if( gdc=='.' && nbd > 1) gdc='?';
+ else if( gdc==',' && nbc > 1) gdc='?';
+
+ return gdc;
+}
+
+
+gchar *hb_string_dup_raw_amount_clean(const gchar *string, gint digits)
+{
+gint l;
+gchar *new_str, *d;
+gchar gdc;
+const gchar *p = string;
+
+ l = strlen(string);
+ gdc = hb_string_raw_amount_guess_dchar(string, l, digits);
+
+ new_str = d = g_malloc (l+1);
+ while(*p)
+ {
+ if(*p=='-' || g_ascii_isdigit(*p) )
+ *d++ = *p;
+ else
+ if( *p==gdc )
+ {
+ *d++ = '.';
+ }
+ p++;
+ }
+ *d++ = '\0';
+
+ return new_str;
+}
+
+
static gboolean
hb_date_parser_get_nums(gchar *string, gint *n1, gint *n2, gint *n3)
{
//DB( g_print("(qif) hb_qif_parser_get_dmy for '%s'\n", string) );
retval = FALSE;
- str_array = g_strsplit (string, "/", 3);
- if( g_strv_length( str_array ) != 3 )
+ if( string )
{
- g_strfreev (str_array);
- str_array = g_strsplit (string, ".", 3);
- // fix 371381
- //todo test
+ str_array = g_strsplit (string, "/", 3);
if( g_strv_length( str_array ) != 3 )
{
g_strfreev (str_array);
- str_array = g_strsplit (string, "-", 3);
+ str_array = g_strsplit (string, ".", 3);
+ // fix 371381
+ //todo test
+ if( g_strv_length( str_array ) != 3 )
+ {
+ g_strfreev (str_array);
+ str_array = g_strsplit (string, "-", 3);
+ }
}
- }
- if( g_strv_length( str_array ) == 3 )
- {
- *n1 = atoi(str_array[0]);
- *n2 = atoi(str_array[1]);
- *n3 = atoi(str_array[2]);
- retval = TRUE;
- }
-
- g_strfreev (str_array);
+ if( g_strv_length( str_array ) == 3 )
+ {
+ *n1 = atoi(str_array[0]);
+ *n2 = atoi(str_array[1]);
+ *n3 = atoi(str_array[2]);
+ retval = TRUE;
+ }
+ g_strfreev (str_array);
+ }
return retval;
}
gint n1, n2, n3, d, m, y;
guint32 julian = 0;
- DB( g_print("hb_date_get_julian: %s, %d\n", string, datefmt) );
+ DB( g_print("\n[utils] hb_date_get_julian\n") );
+ DB( g_print(" - '%s' dateorder=%d\n", string, datefmt) );
+
if( hb_date_parser_get_nums(string, &n1, &n2, &n3) )
{
- DB( g_print("-> %d %d %d\n", n1, n2, n3) );
+ DB( g_print(" - '%d' '%d' '%d'\n", n1, n2, n3) );
switch(datefmt)
{
y += 1900;
}
- DB( g_print("-> %d %d %d\n", d, m, y) );
-
if(d <= 31 && m <= 12)
{
- date = g_date_new();
- g_date_set_dmy(date, d, m, y);
- if( g_date_valid (date) )
+ if( g_date_valid_dmy(d, m, y) )
{
+ date = g_date_new_dmy(d, m, y);
julian = g_date_get_julian (date);
+ g_date_free(date);
}
- g_date_free(date);
}
+
+ DB( g_print(" > %d %d %d julian=%d\n", d, m, y, julian) );
+
}
return julian;
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
+gint hb_filename_type_get_by_extension(gchar *filepath)
+{
+gint retval = FILETYPE_UNKNOWN;
+gint str_len;
-gchar *hb_filename_new_with_extention(gchar *filename, const gchar *extension)
+ g_return_val_if_fail(filepath != NULL, FILETYPE_UNKNOWN);
+
+ str_len = strlen(filepath);
+ if( str_len >= 4 )
+ {
+ if( strcasecmp(filepath + str_len - 4, ".ofx") == 0)
+ retval = FILETYPE_OFX;
+ else
+ if( strcasecmp(filepath + str_len - 4, ".qif") == 0)
+ retval = FILETYPE_QIF;
+ else
+ if( strcasecmp(filepath + str_len - 4, ".qfx") == 0)
+ retval = FILETYPE_OFX;
+ else
+ if( strcasecmp(filepath + str_len - 4, ".csv") == 0)
+ retval = FILETYPE_CSV_HB;
+ else
+ if( strcasecmp(filepath + str_len - 4, ".xhb") == 0)
+ retval = FILETYPE_HOMEBANK;
+ }
+ return retval;
+}
+
+
+static gchar *hb_filename_new_without_extension(gchar *filename)
{
-gchar *dirname;
-gchar *basename;
-gchar *newbasename;
-gchar *newfilename;
-gchar **str_array;
+gchar *lastdot;
+
+ lastdot = g_strrstr (filename, ".");
+ if(lastdot != NULL)
+ {
+ return g_strndup(filename, strlen(filename) - strlen(lastdot));
+ }
+ return g_strdup(filename);
+}
- dirname = g_path_get_dirname (filename);
+
+static gint hb_filename_backup_list_sort_func(gchar **a, gchar **b)
+{
+gint da = atoi( *a + strlen(*a) - 12);
+gint db = atoi( *b + strlen(*b) - 12);
+
+ return db - da;
+}
+
+
+GPtrArray *hb_filename_backup_list(gchar *filename)
+{
+gchar *dirname, *basename;
+gchar *rawfilename, *pattern;
+GDir *dir;
+const gchar *tmpname;
+GPatternSpec *pspec;
+GPtrArray *array;
+
+ DB( g_print("\n[util] filename backup list\n") );
+
+ dirname = g_path_get_dirname(filename);
basename = g_path_get_basename(filename);
- str_array = g_strsplit(basename, ".", 0);
- newbasename = g_strdup_printf("%s.%s", str_array[0], extension);
- newfilename = g_build_filename(dirname, newbasename, NULL);
- g_strfreev(str_array);
+ DB( g_print(" dir='%s' base='%s'\n", dirname, basename) );
+
+ rawfilename = hb_filename_new_without_extension(basename);
+ pattern = g_strdup_printf("%s-????????.bak", rawfilename);
+
+ pspec = g_pattern_spec_new(pattern);
+
+
+ DB( g_print(" pattern='%s'\n", pattern) );
+
+ array = g_ptr_array_new_with_free_func(g_free);
+
+ dir = g_dir_open (PREFS->path_hbfile, 0, NULL);
+ if (dir)
+ {
+ while ((tmpname = g_dir_read_name (dir)) != NULL)
+ {
+ gboolean match;
+
+ match = g_pattern_match_string(pspec, tmpname);
+ if( match )
+ {
+ DB( g_print(" %d => '%s'\n", match, tmpname) );
+ g_ptr_array_add(array, g_strdup(tmpname));
+ }
+ }
+ }
+ g_free(pattern);
+ g_dir_close (dir);
+ g_pattern_spec_free(pspec);
+ g_free(rawfilename);
+
g_free(basename);
g_free(dirname);
- g_free(newbasename);
+
+ g_ptr_array_sort(array, (GCompareFunc)hb_filename_backup_list_sort_func);
- return newfilename;
+ return array;
}
-/* file backup, qif export */
+gchar *hb_filename_backup_get_filtername(gchar *filename)
+{
+gchar *dirname, *basename;
+gchar *rawfilename, *pattern;
+ DB( g_print("\n[util] filename backup get filtername\n") );
-/*gchar *homebank_filename_without_extention(gchar *path)
-{
-gchar *basename;
-gchar *newname;
-gchar **str_array;
+ dirname = g_path_get_dirname(filename);
+ basename = g_path_get_basename(filename);
- basename = g_path_get_basename(path);
+ DB( g_print(" dir='%s' base='%s'\n", dirname, basename) );
- str_array = g_strsplit(basename, ".", 0);
+ rawfilename = hb_filename_new_without_extension(basename);
- newname = g_strdup(str_array[0]);
+ pattern = g_strdup_printf("%s*.[Bb][Aa][Kk]", rawfilename);
- g_strfreev(str_array);
+ g_free(rawfilename);
g_free(basename);
+ g_free(dirname);
+
+ return pattern;
+}
+
+
+gchar *hb_filename_new_for_backup(gchar *filename)
+{
+gchar *rawfilename, *newfilename;
+GDate date;
+
+ DB( g_print("\n[util] filename new for backup\n") );
+
+ rawfilename = hb_filename_new_without_extension(filename);
+
+ g_date_clear(&date, 1);
+ g_date_set_julian (&date, GLOBALS->today);
+
+ newfilename = g_strdup_printf("%s-%04d%02d%02d.bak",
+ rawfilename,
+ g_date_get_year(&date),
+ g_date_get_month(&date),
+ g_date_get_day(&date)
+ );
+
+ g_free(rawfilename);
+
+ DB( g_print(" - '%s' => '%s'\n", filename, newfilename) );
+
+ return newfilename;
+}
+
+
+gchar *hb_filename_new_with_extension(gchar *filename, const gchar *extension)
+{
+gchar *rawfilename, *newfilename;
+
+ DB( g_print("\n[util] filename new with extension\n") );
+
+ rawfilename = hb_filename_new_without_extension(filename);
+ newfilename = g_strdup_printf("%s.%s", rawfilename, extension);
+ g_free(rawfilename);
+
+ DB( g_print(" - '%s' => '%s'\n", filename, newfilename) );
+
+ return newfilename;
+}
- return newname;
-}*/
/* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
-static gboolean hb_string_isdate(gchar *str)
+gboolean hb_string_isdate(gchar *str)
{
gint d, m, y;
}
-static gboolean hb_string_isdigit(gchar *str)
+gboolean hb_string_isdigit(gchar *str)
{
gboolean valid = TRUE;
while(*str && valid)
}
/*
-static gboolean hb_string_isprint(gchar *str)
+gboolean hb_string_isprint(gchar *str)
{
gboolean valid = TRUE;
while(*str && valid)
-static gboolean hb_string_isprint(gchar *str)
+gboolean hb_string_isprint(gchar *str)
{
gboolean valid = TRUE;
gchar *p;
}
-gboolean hb_string_csv_valid(gchar *str, guint nbcolumns, gint *csvtype)
+gchar *hb_sprint_date(gchar *outstr, guint32 julian)
{
-gchar **str_array;
-gboolean valid = TRUE;
-guint i;
-extern int errno;
-
-#if MYDEBUG == 1
-gchar *type[5] = { "string", "date", "int", "double" };
-gint lasttype;
-#endif
-
- DB( g_print("\n** hb_string_csv_valid: init %d\n", valid) );
-
- hb_string_strip_crlf(str);
- str_array = g_strsplit (str, ";", 0);
-
- DB( g_print(" -> length %d, nbcolumns %d\n", g_strv_length( str_array ), nbcolumns) );
-
- if( g_strv_length( str_array ) != nbcolumns )
- {
- valid = FALSE;
- goto csvend;
- }
+GDate date;
- for(i=0;i<nbcolumns;i++)
+ g_date_clear(&date, 1);
+ g_date_set_julian (&date, julian);
+ switch(PREFS->dtex_datefmt)
{
-#if MYDEBUG == 1
- lasttype = csvtype[i];
-#endif
-
- if(valid == FALSE)
+ case PRF_DATEFMT_MDY:
{
- DB( g_print(" -> fail on column %d, type: %s\n", i, type[lasttype]) );
- break;
+ g_sprintf(outstr, "%02d/%02d/%04d",
+ g_date_get_month(&date),
+ g_date_get_day(&date),
+ g_date_get_year(&date)
+ );
}
-
- DB( g_print(" -> control column %d, type: %d, valid: %d '%s'\n", i, lasttype, valid, str_array[i]) );
-
- switch( csvtype[i] )
+ break;
+ case PRF_DATEFMT_DMY:
{
- case CSV_DATE:
- valid = hb_string_isdate(str_array[i]);
- break;
- case CSV_STRING:
- valid = hb_string_isprint(str_array[i]);
- break;
- case CSV_INT:
- valid = hb_string_isdigit(str_array[i]);
- break;
- case CSV_DOUBLE :
- g_ascii_strtod(str_array[i], NULL);
- //todo : see this errno
- if( errno )
- {
- DB( g_print("errno: %d\n", errno) );
- valid = FALSE;
- }
- break;
+ g_sprintf(outstr, "%02d/%02d/%04d",
+ g_date_get_day(&date),
+ g_date_get_month(&date),
+ g_date_get_year(&date)
+ );
}
+ break;
+ default:
+ g_sprintf(outstr, "%04d/%02d/%02d",
+ g_date_get_year(&date),
+ g_date_get_month(&date),
+ g_date_get_day(&date)
+ );
+ break;
}
-
-csvend:
- g_strfreev (str_array);
-
- DB( g_print(" --> return %d\n", valid) );
-
- return valid;
+ return outstr;
}
+//used only in DB() macro !!
void hb_print_date(guint32 jdate, gchar *label)
{
gchar buffer1[128];