sycn with 0.8.8cvs11
[claws.git] / src / common / utils.c
index 3b861e422a99e3b957c53ef436b5ea25eac60802..ab112f240f8049d5401a8b9eba92b8582d9bc808 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2002 Hiroyuki Yamamoto
+ * Copyright (C) 1999-2003 Hiroyuki Yamamoto
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -470,52 +470,29 @@ wchar_t *wcscasestr(const wchar_t *haystack, const wchar_t *needle)
 }
 
 /* Examine if next block is non-ASCII string */
-gboolean is_next_nonascii(const wchar_t *s)
+gboolean is_next_nonascii(const guchar *s)
 {
-       const wchar_t *wp;
+       const guchar *p;
 
        /* skip head space */
-       for (wp = s; *wp != (wchar_t)0 && iswspace(*wp); wp++)
+       for (p = s; *p != '\0' && isspace(*p); p++)
                ;
-       for (; *wp != (wchar_t)0 && !iswspace(*wp); wp++) {
-               if (*wp > 127)
+       for (; *p != '\0' && !isspace(*p); p++) {
+               if (*p > 127 || *p < 32)
                        return TRUE;
        }
 
        return FALSE;
 }
 
-/* Examine if next block is multi-byte string */
-gboolean is_next_mbs(const wchar_t *s)
+gint get_next_word_len(const gchar *s)
 {
-       gint mbl;
-       const wchar_t *wp;
-       gchar tmp[MB_LEN_MAX];
+       gint len = 0;
 
-       /* skip head space */
-       for (wp = s; *wp != (wchar_t)0 && iswspace(*wp); wp++)
+       for (; *s != '\0' && !isspace(*s); s++, len++)
                ;
-       for (; *wp != (wchar_t)0 && !iswspace(*wp); wp++) {
-               mbl = wctomb(tmp, *wp);
-               if (mbl > 1)
-                       return TRUE;
-       }
-
-       return FALSE;
-}
-
-wchar_t *find_wspace(const wchar_t *s)
-{
-       const wchar_t *wp;
 
-       for (wp = s; *wp != (wchar_t)0 && iswspace(*wp); wp++)
-               ;
-       for (; *wp != (wchar_t)0; wp++) {
-               if (iswspace(*wp))
-                       return (wchar_t *)wp;
-       }
-
-       return NULL;
+       return len;
 }
 
 /* compare subjects */
@@ -1270,22 +1247,21 @@ gchar *get_abbrev_newsgroup_name(const gchar *group, gint len)
        gchar *abbrev_group;
        gchar *ap;
        const gchar *p = group;
-       gint  count = 0;
+       const gchar *last;
 
+       last = group + strlen(group);
        abbrev_group = ap = g_malloc(strlen(group) + 1);
 
        while (*p) {
                while (*p == '.')
                        *ap++ = *p++;
-
-               if ((strlen( p) + count) > len && strchr(p, '.')) {
+               if ((ap - abbrev_group) + (last - p) > len && strchr(p, '.')) {
                        *ap++ = *p++;
                        while (*p != '.') p++;
                } else {
-                       strcpy( ap, p);
+                       strcpy(ap, p);
                        return abbrev_group;
                }
-               count = count + 2;
        }
 
        *ap = '\0';
@@ -2086,7 +2062,7 @@ gint copy_file(const gchar *src, const gchar *dest)
                while (len > 0) {
                        n_write = write(dest_fd, bufp, len);
                        if (n_write <= 0) {
-                               g_warning(_("writing to %s failed.\n"), dest);
+                               g_warning("writing to %s failed.\n", dest);
                                close(dest_fd);
                                close(src_fd);
                                unlink(dest);
@@ -2106,7 +2082,7 @@ gint copy_file(const gchar *src, const gchar *dest)
        close(dest_fd);
 
        if (n_read < 0 || get_file_size(src) != get_file_size(dest)) {
-               g_warning(_("File copy from %s to %s failed.\n"), src, dest);
+               g_warning("File copy from %s to %s failed.\n", src, dest);
                unlink(dest);
                if (dest_bak) {
                        if (rename(dest_bak, dest) < 0)
@@ -2147,14 +2123,14 @@ gint append_file(const gchar *src, const gchar *dest, gboolean keep_backup)
 
        if (change_file_mode_rw(dest_fp, dest) < 0) {
                FILE_OP_ERROR(dest, "chmod");
-               g_warning(_("can't change file mode\n"));
+               g_warning("can't change file mode\n");
        }
 
        while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), src_fp)) > 0) {
                if (n_read < sizeof(buf) && ferror(src_fp))
                        break;
                if (fwrite(buf, n_read, 1, dest_fp) < 1) {
-                       g_warning(_("writing to %s failed.\n"), dest);
+                       g_warning("writing to %s failed.\n", dest);
                        fclose(dest_fp);
                        fclose(src_fp);
                        unlink(dest);
@@ -2215,14 +2191,14 @@ gint copy_file(const gchar *src, const gchar *dest, gboolean keep_backup)
 
        if (change_file_mode_rw(dest_fp, dest) < 0) {
                FILE_OP_ERROR(dest, "chmod");
-               g_warning(_("can't change file mode\n"));
+               g_warning("can't change file mode\n");
        }
 
        while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), src_fp)) > 0) {
                if (n_read < sizeof(buf) && ferror(src_fp))
                        break;
                if (fwrite(buf, n_read, 1, dest_fp) < 1) {
-                       g_warning(_("writing to %s failed.\n"), dest);
+                       g_warning("writing to %s failed.\n", dest);
                        fclose(dest_fp);
                        fclose(src_fp);
                        unlink(dest);
@@ -2314,7 +2290,7 @@ gint copy_file_part(FILE *fp, off_t offset, size_t length, const gchar *dest)
                if (n_read < to_read && ferror(fp))
                        break;
                if (fwrite(buf, n_read, 1, dest_fp) < 1) {
-                       g_warning(_("writing to %s failed.\n"), dest);
+                       g_warning("writing to %s failed.\n", dest);
                        fclose(dest_fp);
                        unlink(dest);
                        return -1;
@@ -2345,6 +2321,39 @@ gint copy_file_part(FILE *fp, off_t offset, size_t length, const gchar *dest)
 /* convert line endings into CRLF. If the last line doesn't end with
  * linebreak, add it.
  */
+gchar *canonicalize_str(const gchar *str)
+{
+       const gchar *p;
+       guint new_len = 0;
+       gchar *out, *outp;
+
+       for (p = str; *p != '\0'; ++p) {
+               if (*p != '\r') {
+                       ++new_len;
+                       if (*p == '\n')
+                               ++new_len;
+               }
+       }
+       if (p == str || *(p - 1) != '\n')
+               new_len += 2;
+
+       out = outp = g_malloc(new_len + 1);
+       for (p = str; *p != '\0'; ++p) {
+               if (*p != '\r') {
+                       if (*p == '\n')
+                               *outp++ = '\r';
+                       *outp++ = *p;
+               }
+       }
+       if (p == str || *(p - 1) != '\n') {
+               *outp++ = '\r';
+               *outp++ = '\n';
+       }
+       *outp = '\0';
+
+       return out;
+}
+
 gint canonicalize_file(const gchar *src, const gchar *dest)
 {
        FILE *src_fp, *dest_fp;
@@ -2406,7 +2415,7 @@ gint canonicalize_file(const gchar *src, const gchar *dest)
        }
 
        if (ferror(src_fp)) {
-               FILE_OP_ERROR(src, "fread");
+               FILE_OP_ERROR(src, "fgets");
                err = TRUE;
        }
        fclose(src_fp);
@@ -2445,6 +2454,79 @@ gint canonicalize_file_replace(const gchar *file)
        return 0;
 }
 
+gint uncanonicalize_file(const gchar *src, const gchar *dest)
+{
+       FILE *src_fp, *dest_fp;
+       gchar buf[BUFFSIZE];
+       gboolean err = FALSE;
+
+       if ((src_fp = fopen(src, "rb")) == NULL) {
+               FILE_OP_ERROR(src, "fopen");
+               return -1;
+       }
+
+       if ((dest_fp = fopen(dest, "wb")) == NULL) {
+               FILE_OP_ERROR(dest, "fopen");
+               fclose(src_fp);
+               return -1;
+       }
+
+       if (change_file_mode_rw(dest_fp, dest) < 0) {
+               FILE_OP_ERROR(dest, "chmod");
+               g_warning("can't change file mode\n");
+       }
+
+       while (fgets(buf, sizeof(buf), src_fp) != NULL) {
+               strcrchomp(buf);
+               if (fputs(buf, dest_fp) == EOF) {
+                       g_warning("writing to %s failed.\n", dest);
+                       fclose(dest_fp);
+                       fclose(src_fp);
+                       unlink(dest);
+                       return -1;
+               }
+       }
+
+       if (ferror(src_fp)) {
+               FILE_OP_ERROR(src, "fgets");
+               err = TRUE;
+       }
+       fclose(src_fp);
+       if (fclose(dest_fp) == EOF) {
+               FILE_OP_ERROR(dest, "fclose");
+               err = TRUE;
+       }
+
+       if (err) {
+               unlink(dest);
+               return -1;
+       }
+
+       return 0;
+}
+
+gint uncanonicalize_file_replace(const gchar *file)
+{
+       gchar *tmp_file;
+
+       tmp_file = get_tmp_file();
+
+       if (uncanonicalize_file(file, tmp_file) < 0) {
+               g_free(tmp_file);
+               return -1;
+       }
+
+       if (move_file(tmp_file, file, TRUE) < 0) {
+               g_warning("can't replace %s .\n", file);
+               unlink(tmp_file);
+               g_free(tmp_file);
+               return -1;
+       }
+
+       g_free(tmp_file);
+       return 0;
+}
+
 gint change_file_mode_rw(FILE *fp, const gchar *file)
 {
 #if HAVE_FCHMOD
@@ -2774,7 +2856,6 @@ void decode_uri(gchar *decoded_uri, const gchar *encoded_uri)
 
 gint open_uri(const gchar *uri, const gchar *cmdline)
 {
-       static gchar *default_cmdline = "netscape -remote openURL(%s,raise)";
        gchar buf[BUFFSIZE];
        gchar *p;
        gchar encoded_uri[BUFFSIZE];
@@ -2790,9 +2871,9 @@ gint open_uri(const gchar *uri, const gchar *cmdline)
                g_snprintf(buf, sizeof(buf), cmdline, encoded_uri);
        else {
                if (cmdline)
-                       g_warning(_("Open URI command line is invalid: `%s'"),
+                       g_warning("Open URI command line is invalid: `%s'",
                                  cmdline);
-               g_snprintf(buf, sizeof(buf), default_cmdline, encoded_uri);
+               g_snprintf(buf, sizeof(buf), DEFAULT_BROWSER_CMD, encoded_uri);
        }
        
        execute_command_line(buf, TRUE);
@@ -3030,10 +3111,11 @@ FILE *get_tmpfile_in_dir(const gchar *dir, gchar **filename)
 /* allow Mutt-like patterns in quick search */
 gchar *expand_search_string(const gchar *search_string)
 {
-       int i, len, new_len = 0;
+       int i = 0;
        gchar term_char, save_char;
        gchar *cmd_start, *cmd_end;
-       gchar *new_str = NULL;
+       GString *matcherstr;
+       gchar *returnstr = NULL;
        gchar *copy_str;
        gboolean casesens, dontmatch;
        /* list of allowed pattern abbreviations */
@@ -3060,6 +3142,7 @@ gchar *expand_search_string(const gchar *search_string)
                { "h",  "headers_part",                 1,      TRUE,   TRUE  },
                { "i",  "header \"Message-Id\"",        1,      TRUE,   TRUE  },
                { "I",  "inreplyto",                    1,      TRUE,   TRUE  },
+               { "L",  "locked",                       0,      FALSE,  FALSE },
                { "n",  "newsgroups",                   1,      TRUE,   TRUE  },
                { "N",  "new",                          0,      FALSE,  FALSE },
                { "O",  "~new",                         0,      FALSE,  FALSE },
@@ -3101,6 +3184,7 @@ gchar *expand_search_string(const gchar *search_string)
        if (cmds[i].command)
                return copy_str;
 
+       matcherstr = g_string_sized_new(16);
        cmd_start = cmd_end = copy_str;
        while (cmd_end && *cmd_end) {
                /* skip all white spaces */
@@ -3136,26 +3220,15 @@ gchar *expand_search_string(const gchar *search_string)
                        if (!strcmp(cmd_start, cmds[i].abbreviated)) {
                                /* restore character */
                                *cmd_end = save_char;
-                               len = strlen(cmds[i].command) + 1;
-                               if (dontmatch)
-                                       len++;
-                               if (casesens)
-                                       len++;
 
                                /* copy command */
-                               if (new_str) {
-                                       new_len += 1;
-                                       new_str = g_realloc(new_str, new_len);
-                                       strcat(new_str, " ");
+                               if (matcherstr->len > 0) {
+                                       g_string_append(matcherstr, " ");
                                }
-                               new_len += (len + 1);
-                               new_str = g_realloc(new_str, new_len);
-                               if (new_len == len + 1)
-                                       *new_str = '\0';
                                if (dontmatch)
-                                       strcat(new_str, "~");
-                               strcat(new_str, cmds[i].command);
-                               strcat(new_str, " ");
+                                       g_string_append(matcherstr, "~");
+                               g_string_append(matcherstr, cmds[i].command);
+                               g_string_append(matcherstr, " ");
 
                                /* stop if no params required */
                                if (cmds[i].numparams == 0)
@@ -3184,33 +3257,23 @@ gchar *expand_search_string(const gchar *search_string)
                                save_char = *cmd_end;
                                *cmd_end = '\0';
 
-                               new_len += strlen(cmd_start);
-
-                               /* do we need to add regexpcase ? */
-                               if (cmds[i].qualifier)
-                                       new_len += 10; /* "regexpcase " */
-
-                               if (term_char != '"')
-                                       new_len += 2;
-                               new_str = g_realloc(new_str, new_len);
-
                                if (cmds[i].qualifier) {
                                        if (casesens)
-                                               strcat(new_str, "regexp ");
+                                               g_string_append(matcherstr, "regexp ");
                                        else
-                                               strcat(new_str, "regexpcase ");
+                                               g_string_append(matcherstr, "regexpcase ");
                                }
 
                                /* do we need to add quotes ? */
                                if (cmds[i].quotes && term_char != '"')
-                                       strcat(new_str, "\"");
+                                       g_string_append(matcherstr, "\"");
 
                                /* copy actual parameter */
-                               strcat(new_str, cmd_start);
+                               g_string_append(matcherstr, cmd_start);
 
                                /* do we need to add quotes ? */
                                if (cmds[i].quotes && term_char != '"')
-                                       strcat(new_str, "\"");
+                                       g_string_append(matcherstr, "\"");
 
                                /* restore original character */
                                *cmd_end = save_char;
@@ -3226,6 +3289,29 @@ gchar *expand_search_string(const gchar *search_string)
        }
 
        g_free(copy_str);
-       return new_str;
+       returnstr = matcherstr->str;
+       g_string_free(matcherstr, FALSE);
+       return returnstr;
+}
+
+guint g_stricase_hash(gconstpointer gptr)
+{
+       guint hash_result = 0;
+       const char *str;
+
+       for (str = gptr; str && *str; str++) {
+               if (isupper(*str)) hash_result += (*str + ' ');
+               else hash_result += *str;
+       }
+
+       return hash_result;
+}
+
+gint g_stricase_equal(gconstpointer gptr1, gconstpointer gptr2)
+{
+       const char *str1 = gptr1;
+       const char *str2 = gptr2;
+
+       return !strcasecmp(str1, str2);
 }