]>
Dogcows Code - chaz/homebank/blob - src/hb-misc.c
1 /* HomeBank -- Free, easy, personal accounting for everyone.
2 * Copyright (C) 1995-2017 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 cur
= &PREFS
->minor_cur
;
227 monval
= hb_amount_to_euro(value
);
228 g_ascii_formatd(formatd_buf
, outlen
, cur
->format
, monval
);
229 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
234 void hb_strfmon_int(gchar
*outstr
, gint outlen
, gdouble value
, guint32 kcur
, gboolean minor
)
236 gchar formatd_buf
[outlen
];
242 cur
= hb_strfmon_check(outstr
, kcur
);
245 monval
= hb_amount_round(value
, cur
->frac_digits
);
246 g_ascii_formatd(formatd_buf
, outlen
, "%0.f", monval
);
247 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
252 cur
= &PREFS
->minor_cur
;
253 monval
= hb_amount_to_euro(value
);
254 g_ascii_formatd(formatd_buf
, outlen
, cur
->format
, monval
);
255 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
261 void hb_strfnum(gchar
*outstr
, gint outlen
, gdouble value
, guint32 kcur
, gboolean minor
)
263 gchar formatd_buf
[outlen
];
269 cur
= hb_strfmon_check(outstr
, kcur
);
272 monval
= hb_amount_round(value
, cur
->frac_digits
);
273 g_ascii_formatd(formatd_buf
, outlen
, "%.2f", monval
);
274 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
279 cur
= &PREFS
->minor_cur
;
280 monval
= hb_amount_to_euro(value
);
281 g_ascii_formatd(formatd_buf
, outlen
, "%.2f", monval
);
282 hb_str_formatd(outstr
, outlen
, formatd_buf
, cur
, TRUE
);
290 gchar
*get_normal_color_amount(gdouble value
)
295 value
= hb_amount_round(value
, 2);
297 if(value
!= 0.0 && PREFS
->custom_colors
== TRUE
)
299 color
= (value
> 0.0) ? PREFS
->color_inc
: PREFS
->color_exp
;
305 gchar
*get_minimum_color_amount(gdouble value
, gdouble minvalue
)
310 value
= hb_amount_round(value
, 2);
311 if(value
!= 0.0 && PREFS
->custom_colors
== TRUE
)
313 color
= (value
> 0.0) ? PREFS
->color_inc
: PREFS
->color_exp
;
314 if( value
< minvalue
)
315 color
= PREFS
->color_warn
;
320 void hb_label_set_amount(GtkLabel
*label
, gdouble value
, guint32 kcur
, gboolean minor
)
322 gchar strbuffer
[G_ASCII_DTOSTR_BUF_SIZE
];
324 hb_strfmon(strbuffer
, G_ASCII_DTOSTR_BUF_SIZE
-1, value
, kcur
, minor
);
325 gtk_label_set_text(GTK_LABEL(label
), strbuffer
);
331 ** format/color and set a label text with a amount value
333 void hb_label_set_colvalue(GtkLabel
*label
, gdouble value
, guint32 kcur
, gboolean minor
)
335 gchar strbuffer
[G_ASCII_DTOSTR_BUF_SIZE
];
339 hb_strfmon(strbuffer
, G_ASCII_DTOSTR_BUF_SIZE
-1, value
, kcur
, minor
);
341 if(value
!= 0.0 && PREFS
->custom_colors
== TRUE
)
343 color
= get_normal_color_amount(value
);
345 //g_print("color: %s\n", color);
349 markuptxt
= g_strdup_printf("<span color='%s'>%s</span>", color
, strbuffer
);
350 gtk_label_set_markup(GTK_LABEL(label
), markuptxt
);
356 gtk_label_set_text(GTK_LABEL(label
), strbuffer
);
367 gint
hb_string_compare(gchar
*s1
, gchar
*s2
)
371 if (s1
== NULL
|| s2
== NULL
)
373 if (s1
== NULL
&& s2
== NULL
)
376 retval
= (s1
== NULL
) ? -1 : 1;
380 retval
= strcasecmp(s1
, s2
);
388 * compare 2 utf8 string
390 gint
hb_string_utf8_compare(gchar
*s1
, gchar
*s2
)
395 if (s1
== NULL
|| s2
== NULL
)
397 if (s1
== NULL
&& s2
== NULL
)
400 retval
= (s1
== NULL
) ? -1 : 1;
405 //retval = g_utf8_collate(s1 != NULL ? s1 : "", s2 != NULL ? s2 : "");
406 ns1
= g_utf8_normalize(s1
, -1, G_NORMALIZE_DEFAULT
);
407 ns2
= g_utf8_normalize(s2
, -1, G_NORMALIZE_DEFAULT
);
408 retval
= strcasecmp(ns1
, ns2
);
417 void hb_string_strip_crlf(gchar
*str
)
425 if( *p
== '\n' || *p
== '\r')
435 void hb_string_replace_char(gchar c
, gchar
*str
)
455 /*static void strip_extra_spaces(char* str) {
457 for(i=x=1; str[i]; ++i)
458 if(!isspace(str[i]) || (i>0 && !isspace(str[i-1])))
466 hb_strdup_nobrackets (const gchar
*str
)
474 length
= strlen (str
) + 1;
475 new_str
= g_new (char, length
);
480 if( *s
!= '[' && *s
!= ']' )
494 hb_date_parser_get_nums(gchar
*string
, gint
*n1
, gint
*n2
, gint
*n3
)
499 //DB( g_print("(qif) hb_qif_parser_get_dmy for '%s'\n", string) );
502 str_array
= g_strsplit (string
, "/", 3);
503 if( g_strv_length( str_array
) != 3 )
505 g_strfreev (str_array
);
506 str_array
= g_strsplit (string
, ".", 3);
509 if( g_strv_length( str_array
) != 3 )
511 g_strfreev (str_array
);
512 str_array
= g_strsplit (string
, "-", 3);
516 if( g_strv_length( str_array
) == 3 )
518 *n1
= atoi(str_array
[0]);
519 *n2
= atoi(str_array
[1]);
520 *n3
= atoi(str_array
[2]);
524 g_strfreev (str_array
);
530 guint32
hb_date_get_julian(gchar
*string
, gint datefmt
)
533 gint n1
, n2
, n3
, d
, m
, y
;
536 DB( g_print("\n[utils] hb_date_get_julian\n") );
538 DB( g_print(" - '%s' dateorder=%d\n", string
, datefmt
) );
540 if( hb_date_parser_get_nums(string
, &n1
, &n2
, &n3
) )
542 DB( g_print(" - '%d' '%d' '%d'\n", n1
, n2
, n3
) );
546 case PRF_DATEFMT_MDY
:
551 case PRF_DATEFMT_DMY
:
557 case PRF_DATEFMT_YMD
:
564 //correct for 2 digits year
573 if(d
<= 31 && m
<= 12)
575 if( g_date_valid_dmy(d
, m
, y
) )
577 date
= g_date_new_dmy(d
, m
, y
);
578 julian
= g_date_get_julian (date
);
583 DB( g_print(" > %d %d %d julian=%d\n", d
, m
, y
, julian
) );
591 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
594 gchar
*hb_util_filename_new_with_extension(gchar
*filename
, const gchar
*extension
)
596 gchar
*lastdot
, *fwe
;
599 DB( g_print("\n[util] filename with extension\n") );
601 DB( g_print(" - orig: '%s' => '%s'\n", filename
, extension
) );
603 //duplicate without extensions
604 lastdot
= g_strrstr(filename
, ".");
607 fwe
= g_strndup(filename
, strlen(filename
) - strlen(lastdot
));
608 DB( g_print(" - fwe: '%s'\n", fwe
) );
609 newfilename
= g_strdup_printf("%s.%s", fwe
, extension
);
614 newfilename
= g_strdup_printf("%s.%s", filename
, extension
);
617 DB( g_print(" - new: '%s'\n", newfilename
) );
623 /* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*/
626 gboolean
hb_string_isdate(gchar
*str
)
630 return(hb_date_parser_get_nums(str
, &d
, &m
, &y
));
634 gboolean
hb_string_isdigit(gchar
*str
)
636 gboolean valid
= TRUE
;
638 valid
= g_ascii_isdigit(*str
++);
643 gboolean hb_string_isprint(gchar *str)
645 gboolean valid = TRUE;
647 valid = g_ascii_isprint(*str++);
654 gboolean
hb_string_isprint(gchar
*str
)
656 gboolean valid
= TRUE
;
660 if(g_utf8_validate(str
, -1, NULL
))
665 c
= g_utf8_get_char(p
);
666 valid
= g_unichar_isprint(c
);
667 p
= g_utf8_next_char(p
);
674 gchar
*hb_sprint_date(gchar
*outstr
, guint32 julian
)
678 g_date_clear(&date
, 1);
679 g_date_set_julian (&date
, julian
);
680 switch(PREFS
->dtex_datefmt
)
682 case PRF_DATEFMT_MDY
:
684 g_sprintf(outstr
, "%02d/%02d/%04d",
685 g_date_get_month(&date
),
686 g_date_get_day(&date
),
687 g_date_get_year(&date
)
691 case PRF_DATEFMT_DMY
:
693 g_sprintf(outstr
, "%02d/%02d/%04d",
694 g_date_get_day(&date
),
695 g_date_get_month(&date
),
696 g_date_get_year(&date
)
700 g_sprintf(outstr
, "%04d/%02d/%02d",
701 g_date_get_year(&date
),
702 g_date_get_month(&date
),
703 g_date_get_day(&date
)
711 //used only in DB() macro !!
712 void hb_print_date(guint32 jdate
, gchar
*label
)
717 date
= g_date_new_julian(jdate
);
718 g_date_strftime (buffer1
, 128-1, "%x", date
);
720 g_print(" - %s %s\n", label
!= NULL
? label
:"date is", buffer1
);
726 ** parse a string an retrieve an iso date (dd-mm-yy(yy) or dd/mm/yy(yy))
730 guint32 hb_date_get_julian_parse(gchar *str)
732 gchar **str_array = NULL;
735 guint32 julian = GLOBALS->today;
737 // try with - separator
738 if( g_strrstr(str, "-") != NULL )
740 str_array = g_strsplit (str, "-", 3);
744 if( g_strrstr(str, "/") != NULL )
746 str_array = g_strsplit (str, "/", 3);
750 if( g_strv_length( str_array ) == 3 )
752 d = atoi(str_array[0]);
753 m = atoi(str_array[1]);
754 y = atoi(str_array[2]);
756 //correct for 2 digits year
765 //todo: here if month is > 12 then the format is probably mm/dd/yy(yy)
766 //or maybe check with g_date_valid_julian(julian)
771 g_date_set_dmy(date, d, m, y);
772 julian = g_date_get_julian (date);
775 DB( g_print("date: %s :: %d %d %d :: %d\n", str, d, m, y, julian ) );
779 g_strfreev (str_array);
785 /* -------------------- */
793 void hex_dump(guchar
*ptr
, guint length
)
795 guchar ascii
[MAX_DUMP
+4];
798 g_print("**hex_dump - %d bytes\n", length
);
802 g_print("%08x: ", (guint
)ptr
+i
);
804 for(j
=0;j
<MAX_DUMP
;j
++)
806 if(i
>= length
) break;
809 if(ptr
[i
] >= 32 && ptr
[i
] <= 126)
814 g_print("%02x ", ptr
[i
]);
819 g_print(" '%s'\n", ascii
);
This page took 0.087292 seconds and 4 git commands to generate.