397{
399 char fmt[128], tmp[1024];
400 char *p = NULL, *tags = NULL;
404 size_t colorlen;
405
409
411 return src;
412
417
422
423 buf[0] = '\0';
424 switch (op)
425 {
426 case 'A':
427 case 'I':
428 if (op == 'A')
429 {
430 if (reply_to && reply_to->
mailbox)
431 {
436 break;
437 }
438 }
439 else
440 {
442 {
446 break;
447 }
448 }
449
450
451 case 'a':
454 {
456 }
457 else
458 {
460 }
462 break;
463
464 case 'B':
465 case 'K':
468 {
471 }
472 else if (optional)
473 {
474 optional = false;
475 }
476 break;
477
478 case 'b':
479 if (m)
480 {
482#ifdef USE_NOTMUCH
484 {
486 if (rel_path)
487 p = rel_path;
488 }
489#endif
490
491 if (p)
493 else
495 }
496 else
497 {
499 }
502 break;
503
504 case 'c':
506 if (src[0] == 'r')
507 {
509 src++;
510 }
511 else
512 {
514 }
517 break;
518
519 case 'C':
521 snprintf(fmt + colorlen, sizeof(fmt) - colorlen, "%%%sd", prec);
523 snprintf(buf, buflen, fmt, e->
msgno + 1);
524 break;
525
526 case 'd':
527 case 'D':
528 case '{':
529 case '[':
530 case '(':
531 case '<':
532
533 {
534 const char *cp = NULL;
535 time_t now;
536 int j = 0;
537
538 if (optional && ((op == '[') || (op == '(')))
539 {
543
544 char *is = (char *) prec;
545 bool invert = false;
546 if (*is == '>')
547 {
548 invert = true;
549 is++;
550 }
551
552 while (*is && (*is != '?'))
553 {
554 int t = strtol(is, &is, 10);
555
556 switch (*(is++))
557 {
558 case 'y':
559 if (t > 1)
560 {
561 t--;
562 t *= (60 * 60 * 24 * 365);
563 }
564 t += ((tm.tm_mon * 60 * 60 * 24 * 30) + (tm.tm_mday * 60 * 60 * 24) +
565 (tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
566 break;
567
568 case 'm':
569 if (t > 1)
570 {
571 t--;
572 t *= (60 * 60 * 24 * 30);
573 }
574 t += ((tm.tm_mday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
575 (tm.tm_min * 60) + tm.tm_sec);
576 break;
577
578 case 'w':
579 if (t > 1)
580 {
581 t--;
582 t *= (60 * 60 * 24 * 7);
583 }
584 t += ((tm.tm_wday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
585 (tm.tm_min * 60) + tm.tm_sec);
586 break;
587
588 case 'd':
589 if (t > 1)
590 {
591 t--;
592 t *= (60 * 60 * 24);
593 }
594 t += ((tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
595 break;
596
597 case 'H':
598 if (t > 1)
599 {
600 t--;
601 t *= (60 * 60);
602 }
603 t += ((tm.tm_min * 60) + tm.tm_sec);
604 break;
605
606 case 'M':
607 if (t > 1)
608 {
609 t--;
610 t *= (60);
611 }
612 t += (tm.tm_sec);
613 break;
614
615 default:
616 break;
617 }
618 j += t;
619 }
620
621 if (j < 0)
622 j *= -1;
623
624 if (((now > j) || (now < (-1 * j))) ^ invert)
625 optional = false;
626 break;
627 }
628
629 p = buf;
630
631 cp = ((op ==
'd') || (op ==
'D')) ? (
NONULL(c_date_format)) : src;
632 bool use_c_locale = false;
633 if (*cp == '!')
634 {
635 use_c_locale = true;
636 cp++;
637 }
638
639 size_t len = buflen - 1;
640 while ((len > 0) &&
641 ((((op == 'd') || (op == 'D')) && *cp) ||
642 ((op == '{') && (*cp != '}')) || ((op == '[') && (*cp != ']')) ||
643 ((op == '(') && (*cp != ')')) || ((op == '<') && (*cp != '>'))))
644 {
645 if (*cp == '%')
646 {
647 cp++;
648 if (((*cp == 'Z') || (*cp == 'z')) && ((op == 'd') || (op == '{')))
649 {
650 if (len >= 5)
651 {
653 p += 5;
654 len -= 5;
655 }
656 else
657 {
658 break;
659 }
660 }
661 else
662 {
663 if (len >= 2)
664 {
665 *p++ = '%';
666 *p++ = *cp;
667 len -= 2;
668 }
669 else
670 {
671 break;
672 }
673 }
674 cp++;
675 }
676 else
677 {
678 *p++ = *cp++;
679 len--;
680 }
681 }
682 *p = '\0';
683
684 struct tm tm = { 0 };
685 if ((op == '[') || (op == 'D'))
686 {
688 }
689 else if (op == '(')
690 {
692 }
693 else if (op == '<')
694 {
696 }
697 else
698 {
699
703 else
706 }
707
708 if (use_c_locale)
710 else
711 strftime(tmp, sizeof(tmp), buf, &tm);
712
716
717 if ((len > 0) && (op != 'd') && (op != 'D'))
718 src = cp + 1;
719 break;
720 }
721
722 case 'e':
723 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
725 break;
726
727 case 'E':
728 if (!optional)
729 {
730 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
732 }
734 {
735 optional = false;
736 }
737 break;
738
739 case 'f':
740 {
746 break;
747 }
748
749 case 'F':
750 if (!optional)
751 {
752 const bool is_plain = (src[0] == 'p');
758
759 if (is_plain)
760 src++;
761 }
763 {
764 optional = false;
765 }
766 break;
767
768 case 'g':
770 if (!optional)
771 {
775 }
776 else if (!tags)
777 {
778 optional = false;
779 }
781 break;
782
783 case 'G':
784 {
785 char format[3] = { 0 };
786 char *tag = NULL;
787
788 if (!optional)
789 {
790 format[0] = op;
791 format[1] = *src;
792 format[2] = '\0';
793
795 if (tag)
796 {
802 }
803 src++;
804 }
805 else
806 {
807 format[0] = op;
808 format[1] = *prec;
809 format[2] = '\0';
810
812 if (tag)
813 {
815 if (!tags)
816 optional = false;
818 }
819 }
820 break;
821 }
822
823 case 'H':
824
825 if (optional)
827
829 break;
830
831 case 'i':
833 break;
834
835 case 'J':
836 {
837 bool have_tags = true;
839 if (tags)
840 {
842 {
843 char *parent_tags = NULL;
845 {
847 }
849 {
852 }
854 have_tags = false;
856 }
857 }
858 else
859 {
860 have_tags = false;
861 }
862
863 if (optional)
864 optional = have_tags;
865
867 if (have_tags)
868 mutt_format_s(buf + colorlen, buflen - colorlen, prec, tags);
869 else
873 break;
874 }
875
876 case 'l':
877 if (!optional)
878 {
879 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
881 snprintf(buf + colorlen, buflen - colorlen, fmt, e->
lines);
883 }
884 else if (e->
lines <= 0)
885 {
886 optional = false;
887 }
888 break;
889
890 case 'L':
891 if (!optional)
892 {
897 }
900 {
901 optional = false;
902 }
903 break;
904
905 case 'm':
906 if (m)
907 {
908 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
909 snprintf(buf, buflen, fmt, m->
msg_count);
910 }
911 else
912 {
914 }
915 break;
916
917 case 'n':
921 break;
922
923 case 'M':
924 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
925 if (!optional)
926 {
929 {
930 snprintf(buf + colorlen, buflen - colorlen, fmt, e->
num_hidden);
932 }
933 else if (is_index && threads)
934 {
937 }
938 else
939 {
940 *buf = '\0';
941 }
942 }
943 else
944 {
946 optional = false;
947 }
948 break;
949
950 case 'N':
951 if (!optional)
952 {
953 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
954 snprintf(buf, buflen, fmt, e->
score);
955 }
956 else
957 {
959 optional = false;
960 }
961 break;
962
963 case 'O':
964 if (!optional)
965 {
968 if (!c_save_address && (p = strpbrk(tmp, "%@")))
969 *p = '\0';
971 }
974 {
975 optional = false;
976 }
977 break;
978
979 case 'P':
981 break;
982
983#ifdef USE_NNTP
984 case 'q':
986 break;
987#endif
988
989 case 'r':
990 {
995 if (optional && (tmp[0] == '\0'))
996 optional = false;
998 break;
999 }
1000
1001 case 'R':
1002 {
1007 if (optional && (tmp[0] == '\0'))
1008 optional = false;
1010 break;
1011 }
1012
1013 case 's':
1014 {
1016 char *subj = NULL;
1019 else
1022 {
1024 {
1028 snprintf(tmp,
sizeof(tmp),
"%s%s", e->
tree, buf);
1030 }
1031 else
1032 {
1034 }
1035 }
1036 else
1037 {
1041 }
1042 break;
1043 }
1044
1045 case 'S':
1046 {
1047 const char *wch = NULL;
1058 else if (e->
read && (msg_in_pager != e->
msgno))
1062 else
1064
1065 snprintf(tmp, sizeof(tmp), "%s", wch);
1067 mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1069 break;
1070 }
1071
1072 case 't':
1073 tmp[0] = '\0';
1076 {
1077 if (to)
1079 else if (cc)
1081 }
1083 break;
1084
1085 case 'T':
1086 {
1087 int i;
1088 snprintf(fmt, sizeof(fmt), "%%%ss", prec);
1089 snprintf(buf, buflen, fmt,
1091 c_to_chars->
chars[i] :
1092 " ");
1093 break;
1094 }
1095
1096 case 'u':
1098 {
1100 p = strpbrk(tmp, "%@");
1101 if (p)
1102 *p = '\0';
1103 }
1104 else
1105 {
1106 tmp[0] = '\0';
1107 }
1109 break;
1110
1111 case 'v':
1113 {
1114 if (to)
1116 else if (cc)
1118 else
1119 *tmp = '\0';
1120 }
1121 else
1122 {
1124 }
1125 p = strpbrk(tmp, " %@");
1126 if (p)
1127 *p = '\0';
1129 break;
1130
1131 case 'W':
1132 if (!optional)
1133 {
1135 }
1137 {
1138 optional = false;
1139 }
1140 break;
1141
1142#ifdef USE_NNTP
1143 case 'x':
1144 if (!optional)
1145 {
1147 }
1149 {
1150 optional = false;
1151 }
1152 break;
1153#endif
1154
1155 case 'X':
1156 {
1158 if (msg)
1159 {
1162
1163
1164 if (optional)
1165 optional = (count != 0);
1166
1167 snprintf(fmt, sizeof(fmt), "%%%sd", prec);
1168 snprintf(buf, buflen, fmt, count);
1169 }
1170 break;
1171 }
1172
1173 case 'y':
1174 if (optional)
1176
1180 break;
1181
1182 case 'Y':
1183 {
1184 bool label = true;
1186 {
1187 struct Email *e_tmp = NULL;
1190 {
1192 }
1196 {
1198 }
1200 label = false;
1201 }
1202 else
1203 {
1204 label = false;
1205 }
1206
1207 if (optional)
1208 optional = label;
1209
1211 if (label)
1213 else
1216 break;
1217 }
1218
1219 case 'z':
1220 if (src[0] == 's')
1221 {
1222 const char *ch = NULL;
1224 {
1226 }
1228 {
1230 }
1232 {
1234 }
1236 {
1238 }
1239 else if (e->
read && (msg_in_pager != e->
msgno))
1240 {
1243 else
1245 }
1246 else
1247 {
1250 else
1252 }
1253
1254 snprintf(tmp, sizeof(tmp), "%s", ch);
1255 src++;
1256 }
1257 else if (src[0] == 'c')
1258 {
1259 const char *ch = NULL;
1261 {
1263 }
1265 {
1267 }
1269 {
1271 }
1273 {
1275 }
1276 else
1277 {
1279 }
1280
1281 snprintf(tmp, sizeof(tmp), "%s", ch);
1282 src++;
1283 }
1284 else if (src[0] == 't')
1285 {
1286 const char *ch = NULL;
1291 else
1293
1294 snprintf(tmp, sizeof(tmp), "%s", ch);
1295 src++;
1296 }
1297 else
1298 {
1299 break;
1300 }
1301
1303 mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1305 break;
1306
1307 case 'Z':
1308 {
1309
1310 const char *first = NULL;
1312 {
1314 }
1316 {
1318 }
1319 else if (e->
read && (msg_in_pager != e->
msgno))
1320 {
1323 else
1325 }
1326 else
1327 {
1330 else
1332 }
1333
1334
1335 const char *second = NULL;
1348 else
1350
1351
1352 const char *third = NULL;
1357 else
1359
1360 snprintf(tmp, sizeof(tmp), "%s%s%s", first, second, third);
1361 }
1362
1364 mutt_format_s(buf + colorlen, buflen - colorlen, prec, tmp);
1366 break;
1367
1368 case '@':
1369 {
1370 if (!m)
1371 break;
1372
1373 const char *end = src;
1374 static unsigned char recurse = 0;
1375
1376 while ((*end != '\0') && (*end != '@'))
1377 end++;
1378 if ((*end == '@') && (recurse < 20))
1379 {
1380 recurse++;
1386 recurse--;
1387
1388 src = end + 1;
1389 break;
1390 }
1391 }
1392
1393
1394 default:
1395 snprintf(buf, buflen, "%%%s%c", prec, op);
1396 break;
1397 }
1398
1399 if (optional)
1400 {
1402 }
1404 {
1406 }
1407
1408
1409 return src;
1410}
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.
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 enum ToChars 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 bool thread_is_new(struct Email *e)
Does the email thread contain any new emails?
@ 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.
@ 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.
const char * mbtable_get_nth_wchar(const struct MbTable *table, int index)
Extract one char from a multi-byte table.
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 **ptr)
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.