Introduction
Introduction Statistics Contact Development Disclaimer Help
cal.c - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
cal.c (5009B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <limits.h>
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <time.h>
8 #include <unistd.h>
9
10 #include "util.h"
11
12 enum { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
13 enum caltype { JULIAN, GREGORIAN };
14 enum { TRANS_YEAR = 1752, TRANS_MONTH = SEP, TRANS_DAY = 2 };
15
16 static struct tm *ltime;
17
18 static int
19 isleap(size_t year, enum caltype cal)
20 {
21 if (cal == GREGORIAN) {
22 if (year % 400 == 0)
23 return 1;
24 if (year % 100 == 0)
25 return 0;
26 return (year % 4 == 0);
27 }
28 else { /* cal == Julian */
29 return (year % 4 == 0);
30 }
31 }
32
33 static int
34 monthlength(size_t year, int month, enum caltype cal)
35 {
36 int mdays[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
37
38 return (month == FEB && isleap(year, cal)) ? 29 : mdays[month];
39 }
40
41 /* From http://www.tondering.dk/claus/cal/chrweek.php#calcdow */
42 static int
43 dayofweek(size_t year, int month, int dom, enum caltype cal)
44 {
45 size_t y;
46 int m, a;
47
48 a = (13 - month) / 12;
49 y = year - a;
50 m = month + 12 * a - 1;
51
52 if (cal == GREGORIAN)
53 return (dom + y + y / 4 - y / 100 + y / 400 + (31 * m) /…
54 else /* cal == Julian */
55 return (5 + dom + y + y / 4 + (31 * m) / 12) % 7;
56 }
57
58 static void
59 printgrid(size_t year, int month, int fday, int line)
60 {
61 enum caltype cal;
62 int offset, dom, d = 0, trans; /* are we in the transition from …
63 int today = 0;
64
65 cal = (year < TRANS_YEAR || (year == TRANS_YEAR && month <= TRAN…
66 trans = (year == TRANS_YEAR && month == TRANS_MONTH);
67 offset = dayofweek(year, month, 1, cal) - fday;
68
69 if (offset < 0)
70 offset += 7;
71 if (line == 1) {
72 for (; d < offset; ++d)
73 printf(" ");
74 dom = 1;
75 } else {
76 dom = 8 - offset + (line - 2) * 7;
77 if (trans && !(line == 2 && fday == 3))
78 dom += 11;
79 }
80 if (ltime && year == ltime->tm_year + 1900 && month == ltime->tm…
81 today = ltime->tm_mday;
82 for (; d < 7 && dom <= monthlength(year, month, cal); ++d, ++dom…
83 if (dom == today)
84 printf("\x1b[7m%2d\x1b[0m ", dom); /* highlight …
85 else
86 printf("%2d ", dom);
87 if (trans && dom == TRANS_DAY)
88 dom += 11;
89 }
90 for (; d < 7; ++d)
91 printf(" ");
92 }
93
94 static void
95 drawcal(size_t year, int month, size_t ncols, size_t nmons, int fday)
96 {
97 char *smon[] = { "January", "February", "March", "April",
98 "May", "June", "July", "August",
99 "September", "October", "November", "December" …
100 char *days[] = { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa", };
101 size_t m, n, col, cur_year, cur_month, dow;
102 int line, pad;
103 char month_year[sizeof("Su Mo Tu We Th Fr Sa")];
104
105 for (m = 0; m < nmons; ) {
106 n = m;
107 for (col = 0; m < nmons && col < ncols; ++col, ++m) {
108 cur_year = year + m / 12;
109 cur_month = month + m % 12;
110 if (cur_month > 11) {
111 cur_month -= 12;
112 cur_year += 1;
113 }
114 snprintf(month_year, sizeof(month_year), "%s %zu…
115 pad = sizeof(month_year) - 1 - strlen(month_year…
116 printf("%*s%s%*s ", pad / 2 + pad % 2, "", mon…
117 }
118 putchar('\n');
119 for (col = 0, m = n; m < nmons && col < ncols; ++col, ++…
120 for (dow = fday; dow < (fday + 7); ++dow)
121 printf("%s ", days[dow % 7]);
122 printf(" ");
123 }
124 putchar('\n');
125 for (line = 1; line <= 6; ++line) {
126 for (col = 0, m = n; m < nmons && col < ncols; +…
127 cur_year = year + m / 12;
128 cur_month = month + m % 12;
129 if (cur_month > 11) {
130 cur_month -= 12;
131 cur_year += 1;
132 }
133 printgrid(cur_year, cur_month, fday, lin…
134 printf(" ");
135 }
136 putchar('\n');
137 }
138 }
139 }
140
141 static void
142 usage(void)
143 {
144 eprintf("usage: %s [-1 | -3 | -y | -n num] "
145 "[-s | -m | -f num] [-c num] [[month] year]\n", argv0);
146 }
147
148 int
149 main(int argc, char *argv[])
150 {
151 time_t now;
152 size_t year, ncols, nmons;
153 int fday, month;
154
155 now = time(NULL);
156 ltime = localtime(&now);
157 year = ltime->tm_year + 1900;
158 month = ltime->tm_mon + 1;
159 fday = 0;
160
161 if (!isatty(STDOUT_FILENO))
162 ltime = NULL; /* don't highlight today's date */
163
164 ncols = 3;
165 nmons = 0;
166
167 ARGBEGIN {
168 case '1':
169 nmons = 1;
170 break;
171 case '3':
172 nmons = 3;
173 if (--month == 0) {
174 month = 12;
175 year--;
176 }
177 break;
178 case 'c':
179 ncols = estrtonum(EARGF(usage()), 0, MIN(SIZE_MAX, LLONG…
180 break;
181 case 'f':
182 fday = estrtonum(EARGF(usage()), 0, 6);
183 break;
184 case 'm': /* Monday */
185 fday = 1;
186 break;
187 case 'n':
188 nmons = estrtonum(EARGF(usage()), 1, MIN(SIZE_MAX, LLONG…
189 break;
190 case 's': /* Sunday */
191 fday = 0;
192 break;
193 case 'y':
194 month = 1;
195 nmons = 12;
196 break;
197 default:
198 usage();
199 } ARGEND
200
201 if (nmons == 0) {
202 if (argc == 1) {
203 month = 1;
204 nmons = 12;
205 } else {
206 nmons = 1;
207 }
208 }
209
210 switch (argc) {
211 case 2:
212 month = estrtonum(argv[0], 1, 12);
213 argv++;
214 case 1: /* fallthrough */
215 year = estrtonum(argv[0], 0, INT_MAX);
216 break;
217 case 0:
218 break;
219 default:
220 usage();
221 }
222
223 drawcal(year, month - 1, ncols, nmons, fday);
224
225 return fshut(stdout, "<stdout>");
226 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.