2006-09-21 [paul] 2.4.0cvs206
[claws.git] / src / common / utils.c
index 33e160f8acc774f79866848e892a034fa1fda58f..ebd4020ff08f703c962e8379c9a8b4984d5d6cb3 100644 (file)
@@ -334,20 +334,44 @@ gchar *itos(gint n)
        return itos_buf(nstr, n);
 }
 
+#define divide(num,divisor,i,d)                \
+{                                      \
+       register int tmp;               \
+       i = num/divisor;                \
+       tmp = i*divisor;                \
+       d = num-tmp;                    \
+       if (d > 1000) d /= 1000;        \
+       else if (d > 100) d /= 100;     \
+       else if (d > 10) d /= 10;               \
+}
+
 gchar *to_human_readable(off_t size)
 {
        static gchar str[14];
-
-       if (size < 1024)
-               g_snprintf(str, sizeof(str), _("%dB"), (gint)size);
-       else if (size >> 10 < 1024)
-               g_snprintf(str, sizeof(str), _("%.1fKB"), (gfloat)size / (1 << 10));
-       else if (size >> 20 < 1024)
-               g_snprintf(str, sizeof(str), _("%.2fMB"), (gfloat)size / (1 << 20));
-       else
-               g_snprintf(str, sizeof(str), _("%.2fGB"), (gfloat)size / (1 << 30));
-
-       return str;
+       static gchar *b_format = NULL, *kb_format = NULL, 
+                    *mb_format = NULL, *gb_format = NULL;
+       register int t = 0, r = 0;
+       if (b_format == NULL) {
+               b_format  = _("%dB");
+               kb_format = _("%d.%dKB");
+               mb_format = _("%.2fMB");
+               gb_format = _("%.2fGB");
+       }
+       
+       if (size < 1024) {
+               g_snprintf(str, sizeof(str), b_format, (gint)size);
+               return str;
+       } else if (size >> 10 < 1024) {
+               divide(size, (1 << 10), t, r);
+               g_snprintf(str, sizeof(str), kb_format, t, r);
+               return str;
+       } else if (size >> 20 < 1024) {
+               g_snprintf(str, sizeof(str), mb_format, (gfloat)size / (1 << 20));
+               return str;
+       } else {
+               g_snprintf(str, sizeof(str), gb_format, (gfloat)size / (1 << 30));
+               return str;
+       }
 }
 
 /* strcmp with NULL-checking */
@@ -535,210 +559,6 @@ gchar *strncpy2(gchar *dest, const gchar *src, size_t n)
        return dest;
 }
 
-#if !HAVE_ISWALNUM
-int iswalnum(wint_t wc)
-{
-       return g_ascii_isalnum((int)wc);
-}
-#endif
-
-#if !HAVE_ISWSPACE
-int iswspace(wint_t wc)
-{
-       return g_ascii_isspace((int)wc);
-}
-#endif
-
-#if !HAVE_TOWLOWER
-wint_t towlower(wint_t wc)
-{
-       if (wc >= L'A' && wc <= L'Z')
-               return wc + L'a' - L'A';
-
-       return wc;
-}
-#endif
-
-#if !HAVE_WCSLEN
-size_t wcslen(const wchar_t *s)
-{
-       size_t len = 0;
-
-       while (*s != L'\0')
-               ++len, ++s;
-
-       return len;
-}
-#endif
-
-#if !HAVE_WCSCPY
-/* Copy SRC to DEST.  */
-wchar_t *wcscpy(wchar_t *dest, const wchar_t *src)
-{
-       wint_t c;
-       wchar_t *s = dest;
-
-       do {
-               c = *src++;
-               *dest++ = c;
-       } while (c != L'\0');
-
-       return s;
-}
-#endif
-
-#if !HAVE_WCSNCPY
-/* Copy no more than N wide-characters of SRC to DEST.  */
-wchar_t *wcsncpy (wchar_t *dest, const wchar_t *src, size_t n)
-{
-       wint_t c;
-       wchar_t *s = dest;
-
-       do {
-               c = *src++;
-               *dest++ = c;
-               if (--n == 0)
-                       return s;
-       } while (c != L'\0');
-
-       /* zero fill */
-       do
-               *dest++ = L'\0';
-       while (--n > 0);
-
-       return s;
-}
-#endif
-
-/* Duplicate S, returning an identical malloc'd string. */
-wchar_t *wcsdup(const wchar_t *s)
-{
-       wchar_t *new_str;
-
-       if (s) {
-               new_str = g_new(wchar_t, wcslen(s) + 1);
-               wcscpy(new_str, s);
-       } else
-               new_str = NULL;
-
-       return new_str;
-}
-
-/* Duplicate no more than N wide-characters of S,
-   returning an identical malloc'd string. */
-wchar_t *wcsndup(const wchar_t *s, size_t n)
-{
-       wchar_t *new_str;
-
-       if (s) {
-               new_str = g_new(wchar_t, n + 1);
-               wcsncpy(new_str, s, n);
-               new_str[n] = (wchar_t)0;
-       } else
-               new_str = NULL;
-
-       return new_str;
-}
-
-wchar_t *strdup_mbstowcs(const gchar *s)
-{
-       wchar_t *new_str;
-
-       if (s) {
-               new_str = g_new(wchar_t, strlen(s) + 1);
-               if (mbstowcs(new_str, s, strlen(s) + 1) < 0) {
-                       g_free(new_str);
-                       new_str = NULL;
-               } else
-                       new_str = g_realloc(new_str,
-                                           sizeof(wchar_t) * (wcslen(new_str) + 1));
-       } else
-               new_str = NULL;
-
-       return new_str;
-}
-
-gchar *strdup_wcstombs(const wchar_t *s)
-{
-       gchar *new_str;
-       size_t len;
-
-       if (s) {
-               len = wcslen(s) * MB_CUR_MAX + 1;
-               new_str = g_new(gchar, len);
-               if (wcstombs(new_str, s, len) < 0) {
-                       g_free(new_str);
-                       new_str = NULL;
-               } else
-                       new_str = g_realloc(new_str, strlen(new_str) + 1);
-       } else
-               new_str = NULL;
-
-       return new_str;
-}
-
-/* Compare S1 and S2, ignoring case.  */
-gint wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n)
-{
-       wint_t c1;
-       wint_t c2;
-
-       while (n--) {
-               c1 = towlower(*s1++);
-               c2 = towlower(*s2++);
-               if (c1 != c2)
-                       return c1 - c2;
-               else if (c1 == 0 && c2 == 0)
-                       break;
-       }
-
-       return 0;
-}
-
-/* Find the first occurrence of NEEDLE in HAYSTACK, ignoring case.  */
-wchar_t *wcscasestr(const wchar_t *haystack, const wchar_t *needle)
-{
-       register size_t haystack_len, needle_len;
-
-       haystack_len = wcslen(haystack);
-       needle_len   = wcslen(needle);
-
-       if (haystack_len < needle_len || needle_len == 0)
-               return NULL;
-
-       while (haystack_len >= needle_len) {
-               if (!wcsncasecmp(haystack, needle, needle_len))
-                       return (wchar_t *)haystack;
-               else {
-                       haystack++;
-                       haystack_len--;
-               }
-       }
-
-       return NULL;
-}
-
-gint get_mbs_len(const gchar *s)
-{
-       const gchar *p = s;
-       gint mb_len;
-       gint len = 0;
-
-       if (!p)
-               return -1;
-
-       while (*p != '\0') {
-               mb_len = g_utf8_skip[*(guchar *)p];
-               if (mb_len == 0)
-                       break;
-               else
-                       len++;
-
-               p += mb_len;
-       }
-
-       return len;
-}
 
 /* Examine if next block is non-ASCII string */
 gboolean is_next_nonascii(const gchar *s)
@@ -3271,6 +3091,7 @@ FILE *my_tmpfile(void)
        gchar *fname;
        gint fd;
        FILE *fp;
+       gchar buf[2]="\0";
 
        tmpdir = get_tmp_dir();
        tmplen = strlen(tmpdir);
@@ -3292,13 +3113,23 @@ FILE *my_tmpfile(void)
 
 #ifndef G_OS_WIN32
        g_unlink(fname);
+       
+       /* verify that we can write in the file after unlinking */
+       if (write(fd, buf, 1) < 0) {
+               close(fd);
+               return tmpfile();
+       }
+       
 #endif
 
        fp = fdopen(fd, "w+b");
        if (!fp)
                close(fd);
-       else
+       else {
+               rewind(fp);
                return fp;
+       }
+
 #endif /* HAVE_MKSTEMP || G_OS_WIN32 */
 
        return tmpfile();
@@ -3845,7 +3676,8 @@ int subject_get_prefix_length(const gchar *subject)
                "VS\\:",                        /* "VS" (Norwegian) */
                "Vs\\:",                        /* "Vs" (Norwegian) */
                "AD\\:",                        /* "AD" (Norwegian) */
-               "Ad\\:"                         /* "Ad" (Norwegian) */
+               "Ad\\:",                        /* "Ad" (Norwegian) */
+               "\347\255\224\345\244\215\\:"   /* "Re" (Chinese, UTF-8) */
                /* add more */
        };
        const int PREFIXES = sizeof prefixes / sizeof prefixes[0];
@@ -4314,7 +4146,7 @@ gboolean get_uri_part(const gchar *start, const gchar *scanpos,
        for (ep_ = scanpos; *ep_ != '\0'; ep_++) {
                if (!g_ascii_isgraph(*(const guchar *)ep_) ||
                    !IS_ASCII(*(const guchar *)ep_) ||
-                   strchr("[]{}<>\"'", *ep_)) {
+                   strchr("[]{}<>\"", *ep_)) {
                        break;
                } else if (strchr("(", *ep_)) {
                        parenthese_cnt++;
@@ -4688,7 +4520,7 @@ gchar *make_http_string(const gchar *bp, const gchar *ep)
        return result;
 }
 
-static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type)
+static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type, const gchar *file_to_open)
 {
        FILE *fp = fopen(path, "rb");
        gchar buf[BUFFSIZE];
@@ -4696,7 +4528,7 @@ static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type)
        if (!fp)
                return NULL;
        while (fgets(buf, sizeof (buf), fp) != NULL) {
-               gchar **parts = g_strsplit(buf, ";", -1);
+               gchar **parts = g_strsplit(buf, ";", 3);
                gchar *trimmed = parts[0];
                while (trimmed[0] == ' ')
                        trimmed++;
@@ -4704,19 +4536,63 @@ static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type)
                        trimmed[strlen(trimmed)-1] = '\0';
 
                if (!strcmp(trimmed, type)) {
+                       gboolean needsterminal = FALSE;
+                       if (parts[2] && strstr(parts[2], "needsterminal")) {
+                               needsterminal = TRUE;
+                       }
+                       if (parts[2] && strstr(parts[2], "test=")) {
+                               gchar *orig_testcmd = g_strdup(strstr(parts[2], "test=")+5);
+                               gchar *testcmd = orig_testcmd;
+                               if (strstr(testcmd,";"))
+                                       *(strstr(testcmd,";")) = '\0';
+                               while (testcmd[0] == ' ')
+                                       testcmd++;
+                               while (testcmd[strlen(testcmd)-1] == '\n')
+                                       testcmd[strlen(testcmd)-1] = '\0';
+                               while (testcmd[strlen(testcmd)-1] == '\r')
+                                       testcmd[strlen(testcmd)-1] = '\0';
+                               while (testcmd[strlen(testcmd)-1] == ' ')
+                                       testcmd[strlen(testcmd)-1] = '\0';
+                                       
+                               if (strstr(testcmd, "%s")) {
+                                       gchar *tmp = g_strdup_printf(testcmd, file_to_open);
+                                       gint res = system(tmp);
+                                       g_free(tmp);
+                                       g_free(orig_testcmd);
+                                       
+                                       if (res != 0) {
+                                               g_strfreev(parts);
+                                               continue;
+                                       }
+                               } else {
+                                       gint res = system(testcmd);
+                                       g_free(orig_testcmd);
+                                       
+                                       if (res != 0) {
+                                               g_strfreev(parts);
+                                               continue;
+                                       }
+                               }
+                       }
+                       
                        trimmed = parts[1];
                        while (trimmed[0] == ' ')
                                trimmed++;
-                       while (trimmed[strlen(trimmed)-1] == ' ')
-                               trimmed[strlen(trimmed)-1] = '\0';
                        while (trimmed[strlen(trimmed)-1] == '\n')
                                trimmed[strlen(trimmed)-1] = '\0';
                        while (trimmed[strlen(trimmed)-1] == '\r')
                                trimmed[strlen(trimmed)-1] = '\0';
+                       while (trimmed[strlen(trimmed)-1] == ' ')
+                               trimmed[strlen(trimmed)-1] = '\0';
                        result = g_strdup(trimmed);
                        g_strfreev(parts);
                        fclose(fp);
-                       if (strstr(result, "%s") && !strstr(result, "'%s'")) {
+                       /* if there are no single quotes around %s, add them.
+                        * '.*%s.*' is ok, as in display 'png:%s'
+                        */
+                       if (strstr(result, "%s") 
+                       && !(strstr(result, "'") < strstr(result,"%s") &&
+                            strstr(strstr(result,"%s"), "'"))) {
                                gchar *start = g_strdup(result);
                                gchar *end = g_strdup(strstr(result, "%s")+2);
                                gchar *tmp;
@@ -4727,6 +4603,11 @@ static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type)
                                g_free(result);
                                result = tmp;
                        }
+                       if (needsterminal) {
+                               gchar *tmp = g_strdup_printf("xterm -e %s", result);
+                               g_free(result);
+                               result = tmp;
+                       }
                        return result;
                }
                g_strfreev(parts);
@@ -4734,21 +4615,64 @@ static gchar *mailcap_get_command_in_file(const gchar *path, const gchar *type)
        fclose(fp);
        return NULL;
 }
-gchar *mailcap_get_command_for_type(const gchar *type)
+gchar *mailcap_get_command_for_type(const gchar *type, const gchar *file_to_open)
 {
        gchar *result = NULL;
        gchar *path = NULL;
        if (type == NULL)
                return NULL;
        path = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".mailcap", NULL);
-       result = mailcap_get_command_in_file(path, type);
+       result = mailcap_get_command_in_file(path, type, file_to_open);
        g_free(path);
        if (result)
                return result;
-       result = mailcap_get_command_in_file("/etc/mailcap", type);
+       result = mailcap_get_command_in_file("/etc/mailcap", type, file_to_open);
        return result;
 }
 
+void mailcap_update_default(const gchar *type, const gchar *command)
+{
+       gchar *path = NULL, *outpath = NULL;
+       path = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".mailcap", NULL);
+       outpath = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".mailcap.new", NULL);
+       FILE *fp = fopen(path, "rb");
+       FILE *outfp = fopen(outpath, "wb");
+       gchar buf[BUFFSIZE];
+
+       if (!fp) {
+               g_free(path);
+               g_free(outpath);
+               return;
+       }
+       if (!outfp) {
+               g_free(path);
+               g_free(outpath);
+               fclose(fp);
+               return;
+       }
+       while (fgets(buf, sizeof (buf), fp) != NULL) {
+               gchar **parts = g_strsplit(buf, ";", 3);
+               gchar *trimmed = parts[0];
+               while (trimmed[0] == ' ')
+                       trimmed++;
+               while (trimmed[strlen(trimmed)-1] == ' ')
+                       trimmed[strlen(trimmed)-1] = '\0';
+
+               if (!strcmp(trimmed, type)) {
+                       g_strfreev(parts);
+                       continue;
+               }
+               else {
+                       fputs(buf, outfp);
+               }
+               g_strfreev(parts);
+       }
+       fprintf(outfp, "%s; %s\n", type, command);
+       fclose(fp);
+       fclose(outfp);
+       g_rename(outpath, path);
+}
+
 gint copy_dir(const gchar *src, const gchar *dst)
 {
        GDir *dir;
@@ -4804,3 +4728,25 @@ gboolean file_is_email (const gchar *filename)
        fclose(fp);
        return (score >= 3);
 }
+
+gboolean sc_g_list_bigger(GList *list, gint max)
+{
+       GList *cur = list;
+       int i = 0;
+       while (cur && i <= max+1) {
+               i++;
+               cur = cur->next;
+       }
+       return (i > max);
+}
+
+gboolean sc_g_slist_bigger(GSList *list, gint max)
+{
+       GSList *cur = list;
+       int i = 0;
+       while (cur && i <= max+1) {
+               i++;
+               cur = cur->next;
+       }
+       return (i > max);
+}