455{
457 char fmt[128], tmp[1024];
458 char *p = NULL, *tags = NULL;
462 size_t colorlen;
463
467
469 return src;
470
475
480
481 buf[0] = '\0';
482 switch (op)
483 {
484 case 'A':
485 case 'I':
486 if (op == 'A')
487 {
488 if (reply_to && reply_to->
mailbox)
489 {
494 break;
495 }
496 }
497 else
498 {
500 {
504 break;
505 }
506 }
507
508
509 case 'a':
512 {
514 }
515 else
516 {
518 }
520 break;
521
522 case 'B':
523 case 'K':
526 {
529 }
530 else if (optional)
531 {
532 optional = false;
533 }
534 break;
535
536 case 'b':
537 if (m)
538 {
540#ifdef USE_NOTMUCH
542 {
544 if (rel_path)
545 p = rel_path;
546 }
547#endif
548
549 if (p)
551 else
553 }
554 else
555 {
557 }
560 break;
561
562 case 'c':
564 if (src[0] == 'r')
565 {
567 src++;
568 }
569 else
570 {
572 }
575 break;
576
577 case 'C':
579 snprintf(fmt + colorlen, sizeof(fmt) - colorlen, "%%%sd", prec);
581 snprintf(buf, buflen, fmt, e->
msgno + 1);
582 break;
583
584 case 'd':
585 case 'D':
586 case '{':
587 case '[':
588 case '(':
589 case '<':
590
591 {
592 const char *cp = NULL;
593 time_t now;
594 int j = 0;
595
596 if (optional && ((op == '[') || (op == '(')))
597 {
601
602 char *is = (char *) prec;
603 bool invert = false;
604 if (*is == '>')
605 {
606 invert = true;
607 is++;
608 }
609
610 while (*is && (*is != '?'))
611 {
612 int t = strtol(is, &is, 10);
613
614 switch (*(is++))
615 {
616 case 'y':
617 if (t > 1)
618 {
619 t--;
620 t *= (60 * 60 * 24 * 365);
621 }
622 t += ((tm.tm_mon * 60 * 60 * 24 * 30) + (tm.tm_mday * 60 * 60 * 24) +
623 (tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
624 break;
625
626 case 'm':
627 if (t > 1)
628 {
629 t--;
630 t *= (60 * 60 * 24 * 30);
631 }
632 t += ((tm.tm_mday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
633 (tm.tm_min * 60) + tm.tm_sec);
634 break;
635
636 case 'w':
637 if (t > 1)
638 {
639 t--;
640 t *= (60 * 60 * 24 * 7);
641 }
642 t += ((tm.tm_wday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
643 (tm.tm_min * 60) + tm.tm_sec);
644 break;
645
646 case 'd':
647 if (t > 1)
648 {
649 t--;
650 t *= (60 * 60 * 24);
651 }
652 t += ((tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
653 break;
654
655 case 'H':
656 if (t > 1)
657 {
658 t--;
659 t *= (60 * 60);
660 }
661 t += ((tm.tm_min * 60) + tm.tm_sec);
662 break;
663
664 case 'M':
665 if (t > 1)
666 {
667 t--;
668 t *= (60);
669 }
670 t += (tm.tm_sec);
671 break;
672
673 default:
674 break;
675 }
676 j += t;
677 }
678
679 if (j < 0)
680 j *= -1;
681
682 if (((now > j) || (now < (-1 * j))) ^ invert)
683 optional = false;
684 break;
685 }
686
687 p = buf;
688
689 cp = ((op ==
'd') || (op ==
'D')) ? (
NONULL(c_date_format)) : src;
690 bool do_locales;
691 if (*cp == '!')
692 {
693 do_locales = false;
694 cp++;
695 }
696 else
697 {
698 do_locales = true;
699 }
700
701 size_t len = buflen - 1;
702 while ((len > 0) &&
703 ((((op == 'd') || (op == 'D')) && *cp) ||
704 ((op == '{') && (*cp != '}')) || ((op == '[') && (*cp != ']')) ||
705 ((op == '(') && (*cp != ')')) || ((op == '<') && (*cp != '>'))))
706 {
707 if (*cp == '%')
708 {
709 cp++;
710 if (((*cp == 'Z') || (*cp == 'z')) && ((op == 'd') || (op == '{')))
711 {
712 if (len >= 5)
713 {
715 p += 5;
716 len -= 5;
717 }
718 else
719 {
720 break;
721 }
722 }
723 else
724 {
725 if (len >= 2)
726 {
727 *p++ = '%';
728 *p++ = *cp;
729 len -= 2;
730 }
731 else
732 {
733 break;
734 }
735 }
736 cp++;
737 }
738 else
739 {
740 *p++ = *cp++;
741 len--;
742 }
743 }
744 *p = '\0';
745
746 struct tm tm;
747 if ((op == '[') || (op == 'D'))
748 {
750 }
751 else if (op == '(')
752 {
754 }
755 else if (op == '<')
756 {
758 }
759 else
760 {
761
765 else
768 }
769
770 if (!do_locales)
771 setlocale(LC_TIME, "C");
772 strftime(tmp, sizeof(tmp), buf, &tm);
773 if (!do_locales)
774 setlocale(LC_TIME, "");
775
779
780 if ((len > 0) && (op != 'd') && (op != 'D'))
781 src = cp + 1;
782 break;
783 }
784
785 case 'e':
786 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
788 break;
789
790 case 'E':
791 if (!optional)
792 {
793 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
795 }
797 {
798 optional = false;
799 }
800 break;
801
802 case 'f':
803 {
809 break;
810 }
811
812 case 'F':
813 if (!optional)
814 {
815 const bool is_plain = (src[0] == 'p');
821
822 if (is_plain)
823 src++;
824 }
826 {
827 optional = false;
828 }
829 break;
830
831 case 'g':
833 if (!optional)
834 {
838 }
839 else if (!tags)
840 {
841 optional = false;
842 }
844 break;
845
846 case 'G':
847 {
848 char format[3] = { 0 };
849 char *tag = NULL;
850
851 if (!optional)
852 {
853 format[0] = op;
854 format[1] = *src;
855 format[2] = '\0';
856
858 if (tag)
859 {
865 }
866 src++;
867 }
868 else
869 {
870 format[0] = op;
871 format[1] = *prec;
872 format[2] = '\0';
873
875 if (tag)
876 {
878 if (!tags)
879 optional = false;
881 }
882 }
883 break;
884 }
885
886 case 'H':
887
888 if (optional)
890
892 break;
893
894 case 'i':
896 break;
897
898 case 'J':
899 {
900 bool have_tags = true;
902 if (tags)
903 {
905 {
906 char *parent_tags = NULL;
908 {
910 }
912 {
915 }
917 have_tags = false;
919 }
920 }
921 else
922 {
923 have_tags = false;
924 }
925
926 if (optional)
927 optional = have_tags;
928
930 if (have_tags)
931 mutt_format_s(buf + colorlen, buflen - colorlen, prec, tags);
932 else
936 break;
937 }
938
939 case 'l':
940 if (!optional)
941 {
942 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
944 snprintf(buf + colorlen, buflen - colorlen, fmt, e->
lines);
946 }
947 else if (e->
lines <= 0)
948 {
949 optional = false;
950 }
951 break;
952
953 case 'L':
954 if (!optional)
955 {
960 }
963 {
964 optional = false;
965 }
966 break;
967
968 case 'm':
969 if (m)
970 {
971 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
972 snprintf(buf, buflen, fmt, m->
msg_count);
973 }
974 else
975 {
977 }
978 break;
979
980 case 'n':
984 break;
985
986 case 'M':
987 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
988 if (!optional)
989 {
992 {
993 snprintf(buf + colorlen, buflen - colorlen, fmt, e->
num_hidden);
995 }
996 else if (is_index && threads)
997 {
1000 }
1001 else
1002 {
1003 *buf = '\0';
1004 }
1005 }
1006 else
1007 {
1009 optional = false;
1010 }
1011 break;
1012
1013 case 'N':
1014 if (!optional)
1015 {
1016 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
1017 snprintf(buf, buflen, fmt, e->
score);
1018 }
1019 else
1020 {
1022 optional = false;
1023 }
1024 break;
1025
1026 case 'O':
1027 if (!optional)
1028 {
1031 if (!c_save_address && (p = strpbrk(tmp, "%@")))
1032 *p = '\0';
1034 }
1037 {
1038 optional = false;
1039 }
1040 break;
1041
1042 case 'P':
1044 break;
1045
1046#ifdef USE_NNTP
1047 case 'q':
1049 break;
1050#endif
1051
1052 case 'r':
1053 {
1058 if (optional && (tmp[0] == '\0'))
1059 optional = false;
1061 break;
1062 }
1063
1064 case 'R':
1065 {
1070 if (optional && (tmp[0] == '\0'))
1071 optional = false;
1073 break;
1074 }
1075
1076 case 's':
1077 {
1079 char *subj = NULL;
1082 else
1085 {
1087 {
1091 snprintf(tmp,
sizeof(tmp),
"%s%s", e->
tree, buf);
1093 }
1094 else
1095 {
1097 }
1098 }
1099 else
1100 {
1104 }
1105 break;
1106 }
1107
1108 case 'S':
1109 {
1110 const char *wch = NULL;
1121 else if (e->
read && (msg_in_pager != e->
msgno))
1125 else
1127
1128 snprintf(tmp, sizeof(tmp), "%s", wch);
1130 mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1132 break;
1133 }
1134
1135 case 't':
1136 tmp[0] = '\0';
1139 {
1140 if (to)
1142 else if (cc)
1144 }
1146 break;
1147
1148 case 'T':
1149 {
1150 int i;
1151 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
1152 snprintf(buf, buflen, fmt,
1154 c_to_chars->
chars[i] :
1155 " ");
1156 break;
1157 }
1158
1159 case 'u':
1161 {
1163 p = strpbrk(tmp, "%@");
1164 if (p)
1165 *p = '\0';
1166 }
1167 else
1168 {
1169 tmp[0] = '\0';
1170 }
1172 break;
1173
1174 case 'v':
1176 {
1177 if (to)
1179 else if (cc)
1181 else
1182 *tmp = '\0';
1183 }
1184 else
1185 {
1187 }
1188 p = strpbrk(tmp, " %@");
1189 if (p)
1190 *p = '\0';
1192 break;
1193
1194 case 'W':
1195 if (!optional)
1196 {
1198 }
1200 {
1201 optional = false;
1202 }
1203 break;
1204
1205#ifdef USE_NNTP
1206 case 'x':
1207 if (!optional)
1208 {
1210 }
1212 {
1213 optional = false;
1214 }
1215 break;
1216#endif
1217
1218 case 'X':
1219 {
1221 if (msg)
1222 {
1225
1226
1227 if (optional)
1228 optional = (count != 0);
1229
1230 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
1231 snprintf(buf, buflen, fmt, count);
1232 }
1233 break;
1234 }
1235
1236 case 'y':
1237 if (optional)
1239
1243 break;
1244
1245 case 'Y':
1246 {
1247 bool label = true;
1249 {
1250 struct Email *e_tmp = NULL;
1253 {
1255 }
1259 {
1261 }
1263 label = false;
1264 }
1265 else
1266 {
1267 label = false;
1268 }
1269
1270 if (optional)
1271 optional = label;
1272
1274 if (label)
1276 else
1279 break;
1280 }
1281
1282 case 'z':
1283 if (src[0] == 's')
1284 {
1285 const char *ch = NULL;
1287 {
1289 }
1291 {
1293 }
1295 {
1297 }
1299 {
1301 }
1302 else if (e->
read && (msg_in_pager != e->
msgno))
1303 {
1306 else
1308 }
1309 else
1310 {
1313 else
1315 }
1316
1317 snprintf(tmp, sizeof(tmp), "%s", ch);
1318 src++;
1319 }
1320 else if (src[0] == 'c')
1321 {
1322 const char *ch = NULL;
1324 {
1326 }
1328 {
1330 }
1332 {
1334 }
1336 {
1338 }
1339 else
1340 {
1342 }
1343
1344 snprintf(tmp, sizeof(tmp), "%s", ch);
1345 src++;
1346 }
1347 else if (src[0] == 't')
1348 {
1349 const char *ch = NULL;
1354 else
1356
1357 snprintf(tmp, sizeof(tmp), "%s", ch);
1358 src++;
1359 }
1360 else
1361 {
1362 break;
1363 }
1364
1366 mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1368 break;
1369
1370 case 'Z':
1371 {
1372
1373 const char *first = NULL;
1375 {
1377 }
1379 {
1381 }
1382 else if (e->
read && (msg_in_pager != e->
msgno))
1383 {
1386 else
1388 }
1389 else
1390 {
1393 else
1395 }
1396
1397
1398 const char *second = NULL;
1411 else
1413
1414
1415 const char *third = NULL;
1420 else
1422
1423 snprintf(tmp, sizeof(tmp), "%s%s%s", first, second, third);
1424 }
1425
1427 mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1429 break;
1430
1431 case '@':
1432 {
1433 if (!m)
1434 break;
1435
1436 const char *end = src;
1437 static unsigned char recurse = 0;
1438
1439 while ((*end != '\0') && (*end != '@'))
1440 end++;
1441 if ((*end == '@') && (recurse < 20))
1442 {
1443 recurse++;
1449 recurse--;
1450
1451 src = end + 1;
1452 break;
1453 }
1454 }
1455
1456
1457 default:
1458 snprintf(buf, buflen, "%%%s%c", prec, op);
1459 break;
1460 }
1461
1462 if (optional)
1463 {
1465 }
1467 {
1469 }
1470
1471
1472 return src;
1473}
const char * mutt_addr_for_display(const struct Address *a)
Convert an Address for display purposes.
bool mutt_addr_is_user(const struct Address *addr)
Does the address belong to the user.
int mutt_count_body_parts(const struct Mailbox *m, struct Email *e, FILE *fp)
Count the MIME Body parts.
bool buf_is_empty(const struct Buffer *buf)
Is the Buffer empty?
@ MT_COLOR_INDEX_AUTHOR
Index: author field.
@ MT_COLOR_INDEX_SIZE
Index: size field.
@ MT_COLOR_INDEX_TAGS
Index: tags field (g, J)
@ MT_COLOR_INDEX_SUBJECT
Index: subject field.
@ MT_COLOR_INDEX_DATE
Index: date field.
@ MT_COLOR_INDEX_TAG
Index: tag field (G)
@ MT_COLOR_INDEX_LABEL
Index: label field.
@ MT_COLOR_INDEX
Index: default colour.
@ MT_COLOR_INDEX_NUMBER
Index: index number.
@ MT_COLOR_INDEX_FLAGS
Index: flags field.
@ MT_COLOR_INDEX_COLLAPSED
Index: number of messages in collapsed thread.
struct MbTable * cs_subset_mbtable(const struct ConfigSubset *sub, const char *name)
Get a Multibyte table config item by name.
bool cs_subset_bool(const struct ConfigSubset *sub, const char *name)
Get a boolean config item by name.
void mutt_format_s_x(char *buf, size_t buflen, const char *prec, const char *s, bool arboreal)
Format a string like snprintf()
size_t email_size(const struct Email *e)
Compute the size of an email.
static const char * index_format_str(char *buf, size_t buflen, size_t col, int cols, char op, const char *src, const char *prec, const char *if_str, const char *else_str, intptr_t data, MuttFormatFlags flags)
Format a string for the index list - Implements format_t -.
void * mutt_hash_find(const struct HashTable *table, const char *strkey)
Find the HashElem data in a Hash Table element using a key.
@ FLAG_CHAR_CRYPT_CONTAINS_KEY
Character denoting a message contains a PGP key.
@ FLAG_CHAR_CRYPT_SIGNED
Character denoting a message is signed.
@ FLAG_CHAR_CRYPT_NO_CRYPTO
Character denoting a message has no cryptography information.
@ FLAG_CHAR_CRYPT_GOOD_SIGN
Character denoting a message signed with a verified key.
@ FLAG_CHAR_CRYPT_ENCRYPTED
Character denoting a message is PGP-encrypted.
static void make_from_addr(struct Envelope *env, char *buf, size_t buflen, bool do_lists)
Create a 'from' address for a reply email.
static bool thread_is_old(struct Email *e)
Does the email thread contain any unread emails?
static int user_is_recipient(struct Email *e)
Is the user a recipient of the message.
static size_t add_index_color(char *buf, size_t buflen, MuttFormatFlags flags, enum ColorId color)
Insert a color marker into a string.
static void make_from(struct Envelope *env, char *buf, size_t buflen, bool do_lists, MuttFormatFlags flags)
Generate a From: field (with optional prefix)
static const char * get_nth_wchar(const struct MbTable *table, int index)
Extract one char from a multi-byte table.
static bool thread_is_new(struct Email *e)
Does the email thread contain any new emails?
@ FLAG_CHAR_OLD
Character denoting an email that has been read.
@ FLAG_CHAR_REPLIED
Character denoting an email that has been replied to.
@ FLAG_CHAR_OLD_THREAD
Character denoting a thread of emails that has been read.
@ FLAG_CHAR_ZEMPTY
Character denoting a read email, $index_format Z expando.
@ FLAG_CHAR_TAGGED
Character denoting a tagged email.
@ FLAG_CHAR_NEW
Character denoting an unread email.
@ FLAG_CHAR_DELETED
Character denoting a deleted email.
@ FLAG_CHAR_NEW_THREAD
Character denoting a thread containing at least one new email.
@ FLAG_CHAR_DELETED_ATTACH
Character denoting a deleted attachment.
@ FLAG_CHAR_SEMPTY
Character denoting a read email, $index_format S expando.
@ FLAG_CHAR_IMPORTANT
Character denoting a important (flagged) email.
const char * mutt_idxfmt_hook(const char *name, struct Mailbox *m, struct Email *e)
Get index-format-hook format string.
@ MUTT_NOTMUCH
'Notmuch' (virtual) Mailbox type
bool check_for_mailing_list(struct AddressList *al, const char *pfx, char *buf, int buflen)
Search list of addresses for a mailing list.
bool check_for_mailing_list_addr(struct AddressList *al, char *buf, int buflen)
Check an address list for a mailing list.
bool first_mailing_list(char *buf, size_t buflen, struct AddressList *al)
Get the first mailing list in the list of addresses.
bool mutt_mb_get_initials(const char *name, char *buf, size_t buflen)
Turn a name into initials.
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone.
bool mutt_istr_equal(const char *a, const char *b)
Compare two strings, ignoring case.
char * mutt_strn_copy(char *dest, const char *src, size_t len, size_t dsize)
Copy a sub-string into a buffer.
int mutt_messages_in_thread(struct Mailbox *m, struct Email *e, enum MessageInThread mit)
Count the messages in a thread.
#define mutt_using_threads()
@ MIT_NUM_MESSAGES
How many messages are in the thread.
@ MIT_POSITION
Our position in the thread.
int mx_msg_close(struct Mailbox *m, struct Message **msg)
Close a message.
struct Message * mx_msg_open(struct Mailbox *m, struct Email *e)
Return a stream pointer for a message.
#define SEC_GOODSIGN
Email has a valid signature.
#define APPLICATION_PGP
Use PGP to encrypt/sign.
#define SEC_ENCRYPT
Email is encrypted.
#define SEC_SIGN
Email is signed.
char * nm_email_get_folder_rel_db(struct Mailbox *m, struct Email *e)
Get the folder for a Email from the same level as the notmuch database.
#define TAILQ_FIRST(head)
const char * mutt_get_name(const struct Address *a)
Pick the best name to display from an address.
The envelope/body of an email.
unsigned int zminutes
Minutes away from UTC.
struct Envelope * env
Envelope information.
bool collapsed
Is this message part of a collapsed thread?
int lines
How many lines in the body of this message?
SecurityFlags security
bit 0-10: flags, bit 11,12: application, bit 13: traditional pgp See: ncrypt/lib.h pgplib....
struct Body * body
List of MIME parts.
char * tree
Character string to print thread tree.
bool old
Email is seen, but unread.
size_t num_hidden
Number of hidden messages in this view (only valid when collapsed is set)
bool zoccident
True, if west of UTC, False if east.
bool attach_del
Has an attachment marked for deletion.
bool flagged
Marked important?
unsigned int zhours
Hours away from UTC.
time_t date_sent
Time when the message was sent (UTC)
bool replied
Email has been replied to.
struct TagList tags
For drivers that support server tagging.
int msgno
Number displayed to the user.
bool deleted
Email is deleted.
bool tagged
Email is tagged.
time_t received
Time when the message was placed in the mailbox.
struct MuttThread * thread
Thread of Emails.
struct AddressList to
Email's 'To' list.
struct AddressList reply_to
Email's 'reply-to'.
char * message_id
Message ID.
char * x_comment_to
List of 'X-comment-to' fields.
char * newsgroups
List of newsgroups.
struct AddressList cc
Email's 'Cc' list.
struct Buffer spam
Spam header.
char * subject
Email's subject.
char * organization
Organisation header.
char * disp_subj
Display subject (modified copy of subject)
struct AddressList from
Email's 'From' list.
int msg_count
Total number of messages.
enum MailboxType type
Mailbox type.
Multibyte character table.
int len
Number of characters.
char ** chars
The array of multibyte character strings.
A local copy of an email.
FILE * fp
pointer to the message data
struct Message::@0 flags
Flags for the Message.
struct MuttThread * parent
Parent of this Thread.
struct MuttThread * prev
Previous sibling Thread.
struct Email * message
Email this Thread refers to.
bool subjrx_apply_mods(struct Envelope *env)
Apply regex modifications to the subject.