1
2 /*
3 * Osmo - a handy personal organizer
4 *
5 * Copyright (C) 2007 Tomasz Maka <pasp@users.sourceforge.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */
21
22 #include "utils.h"
23 #include "utils_gui.h"
24 #include "utils_time.h"
25 #include "utils_date.h"
26 #include "i18n.h"
27 #include "options_prefs.h"
28
29 /*------------------------------------------------------------------------------*/
30
31 gchar *
utl_text_with_tags_to_html(gchar * input_text)32 utl_text_with_tags_to_html (gchar *input_text)
33 {
34 const gchar *html_tags[] = {
35 "mark_color", "<span style=\"background-color:#FFFF00;\">",
36 "bold", "<span style=\"font-weight: bold;\">",
37 "italic", "<span style=\"font-style: italic;\">",
38 "underline", "<span style=\"text-decoration:underline;\">",
39 "strike", "<span style=\"text-decoration:line-through;\">"
40 };
41 guint n_pairs = G_N_ELEMENTS (html_tags) / 2;
42 gchar *output = g_strdup ("");
43 gunichar TAG_CHAR = TAG; /* Unicode chars in the Private Use Area. */
44 gchar tag_char_utf8[7] = {0};
45 gchar **tokens, *o_links_1_text, *o_links_2_text;
46 gint count, i;
47
48 g_unichar_to_utf8 (TAG_CHAR, tag_char_utf8);
49
50 tokens = g_strsplit (input_text, tag_char_utf8, 0);
51
52 for (count = 0; tokens[count]; count++)
53 {
54 if (count % 2 == 0) { /* normal text */
55 output = utl_strconcat (output, tokens[count], NULL);
56 } else {
57 if (tokens[count][0] != '/') { /* opening tag */
58 for (i=0; i < n_pairs; i++) {
59 if (!strcmp(html_tags[i*2+0], tokens[count])) {
60 output = utl_strconcat (output, html_tags[i*2+1], NULL);
61 break;
62 }
63 }
64 } else {
65 /* closing tag */
66 output = utl_strconcat (output, "</span>", NULL);
67 }
68 }
69 }
70
71 g_strfreev (tokens);
72
73 o_links_1_text = utl_text_replace (output, REGEX_URL, "<a href=\"\\0\">\\0</a>");
74 g_free (output);
75
76 o_links_2_text = utl_text_replace (o_links_1_text, REGEX_EMAIL, "<a href=\"mailto:\\0\">\\0</a>");
77 g_free (o_links_1_text);
78
79 return o_links_2_text;
80 }
81
82 /*------------------------------------------------------------------------------*/
83
84 gchar *
utl_text_replace(const gchar * text,const gchar * regex,const gchar * replacement)85 utl_text_replace (const gchar *text, const gchar *regex, const gchar *replacement)
86 {
87 GRegex *reg = g_regex_new (regex, G_REGEX_OPTIMIZE, 0, NULL);
88 gchar *buffer = g_regex_replace (reg, text, -1, 0, replacement, 0, NULL);
89 g_regex_unref (reg);
90
91 return buffer;
92 }
93
94 gboolean
utl_text_match(const gchar * text,const gchar * regex)95 utl_text_match (const gchar *text, const gchar *regex) {
96 GRegex *reg = g_regex_new (regex, G_REGEX_OPTIMIZE, 0, NULL);
97 gboolean matched = g_regex_match (reg, text, 0, NULL);
98 g_regex_unref (reg);
99
100 return matched;
101 }
102
103 /*------------------------------------------------------------------------------*/
104
105 #ifdef HAVE_LIBWEBKIT
106
107 gboolean
utl_webkit_on_menu(WebKitWebView * web_view,WebKitContextMenu * context_menu,GdkEvent * event,WebKitHitTestResult * hit_test_result,gpointer user_data)108 utl_webkit_on_menu (WebKitWebView *web_view,
109 WebKitContextMenu *context_menu,
110 GdkEvent *event,
111 WebKitHitTestResult *hit_test_result,
112 gpointer user_data) {
113 /* don't show popup menus */
114 return TRUE;
115 }
116
117 gboolean
utl_webkit_link_clicked(WebKitWebView * web_view,WebKitPolicyDecision * decision,WebKitPolicyDecisionType decision_type,gpointer user_data)118 utl_webkit_link_clicked(WebKitWebView *web_view,
119 WebKitPolicyDecision *decision,
120 WebKitPolicyDecisionType decision_type,
121 gpointer user_data) {
122 WebKitNavigationPolicyDecision *navigation_decision;
123 WebKitNavigationAction * navigation_action;
124 WebKitNavigationType navigation_type;
125 WebKitURIRequest *request;
126 const gchar *uri;
127
128
129 g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(web_view), FALSE);
130 if (decision_type != WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION) {
131 return FALSE;
132 }
133
134 navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION(decision);
135 navigation_action = webkit_navigation_policy_decision_get_navigation_action(navigation_decision);
136 navigation_type = webkit_navigation_action_get_navigation_type(navigation_action);
137 if (navigation_type != WEBKIT_NAVIGATION_TYPE_LINK_CLICKED) {
138 return FALSE;
139 }
140 request = webkit_navigation_action_get_request (navigation_action);
141 uri = webkit_uri_request_get_uri(request);
142 webkit_policy_decision_ignore(decision);
143
144 utl_run_helper((gchar *) uri, utl_get_link_type((gchar *) uri));
145
146 return FALSE;
147 }
148
149 #endif /* HAVE_LIBWEBKIT */
150
151 /*------------------------------------------------------------------------------*/
152
153 gchar *
utl_text_to_html_page(const gchar * text,const gchar * font_family,const gchar * background_color,const gchar * text_color,const gchar * header_html,const gchar * top_html,const gchar * bottom_html)154 utl_text_to_html_page (const gchar *text, const gchar *font_family,
155 const gchar *background_color, const gchar *text_color,
156 const gchar *header_html, const gchar *top_html, const gchar *bottom_html)
157 {
158 gunichar TAG_CHAR = TAG; /* Unicode chars in the Private Use Area. */
159 gchar *output = g_strdup ("");
160 gchar tag_char_utf8[7] = {0};
161 gchar **tokens, *itext, *o_links_1_text, *o_links_2_text;
162 gint count, i;
163 const gchar *html_tags[] = {
164 "mark_color", "<span style=\"background-color:#FFFF00;\">",
165 "bold", "<span style=\"font-weight: bold;\">",
166 "italic", "<span style=\"font-style: italic;\">",
167 "underline", "<span style=\"text-decoration:underline;\">",
168 "strike", "<span style=\"text-decoration:line-through;\">"
169 };
170 guint n_pairs = G_N_ELEMENTS (html_tags) / 2;
171
172 g_unichar_to_utf8 (TAG_CHAR, tag_char_utf8);
173
174 itext = utl_text_to_html (text, FALSE, TRUE);
175
176 output = utl_strconcat (output, "<html><head>", NULL);
177 output = utl_strconcat (output, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />", NULL);
178 output = utl_strconcat (output, "<style type=\"text/css\">", NULL);
179 output = utl_strconcat (output, "body {", NULL);
180
181 if (background_color != NULL) {
182 output = utl_strconcat (output, "background-color: ", background_color, "; ", NULL);
183 }
184 if (text_color != NULL) {
185 output = utl_strconcat (output, "text-color: ", text_color, "; ", NULL);
186 }
187 if (font_family != NULL) {
188 output = utl_strconcat (output, "font-family: ", font_family, "; ", NULL);
189 }
190
191 output = utl_strconcat (output, "line-height: 145\%; ", NULL);
192 output = utl_strconcat (output, "} </style>", NULL);
193
194 if (header_html != NULL) {
195 output = utl_strconcat (output, header_html, NULL);
196 }
197 output = utl_strconcat (output, "</head><body>", NULL);
198
199 if (top_html != NULL) {
200 output = utl_strconcat (output, top_html, NULL);
201 }
202
203 output = utl_strconcat (output, "<span style=\"white-space: pre-wrap;\">", NULL);
204
205 tokens = g_strsplit (itext, tag_char_utf8, 0);
206 g_free (itext);
207
208 for (count = 0; tokens[count]; count++)
209 {
210 if (count % 2 == 0) { /* normal text */
211 output = utl_strconcat (output, tokens[count], NULL);
212 } else {
213 if (tokens[count][0] != '/') { /* opening tag */
214 for (i=0; i < n_pairs; i++) {
215 if (!strcmp(html_tags[i*2+0], tokens[count])) {
216 output = utl_strconcat (output, html_tags[i*2+1], NULL);
217 break;
218 }
219 }
220 } else {
221 /* closing tag */
222 output = utl_strconcat (output, "</span>", NULL);
223 }
224 }
225 }
226
227 g_strfreev (tokens);
228
229 output = utl_strconcat (output, "</span>", NULL);
230
231 if (bottom_html != NULL) {
232 output = utl_strconcat (output, bottom_html, NULL);
233 }
234
235 output = utl_strconcat (output, "</body></html>", NULL);
236
237 o_links_1_text = utl_text_replace (output, REGEX_URL, "<a href=\"\\0\">\\0</a>");
238 g_free (output);
239
240 o_links_2_text = utl_text_replace (o_links_1_text, REGEX_EMAIL, "<a href=\"mailto:\\0\">\\0</a>");
241 g_free (o_links_1_text);
242
243 return o_links_2_text;
244 }
245
246 /*------------------------------------------------------------------------------*/
247
248 gchar *
utl_text_to_html(const gchar * text,gboolean ignoreBR,gboolean ignoreSP)249 utl_text_to_html (const gchar *text,
250 gboolean ignoreBR, /* ignore line breaks */
251 gboolean ignoreSP /* ignore spaces */)
252 {
253
254 const gchar *pairs[] = {
255 "&", "&",
256 "\"", """,
257 "<", "<",
258 ">", ">"
259 };
260
261 GRegex *reg;
262 gint i = 0;
263 gchar *buffer = NULL, *temp = NULL;
264 guint n_pairs = G_N_ELEMENTS (pairs) / 2;
265
266 temp = g_strdup(text);
267
268 for (i=0; i < n_pairs; i++) {
269 reg = g_regex_new (pairs[i*2+0], 0, 0, NULL);
270 buffer = g_regex_replace_literal (reg, temp, -1, 0, pairs[i*2+1], 0, NULL);
271 g_free (temp);
272 temp = buffer;
273 g_regex_unref (reg);
274 }
275
276 if (ignoreBR == FALSE) {
277 reg = g_regex_new ("\\n", 0, 0, NULL);
278 buffer = g_regex_replace_literal (reg, temp, -1, 0, "<br />", 0, NULL);
279 g_free (temp);
280 temp = buffer;
281 g_regex_unref (reg);
282 }
283
284 if (ignoreSP == FALSE) {
285 reg = g_regex_new (" ", 0, 0, NULL);
286 buffer = g_regex_replace_literal (reg, temp, -1, 0, "%20", 0, NULL);
287 g_free (temp);
288 temp = buffer;
289 g_regex_unref (reg);
290 }
291
292 return temp;
293 }
294
295 /*------------------------------------------------------------------------------*/
296
297 gchar *
utl_get_day_name(guint day,gboolean short_name)298 utl_get_day_name (guint day, gboolean short_name)
299 {
300 static gchar buffer[BUFFER_SIZE];
301 GDate *tmpdate = NULL;
302
303 g_return_val_if_fail (day > 0 && day <= 31, buffer);
304
305 tmpdate = g_date_new_dmy (day, 1, 2007);
306 g_return_val_if_fail (tmpdate != NULL, buffer);
307
308 g_date_strftime (buffer, BUFFER_SIZE, short_name ? "%a" : "%A", tmpdate);
309 g_date_free (tmpdate);
310
311 return buffer;
312 }
313
314 /*------------------------------------------------------------------------------*/
315
316 gchar *
utl_get_julian_day_name(guint32 julian)317 utl_get_julian_day_name (guint32 julian)
318 {
319 static gchar buffer[BUFFER_SIZE];
320 GDate *tmpdate = NULL;
321
322 buffer[0] = '\0';
323 g_return_val_if_fail (g_date_valid_julian (julian) == TRUE, buffer);
324
325 tmpdate = g_date_new_julian (julian);
326 g_return_val_if_fail (tmpdate != NULL, buffer);
327
328 g_date_strftime (buffer, BUFFER_SIZE, "%A", tmpdate);
329 g_date_free (tmpdate);
330
331 return buffer;
332 }
333
334 /*------------------------------------------------------------------------------*/
335
336 gchar *
utl_get_date_name(const GDate * date)337 utl_get_date_name (const GDate *date)
338 {
339 static gchar buffer[BUFFER_SIZE];
340
341 g_date_strftime (buffer, BUFFER_SIZE, "%e %B %Y", date); /* e.g. 1 August 1999 */
342 return buffer;
343 }
344
345 /*------------------------------------------------------------------------------*/
346
347 gchar *
utl_get_date_name_format(const GDate * date,gchar * fmt)348 utl_get_date_name_format (const GDate *date, gchar *fmt)
349 {
350 static gchar buffer[BUFFER_SIZE];
351
352 g_date_strftime (buffer, BUFFER_SIZE, fmt, date);
353 return buffer;
354 }
355
356 /*------------------------------------------------------------------------------*/
357
358 guint
utl_get_weekend_days_in_month(const GDate * date)359 utl_get_weekend_days_in_month (const GDate *date)
360 {
361 GDate *tmpdate = NULL;
362 guint i, day, days, weekend_days;
363
364 tmpdate = g_date_new_dmy (1, g_date_get_month (date), g_date_get_year (date));
365 g_return_val_if_fail (tmpdate != NULL, 0);
366
367 days = utl_date_get_days_in_month (tmpdate);
368 weekend_days = 0;
369
370 for (i = 1; i <= days; i++) {
371 g_date_set_day (tmpdate, i);
372 day = g_date_get_weekday (tmpdate);
373 if (day == G_DATE_SATURDAY || day == G_DATE_SUNDAY) {
374 weekend_days++;
375 }
376 }
377
378 g_date_free (tmpdate);
379 return weekend_days;
380 }
381
382 /*------------------------------------------------------------------------------*/
383
384 guint
utl_get_weekend_days_in_month_my(guint month,guint year)385 utl_get_weekend_days_in_month_my (guint month, guint year)
386 {
387 GDate *tmpdate = NULL;
388 guint i, day, days, weekend_days;
389
390 g_return_val_if_fail (g_date_valid_dmy (1, month, year) == TRUE, 0);
391
392 tmpdate = g_date_new_dmy (1, month, year);
393 g_return_val_if_fail (tmpdate != NULL, 0);
394
395 days = utl_date_get_days_in_month (tmpdate);
396 weekend_days = 0;
397
398 for (i = 1; i <= days; i++) {
399 g_date_set_day (tmpdate, i);
400 day = g_date_get_weekday (tmpdate);
401 if (day == G_DATE_SATURDAY || day == G_DATE_SUNDAY) {
402 weekend_days++;
403 }
404 }
405
406 g_date_free (tmpdate);
407 return weekend_days;
408 }
409
410 /*------------------------------------------------------------------------------*/
411
412 guint
utl_get_days_per_year(guint year)413 utl_get_days_per_year (guint year)
414 {
415 return (g_date_is_leap_year (year) ? 366 : 365);
416 }
417
418 /*------------------------------------------------------------------------------*/
419
420 void
utl_subtract_from_date(guint32 date,gint time,gint days,gint seconds,guint32 * new_date,gint * new_time)421 utl_subtract_from_date (guint32 date, gint time, gint days, gint seconds, guint32 *new_date, gint *new_time)
422 {
423 *new_date = date - days;
424
425 if (time >= 0) {
426 *new_time = time - seconds;
427
428 if (*new_time < 0) {
429 *new_time = (*new_time) + 24 * 3600;
430 *new_date = (*new_date) - 1;
431 }
432 } else {
433 *new_time = -1;
434 }
435 }
436
437 /*------------------------------------------------------------------------------*/
438 /* This routine has been taken from http://www.voidware.com/moon_phase.htm
439 calculates the moon phase (0-7), accurate to 1 segment: 0 = > new moon, 4 => full moon.
440 */
441
442 gint
utl_calc_moon_phase(const GDate * date)443 utl_calc_moon_phase (const GDate *date)
444 {
445 gdouble jd;
446 gint day, month, year;
447 gint b, c, e;
448
449 utl_date_get_dmy (date, &day, &month, &year);
450
451 if (month < 3) {
452 year--;
453 month += 12;
454 }
455 month++;
456 c = 365.25 * year;
457 e = 30.6 * month;
458 jd = c + e + day - 694039.09; /* jd is total days elapsed */
459 jd /= 29.53; /* divide by the moon cycle (29.53 days) */
460 b = jd; /* int(jd) -> b, take integer part of jd */
461 jd -= b; /* subtract integer part to leave fractional part of original jd */
462 b = jd * 8 + 0.5; /* scale fraction from 0-8 and round by adding 0.5 */
463 b = b & 7; /* 0 and 8 are the same so turn 8 into 0 */
464
465 return b;
466 }
467
468 /*------------------------------------------------------------------------------*/
469
470 gchar*
utl_get_moon_phase_name(gint phase)471 utl_get_moon_phase_name (gint phase)
472 {
473 const gchar *phase_names[] = {
474 N_("New Moon"), N_("Waxing Crescent Moon"), N_("Quarter Moon"), N_("Waxing Gibbous Moon"),
475 N_("Full Moon"), N_("Waning Gibbous Moon"), N_("Last Quarter Moon"), N_("Waning Crescent Moon")
476 };
477
478 return (gchar *) gettext (phase_names[phase]);
479 }
480
481 /*------------------------------------------------------------------------------*/
482
483 void
utl_name_strcat(gchar * first,gchar * second,gchar * buffer)484 utl_name_strcat (gchar *first, gchar *second, gchar *buffer)
485 {
486 gchar tmpbuff[BUFFER_SIZE];
487 gboolean flag;
488
489 buffer[0] = '\0';
490 g_return_if_fail (first != NULL || second != NULL);
491
492 g_snprintf (tmpbuff, BUFFER_SIZE, "(%s)", _("None"));
493 flag = FALSE;
494
495 if (first != NULL) {
496
497 if (strcmp (first, tmpbuff) != 0) {
498 flag = TRUE;
499 g_strlcpy (buffer, first, BUFFER_SIZE);
500 }
501
502 g_free (first);
503 }
504
505 if (second != NULL) {
506
507 if (strcmp (second, tmpbuff) != 0) {
508 if (flag == TRUE) {
509 g_strlcat (buffer, " ", BUFFER_SIZE);
510 g_strlcat (buffer, second, BUFFER_SIZE);
511 } else {
512 g_strlcpy (buffer, second, BUFFER_SIZE);
513 }
514 }
515
516 g_free (second);
517 }
518
519 g_return_if_fail (strlen (buffer) > 0);
520 }
521
522 /*------------------------------------------------------------------------------*/
523
524 void
utl_xml_get_int(gchar * name,gint * iname,xmlNodePtr node)525 utl_xml_get_int (gchar *name, gint *iname, xmlNodePtr node)
526 {
527 xmlChar *key;
528
529 if ((xmlStrcmp (node->name, (const xmlChar *) name)) == 0) {
530 key = xmlNodeGetContent (node->xmlChildrenNode);
531 if (key != NULL) {
532 *iname = atoi ((gchar *) key);
533 xmlFree (key);
534 }
535 }
536 }
537
538 /*------------------------------------------------------------------------------*/
539
540 void
utl_xml_get_uint(gchar * name,guint * uname,xmlNodePtr node)541 utl_xml_get_uint (gchar *name, guint *uname, xmlNodePtr node)
542 {
543 xmlChar *key;
544
545 if ((xmlStrcmp (node->name, (const xmlChar *) name)) == 0) {
546 key = xmlNodeGetContent (node->xmlChildrenNode);
547 if (key != NULL) {
548 *uname = (guint) atoi ((gchar *) key);
549 xmlFree (key);
550 }
551 }
552 }
553
554 /*------------------------------------------------------------------------------*/
555
556 void
utl_xml_get_char(gchar * name,gchar * cname,xmlNodePtr node)557 utl_xml_get_char (gchar *name, gchar *cname, xmlNodePtr node)
558 {
559 xmlChar *key;
560
561 if ((xmlStrcmp (node->name, (const xmlChar *) name)) == 0) {
562 key = xmlNodeGetContent (node->xmlChildrenNode);
563 if (key != NULL) {
564 *cname = key[0];
565 xmlFree (key);
566 }
567 }
568 }
569
570 /*------------------------------------------------------------------------------*/
571
572 void
utl_xml_get_str(gchar * name,gchar ** sname,xmlNodePtr node)573 utl_xml_get_str (gchar *name, gchar **sname, xmlNodePtr node)
574 {
575 xmlChar *key;
576
577 if ((xmlStrcmp (node->name, (const xmlChar *) name)) == 0) {
578
579 key = xmlNodeGetContent (node->xmlChildrenNode);
580
581 if (key != NULL) {
582 *sname = g_strdup ((gchar *) key);
583 xmlFree (key);
584 }
585 }
586 }
587
588 /*------------------------------------------------------------------------------*/
589
590 void
utl_xml_get_strn(gchar * name,gchar * sname,gint buffer_size,xmlNodePtr node)591 utl_xml_get_strn (gchar *name, gchar *sname, gint buffer_size, xmlNodePtr node)
592 {
593 xmlChar *key;
594
595 if ((xmlStrcmp (node->name, (const xmlChar *) name)) == 0) {
596
597 key = xmlNodeGetContent (node->xmlChildrenNode);
598
599 if (key != NULL) {
600 g_strlcpy (sname, (gchar *) key, buffer_size);
601 xmlFree (key);
602 }
603 }
604 }
605
606 /*------------------------------------------------------------------------------*/
607
608 void
utl_xml_put_int(gchar * name,gint value,xmlNodePtr node)609 utl_xml_put_int (gchar *name, gint value, xmlNodePtr node)
610 {
611 gchar buffer[32];
612
613 g_snprintf (buffer, 32, "%d", value);
614 xmlNewChild (node, NULL, (const xmlChar *) name, (xmlChar *) buffer);
615 }
616
617 /*------------------------------------------------------------------------------*/
618
619 void
utl_xml_put_uint(gchar * name,guint value,xmlNodePtr node)620 utl_xml_put_uint (gchar *name, guint value, xmlNodePtr node)
621 {
622 gchar buffer[32];
623
624 g_snprintf (buffer, 32, "%d", value);
625 xmlNewChild (node, NULL, (const xmlChar *) name, (xmlChar *) buffer);
626 }
627
628 /*------------------------------------------------------------------------------*/
629
630 void
utl_xml_put_char(gchar * name,gchar character,xmlNodePtr node)631 utl_xml_put_char (gchar *name, gchar character, xmlNodePtr node)
632 {
633 gchar buffer[32];
634
635 g_snprintf (buffer, 32, "%c", character);
636 xmlNewTextChild (node, NULL, (const xmlChar *) name, (xmlChar *) buffer);
637 }
638
639 /*------------------------------------------------------------------------------*/
640
641 void
utl_xml_put_str(gchar * name,gchar * string,xmlNodePtr node)642 utl_xml_put_str (gchar *name, gchar *string, xmlNodePtr node)
643 {
644 xmlNewTextChild (node, NULL, (const xmlChar *) name, (xmlChar *) string);
645 }
646
647 /*------------------------------------------------------------------------------*/
648
649 void
utl_xml_put_strn(gchar * name,gchar * string,gint buffer_size,xmlNodePtr node)650 utl_xml_put_strn (gchar *name, gchar *string, gint buffer_size, xmlNodePtr node)
651 {
652 gchar buffer[BUFFER_SIZE];
653
654 if (buffer_size > BUFFER_SIZE) buffer_size = BUFFER_SIZE;
655 g_snprintf (buffer, buffer_size, "%s", string);
656 xmlNewTextChild (node, NULL, (const xmlChar *) name, (xmlChar *) buffer);
657 }
658 /*------------------------------------------------------------------------------*/
659 void
utl_xml_write_doc(const char * filename,xmlDocPtr doc)660 utl_xml_write_doc(const char *filename, xmlDocPtr doc) {
661 gchar *tmp_filename = g_strconcat(filename, ".tmp", NULL);
662
663 if (xmlSaveFormatFileEnc(tmp_filename, doc, "utf-8", 1) == -1) {
664 g_warning("Failed to write a file %s", filename);
665 } else if (g_rename(tmp_filename, filename) == -1) {
666 g_warning("Failed to replace the written file %s", filename);
667 }
668
669 g_free(tmp_filename);
670 }
671
672 /*------------------------------------------------------------------------------*/
673
674 gboolean
utl_is_valid_command(gchar * command)675 utl_is_valid_command (gchar *command) {
676
677 gchar *found_path;
678
679 found_path = g_find_program_in_path (command);
680
681 if (found_path != NULL) {
682 g_free (found_path);
683 return TRUE;
684 }
685
686 return FALSE;
687 }
688
689 /*------------------------------------------------------------------------------*/
690
691 void
utl_run_command(gchar * command,gboolean sync)692 utl_run_command (gchar *command, gboolean sync) {
693 GError *err = NULL;
694 gchar *cmdline[4];
695
696 cmdline[0] = "sh";
697 cmdline[1] = "-c";
698 cmdline[2] = command;
699 cmdline[3] = 0;
700
701 if (sync == FALSE) {
702 g_spawn_async (NULL, (gchar **)cmdline, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL,
703 NULL, NULL, NULL, &err);
704 } else {
705 g_spawn_sync (NULL, (gchar **)cmdline, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL,
706 NULL, NULL, NULL, NULL, NULL, &err);
707 }
708 if(err) {
709 fprintf(stderr, "Failed to execute command %s: %s", command, err->message);
710 g_error_free (err);
711 }
712 }
713
714 /*------------------------------------------------------------------------------*/
715
716 gboolean
utl_run_helper(gchar * parameter,gint helper)717 utl_run_helper (gchar *parameter, gint helper) {
718
719 gchar command[PATH_MAX], quoted[PATH_MAX];
720 gboolean sync = FALSE;
721
722 g_snprintf(quoted, PATH_MAX, "\"%s\"", parameter);
723
724 if (helper == EMAIL) {
725 g_snprintf(command, PATH_MAX, config.email_client, quoted);
726 } else if (helper == WWW) {
727 g_snprintf(command, PATH_MAX, config.web_browser, quoted);
728 } else if (helper == SOUND) {
729 g_snprintf(command, PATH_MAX, config.sound_player, quoted);
730 sync = TRUE;
731 } else {
732 return FALSE;
733 }
734
735 utl_run_command (command, sync);
736
737 return TRUE;
738 }
739
740 /*------------------------------------------------------------------------------*/
741
742 gint
utl_get_link_type(gchar * link)743 utl_get_link_type (gchar *link)
744 {
745 gint i, n, d;
746
747 g_return_val_if_fail (link != NULL, UNKNOWN);
748
749 for (i = n = d = 0; i < strlen (link); i++) {
750 if (link[i] == '@') n++;
751 if (link[i] == '.') d++;
752 }
753
754 if (!strncasecmp (link, "https://", 8) || !strncasecmp (link, "http://", 7) || !strncasecmp(link, "www", 3)) {
755 return WWW;
756 } else if (n == 1) {
757 return EMAIL;
758 } else if (n == 0 && d >= 1) {
759 return WWW;
760 } else {
761 return UNKNOWN;
762 }
763 }
764
765 /*------------------------------------------------------------------------------*/
766
767 void
utl_cairo_draw(cairo_t * cr,gint stroke)768 utl_cairo_draw (cairo_t *cr, gint stroke)
769 {
770 if (stroke) {
771 cairo_set_line_width (cr, stroke);
772 cairo_stroke (cr);
773 } else {
774 cairo_fill (cr);
775 }
776 }
777
778 /*------------------------------------------------------------------------------*/
779
780 void
utl_draw_rounded_rectangle(cairo_t * cr,gint x,gint y,gint w,gint h,gint a,gint s)781 utl_draw_rounded_rectangle (cairo_t *cr, gint x, gint y, gint w, gint h, gint a, gint s)
782 {
783 cairo_move_to (cr, x + a + s, y + s);
784 cairo_line_to (cr, x + w - a - s, y + s);
785 cairo_arc (cr, x + w - a - s, y + a + s, a, 1.5 * M_PI, 2.0 * M_PI);
786 cairo_line_to (cr, x + w - s, y + h - a - s);
787 cairo_arc (cr, x + w - a - s, y + h - a - s, a, 0.0 * M_PI, 0.5 * M_PI);
788 cairo_line_to (cr, x + a + s, y + h - s);
789 cairo_arc (cr, x + a + s, y + h - a - s, a, 0.5 * M_PI, 1.0 * M_PI);
790 cairo_line_to (cr, x + s, y + a + s);
791 cairo_arc (cr, x + a + s, y + a + s, a, 1.0 * M_PI, 1.5 * M_PI);
792 }
793
794 /*------------------------------------------------------------------------------*/
795
796 void
utl_draw_left_arrow(cairo_t * cr,gdouble x,gdouble y,gdouble w,gdouble h,gdouble a)797 utl_draw_left_arrow (cairo_t *cr, gdouble x, gdouble y, gdouble w, gdouble h, gdouble a)
798 {
799 cairo_move_to (cr, x, y);
800 cairo_line_to (cr, x + w * a, y + h * 0.50);
801 cairo_line_to (cr, x + w * a, y + h * 0.25);
802 cairo_line_to (cr, x + w * 1, y + h * 0.25);
803 cairo_line_to (cr, x + w * 1, y - h * 0.25);
804 cairo_line_to (cr, x + w * a, y - h * 0.25);
805 cairo_line_to (cr, x + w * a, y - h * 0.50);
806 cairo_close_path (cr);
807 }
808
809 /*------------------------------------------------------------------------------*/
810
811 gpointer
utl_snd_play_thread(gpointer * data)812 utl_snd_play_thread (gpointer *data) {
813
814 gchar sound_filename[PATH_MAX];
815 gint i;
816
817 g_snprintf (sound_filename, PATH_MAX, "%s%c%s%c%s", SOUNDSDIR, G_DIR_SEPARATOR, "osmo",
818 G_DIR_SEPARATOR, "alarm.wav");
819
820 for (i=0; i < (size_t) data; i++) {
821 utl_run_helper (sound_filename, SOUND);
822 }
823
824 return NULL;
825 }
826
827
828 void
utl_play_alarm_sound(guint repetitions)829 utl_play_alarm_sound (guint repetitions)
830 {
831 GThread *thread;
832 if (repetitions == 0)
833 return;
834
835 thread = g_thread_try_new ("osmo", (GThreadFunc) utl_snd_play_thread, (gpointer) ((size_t) repetitions), NULL);
836 if(thread) {
837 g_thread_unref(thread);
838 }
839 }
840
841 /*------------------------------------------------------------------------------*/
842
843 gchar*
utl_add_timestamp_to_filename(gchar * filename,gchar * extension)844 utl_add_timestamp_to_filename (gchar *filename, gchar *extension) {
845
846 static gchar filename_buffer[BUFFER_SIZE];
847
848 g_snprintf (filename_buffer, BUFFER_SIZE, "%s-%4d%02d%02d%02d%02d.%s",
849 filename,
850 utl_date_get_current_year(), utl_date_get_current_month(), utl_date_get_current_day(),
851 utl_time_get_current_hour(), utl_time_get_current_minute(),
852 extension);
853
854 return filename_buffer;
855 }
856
857 /*------------------------------------------------------------------------------*/
858
859 gchar *
utl_strconcat(gchar * string,...)860 utl_strconcat (gchar *string, ...) {
861
862 gchar *tmp_holder, *tmp_str;
863 va_list arguments;
864
865 va_start (arguments, string);
866
867 while ((tmp_str = va_arg (arguments, gchar *)) != NULL) {
868 tmp_holder = string;
869 string = g_strconcat (tmp_holder, tmp_str, NULL);
870 g_free (tmp_holder);
871 }
872
873 va_end (arguments);
874
875 return string;
876 }
877
878 /*------------------------------------------------------------------------------*/
879
880 gint
utl_text_strcmp(const gchar * string1,const gchar * string2)881 utl_text_strcmp (const gchar *string1, const gchar *string2) {
882 if (string1 == NULL && string2 == NULL) {
883 return 0;
884 } if (string1 == NULL) {
885 return -1;
886 } else if (string2 == NULL) {
887 return 1;
888 } else {
889 return g_utf8_collate(string1, string2);
890 }
891 }
892
893 /*------------------------------------------------------------------------------*/
894
895 static gboolean
find_substring(const gchar * haystack,const gchar * needle,gboolean case_sensitive)896 find_substring(const gchar *haystack, const gchar *needle, gboolean case_sensitive) {
897 gint window_len, text_len, i, diff;
898 gchar *window_start, *window_end, *casefold1, *casefold2;
899
900 window_len = g_utf8_strlen(needle, -1);
901 if (window_len == 0) {
902 return TRUE;
903 }
904 text_len = g_utf8_strlen(haystack, -1);
905 if (text_len == 0) {
906 return FALSE;
907 }
908 if(case_sensitive == TRUE) {
909 casefold1 = g_strdup(needle);
910 } else {
911 casefold1 = g_utf8_casefold(needle, -1);
912 }
913 for (i = 0; i <= text_len - window_len; i++) {
914 window_start = g_utf8_offset_to_pointer(haystack, i);
915 window_end = g_utf8_offset_to_pointer(haystack, i + window_len);
916 if(case_sensitive == TRUE) {
917 casefold2 = g_strndup(window_start, window_end - window_start);
918 } else {
919 casefold2 = g_utf8_casefold(window_start, window_end - window_start);
920 }
921 diff = g_utf8_collate(casefold1, casefold2);
922 g_free(casefold2);
923 if (!diff) {
924 g_free(casefold1);
925 return TRUE;
926 }
927 }
928 g_free(casefold1);
929 return FALSE;
930 }
931
932 /*------------------------------------------------------------------------------*/
933
934 gboolean
utl_text_strcasestr(const gchar * haystack,const gchar * needle)935 utl_text_strcasestr(const gchar *haystack, const gchar *needle) {
936 return find_substring(haystack, needle, FALSE);
937 }
938
939 /*------------------------------------------------------------------------------*/
940
941 gboolean
utl_text_strstr(const gchar * haystack,const gchar * needle)942 utl_text_strstr(const gchar *haystack, const gchar *needle) {
943 return find_substring(haystack, needle, TRUE);
944 }
945
946 /*------------------------------------------------------------------------------*/
947
948 void
utl_free_list(GList * list,GDestroyNotify free_func)949 utl_free_list (GList *list, GDestroyNotify free_func) {
950 #if GLIB_CHECK_VERSION(2, 28, 0)
951 g_list_free_full(list, free_func);
952 #else
953 GList *l;
954 for (l = list; l; l = l->next) {
955 free_func(l->data);
956 }
957 g_list_free(list);
958 #endif
959 }
960
961 /*------------------------------------------------------------------------------*/
962 #ifdef HAVE_LIBWEBKIT
963 WebKitWebView *
utl_create_webkit_web_view(GUI * appGUI)964 utl_create_webkit_web_view(GUI *appGUI) {
965 WebKitSettings *settings;
966 WebKitWebView *view;
967 WebKitUserContentManager *manager;
968 WebKitUserStyleSheet *stylesheet;
969 settings = webkit_settings_new();
970
971 manager = webkit_user_content_manager_new();
972 if (appGUI->stylesheet) {
973 stylesheet = webkit_user_style_sheet_new(appGUI->stylesheet, WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, WEBKIT_USER_STYLE_LEVEL_USER, NULL, NULL);
974 webkit_user_content_manager_add_style_sheet(manager, stylesheet);
975 }
976
977 webkit_settings_set_enable_javascript(settings, FALSE);
978 webkit_settings_set_enable_plugins(settings, FALSE);
979 webkit_settings_set_enable_java(settings, FALSE);
980
981 view = WEBKIT_WEB_VIEW(webkit_web_view_new_with_user_content_manager(manager));
982 webkit_web_view_set_settings(view, settings);
983 webkit_web_view_set_editable(view, FALSE);
984 return view;
985 }
986 #endif /* HAVE_LIBWEBKIT */
987
988 /*------------------------------------------------------------------------------*/
989
990 gint
991 /*utl_open_count_url_links (gchar *text, gint *tsize, gboolean url_count) {*/
utl_open_count_url_links(gchar * text,gboolean url_count)992 utl_open_count_url_links (gchar *text, gboolean url_count) {
993
994 GRegex *regex = NULL;
995 GMatchInfo *match_info = NULL;
996 gchar url_path[PATH_MAX], command[PATH_MAX];
997 gchar *URL = NULL, *qURL = NULL;
998 gint k = 0, tsize;
999
1000 regex = g_regex_new (REGEX_URL, 0, 0, NULL);
1001 g_regex_match (regex, text, 0, &match_info);
1002
1003 url_path[0] = '\0';
1004 tsize = strlen(config.web_browser);
1005
1006 while (g_match_info_matches (match_info)) {
1007
1008 URL = g_match_info_fetch (match_info, 0);
1009 qURL = g_shell_quote (URL);
1010 if (url_count == FALSE) {
1011 if (tsize + strlen(qURL) < PATH_MAX) {
1012 tsize += strlen(qURL) + 1 /* space */;
1013 strcat (url_path, qURL);
1014 strcat (url_path, " ");
1015 k++;
1016 }
1017 } else {
1018 tsize += strlen(qURL) + 1 /* space */;
1019 k++;
1020 }
1021 g_free (qURL);
1022 g_free (URL);
1023 g_match_info_next (match_info, NULL);
1024 }
1025
1026 if (url_count == FALSE) {
1027 g_snprintf(command, PATH_MAX, config.web_browser, url_path);
1028 utl_run_command (command, FALSE);
1029 }
1030
1031 g_match_info_free (match_info);
1032 g_regex_unref (regex);
1033
1034 return k;
1035 }
1036
1037 /*------------------------------------------------------------------------------*/
1038
1039