]>
Dogcows Code - chaz/homebank/blob - src/hb-misc.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2018 Maxime DOYEN
4 * This file is part of HomeBank.
6 * HomeBank is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * HomeBank is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 //nota: this file should be renamed hb-utils
34 /* our global datas */
35 extern struct HomeBank
*GLOBALS
;
36 extern struct Preferences
*PREFS
;
38 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
40 static const double fac
[7] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };
42 double hb_amount_round(const double x
, unsigned int digits
)
44 digits
= MAX(digits
, 6);
45 return floor((x
* fac
[digits
]) + 0.5) / fac
[digits
];
49 // used to convert from national to euro currency
50 // used in hb_account.c :: only when convert account to euro
51 // round option is to 0.5 case so 1.32 is 1.3, but 1.35 is 1.4
53 gdouble
hb_amount_to_euro(gdouble amount
)
55 return hb_amount_round((amount
* PREFS
->euro_value
), PREFS
->minor_cur
.frac_digits
);
59 /* new >5.1 currency fct
61 * convert an amount in base currency
64 gdouble
hb_amount_base(gdouble value
, guint32 kcur
)
69 if(kcur
== GLOBALS
->kcur
)
72 cur
= da_cur_get(kcur
);
73 if(cur
== NULL
|| cur
->rate
== 0.0)
76 newvalue
= value
/ cur
->rate
;
77 return hb_amount_round(newvalue
, cur
->frac_digits
);
81 static Currency
*hb_strfmon_check(gchar
*outstr
, guint32 kcur
)
83 Currency
*cur
= da_cur_get(kcur
);
86 g_stpcpy(outstr
, "nan");
91 gchar
*hb_str_rate(gchar
*outstr
, gint outlen
, gdouble rate
)
96 count
= g_snprintf(outstr
, outlen
, "%.6f", rate
);
97 //remove trailing 0 and decimal point
107 if(*p
== '.' || *p
== ',')
113 /* this function copy a number 99999.99 at s into d and count
114 * number of digits for integer part and decimal part
116 static gchar
* _strfnumcopycount(gchar
*s
, gchar
*d
, gchar
*decchar
, gint
*plen
, gint
*pnbint
, gint
*pnbdec
)
118 gint len
=0, nbint
=0, nbdec
=0;
126 while(*s
!= 0 && *s
!= '.') {
133 d
= g_stpcpy(d
, decchar
);
143 // end string | fill external count
152 //todo: used only in ui_prefs.c
153 gchar
*hb_str_formatd(gchar
*outstr
, gint outlen
, gchar
*buf1
, Currency
*cur
, gboolean showsymbol
)
159 if(showsymbol
&& cur
->sym_prefix
)
161 d
= g_stpcpy (d
, cur
->symbol
);
166 d
= _strfnumcopycount(buf1
, d
, cur
->decimal_char
, &len
, &nbi
, &nbd
);
168 if( cur
->grouping_char
!= NULL
&& strlen(cur
->grouping_char
) > 0 )
181 if( !(grpcnt
% 3) && i
<(nbi
-1))
183 d
= g_stpcpy(d
, cur
->grouping_char
);
190 d
= g_stpcpy(d
, cur
->decimal_char
);
191 d
= g_stpcpy(d
, s
+1);
196 if(showsymbol
&& !cur
->sym_prefix
)
199 d
= g_stpcpy (d
, cur
->symbol
);
208 void hb_strfmon(gchar
*outstr
, gint outlen
, gdouble value
, guint32 kcur
, gboolean minor
)
210 gchar formatd_buf
[outlen
];
216 cur
= hb_strfmon_check(outstr
, kcur
);
219 monval
= hb_amount_round(value
, cur
->frac_digits
);
220 g_ascii_formatd(formatd_buf
, outlen
, cur
->format
, monval
);
221 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
226 monval
= hb_amount_base(value
, kcur
);
227 monval
= hb_amount_to_euro(monval
);
228 cur
= &PREFS
->minor_cur
;
229 g_ascii_formatd(formatd_buf
, outlen
, cur
->format
, monval
);
230 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
236 void hb_strfmon_int(gchar
*outstr
, gint outlen
, gdouble value
, guint32 kcur
, gboolean minor
)
238 gchar formatd_buf
[outlen
];
244 cur
= hb_strfmon_check(outstr
, kcur
);
247 monval
= hb_amount_round(value
, cur
->frac_digits
);
248 g_ascii_formatd(formatd_buf
, outlen
, "%0.f", monval
);
249 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
254 monval
= hb_amount_base(value
, kcur
);
255 monval
= hb_amount_to_euro(monval
);
256 cur
= &PREFS
->minor_cur
;
257 g_ascii_formatd(formatd_buf
, outlen
, cur
->format
, monval
);
258 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
264 void hb_strfnum(gchar
*outstr
, gint outlen
, gdouble value
, guint32 kcur
, gboolean minor
)
266 gchar formatd_buf
[outlen
];
272 cur
= hb_strfmon_check(outstr
, kcur
);
275 monval
= hb_amount_round(value
, cur
->frac_digits
);
276 g_ascii_formatd(formatd_buf
, outlen
, "%.2f", monval
);
277 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
282 cur
= &PREFS
->minor_cur
;
283 monval
= hb_amount_to_euro(value
);
284 g_ascii_formatd(formatd_buf
, outlen
, "%.2f", monval
);
285 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
292 gchar
*get_normal_color_amount(gdouble value
)
297 value
= hb_amount_round(value
, 2);
299 if(value
!= 0.0 && PREFS
->custom_colors
== TRUE
)
301 color
= (value
> 0.0) ? PREFS
->color_inc
: PREFS
->color_exp
;
307 gchar
*get_minimum_color_amount(gdouble value
, gdouble minvalue
)
312 value
= hb_amount_round(value
, 2);
313 if(value
!= 0.0 && PREFS
->custom_colors
== TRUE
)
315 color
= (value
> 0.0) ? PREFS
->color_inc
: PREFS
->color_exp
;
316 if( value
< minvalue
)
317 color
= PREFS
->color_warn
;
322 void hb_label_set_amount(GtkLabel
*label
, gdouble value
, guint32 kcur
, gboolean minor
)
324 gchar strbuffer
[G_ASCII_DTOSTR_BUF_SIZE
];
326 hb_strfmon(strbuffer
, G_ASCII_DTOSTR_BUF_SIZE
-1, value
, kcur
, minor
);
327 gtk_label_set_text(GTK_LABEL(label
), strbuffer
);
333 ** format/color and set a label text with a amount value
335 void hb_label_set_colvalue(GtkLabel
*label
, gdouble value
, guint32 kcur
, gboolean minor
)
337 gchar strbuffer
[G_ASCII_DTOSTR_BUF_SIZE
];
341 hb_strfmon(strbuffer
, G_ASCII_DTOSTR_BUF_SIZE
-1, value
, kcur
, minor
);
343 if(value
!= 0.0 && PREFS
->custom_colors
== TRUE
)
345 color
= get_normal_color_amount(value
);
347 //g_print("color: %s\n", color);
351 markuptxt
= g_strdup_printf("<span color='%s'>%s</span>", color
, strbuffer
);
352 gtk_label_set_markup(GTK_LABEL(label
), markuptxt
);
358 gtk_label_set_text(GTK_LABEL(label
), strbuffer
);
369 gint
hb_string_compare(gchar
*s1
, gchar
*s2
)
373 if (s1
== NULL
|| s2
== NULL
)
375 if (s1
== NULL
&& s2
== NULL
)
378 retval
= (s1
== NULL
) ? -1 : 1;
382 retval
= strcasecmp(s1
, s2
);
390 * compare 2 utf8 string
392 gint
hb_string_utf8_compare(gchar
*s1
, gchar
*s2
)
397 if (s1
== NULL
|| s2
== NULL
)
399 if (s1
== NULL
&& s2
== NULL
)
402 retval
= (s1
== NULL
) ? -1 : 1;
407 //retval = g_utf8_collate(s1 != NULL ? s1 : "", s2 != NULL ? s2 : "");
408 ns1
= g_utf8_normalize(s1
, -1, G_NORMALIZE_DEFAULT
);
409 ns2
= g_utf8_normalize(s2
, -1, G_NORMALIZE_DEFAULT
);
410 retval
= strcasecmp(ns1
, ns2
);
419 void hb_string_strip_crlf(gchar
*str
)
427 if( *p
== '\n' || *p
== '\r')
437 void hb_string_replace_char(gchar c
, gchar
*str
)
457 gchar
*hb_string_copy_jsonpair(gchar
*dst
, gchar
*str
)
471 if( *str
!='{' && *str
!='\"' )
482 void hb_string_inline(gchar
*str
)
491 if( !(*s
==' ' || *s
=='\t' || *s
=='\n' || *s
=='\r') )
502 /*void strip_extra_spaces(char* str) {
504 for(i=x=1; str[i]; ++i)
505 if(!isspace(str[i]) || (i>0 && !isspace(str[i-1])))
513 hb_strdup_nobrackets (const gchar
*str
)
521 length
= strlen (str
) + 1;
522 new_str
= g_new (char, length
);
527 if( *s
!= '[' && *s
!= ']' )
541 hb_date_parser_get_nums(gchar
*string
, gint
*n1
, gint
*n2
, gint
*n3
)
546 //DB( g_print("(qif) hb_qif_parser_get_dmy for '%s'\n", string) );
549 str_array
= g_strsplit (string
, "/", 3);
550 if( g_strv_length( str_array
) != 3 )
552 g_strfreev (str_array
);
553 str_array
= g_strsplit (string
, ".", 3);
556 if( g_strv_length( str_array
) != 3 )
558 g_strfreev (str_array
);
559 str_array
= g_strsplit (string
, "-", 3);
563 if( g_strv_length( str_array
) == 3 )
565 *n1
= atoi(str_array
[0]);
566 *n2
= atoi(str_array
[1]);
567 *n3
= atoi(str_array
[2]);
571 g_strfreev (str_array
);
577 guint32
hb_date_get_julian(gchar
*string
, gint datefmt
)
580 gint n1
, n2
, n3
, d
, m
, y
;
583 DB( g_print("\n[utils] hb_date_get_julian\n") );
585 DB( g_print(" - '%s' dateorder=%d\n", string
, datefmt
) );
587 if( hb_date_parser_get_nums(string
, &n1
, &n2
, &n3
) )
589 DB( g_print(" - '%d' '%d' '%d'\n", n1
, n2
, n3
) );
593 case PRF_DATEFMT_MDY
:
598 case PRF_DATEFMT_DMY
:
604 case PRF_DATEFMT_YMD
:
611 //correct for 2 digits year
620 if(d
<= 31 && m
<= 12)
622 if( g_date_valid_dmy(d
, m
, y
) )
624 date
= g_date_new_dmy(d
, m
, y
);
625 julian
= g_date_get_julian (date
);
630 DB( g_print(" > %d %d %d julian=%d\n", d
, m
, y
, julian
) );
638 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
641 gchar
*hb_filename_new_with_extension(gchar
*filename
, const gchar
*extension
)
643 gchar
*lastdot
, *fwe
;
646 DB( g_print("\n[util] filename with extension\n") );
648 DB( g_print(" - orig: '%s' => '%s'\n", filename
, extension
) );
650 //duplicate without extensions
651 lastdot
= g_strrstr(filename
, ".");
654 fwe
= g_strndup(filename
, strlen(filename
) - strlen(lastdot
));
655 DB( g_print(" - fwe: '%s'\n", fwe
) );
656 newfilename
= g_strdup_printf("%s.%s", fwe
, extension
);
661 newfilename
= g_strdup_printf("%s.%s", filename
, extension
);
664 DB( g_print(" - new: '%s'\n", newfilename
) );
670 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
673 gboolean
hb_string_isdate(gchar
*str
)
677 return(hb_date_parser_get_nums(str
, &d
, &m
, &y
));
681 gboolean
hb_string_isdigit(gchar
*str
)
683 gboolean valid
= TRUE
;
685 valid
= g_ascii_isdigit(*str
++);
690 gboolean hb_string_isprint(gchar *str)
692 gboolean valid = TRUE;
694 valid = g_ascii_isprint(*str++);
701 gboolean
hb_string_isprint(gchar
*str
)
703 gboolean valid
= TRUE
;
707 if(g_utf8_validate(str
, -1, NULL
))
712 c
= g_utf8_get_char(p
);
713 valid
= g_unichar_isprint(c
);
714 p
= g_utf8_next_char(p
);
721 gchar
*hb_sprint_date(gchar
*outstr
, guint32 julian
)
725 g_date_clear(&date
, 1);
726 g_date_set_julian (&date
, julian
);
727 switch(PREFS
->dtex_datefmt
)
729 case PRF_DATEFMT_MDY
:
731 g_sprintf(outstr
, "%02d/%02d/%04d",
732 g_date_get_month(&date
),
733 g_date_get_day(&date
),
734 g_date_get_year(&date
)
738 case PRF_DATEFMT_DMY
:
740 g_sprintf(outstr
, "%02d/%02d/%04d",
741 g_date_get_day(&date
),
742 g_date_get_month(&date
),
743 g_date_get_year(&date
)
748 g_sprintf(outstr
, "%04d/%02d/%02d",
749 g_date_get_year(&date
),
750 g_date_get_month(&date
),
751 g_date_get_day(&date
)
759 //used only in DB() macro !!
760 void hb_print_date(guint32 jdate
, gchar
*label
)
765 date
= g_date_new_julian(jdate
);
766 g_date_strftime (buffer1
, 128-1, "%x", date
);
768 g_print(" - %s %s\n", label
!= NULL
? label
:"date is", buffer1
);
774 ** parse a string an retrieve an iso date (dd-mm-yy(yy) or dd/mm/yy(yy))
778 guint32 hb_date_get_julian_parse(gchar *str)
780 gchar **str_array = NULL;
783 guint32 julian = GLOBALS->today;
785 // try with - separator
786 if( g_strrstr(str, "-") != NULL )
788 str_array = g_strsplit (str, "-", 3);
792 if( g_strrstr(str, "/") != NULL )
794 str_array = g_strsplit (str, "/", 3);
798 if( g_strv_length( str_array ) == 3 )
800 d = atoi(str_array[0]);
801 m = atoi(str_array[1]);
802 y = atoi(str_array[2]);
804 //correct for 2 digits year
813 //todo: here if month is > 12 then the format is probably mm/dd/yy(yy)
814 //or maybe check with g_date_valid_julian(julian)
819 g_date_set_dmy(date, d, m, y);
820 julian = g_date_get_julian (date);
823 DB( g_print("date: %s :: %d %d %d :: %d\n", str, d, m, y, julian ) );
827 g_strfreev (str_array);
833 /* -------------------- */
841 void hex_dump(guchar
*ptr
, guint length
)
843 guchar ascii
[MAX_DUMP
+4];
846 g_print("**hex_dump - %d bytes\n", length
);
850 g_print("%08x: ", (guint
)ptr
+i
);
852 for(j
=0;j
<MAX_DUMP
;j
++)
854 if(i
>= length
) break;
857 if(ptr
[i
] >= 32 && ptr
[i
] <= 126)
862 g_print("%02x ", ptr
[i
]);
867 g_print(" '%s'\n", ascii
);
This page took 0.076525 seconds and 4 git commands to generate.