From ece60f2e820ccb2635a96a7f92d37c980c6172f5 Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Sun, 14 Nov 2010 16:40:43 +0200 Subject: [PATCH] * mu-msg-flags: overhaul; cleaned up things, and should be a bit faster --- src/mu-msg-flags.c | 149 +++++++++++++++++++++++++-------------------- src/mu-msg-flags.h | 79 ++++++++++++++++-------- 2 files changed, 138 insertions(+), 90 deletions(-) diff --git a/src/mu-msg-flags.c b/src/mu-msg-flags.c index 7b766242..e975df7d 100644 --- a/src/mu-msg-flags.c +++ b/src/mu-msg-flags.c @@ -1,5 +1,5 @@ /* -** Copyright (C) 2010 Dirk-Jan C. Binnema +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema ** ** 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 the @@ -24,84 +24,100 @@ #include "mu-msg-flags.h" -static struct { - char kar; - MuMsgFlags flag; - gboolean file_flag; -} FLAG_CHARS[] = { - {'D', MU_MSG_FLAG_DRAFT, TRUE}, - {'F', MU_MSG_FLAG_FLAGGED, TRUE}, - {'N', MU_MSG_FLAG_NEW, TRUE}, - {'P', MU_MSG_FLAG_PASSED, TRUE}, - {'R', MU_MSG_FLAG_REPLIED, TRUE}, - {'S', MU_MSG_FLAG_SEEN, TRUE}, - {'T', MU_MSG_FLAG_TRASHED, TRUE}, - {'a', MU_MSG_FLAG_HAS_ATTACH, FALSE}, - {'s', MU_MSG_FLAG_SIGNED, FALSE}, - {'x', MU_MSG_FLAG_ENCRYPTED, FALSE} +static const MuMsgFlags ALL_FLAGS[] = { + MU_MSG_FLAG_NEW, + MU_MSG_FLAG_PASSED, + MU_MSG_FLAG_REPLIED, + MU_MSG_FLAG_SEEN, + MU_MSG_FLAG_TRASHED, + MU_MSG_FLAG_DRAFT, + MU_MSG_FLAG_FLAGGED, + MU_MSG_FLAG_SIGNED, + MU_MSG_FLAG_ENCRYPTED, + MU_MSG_FLAG_HAS_ATTACH }; MuMsgFlags -mu_msg_flags_from_str (const char* str) +mu_msg_flag_from_char (char k) { - MuMsgFlags flags = 0; - while (str[0]) { - int i; - MuMsgFlags oneflag = MU_MSG_FLAG_UNKNOWN; - for (i = 0; i != G_N_ELEMENTS(FLAG_CHARS); ++i) { - if (str[0] == FLAG_CHARS[i].kar) { - oneflag = FLAG_CHARS[i].flag; - break; - } - } - if (oneflag == MU_MSG_FLAG_UNKNOWN) - return MU_MSG_FLAG_UNKNOWN; - else - flags |= oneflag; + switch (k) { + case 'N': return MU_MSG_FLAG_NEW; + + case 'P': return MU_MSG_FLAG_PASSED; + case 'R': return MU_MSG_FLAG_REPLIED; + case 'S': return MU_MSG_FLAG_SEEN; + case 'T': return MU_MSG_FLAG_TRASHED; + case 'D': return MU_MSG_FLAG_DRAFT; + case 'F': return MU_MSG_FLAG_FLAGGED; - ++str; + case 'Z': return MU_MSG_FLAG_SIGNED; + case 'X': return MU_MSG_FLAG_ENCRYPTED; + case 'A': return MU_MSG_FLAG_HAS_ATTACH; + + default: + g_warning ("%s: unknown flag %c", __FUNCTION__, k); + return MU_MSG_FLAG_NONE; } - - return flags; } -MuMsgFlags -mu_msg_flags_from_char (char c) +char +mu_msg_flag_to_char (MuMsgFlags flag) { - char str[2]; - - str[0] = c; - str[1] = '\0'; - - return mu_msg_flags_from_str (str); + switch (flag) { + case MU_MSG_FLAG_NEW: return 'N'; + case MU_MSG_FLAG_PASSED: return 'P'; + case MU_MSG_FLAG_REPLIED: return 'R'; + case MU_MSG_FLAG_SEEN: return 'S'; + case MU_MSG_FLAG_TRASHED: return 'T'; + case MU_MSG_FLAG_DRAFT: return 'D'; + case MU_MSG_FLAG_FLAGGED: return 'F'; + + case MU_MSG_FLAG_SIGNED: return 'Z'; + case MU_MSG_FLAG_ENCRYPTED: return 'X'; + case MU_MSG_FLAG_HAS_ATTACH: return 'A'; + + default: + g_warning ("%s: unknown flag 0x%x", __FUNCTION__, flag); + return 0; + } } const char* -mu_msg_flags_to_str_s (MuMsgFlags flags) +mu_msg_flags_to_str_s (MuMsgFlags flags) { - int i = 0, j = 0; - static char buf[G_N_ELEMENTS(FLAG_CHARS) + 1]; + int i, j; + static char buf[16]; /* more than enough */ - for (i = 0; i != G_N_ELEMENTS(FLAG_CHARS); ++i) - if (flags & FLAG_CHARS[i].flag) - buf[j++] = FLAG_CHARS[i].kar; + for (i = j = 0; i != G_N_ELEMENTS(ALL_FLAGS); ++i) { + if (flags & ALL_FLAGS[i]) { + char k; + if ((k = mu_msg_flag_to_char (ALL_FLAGS[i])) == 0) + return NULL; + buf[j++] = k; + } + } buf[j] = '\0'; + return buf; } - -gboolean -mu_msg_flags_is_file_flag (MuMsgFlags flag) +MuMsgFlags +mu_msg_flags_from_str (const char* str) { - int i = 0; + MuMsgFlags flags; - for (i = 0; i != G_N_ELEMENTS(FLAG_CHARS); ++i) - if (flag == FLAG_CHARS[i].flag) - return FLAG_CHARS[i].file_flag; - - return FALSE; + for (flags = MU_MSG_FLAG_NONE; str && *str; ++str) { + MuMsgFlags flag; + if ((flag = mu_msg_flag_to_char (*str)) == 0) { + flags = 0; + break; + } + flags |= flag; + } + + return flags; } @@ -166,9 +182,9 @@ mu_msg_flags_from_file (const char* path) MsgType mtype; char *info = NULL; - g_return_val_if_fail (path, MU_MSG_FLAG_UNKNOWN); + g_return_val_if_fail (path, MU_MSG_FLAG_NONE); g_return_val_if_fail (!g_str_has_suffix(path,G_DIR_SEPARATOR_S), - MU_MSG_FLAG_UNKNOWN); + MU_MSG_FLAG_NONE); mtype = check_msg_type (path, &info); @@ -185,16 +201,19 @@ mu_msg_flags_from_file (const char* path) if (cursor && cursor[0]=='2' && cursor[1]==',') { cursor += 2; /* jump past 2, */ while (*cursor) { - MuMsgFlags oneflag = - mu_msg_flags_from_char (*cursor); - /* ignore anything but file flags */ - if (mu_msg_flags_is_file_flag(oneflag)) - flags |= oneflag; + switch (*cursor) { + case 'P': flags |= MU_MSG_FLAG_PASSED; break; + case 'T': flags |= MU_MSG_FLAG_TRASHED; break; + case 'R': flags |= MU_MSG_FLAG_REPLIED; break; + case 'S': flags |= MU_MSG_FLAG_SEEN; break; + case 'D': flags |= MU_MSG_FLAG_DRAFT; break; + case 'F': flags |= MU_MSG_FLAG_FLAGGED; break; + } ++cursor; } } } g_free (info); + return flags; } - diff --git a/src/mu-msg-flags.h b/src/mu-msg-flags.h index d3d67105..520d24e8 100644 --- a/src/mu-msg-flags.h +++ b/src/mu-msg-flags.h @@ -1,5 +1,5 @@ /* -** Copyright (C) 2010 Dirk-Jan C. Binnema +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema ** ** 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 the @@ -24,32 +24,51 @@ G_BEGIN_DECLS -enum _MuMsgFlags { - MU_MSG_FLAG_UNKNOWN = 0, - MU_MSG_FLAG_NONE = 1 << 0, +/* the MU_MSG_FLAG_-flags are retrieved from the filename of + * the message, as per the maildir spec: + * http://cr.yp.to/proto/maildir.html not all (possibly not any) mail + * clients respect this fully -- therefore, we map these flags to + * MU_MSG_FLAG values. + * + * the other flags are determined from the contents of the + * message. Note that these flags are far from orthogonal, + * unfortunately. + * + */ +enum _MuMsgFlags { + MU_MSG_FLAG_NONE = 0, - /* these we get from the file */ - MU_MSG_FLAG_NEW = 1 << 1, - MU_MSG_FLAG_SEEN = 1 << 2, - MU_MSG_FLAG_UNREAD = 1 << 3, - MU_MSG_FLAG_REPLIED = 1 << 4, - MU_MSG_FLAG_FLAGGED = 1 << 5, - MU_MSG_FLAG_TRASHED = 1 << 6, - MU_MSG_FLAG_DRAFT = 1 << 7, - MU_MSG_FLAG_PASSED = 1 << 8, + /* unlike the other MAILDIR flags, the NEW flag is not + * determined by the file name but by the dir: if the message + * is in the 'new' directory, it's considered... new */ + MU_MSG_FLAG_NEW = 1 << 0, + + /* "P"->resent,forwarded,bounced message */ + MU_MSG_FLAG_PASSED = 1 << 1, + /* "R"->replied message */ + MU_MSG_FLAG_REPLIED = 1 << 2, + /* "S"->seen message */ + MU_MSG_FLAG_SEEN = 1 << 3, + /* "T"->trashed message */ + MU_MSG_FLAG_TRASHED = 1 << 4, + /* "D"->draft message */ + MU_MSG_FLAG_DRAFT = 1 << 5, + /* "F"->flagged message */ + MU_MSG_FLAG_FLAGGED = 1 << 6, /* these we get from the contents */ - MU_MSG_FLAG_SIGNED = 1 << 10, - MU_MSG_FLAG_ENCRYPTED = 1 << 11, - MU_MSG_FLAG_HAS_ATTACH = 1 << 12 - -/* any new fields go here */ - /* so the existing numbers stay valid note that we're also */ - /* using these numbers in the database, so they should not change */ + + /* "Z"->signed message */ + MU_MSG_FLAG_SIGNED = 1 << 7, + /* "X"->encrypted message */ + MU_MSG_FLAG_ENCRYPTED = 1 << 8, + /* "A"->message has attachment */ + MU_MSG_FLAG_HAS_ATTACH = 1 << 9 }; typedef enum _MuMsgFlags MuMsgFlags; -/** + +/** * convert the char-per-flag description into a MuMsgFlags value; the characters * D=draft,F=flagged,N=new,P=passed,R=replied,S=seen,T=trashed * a=has-attachment,s=signed, x=encrypted @@ -61,7 +80,7 @@ typedef enum _MuMsgFlags MuMsgFlags; */ MuMsgFlags mu_msg_flags_from_str (const char* str) G_GNUC_PURE; -/** +/** * convert the char-per-flag description into a MuMsgFlags value * * @param c a character @@ -70,7 +89,7 @@ MuMsgFlags mu_msg_flags_from_str (const char* str) G_GNUC_PURE; */ MuMsgFlags mu_msg_flags_from_char (char c) G_GNUC_CONST; -/** +/** * get a string for a given set of flags, OR'ed in * @param flags; one character per flag: * D=draft,F=flagged,N=new,P=passed,R=replied,S=seen,T=trashed @@ -85,7 +104,17 @@ MuMsgFlags mu_msg_flags_from_char (char c) G_GNUC_CONST; */ const char* mu_msg_flags_to_str_s (MuMsgFlags flags) G_GNUC_CONST; -/** + +/** + * get the character for some msg flag, or 0 in case it's not found + * + * @param flags on specific flag (not OR'ed) + * + * @return the char for this flag, or 0 if not found + */ +char mu_msg_flags_char (MuMsgFlags flag); + +/** * get the Maildir flags from a mailfile. The flags are as specified * in http://cr.yp.to/proto/maildir.html, plus MU_MSG_FLAG_NEW for * new messages, ie the ones that live in new/. The flags are @@ -99,7 +128,7 @@ const char* mu_msg_flags_to_str_s (MuMsgFlags flags) G_GNUC_CONST; */ MuMsgFlags mu_msg_flags_from_file (const char* pathname) G_GNUC_PURE; -/** +/** * is the message flag a file flag? ie. encoded in the filename * * @param flag the flag to check; note, this should be a single flag