]> git.sur5r.net Git - i3/i3status/blob - src/print_ddate.c
Implement the i3bar JSON protocol
[i3/i3status] / src / print_ddate.c
1 // vim:ts=8:expandtab
2 #include <time.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6
7 #include "i3status.h"
8
9 /* define fixed output-Strings */
10 char *season_long[5] = {
11         "Chaos",
12         "Discord",
13         "Confusion",
14         "Bureaucracy",
15         "The Aftermath"
16 };
17
18 char *season_short[5] = {
19         "Chs",
20         "Dsc",
21         "Cfn",
22         "Bcy",
23         "Afm"
24 };
25
26 char *day_long[5] = {
27         "Sweetmorn",
28         "Boomtime",
29         "Pungenday",
30         "Prickle-Prickle",
31         "Setting Orange"
32 };
33
34 char *day_short[5] = {
35         "SM",
36         "BT",
37         "PD",
38         "PP",
39         "SO"
40 };
41
42 char *holidays[10] = {
43         "Mungday",
44         "Mojoday",
45         "Syaday",
46         "Zaraday",
47         "Maladay",
48         "Chaoflux",
49         "Discoflux",
50         "Confuflux",
51         "Bureflux",
52         "Afflux"
53 };
54
55 /* A helper-struct, taking the discordian date */
56 struct disc_time {
57         int year;
58         int season;
59         int week_day;
60         int season_day;
61         int st_tibs_day;
62 };
63
64 /* Print the date *dt in format *format */
65 int format_output(char *format, struct disc_time *dt) {
66         char *i;
67         char *tibs_end = 0;
68
69         for (i = format; *i != '\0'; i++) {
70                 if (*i != '%') {
71                         putchar(*i);
72                         continue;
73                 }
74                 switch (*(i+1)) {
75                         /* Weekday in long and abbreviation */
76                         case 'A':
77                                 printf("%s", day_long[dt->week_day]);
78                                 break;
79                         case 'a':
80                                 printf("%s", day_short[dt->week_day]);
81                                 break;
82                         /* Season in long and abbreviation */
83                         case 'B':
84                                 printf("%s", season_long[dt->season]);
85                                 break;
86                         case 'b':
87                                 printf("%s", season_short[dt->season]);
88                                 break;
89                         /* Day of the season (ordinal and cardinal) */
90                         case 'd':
91                                 printf("%d", dt->season_day + 1);
92                                 break;
93                         case 'e':
94                                 printf("%d", dt->season_day + 1);
95                                 switch (dt->season_day) {
96                                         case 0:
97                                                 printf("st");
98                                                 break;
99                                         case 1:
100                                                 printf("nd");
101                                                 break;
102                                         case 2:
103                                                 printf("rd");
104                                                 break;
105                                         default:
106                                                 printf("th");
107                                                 break;
108                                 }
109                                 break;
110                         /* YOLD */
111                         case 'Y':
112                                 printf("%d", dt->year);
113                                 break;
114                         /* Holidays */
115                         case 'H':
116                                 if (dt->season_day == 4) {
117                                         printf(holidays[dt->season]);
118                                 }
119                                 if (dt->season_day == 49) {
120                                         printf(holidays[dt->season + 5]);
121                                 }
122                                 break;
123                         /* Stop parsing the format string, except on Holidays */
124                         case 'N':
125                                 if (dt->season_day != 4 && dt->season_day != 49) {
126                                         return 0;
127                                 }
128                                 break;
129                         /* Newline- and Tabbing-characters */
130                         case 'n':
131                                 printf("\n");
132                                 break;
133                         case 't':
134                                 printf("\t");
135                                 break;
136                         /* The St. Tib's Day replacement */
137                         case '{':
138                                 tibs_end = strstr(i, "%}");
139                                 if (tibs_end == NULL) {
140                                         i++;
141                                         break;
142                                 }
143                                 if (dt->st_tibs_day) {
144                                         /* We outpt "St. Tib's Day... */
145                                         printf("St. Tib's Day");
146                                 } else {
147                                         /* ...or parse the substring between %{ and %} ... */
148                                         *tibs_end = '\0';
149                                         if (!format_output(i + 2, dt)) return 0;
150                                         *tibs_end = '%';
151                                 }
152                                 /* ...and continue with the rest */
153                                 i = tibs_end;
154                                 break;
155                         case '}':
156                                 i++;
157                                 break;
158                         default:
159                                 /* No escape-sequence, so we just skip */
160                                 printf("%%%c",*(i+1));
161                                 break;
162                 }
163                 i++;
164         }
165         return 1;
166 }
167
168 /* Get the current date and convert it to discordian */
169 struct disc_time *get_ddate(struct tm *current_tm) {
170         static struct disc_time dt;
171
172         if (current_tm == NULL)
173                 return NULL;
174
175         /* We have to know, whether we have to insert St. Tib's Day, so whether it's a leap
176            year in gregorian calendar */
177         int is_leap_year = !(current_tm->tm_year % 4) &&
178                             (!(current_tm->tm_year % 400) || current_tm->tm_year % 100);
179
180         if (is_leap_year && current_tm->tm_yday == 59) {
181                 /* On St. Tibs Day we don't have to define a date */
182                 dt.st_tibs_day = 1;
183         } else {
184                 dt.st_tibs_day = 0;
185                 dt.season_day = current_tm->tm_yday % 73;
186                 if (is_leap_year && current_tm->tm_yday > 59) {
187                         dt.week_day = (current_tm->tm_yday - 1) % 5;
188                 } else {
189                         dt.week_day = current_tm->tm_yday % 5;
190                 }
191         }
192         dt.year = current_tm->tm_year + 3066;
193         dt.season = current_tm->tm_yday / 73;
194         return &dt;
195 }
196
197 void print_ddate(const char *format, struct tm *current_tm) {
198         static char *form = NULL;
199         struct disc_time *dt;
200         if ((dt = get_ddate(current_tm)) == NULL)
201                 return;
202         if (form == NULL)
203                 if ((form = malloc(strlen(format) + 1)) == NULL)
204                         return;
205         if (output_format == O_I3BAR)
206                 printf("{\"name\":\"ddate\", \"full_text\":\"");
207         strcpy(form, format);
208         format_output(form, dt);
209         if (output_format == O_I3BAR)
210                 printf("\"}");
211 }