aboutsummaryrefslogtreecommitdiff
path: root/mail/mutt/files/extra-patch-smartdate
blob: 09e2db1af99dc112fa440454d4e56cbbbb79409b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
--- hdrline.c.orig	2019-11-11 04:00:36 UTC
+++ hdrline.c
@@ -248,6 +248,89 @@ static char *apply_subject_mods (ENVELOPE *env)
  * %Y = `x-label:' field (if present, tree unfolded, and != parent's x-label)
  * %Z = status flags	*/
 
+static void
+format_smartdate( char *buf, size_t max, struct tm *tm, smartdate_type type )
+{
+    char *strftime_fmt = NULL;
+
+    switch( type ) {
+        case FUTURE:        /* Date in the future */
+            strftime_fmt = "%d%h%y!";
+            break;
+        case SMARTTIME:     /* Today */
+            strftime_fmt = "%I:%M %p";
+            break;
+        case YESTERDAY:     /* Yesterday */
+            strncpy( buf, "Yesterday", max );
+            break;
+        case WEEKDAY:       /* Within the last 7 days */
+            strftime_fmt = "%A";
+            break;
+        case STANDARD:      /* Within the last six months */
+            strftime_fmt = "%h %d";
+            break;
+        case ANCIENT:       /* Older than 6 months */
+            strftime_fmt = "%h %Y";
+            break;
+    }
+
+    if( strftime_fmt != NULL ) {
+        strftime( buf, max, strftime_fmt, tm );
+    }
+}
+
+static void
+smartdate( char *buf, size_t max, struct tm *tm )
+{
+    smartdate_type type = 0;
+
+    struct tm now;
+
+    time_t sse = mktime( tm );   /* Seconds since epoch */
+    time_t sse_now = time(NULL); /* Seconds since epoch until now */
+
+    int dse = 0;            /* Days since epoch */
+    int dse_now = 0;        /* Days since epoch until today */
+
+    /* Calculate the number of days since epoch */
+    dse = sse / (60*60*24);
+    dse_now = sse_now / (60*60*24);
+
+    /* Default display type */
+    type = STANDARD;
+
+    /* Check if the date is in the future */
+    if( dse > dse_now ) {
+        type = FUTURE;
+    }
+    else {
+        int diff = dse_now - dse;
+        if( diff == 0 ) type = SMARTTIME;
+        else if( diff == 1 ) type = YESTERDAY;
+        else if( diff < 7 ) type = WEEKDAY;
+        else if( diff > 215 ) type = ANCIENT;  /* Surely older than six
+                                                  months */
+        else if( diff > 180 ) {
+            /*
+             * Slightly heavy calculation to check if the date is more
+             * than six months in the past.  This calculation uses
+             * calendar months and not the exact number of days.  So,
+             * January 31, 2003 would be considered more than six months
+             * old whether today's date is August 1 or August 31, 2003
+             */
+            int monthdiff;
+            localtime_r( &sse_now, &now );
+            monthdiff = ( now.tm_mon - tm->tm_mon )
+                + ( ( now.tm_year - tm->tm_year ) * 12 );
+            if( monthdiff > 6 ) {
+                type = ANCIENT;
+            }
+        }
+    }
+
+    format_smartdate( buf, max, tm, type );
+}
+
 static const char *
 hdr_format_str (char *dest,
 		size_t destlen,
@@ -421,7 +504,13 @@ hdr_format_str (char *dest,
 
       if (!do_locales)
         setlocale (LC_TIME, "C");
-      strftime (buf2, sizeof (buf2), dest, tm);
+		/* Identify the non-strftime smartdate pattern (%@) */
+		if( strncmp( dest, "%@", 2 ) == 0 ) {
+			smartdate( buf2, sizeof( buf2 ), tm );
+		}
+		else {
+			strftime (buf2, sizeof (buf2), dest, tm);
+		}
       if (!do_locales)
         setlocale (LC_TIME, "");
 
--- mutt.h.orig	2019-12-06 03:41:43 UTC
+++ mutt.h
@@ -165,6 +165,16 @@ typedef enum
   MUTT_WRITE_HEADER_MIME
 } mutt_write_header_mode;
 
+/* flags for SmartDate */
+typedef enum {
+    FUTURE      = 1,
+    SMARTTIME   = 2,
+    YESTERDAY   = 3,
+    WEEKDAY     = 4,
+    STANDARD    = 5,
+    ANCIENT     = 6
+} smartdate_type;
+
 /* types for mutt_add_hook() */
 #define MUTT_FOLDERHOOK  1
 #define MUTT_MBOXHOOK    (1<<1)