* will hang modest
*/
#define HYPERLINKIFY_MAX_LENGTH (1024*50)
-
+#define SIGNATURE_MARKER "--"
/*
/* note: match MARK_AMP_URI_STR as well, because after txt->html, a '&' will look like $(MARK_AMP_URI_STR)"amp;" */
#define MAIL_VIEWER_URL_MATCH_PATTERNS { \
- { "(file|rtsp|http|ftp|https|mms|mmsh|rtsp|rdp|lastfm)://[-a-z0-9_$.+!*(),;:@%=?/~#" MARK_AMP_URI_STR \
+ { "(file|rtsp|http|ftp|https|mms|mmsh|webcal|feed|rtsp|rdp|lastfm|sip)://[-a-z0-9_$.+!*(),;:@%=?/~#" MARK_AMP_URI_STR \
"]+[-a-z0-9_$%" MARK_AMP_URI_STR "=?/~#]", \
NULL, NULL },\
{ "www\\.[-a-z0-9_$.+!*(),;:@%=?/~#" MARK_AMP_URI_STR "]+[-a-z0-9_$%" MARK_AMP_URI_STR "=?/~#]",\
NULL, "http://" }, \
{ "ftp\\.[-a-z0-9_$.+!*(),;:@%=?/~#" MARK_AMP_URI_STR "]+[-a-z0-9_$%" MARK_AMP_URI_STR "=?/~#]",\
NULL, "ftp://" },\
- { "(jabberto|voipto|sipto|sip|chatto|xmpp):[-_a-z@0-9.+]+", \
+ { "(jabberto|voipto|sipto|sip|chatto|skype|xmpp):[-_a-z@0-9.+]+", \
NULL, NULL}, \
{ "mailto:[-_a-z0-9.\\+]+@[-_a-z0-9.]+", \
NULL, NULL},\
/* private */
static gchar* cite (const time_t sent_date, const gchar *from);
-static void hyperlinkify_plain_text (GString *txt);
+static void hyperlinkify_plain_text (GString *txt, gint offset);
static gint cmp_offsets_reverse (const url_match_t *match1, const url_match_t *match2);
-static GSList* get_url_matches (GString *txt);
+static GSList* get_url_matches (GString *txt, gint offset);
static GString* get_next_line (const char *b, const gsize blen, const gchar * iter);
static int get_indent_level (const char *l);
-static void unquote_line (GString * l);
-static void append_quoted (GString * buf, const int indent, const GString * str,
+static void unquote_line (GString * l, const gchar *quote_symbol);
+static void append_quoted (GString * buf, const gchar *quote_symbol,
+ const int indent, const GString * str,
const int cutpoint);
static int get_breakpoint_utf8 (const gchar * s, const gint indent, const gint limit);
static int get_breakpoint_ascii (const gchar * s, const gint indent, const gint limit);
g_return_val_if_fail (text, NULL);
g_return_val_if_fail (content_type, NULL);
- if (!signature)
- retval = g_strdup ("");
- else if (strcmp(content_type, "text/html") == 0) {
- tmp_sig = g_strconcat ("\n", signature, NULL);
- retval = modest_text_utils_convert_to_html_body(tmp_sig, -1, TRUE);
+ if (!signature) {
+ tmp_sig = g_strdup (text);
+ } else {
+ tmp_sig = g_strconcat (text, "\n", SIGNATURE_MARKER, "\n", signature, NULL);
+ }
+
+ if (strcmp (content_type, "text/html") == 0) {
+ retval = modest_text_utils_convert_to_html_body (tmp_sig, -1, TRUE);
g_free (tmp_sig);
} else {
- retval = g_strconcat (text, "\n", signature, NULL);
+ retval = tmp_sig;
}
return retval;
{
struct tm tm;
+ /* To prevent possible problems in strftime that could leave
+ garbage in the s variable */
+ if (s)
+ s[0] = '\0';
+ else
+ return 0;
+
/* does not work on old maemo glib:
* g_date_set_time_t (&date, timet);
*/
gchar *
modest_text_utils_derived_subject (const gchar *subject, const gchar *prefix)
{
- gchar *tmp;
+ gchar *tmp, *subject_dup, *retval;
+ gint prefix_len;
g_return_val_if_fail (prefix, NULL);
if (!subject || subject[0] == '\0')
subject = _("mail_va_no_subject");
- tmp = g_strchug (g_strdup (subject));
+ subject_dup = g_strdup (subject);
+ tmp = g_strchug (subject_dup);
- if (!strncmp (tmp, prefix, strlen (prefix))) {
- return tmp;
- } else {
- g_free (tmp);
- return g_strdup_printf ("%s %s", prefix, subject);
- }
+ /* We do not want things like "Re: Re: Re:" or "Fw: Fw:" so
+ delete the previous ones */
+ prefix_len = strlen (prefix);
+ do {
+ if (g_str_has_prefix (tmp, prefix)) {
+ tmp += prefix_len;
+ tmp = g_strchug (tmp);
+ } else {
+ break;
+ }
+ } while (tmp);
+
+ retval = g_strdup_printf ("%s %s", prefix, tmp);
+ g_free (subject_dup);
+
+ return retval;
}
gchar*
{
GSList *addresses, *cursor;
GHashTable *table;
- gchar *new_list;
+ gchar *new_list = NULL;
g_return_val_if_fail (address_list, NULL);
- table = g_hash_table_new (g_str_hash, g_str_equal);
+ table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
addresses = modest_text_utils_split_addresses_list (address_list);
- new_list = g_strdup("");
cursor = addresses;
while (cursor) {
const gchar* address = (const gchar*)cursor->data;
+ /* We need only the email to just compare it and not
+ the full address which would make "a <a@a.com>"
+ different from "a@a.com" */
+ const gchar *email = get_email_from_address (address);
+
/* ignore the address if already seen */
- if (g_hash_table_lookup (table, address) == 0) {
-
- gchar *tmp = g_strjoin (",", new_list, address, NULL);
- g_free (new_list);
+ if (g_hash_table_lookup (table, email) == 0) {
+ gchar *tmp;
+
+ /* Include the full address and not only the
+ email in the returned list */
+ if (!new_list) {
+ tmp = g_strdup (address);
+ } else {
+ tmp = g_strjoin (",", new_list, address, NULL);
+ g_free (new_list);
+ }
new_list = tmp;
- g_hash_table_insert (table, (gchar*)address, GINT_TO_POINTER(1));
+ g_hash_table_insert (table, (gchar*)email, GINT_TO_POINTER(1));
}
cursor = g_slist_next (cursor);
}
- g_hash_table_destroy (table);
+ g_hash_table_unref (table);
g_slist_foreach (addresses, (GFunc)g_free, NULL);
g_slist_free (addresses);
static void
modest_text_utils_convert_buffer_to_html_start (GString *html, const gchar *data, gssize n)
{
- guint i = 0;
+ guint i;
gboolean space_seen = FALSE;
guint break_dist = 0; /* distance since last break point */
n = strlen (data);
/* replace with special html chars where needed*/
- while (i != n) {
- char kar = data[i];
+ for (i = 0; i != n; ++i) {
+ guchar kar = data[i];
if (space_seen && kar != ' ') {
g_string_append_c (html, ' ');
/* we artificially insert a breakpoint (newline)
* after 256, to make sure our lines are not so long
* they will DOS the regexping later
+ * Also, check that kar is ASCII to make sure that we
+ * don't break a UTF8 char in two
*/
- if (++break_dist == 256) {
+ if (++break_dist >= 256 && kar < 127) {
g_string_append_c (html, '\n');
break_dist = 0;
}
space_seen = TRUE;
break;
default:
- /* Optimization to copy single ascii
- * characters faster */
- if (kar > 31 && kar < 127) {
- g_string_append_c (html, kar);
- } else {
- /* Important: copy full UTF-8 characters,
- * don't copy them byte by byte */
- gunichar c = g_utf8_get_char_validated (data+i, -1);
- if (c != (gunichar) -1 && c != (gunichar) -2) {
- const gchar *copyfrom = data + i;
- int len = g_utf8_next_char(copyfrom) - copyfrom;
- g_string_append_len (html, copyfrom, len);
- i += len - 1;
- } else {
- g_warning ("%s: non-UTF8 byte found, skipping", __FUNCTION__);
- }
- }
+ g_string_append_c (html, kar);
}
- i++;
}
}
g_string_append (html, "</body></html>");
if (len <= HYPERLINKIFY_MAX_LENGTH)
- hyperlinkify_plain_text (html);
+ hyperlinkify_plain_text (html, 0);
modest_text_utils_convert_buffer_to_html_finish (html);
modest_text_utils_convert_buffer_to_html_start (html, data, n);
if (hyperlinkify && (n < HYPERLINKIFY_MAX_LENGTH))
- hyperlinkify_plain_text (html);
+ hyperlinkify_plain_text (html, 0);
modest_text_utils_convert_buffer_to_html_finish (html);
const gchar *my_addrs = addresses;
const gchar *end;
gchar *addr;
+ gboolean after_at = FALSE;
g_return_val_if_fail (addresses, NULL);
/* nope, we are at the start of some address
* now, let's find the end of the address */
end = my_addrs + 1;
- while (end[0] && end[0] != ',' && end[0] != ';')
+ while (end[0] && end[0] != ';' && !(after_at && end[0] == ',')) {
+ if (end[0] == '\"') {
+ while (end[0] && end[0] != '\"')
+ ++end;
+ }
+ if (end[0] == '@') {
+ after_at = TRUE;
+ }
+ if ((end[0] && end[0] == '>')&&(end[1] && end[1] == ',')) {
+ ++end;
+ break;
+ }
++end;
+ }
/* we got the address; copy it and remove trailing whitespace */
addr = g_strndup (my_addrs, end - my_addrs);
*end = range_end;
}
+gchar *
+modest_text_utils_address_with_standard_length (const gchar *recipients_list)
+{
+ gchar ** splitted;
+ gchar ** current;
+ GString *buffer = g_string_new ("");
+
+ splitted = g_strsplit (recipients_list, "\n", 0);
+ current = splitted;
+ while (*current) {
+ gchar *line;
+ if (current != splitted)
+ buffer = g_string_append_c (buffer, '\n');
+ line = g_strndup (*splitted, 1000);
+ buffer = g_string_append (buffer, line);
+ g_free (line);
+ current++;
+ }
+
+ g_strfreev (splitted);
+
+ return g_string_free (buffer, FALSE);
+}
+
/* ******************************************************************* */
/* ************************* UTILIY FUNCTIONS ************************ */
}
static void
-unquote_line (GString * l)
+unquote_line (GString * l, const gchar *quote_symbol)
{
gchar *p;
+ gint quote_len;
p = l->str;
+ quote_len = strlen (quote_symbol);
while (p[0]) {
- if (p[0] == '>') {
- if (p[1] == ' ') {
- p++;
+ if (g_str_has_prefix (p, quote_symbol)) {
+ if (p[quote_len] == ' ') {
+ p += quote_len;
}
} else {
break;
}
static void
-append_quoted (GString * buf, int indent, const GString * str,
+append_quoted (GString * buf, const gchar *quote_symbol,
+ int indent, const GString * str,
const int cutpoint)
{
int i;
+ gchar *quote_concat;
indent = indent < 0 ? abs (indent) - 1 : indent;
+ quote_concat = g_strconcat (quote_symbol, " ", NULL);
for (i = 0; i <= indent; i++) {
- g_string_append (buf, "> ");
+ g_string_append (buf, quote_concat);
}
+ g_free (quote_concat);
if (cutpoint > 0) {
g_string_append_len (buf, str->str, cutpoint);
} else {
}
-static gchar *
-modest_text_utils_quote_plain_text (const gchar *text,
- const gchar *cite,
- const gchar *signature,
- GList *attachments,
- int limit)
+static GString *
+modest_text_utils_quote_body (GString *output, const gchar *text,
+ const gchar *quote_symbol,
+ int limit)
{
+
const gchar *iter;
- gint indent, breakpoint, rem_indent = 0;
- GString *q, *l, *remaining;
gsize len;
- gchar *attachments_string = NULL;
-
- /* remaining will store the rest of the line if we have to break it */
- q = g_string_new ("\n");
- q = g_string_append (q, cite);
- q = g_string_append_c (q, '\n');
- remaining = g_string_new ("");
+ gint indent, breakpoint, rem_indent = 0;
+ GString *l, *remaining;
iter = text;
len = strlen(text);
+ remaining = g_string_new ("");
do {
l = get_next_line (text, len, iter);
iter = iter + l->len + 1;
indent = get_indent_level (l->str);
- unquote_line (l);
+ unquote_line (l, quote_symbol);
if (remaining->len) {
if (l->len && indent == rem_indent) {
get_breakpoint (remaining->str,
rem_indent,
limit);
- append_quoted (q, rem_indent,
+ append_quoted (output, quote_symbol, rem_indent,
remaining, breakpoint);
g_string_erase (remaining, 0,
breakpoint);
g_string_erase (remaining, 0, 1);
}
rem_indent = indent;
- append_quoted (q, indent, l, breakpoint);
+ append_quoted (output, quote_symbol, indent, l, breakpoint);
g_string_free (l, TRUE);
} while ((iter < text + len) || (remaining->str[0]));
- attachments_string = quoted_attachments (attachments);
- q = g_string_append (q, attachments_string);
- g_free (attachments_string);
+ return output;
+}
+
+static gchar *
+modest_text_utils_quote_plain_text (const gchar *text,
+ const gchar *cite,
+ const gchar *signature,
+ GList *attachments,
+ int limit)
+{
+ GString *q;
+ gchar *attachments_string = NULL;
+
+ q = g_string_new ("");
if (signature != NULL) {
- q = g_string_append_c (q, '\n');
+ q = g_string_append (q, "\n--\n");
q = g_string_append (q, signature);
}
+ q = g_string_append (q, "\n");
+ q = g_string_append (q, cite);
+ q = g_string_append_c (q, '\n');
+
+ q = modest_text_utils_quote_body (q, text, ">", limit);
+
+ attachments_string = quoted_attachments (attachments);
+ q = g_string_append (q, attachments_string);
+ g_free (attachments_string);
+
return g_string_free (q, FALSE);
}
+static void
+quote_html_add_to_gstring (GString *string,
+ const gchar *text)
+{
+ if (text && strcmp (text, "")) {
+ gchar *html_text = modest_text_utils_convert_to_html_body (text, -1, TRUE);
+ g_string_append_printf (string, "%s<br/>", html_text);
+ g_free (html_text);
+ }
+}
+
static gchar*
modest_text_utils_quote_html (const gchar *text,
const gchar *cite,
GList *attachments,
int limit)
{
- gchar *result = NULL;
- gchar *signature_result = NULL;
- const gchar *format = \
- "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" \
- "<html>\n" \
- "<body>\n" \
- "<br/>%s<br/>" \
- "<pre>%s<br/>%s<br/>%s</pre>\n" \
- "</body>\n" \
- "</html>\n";
- gchar *attachments_string = NULL;
- gchar *q_attachments_string = NULL;
- gchar *q_cite = NULL;
- gchar *html_text = NULL;
-
- if (signature == NULL)
- signature_result = g_strdup ("");
- else
- signature_result = modest_text_utils_convert_to_html_body (signature, -1, TRUE);
+ GString *result_string;
+
+ result_string =
+ g_string_new ( \
+ "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n" \
+ "<html>\n" \
+ "<body>\n<br/>\n");
+
+ if (text || cite || signature) {
+ GString *quoted_text;
+ g_string_append (result_string, "<pre>\n");
+ if (signature) {
+ quote_html_add_to_gstring (result_string, SIGNATURE_MARKER);
+ quote_html_add_to_gstring (result_string, signature);
+ }
+ quote_html_add_to_gstring (result_string, cite);
+ quoted_text = g_string_new ("");
+ quoted_text = modest_text_utils_quote_body (quoted_text, (text) ? text : "", ">", limit);
+ quote_html_add_to_gstring (result_string, quoted_text->str);
+ g_string_free (quoted_text, TRUE);
+ if (attachments) {
+ gchar *attachments_string = quoted_attachments (attachments);
+ quote_html_add_to_gstring (result_string, attachments_string);
+ g_free (attachments_string);
+ }
+ g_string_append (result_string, "</pre>");
+ }
+ g_string_append (result_string, "</body>");
+ g_string_append (result_string, "</html>");
- attachments_string = quoted_attachments (attachments);
- q_attachments_string = modest_text_utils_convert_to_html_body (attachments_string, -1, TRUE);
- q_cite = modest_text_utils_convert_to_html_body (cite, -1, TRUE);
- html_text = modest_text_utils_convert_to_html_body (text, -1, TRUE);
- result = g_strdup_printf (format, signature_result, q_cite, html_text, q_attachments_string);
- g_free (q_cite);
- g_free (html_text);
- g_free (attachments_string);
- g_free (q_attachments_string);
- g_free (signature_result);
-
- return result;
+ return g_string_free (result_string, FALSE);
}
static gint
return match2->offset - match1->offset;
}
-static gboolean url_matches_block = 0;
+static gint url_matches_block = 0;
static url_match_pattern_t patterns[] = MAIL_VIEWER_URL_MATCH_PATTERNS;
static GSList*
-get_url_matches (GString *txt)
+get_url_matches (GString *txt, gint offset)
{
regmatch_t rm;
- guint rv, i, offset = 0;
+ guint rv, i, tmp_offset = 0;
GSList *match_list = NULL;
const size_t pattern_num = sizeof(patterns)/sizeof(url_match_pattern_t);
/* find all the matches */
for (i = 0; i != pattern_num; ++i) {
- offset = 0;
+ tmp_offset = offset;
while (1) {
url_match_t *match;
gboolean is_submatch;
GSList *cursor;
- if ((rv = regexec (patterns[i].preg, txt->str + offset, 1, &rm, 0)) != 0) {
+ if ((rv = regexec (patterns[i].preg, txt->str + tmp_offset, 1, &rm, 0)) != 0) {
g_return_val_if_fail (rv == REG_NOMATCH, NULL); /* this should not happen */
break; /* try next regexp */
}
while (cursor && !is_submatch) {
const url_match_t *old_match =
(const url_match_t *) cursor->data;
- guint new_offset = offset + rm.rm_so;
+ guint new_offset = tmp_offset + rm.rm_so;
is_submatch = (new_offset > old_match->offset &&
new_offset < old_match->offset + old_match->len);
cursor = g_slist_next (cursor);
if (!is_submatch) {
/* make a list of our matches (<offset, len, prefix> tupels)*/
match = g_slice_new (url_match_t);
- match->offset = offset + rm.rm_so;
+ match->offset = tmp_offset + rm.rm_so;
match->len = rm.rm_eo - rm.rm_so;
match->prefix = patterns[i].prefix;
match_list = g_slist_prepend (match_list, match);
}
- offset += rm.rm_eo;
+ tmp_offset += rm.rm_eo;
}
}
}
static void
-hyperlinkify_plain_text (GString *txt)
+hyperlinkify_plain_text (GString *txt, gint offset)
{
GSList *cursor;
- GSList *match_list = get_url_matches (txt);
+ GSList *match_list = get_url_matches (txt, offset);
/* we will work backwards, so the offsets stay valid */
for (cursor = match_list; cursor; cursor = cursor->next) {
g_slist_free (match_list);
}
+void
+modest_text_utils_hyperlinkify (GString *string_buffer)
+{
+ gchar *after_body;
+ gint offset = 0;
+
+ after_body = strstr (string_buffer->str, "<body>");
+ if (after_body != NULL)
+ offset = after_body - string_buffer->str;
+ hyperlinkify_plain_text (string_buffer, offset);
+}
+
/* for optimization reasons, we change the string in-place */
void
for (i = 0; address[i]; ++i) {
if (address[i] == '<') {
- if (G_UNLIKELY(i == 0))
- return; /* there's nothing else, leave it */
- else {
+ if (G_UNLIKELY(i == 0)) {
+ break; /* there's nothing else, leave it */
+ }else {
address[i] = '\0'; /* terminate the string here */
- return;
+ break;
}
}
}
+
+ g_strchomp (address);
}
int c = prefix_len + 1;
while (sub[c] && sub[c] != ']')
++c;
- if (sub[c])
+ if (!sub[c])
return 0; /* no end to the ']' found */
else
prefix_len = c + 1;
if (!insensitive) {
/* optimization: shortcut if first char is ascii */
- if (((s1[0] & 0xf0)== 0) && ((s2[0] & 0xf0) == 0))
+ if (((s1[0] & 0x80)== 0) && ((s2[0] & 0x80) == 0) &&
+ (s1[0] != s2[0]))
return s1[0] - s2[0];
return g_utf8_collate (s1, s2);
gint result;
gchar *n1, *n2;
- /* optimization: short cut iif first char is ascii */
- if (((s1[0] & 0xf0) == 0) && ((s2[0] & 0xf0) == 0))
+ /* optimization: shortcut if first char is ascii */
+ if (((s1[0] & 0x80) == 0) && ((s2[0] & 0x80) == 0) &&
+ (tolower(s1[0]) != tolower (s2[0])))
return tolower(s1[0]) - tolower(s2[0]);
n1 = g_utf8_strdown (s1, -1);
/* if it's today, show the time, if it's not today, show the date instead */
+ /* TODO: take into account the system config for 24/12h */
if (day == date_day) /* is the date today? */
- modest_text_utils_strftime (date_buf, DATE_BUF_SIZE, "%X", date);
+ modest_text_utils_strftime (date_buf, DATE_BUF_SIZE, _HL("wdgt_va_24h_time"), date);
else
- modest_text_utils_strftime (date_buf, DATE_BUF_SIZE, "%x", date);
+ modest_text_utils_strftime (date_buf, DATE_BUF_SIZE, _HL("wdgt_va_date"), date);
return date_buf; /* this is a static buffer, don't free! */
}
gint i;
const gchar **cursor = NULL;
const gchar *forbidden_names[] = { /* windows does not like these */
- "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6",
- "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
- ".", "..", NULL
+ "CON", "PRN", "AUX", "NUL", ".", "..", "cur", "tmp", "new",
+ NULL /* cur, tmp, new are reserved for Maildir */
};
/* cannot be NULL */
if (len == 0)
return FALSE;
+ /* cannot start with a dot, vfat does not seem to like that */
+ if (folder_name[0] == '.')
+ return FALSE;
+
/* cannot start or end with a space */
if (g_ascii_isspace(folder_name[0]) || g_ascii_isspace(folder_name[len - 1]))
return FALSE;
for (i = 0; i < len; i++)
if (modest_text_utils_is_forbidden_char (folder_name[i], FOLDER_NAME_FORBIDDEN_CHARS))
return FALSE;
+
+ /* Cannot contain Windows port numbers. I'd like to use GRegex
+ but it's still not available in Maemo. sergio */
+ if (!g_ascii_strncasecmp (folder_name, "LPT", 3) ||
+ !g_ascii_strncasecmp (folder_name, "COM", 3)) {
+ glong val;
+ gchar *endptr;
+
+ /* We skip the first 3 characters for the
+ comparison */
+ val = strtol(folder_name+3, &endptr, 10);
+
+ /* If the conversion to long succeeded then the string
+ is not valid for us */
+ if (*endptr == '\0')
+ return FALSE;
+ else
+ return TRUE;
+ }
/* cannot contain a forbidden word */
if (len <= 4) {
const guint GB=1024 * MB;
if (size == 0)
- return g_strdup_printf(_FM("sfil_li_size_kb"), 0);
- if (0 < size && size < KB)
- return g_strdup_printf (_FM("sfil_li_size_kb"), 1);
+ return g_strdup_printf (_FM("sfil_li_size_kb"), (int) 0);
+ if (0 <= size && size < KB)
+ return g_strdup_printf (_FM("sfil_li_size_1kb_99kb"), (int) 1);
else if (KB <= size && size < 100 * KB)
- return g_strdup_printf (_FM("sfil_li_size_1kb_99kb"), size / KB);
+ return g_strdup_printf (_FM("sfil_li_size_1kb_99kb"), (int) size / KB);
else if (100*KB <= size && size < MB)
return g_strdup_printf (_FM("sfil_li_size_100kb_1mb"), (float) size / MB);
else if (MB <= size && size < 10*MB)
return g_strdup_printf (_FM("sfil_li_size_1mb_10mb"), (float) size / MB);
else if (10*MB <= size && size < GB)
- return g_strdup_printf (_FM("sfil_li_size_10mb_1gb"), size / MB);
+ return g_strdup_printf (_FM("sfil_li_size_10mb_1gb"), (int) size / MB);
else
- return g_strdup_printf (_FM("sfil_li_size_1gb_or_greater"), (float) size / GB);
+ return g_strdup_printf (_FM("sfil_li_size_1gb_or_greater"), (float) size / GB);
}
static gchar *
return g_strndup (left_limit + 1, (right_limit - left_limit) - 1);
}
-gchar *
+gchar *
modest_text_utils_get_color_string (GdkColor *color)
{
g_return_val_if_fail (color, NULL);
-
+
return g_strdup_printf ("#%x%x%x%x%x%x%x%x%x%x%x%x",
(color->red >> 12) & 0xf, (color->red >> 8) & 0xf,
(color->red >> 4) & 0xf, (color->red) & 0xf,
return result;
}
+
+gchar *
+modest_text_utils_escape_mnemonics (const gchar *text)
+{
+ const gchar *p;
+ GString *result = NULL;
+
+ if (text == NULL)
+ return NULL;
+
+ result = g_string_new ("");
+ for (p = text; *p != '\0'; p++) {
+ if (*p == '_')
+ result = g_string_append (result, "__");
+ else
+ result = g_string_append_c (result, *p);
+ }
+
+ return g_string_free (result, FALSE);
+}