ncal.c (531a1a4b2cdc1420829e631448322c0babc2963b) ncal.c (0cb2e609d9c2f0ceaf730a57ac5c11580058e7f4)
1/*-
2 * Copyright (c) 1997 Wolfgang Helbig
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 8 unchanged lines hidden (view full) ---

17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
1/*-
2 * Copyright (c) 1997 Wolfgang Helbig
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 8 unchanged lines hidden (view full) ---

17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id$
25 */
27 */
26
27#ifndef lint
28static const char rcsid[] =
29 "$FreeBSD$";
30#endif /* not lint */
31
32#include <calendar.h>
28#include <calendar.h>
33#include <ctype.h>
34#include <err.h>
29#include <err.h>
35#include <langinfo.h>
36#include <locale.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <sysexits.h>
41#include <time.h>
42#include <unistd.h>
30#include <locale.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <sysexits.h>
35#include <time.h>
36#include <unistd.h>
43#include <wchar.h>
44#include <wctype.h>
45#include <term.h>
46#undef lines /* term.h defines this */
47
37
48/* Width of one month with backward compatibility and in regular mode*/
38/* Width of one month with backward compatibility */
49#define MONTH_WIDTH_B_J 27
50#define MONTH_WIDTH_B 20
51
39#define MONTH_WIDTH_B_J 27
40#define MONTH_WIDTH_B 20
41
52#define MONTH_WIDTH_R_J 24
53#define MONTH_WIDTH_R 18
42#define MONTH_WIDTH_J 24
43#define MONTH_WIDTH 18
54
44
55#define MAX_WIDTH 64
45#define MAX_WIDTH 28
56
57typedef struct date date;
58
59struct monthlines {
46
47typedef struct date date;
48
49struct monthlines {
60 wchar_t name[MAX_WIDTH + 1];
50 char name[MAX_WIDTH + 1];
61 char lines[7][MAX_WIDTH + 1];
62 char weeks[MAX_WIDTH + 1];
51 char lines[7][MAX_WIDTH + 1];
52 char weeks[MAX_WIDTH + 1];
63 unsigned int extralen[7];
64};
65
66struct weekdays {
53};
54
55struct weekdays {
67 wchar_t names[7][4];
56 char names[7][4];
68};
69
70/* The switches from Julian to Gregorian in some countries */
71static struct djswitch {
57};
58
59/* The switches from Julian to Gregorian in some countries */
60static struct djswitch {
72 const char *cc; /* Country code according to ISO 3166 */
73 const char *nm; /* Name of country */
61 char *cc; /* Country code according to ISO 3166 */
62 char *nm; /* Name of country */
74 date dt; /* Last day of Julian calendar */
75} switches[] = {
63 date dt; /* Last day of Julian calendar */
64} switches[] = {
76 {"AL", "Albania", {1912, 11, 30}},
77 {"AT", "Austria", {1583, 10, 5}},
78 {"AU", "Australia", {1752, 9, 2}},
79 {"BE", "Belgium", {1582, 12, 14}},
80 {"BG", "Bulgaria", {1916, 3, 18}},
81 {"CA", "Canada", {1752, 9, 2}},
82 {"CH", "Switzerland", {1655, 2, 28}},
83 {"CN", "China", {1911, 12, 18}},
65 {"AL", "Albania", {1912, 11, 30}},
66 {"BG", "Bulgaria", {1916, 3, 18}},
67 {"CA", "Canada", {1752, 9, 2}},
68 {"CH", "Switzerland", {1655, 2, 28}},
69 {"CN", "China", {1911, 12, 18}},
84 {"CZ", "Czech Republic",{1584, 1, 6}},
70 {"CZ", "Czech Republic",{1584, 1, 6}},
85 {"DE", "Germany", {1700, 2, 18}},
86 {"DK", "Denmark", {1700, 2, 18}},
87 {"ES", "Spain", {1582, 10, 4}},
88 {"FI", "Finland", {1753, 2, 17}},
89 {"FR", "France", {1582, 12, 9}},
71 {"DE", "Germany", {1700, 2, 18}},
72 {"DK", "Denmark", {1700, 2, 18}},
73 {"ES", "Spain", {1582, 10, 4}},
74 {"FR", "France", {1582, 12, 9}},
90 {"GB", "United Kingdom",{1752, 9, 2}},
75 {"GB", "United Kingdom",{1752, 9, 2}},
91 {"GR", "Greece", {1924, 3, 9}},
92 {"HU", "Hungary", {1587, 10, 21}},
93 {"IS", "Iceland", {1700, 11, 16}},
94 {"IT", "Italy", {1582, 10, 4}},
95 {"JP", "Japan", {1918, 12, 18}},
96 {"LI", "Lithuania", {1918, 2, 1}},
97 {"LN", "Latin", {9999, 05, 31}},
98 {"LU", "Luxembourg", {1582, 12, 14}},
99 {"LV", "Latvia", {1918, 2, 1}},
100 {"NL", "Netherlands", {1582, 12, 14}},
101 {"NO", "Norway", {1700, 2, 18}},
102 {"PL", "Poland", {1582, 10, 4}},
103 {"PT", "Portugal", {1582, 10, 4}},
104 {"RO", "Romania", {1919, 3, 31}},
105 {"RU", "Russia", {1918, 1, 31}},
106 {"SI", "Slovenia", {1919, 3, 4}},
107 {"SW", "Sweden", {1753, 2, 17}},
108 {"TR", "Turkey", {1926, 12, 18}},
109 {"US", "United States", {1752, 9, 2}},
110 {"YU", "Yugoslavia", {1919, 3, 4}}
76 {"GR", "Greece", {1924, 3, 9}},
77 {"HU", "Hungary", {1587, 10, 21}},
78 {"IS", "Iceland", {1700, 11, 16}},
79 {"IT", "Italy", {1582, 10, 4}},
80 {"JP", "Japan", {1918, 12, 18}},
81 {"LV", "Latvia", {1918, 2, 1}},
82 {"LI", "Lithuania", {1918, 2, 1}},
83 {"NL", "Netherlands", {1701, 4, 30}},
84 {"NO", "Norway", {1700, 2, 18}},
85 {"PT", "Portugal", {1582, 10, 4}},
86 {"RO", "Romania", {1920, 3, 4}},
87 {"RU", "Russia", {1920, 3, 4}},
88 {"SW", "Sweden", {1753, 2, 17}},
89 {"TR", "Turkey", {1926, 12, 18}},
90 {"US", "United States", {1752, 9, 2}},
91 {"YU", "Yugoslavia", {1919, 3, 4}},
111};
112
92};
93
113struct djswitch *dftswitch =
114 switches + sizeof(switches) / sizeof(struct djswitch) - 2;
115 /* default switch (should be "US") */
116
117/* Table used to print day of month and week numbers */
118char daystr[] = " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
119 " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"
120 " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47"
121 " 48 49 50 51 52 53";
122
123/* Table used to print day of year and week numbers */
124char jdaystr[] = " 1 2 3 4 5 6 7 8 9"

--- 29 unchanged lines hidden (view full) ---

154 " 300 301 302 303 304 305 306 307 308 309"
155 " 310 311 312 313 314 315 316 317 318 319"
156 " 320 321 322 323 324 325 326 327 328 329"
157 " 330 331 332 333 334 335 336 337 338 339"
158 " 340 341 342 343 344 345 346 347 348 349"
159 " 350 351 352 353 354 355 356 357 358 359"
160 " 360 361 362 363 364 365 366";
161
94/* Table used to print day of month and week numbers */
95char daystr[] = " 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15"
96 " 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31"
97 " 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47"
98 " 48 49 50 51 52 53";
99
100/* Table used to print day of year and week numbers */
101char jdaystr[] = " 1 2 3 4 5 6 7 8 9"

--- 29 unchanged lines hidden (view full) ---

131 " 300 301 302 303 304 305 306 307 308 309"
132 " 310 311 312 313 314 315 316 317 318 319"
133 " 320 321 322 323 324 325 326 327 328 329"
134 " 330 331 332 333 334 335 336 337 338 339"
135 " 340 341 342 343 344 345 346 347 348 349"
136 " 350 351 352 353 354 355 356 357 358 359"
137 " 360 361 362 363 364 365 366";
138
162int flag_nohighlight; /* user doesn't want a highlighted today */
163int flag_weeks; /* user wants number of week */
139int flag_weeks; /* user wants weekdays */
164int nswitch; /* user defined switch date */
165int nswitchb; /* switch date for backward compatibility */
140int nswitch; /* user defined switch date */
141int nswitchb; /* switch date for backward compatibility */
166int highlightdate;
167
142
168char *center(char *s, char *t, int w);
169wchar_t *wcenter(wchar_t *s, wchar_t *t, int w);
170int firstday(int y, int m);
171void highlight(char *dst, char *src, int len, int *extraletters);
172void mkmonthr(int year, int month, int jd_flag, struct monthlines * monthl);
173void mkmonthb(int year, int month, int jd_flag, struct monthlines * monthl);
174void mkweekdays(struct weekdays * wds);
175void monthranger(int year, int m, int jd_flag, int before, int after);
176void monthrangeb(int year, int m, int jd_flag, int before, int after);
177int parsemonth(const char *s, int *m, int *y);
178void printcc(void);
179void printeaster(int year, int julian, int orthodox);
180date *sdater(int ndays, struct date * d);
181date *sdateb(int ndays, struct date * d);
182int sndaysr(struct date * d);
183int sndaysb(struct date * d);
184static void usage(void);
143char *center(char *s, char *t, int w);
144void mkmonth(int year, int month, int jd_flag, struct monthlines * monthl);
145void mkmonthb(int year, int month, int jd_flag, struct monthlines * monthl);
146void mkweekdays(struct weekdays * wds);
147void printcc(void);
148void printeaster(int year, int julian, int orthodox);
149void printmonth(int year, int month, int jd_flag);
150void printmonthb(int year, int month, int jd_flag);
151void printyear(int year, int jd_flag);
152void printyearb(int year, int jd_flag);
153date *sdate(int ndays, struct date * d);
154date *sdateb(int ndays, struct date * d);
155int sndays(struct date * d);
156int sndaysb(struct date * d);
157void usage(void);
158int weekdayb(int nd);
185
186int
187main(int argc, char *argv[])
188{
189 struct djswitch *p, *q; /* to search user defined switch date */
190 date never = {10000, 1, 1}; /* outside valid range of dates */
191 date ukswitch = {1752, 9, 2};/* switch date for Great Britain */
159
160int
161main(int argc, char *argv[])
162{
163 struct djswitch *p, *q; /* to search user defined switch date */
164 date never = {10000, 1, 1}; /* outside valid range of dates */
165 date ukswitch = {1752, 9, 2};/* switch date for Great Britain */
192 date dt;
193 int ch; /* holds the option character */
194 int m = 0; /* month */
195 int y = 0; /* year */
196 int flag_backward = 0; /* user called cal--backward compat. */
166 int ch; /* holds the option character */
167 int m = 0; /* month */
168 int y = 0; /* year */
169 int flag_backward = 0; /* user called cal--backward compat. */
197 int flag_wholeyear = 0; /* user wants the whole year */
170 int flag_hole_year = 0; /* user wants the whole year */
198 int flag_julian_cal = 0; /* user wants Julian Calendar */
171 int flag_julian_cal = 0; /* user wants Julian Calendar */
199 int flag_julian_day = 0; /* user wants the Julian day numbers */
200 int flag_orthodox = 0; /* user wants Orthodox easter */
201 int flag_easter = 0; /* user wants easter date */
202 int flag_3months = 0; /* user wants 3 month display (-3) */
203 int flag_after = 0; /* user wants to see months after */
204 int flag_before = 0; /* user wants to see months before */
205 int flag_specifiedmonth = 0;/* user wants to see this month (-m) */
206 int flag_givenmonth = 0; /* user has specified month [n] */
207 int flag_givenyear = 0; /* user has specified year [n] */
172 int flag_julian_day = 0; /* user wants the Julian day
173 * numbers */
174 int flag_orthodox = 0; /* use wants Orthodox easter */
175 int flag_easter = 0; /* use wants easter date */
208 char *cp; /* character pointer */
176 char *cp; /* character pointer */
209 char *flag_today = NULL; /* debug: use date as being today */
210 char *flag_month = NULL; /* requested month as string */
211 char *flag_highlightdate = NULL; /* debug: date to highlight */
212 int before, after;
213 const char *locale; /* locale to get country code */
214
177
215 flag_nohighlight = 0;
216 flag_weeks = 0;
178 setlocale(LC_TIME, "");
217
218 /*
179
180 /*
219 * Use locale to determine the country code,
220 * and use the country code to determine the default
221 * switchdate and date format from the switches table.
222 */
223 if (setlocale(LC_ALL, "") == NULL)
224 warn("setlocale");
225 locale = setlocale(LC_TIME, NULL);
226 if (locale == NULL ||
227 strcmp(locale, "C") == 0 ||
228 strcmp(locale, "POSIX") == 0 ||
229 strcmp(locale, "ASCII") == 0 ||
230 strcmp(locale, "US-ASCII") == 0)
231 locale = "_US";
232 q = switches + sizeof(switches) / sizeof(struct djswitch);
233 for (p = switches; p != q; p++)
234 if ((cp = strstr(locale, p->cc)) != NULL && *(cp - 1) == '_')
235 break;
236 if (p == q) {
237 nswitch = ndaysj(&dftswitch->dt);
238 } else {
239 nswitch = ndaysj(&p->dt);
240 dftswitch = p;
241 }
242
243
244 /*
245 * Get the filename portion of argv[0] and set flag_backward if
246 * this program is called "cal".
247 */
181 * Get the filename portion of argv[0] and set flag_backward if
182 * this program is called "cal".
183 */
248 cp = strrchr(argv[0], '/');
249 cp = (cp == NULL) ? argv[0] : cp + 1;
250 if (strcmp("cal", cp) == 0)
184 for (cp = argv[0]; *cp; cp++)
185 ;
186 while (cp >= argv[0] && *cp != '/')
187 cp--;
188 if (strcmp("cal", ++cp) == 0)
251 flag_backward = 1;
252
253 /* Set the switch date to United Kingdom if backwards compatible */
254 if (flag_backward)
255 nswitchb = ndaysj(&ukswitch);
256
189 flag_backward = 1;
190
191 /* Set the switch date to United Kingdom if backwards compatible */
192 if (flag_backward)
193 nswitchb = ndaysj(&ukswitch);
194
257 before = after = -1;
258
259 while ((ch = getopt(argc, argv, "3A:B:Cd:eH:hjJm:Nops:wy")) != -1)
195 while ((ch = getopt(argc, argv, "Jejops:wy")) != -1)
260 switch (ch) {
196 switch (ch) {
261 case '3':
262 flag_3months = 1;
263 break;
264 case 'A':
265 if (flag_after > 0)
266 errx(EX_USAGE, "Double -A specified");
267 flag_after = strtol(optarg, NULL, 10);
268 if (flag_after <= 0)
269 errx(EX_USAGE,
270 "Argument to -A must be positive");
271 break;
272 case 'B':
273 if (flag_before > 0)
274 errx(EX_USAGE, "Double -A specified");
275 flag_before = strtol(optarg, NULL, 10);
276 if (flag_before <= 0)
277 errx(EX_USAGE,
278 "Argument to -B must be positive");
279 break;
280 case 'J':
281 if (flag_backward)
282 usage();
283 nswitch = ndaysj(&never);
284 flag_julian_cal = 1;
285 break;
197 case 'J':
198 if (flag_backward)
199 usage();
200 nswitch = ndaysj(&never);
201 flag_julian_cal = 1;
202 break;
286 case 'C':
287 flag_backward = 1;
288 break;
289 case 'N':
290 flag_backward = 0;
291 break;
292 case 'd':
293 flag_today = optarg;
294 break;
295 case 'H':
296 flag_highlightdate = optarg;
297 break;
298 case 'h':
299 flag_nohighlight = 1;
300 break;
301 case 'e':
302 if (flag_backward)
303 usage();
304 flag_easter = 1;
305 break;
306 case 'j':
307 flag_julian_day = 1;
308 break;
203 case 'e':
204 if (flag_backward)
205 usage();
206 flag_easter = 1;
207 break;
208 case 'j':
209 flag_julian_day = 1;
210 break;
309 case 'm':
310 if (flag_specifiedmonth)
311 errx(EX_USAGE, "Double -m specified");
312 flag_month = optarg;
313 flag_specifiedmonth = 1;
314 break;
315 case 'o':
316 if (flag_backward)
317 usage();
318 flag_orthodox = 1;
319 flag_easter = 1;
320 break;
321 case 'p':
322 if (flag_backward)

--- 15 unchanged lines hidden (view full) ---

338 nswitch = ndaysj(&(p->dt));
339 break;
340 case 'w':
341 if (flag_backward)
342 usage();
343 flag_weeks = 1;
344 break;
345 case 'y':
211 case 'o':
212 if (flag_backward)
213 usage();
214 flag_orthodox = 1;
215 flag_easter = 1;
216 break;
217 case 'p':
218 if (flag_backward)

--- 15 unchanged lines hidden (view full) ---

234 nswitch = ndaysj(&(p->dt));
235 break;
236 case 'w':
237 if (flag_backward)
238 usage();
239 flag_weeks = 1;
240 break;
241 case 'y':
346 flag_wholeyear = 1;
242 flag_hole_year = 1;
347 break;
348 default:
349 usage();
350 }
351
352 argc -= optind;
353 argv += optind;
354
243 break;
244 default:
245 usage();
246 }
247
248 argc -= optind;
249 argv += optind;
250
251 if (argc == 0) {
252 time_t t;
253 struct tm *tm;
254
255 t = time(NULL);
256 tm = localtime(&t);
257 y = tm->tm_year + 1900;
258 m = tm->tm_mon + 1;
259 }
260
355 switch (argc) {
356 case 2:
357 if (flag_easter)
358 usage();
261 switch (argc) {
262 case 2:
263 if (flag_easter)
264 usage();
359 flag_month = *argv++;
360 flag_givenmonth = 1;
361 m = strtol(flag_month, NULL, 10);
265 m = atoi(*argv++);
266 if (m < 1 || m > 12)
267 errx(EX_USAGE, "month %d not in range 1..12", m);
362 /* FALLTHROUGH */
363 case 1:
268 /* FALLTHROUGH */
269 case 1:
364 y = atoi(*argv);
270 y = atoi(*argv++);
365 if (y < 1 || y > 9999)
271 if (y < 1 || y > 9999)
366 errx(EX_USAGE, "year `%s' not in range 1..9999", *argv);
367 argv++;
368 flag_givenyear = 1;
272 errx(EX_USAGE, "year %d not in range 1..9999", y);
369 break;
370 case 0:
273 break;
274 case 0:
371 if (flag_today != NULL) {
372 y = strtol(flag_today, NULL, 10);
373 m = strtol(flag_today + 5, NULL, 10);
374 } else {
375 time_t t;
376 struct tm *tm;
377
378 t = time(NULL);
379 tm = localtime(&t);
380 y = tm->tm_year + 1900;
381 m = tm->tm_mon + 1;
382 }
383 break;
384 default:
385 usage();
386 }
387
275 break;
276 default:
277 usage();
278 }
279
388 if (flag_month != NULL) {
389 if (parsemonth(flag_month, &m, &y)) {
390 errx(EX_USAGE,
391 "%s is neither a month number (1..12) nor a name",
392 flag_month);
393 }
394 }
395
396 /*
397 * What is not supported:
398 * -3 with -A or -B
399 * -3 displays 3 months, -A and -B change that behaviour.
400 * -3 with -y
401 * -3 displays 3 months, -y says display a whole year.
402 * -3 with a given year but no given month or without -m
403 * -3 displays 3 months, no month specified doesn't make clear
404 * which three months.
405 * -m with a given month
406 * conflicting arguments, both specify the same field.
407 * -y with -m
408 * -y displays the whole year, -m displays a single month.
409 * -y with a given month
410 * -y displays the whole year, the given month displays a single
411 * month.
412 * -y with -A or -B
413 * -y displays the whole year, -A and -B display extra months.
414 */
415
416 /* -3 together with -A or -B. */
417 if (flag_3months && (flag_after || flag_before))
418 errx(EX_USAGE, "-3 together with -A and -B is not supported.");
419 /* -3 together with -y. */
420 if (flag_3months && flag_wholeyear)
421 errx(EX_USAGE, "-3 together with -y is not supported.");
422 /* -3 together with givenyear but no givenmonth. */
423 if (flag_3months && flag_givenyear &&
424 !(flag_givenmonth || flag_specifiedmonth))
425 errx(EX_USAGE,
426 "-3 together with a given year but no given month is "
427 "not supported.");
428 /* -m together with xx xxxx. */
429 if (flag_specifiedmonth && flag_givenmonth)
430 errx(EX_USAGE,
431 "-m together with a given month is not supported.");
432 /* -y together with -m. */
433 if (flag_wholeyear && flag_specifiedmonth)
434 errx(EX_USAGE, "-y together with -m is not supported.");
435 /* -y together with xx xxxx. */
436 if (flag_wholeyear && flag_givenmonth)
437 errx(EX_USAGE, "-y together a given month is not supported.");
438 /* -y together with -A or -B. */
439 if (flag_wholeyear && (flag_before > 0 || flag_after > 0))
440 errx(EX_USAGE, "-y together a -A or -B is not supported.");
441 /* The rest should be fine. */
442
443 /* Select the period to display, in order of increasing priority .*/
444 if (flag_wholeyear ||
445 (flag_givenyear && !(flag_givenmonth || flag_specifiedmonth))) {
446 m = 1;
447 before = 0;
448 after = 11;
449 }
450 if (flag_givenyear && flag_givenmonth) {
451 before = 0;
452 after = 0;
453 }
454 if (flag_specifiedmonth) {
455 before = 0;
456 after = 0;
457 }
458 if (flag_before) {
459 before = flag_before;
460 }
461 if (flag_after) {
462 after = flag_after;
463 }
464 if (flag_3months) {
465 before = 1;
466 after = 1;
467 }
468 if (after == -1)
469 after = 0;
470 if (before == -1)
471 before = 0;
472
473 /* Highlight a specified day or today .*/
474 if (flag_highlightdate != NULL) {
475 dt.y = strtol(flag_highlightdate, NULL, 10);
476 dt.m = strtol(flag_highlightdate + 5, NULL, 10);
477 dt.d = strtol(flag_highlightdate + 8, NULL, 10);
478 } else {
479 time_t t;
480 struct tm *tm1;
481
482 t = time(NULL);
483 tm1 = localtime(&t);
484 dt.y = tm1->tm_year + 1900;
485 dt.m = tm1->tm_mon + 1;
486 dt.d = tm1->tm_mday;
487 }
488 highlightdate = sndaysb(&dt);
489
490 /* And now we finally start to calculate and output calendars. */
491 if (flag_easter)
492 printeaster(y, flag_julian_cal, flag_orthodox);
280 if (flag_easter)
281 printeaster(y, flag_julian_cal, flag_orthodox);
282 else if (argc == 1 || flag_hole_year)
283 if (flag_backward)
284 printyearb(y, flag_julian_day);
285 else
286 printyear(y, flag_julian_day);
493 else
494 if (flag_backward)
287 else
288 if (flag_backward)
495 monthrangeb(y, m, flag_julian_day, before, after);
289 printmonthb(y, m, flag_julian_day);
496 else
290 else
497 monthranger(y, m, flag_julian_day, before, after);
291 printmonth(y, m, flag_julian_day);
292
498 return (0);
499}
500
293 return (0);
294}
295
501static void
296void
502usage(void)
503{
504
297usage(void)
298{
299
505 fputs(
506"Usage: cal [general options] [-hjy] [[month] year]\n"
507" cal [general options] [-hj] [-m month] [year]\n"
508" ncal [general options] [-hJjpwy] [-s country_code] [[month] year]\n"
509" ncal [general options] [-hJeo] [year]\n"
510"General options: [-NC3] [-A months] [-B months]\n"
511"For debug the highlighting: [-H yyyy-mm-dd] [-d yyyy-mm]\n",
512 stderr);
300 fprintf(stderr,
301 "usage: cal [-jy] [month[year]]\n"
302 "usage: ncal [-Jjpwy] [-s country_code] [[month] year]\n"
303 "usage: ncal [-Jeo] [year]\n");
513 exit(EX_USAGE);
514}
515
304 exit(EX_USAGE);
305}
306
516/* Print the assumed switches for all countries. */
307/* print the assumed switches for all countries */
517void
518printcc(void)
519{
520 struct djswitch *p;
521 int n; /* number of lines to print */
522 int m; /* offset from left to right table entry on the same line */
523
308void
309printcc(void)
310{
311 struct djswitch *p;
312 int n; /* number of lines to print */
313 int m; /* offset from left to right table entry on the same line */
314
524#define FSTR "%c%s %-15s%4d-%02d-%02d"
525#define DFLT(p) ((p) == dftswitch ? '*' : ' ')
526#define FSTRARG(p) DFLT(p), (p)->cc, (p)->nm, (p)->dt.y, (p)->dt.m, (p)->dt.d
315#define FSTR "%s %-15s %4d-%02d-%02d"
527
528 n = sizeof(switches) / sizeof(struct djswitch);
529 m = (n + 1) / 2;
530 n /= 2;
316
317 n = sizeof(switches) / sizeof(struct djswitch);
318 m = (n + 1) / 2;
319 n /= 2;
531 for (p = switches; p != switches + n; p++)
532 printf(FSTR" "FSTR"\n", FSTRARG(p), FSTRARG(p+m));
320 for (p = switches; p != switches + n; p++) {
321 printf(FSTR" "FSTR"\n" ,
322 p->cc, p->nm, p->dt.y, p->dt.m, p->dt.d,
323 (p+m)->cc, (p+m)->nm, (p+m)->dt.y,
324 (p+m)->dt.m, (p+m)->dt.d);
325 }
533 if (m != n)
326 if (m != n)
534 printf(FSTR"\n", FSTRARG(p));
327 printf(FSTR"\n",
328 p->cc, p->nm, p->dt.y, p->dt.m, p->dt.d);
535}
536
329}
330
537/* Print the date of easter sunday. */
331/* print the date of easter sunday */
538void
539printeaster(int y, int julian, int orthodox)
540{
332void
333printeaster(int y, int julian, int orthodox)
334{
541 date dt;
542 struct tm tm;
543 char buf[MAX_WIDTH];
544 static int d_first = -1;
335 date dt;
545
336
546 if (d_first < 0)
547 d_first = (*nl_langinfo(D_MD_ORDER) == 'd');
548 /* force orthodox easter for years before 1583 */
549 if (y < 1583)
550 orthodox = 1;
551
552 if (orthodox)
553 if (julian)
554 easteroj(y, &dt);
555 else
556 easterog(y, &dt);
557 else
558 easterg(y, &dt);
337 /* force orthodox easter for years before 1583 */
338 if (y < 1583)
339 orthodox = 1;
340
341 if (orthodox)
342 if (julian)
343 easteroj(y, &dt);
344 else
345 easterog(y, &dt);
346 else
347 easterg(y, &dt);
559
560 memset(&tm, 0, sizeof(tm));
561 tm.tm_year = dt.y - 1900;
562 tm.tm_mon = dt.m - 1;
563 tm.tm_mday = dt.d;
564 strftime(buf, sizeof(buf), d_first ? "%e %B %Y" : "%B %e %Y", &tm);
565 printf("%s\n", buf);
348 printf("%04d-%02d-%02d\n", dt.y, dt.m, dt.d);
566}
567
349}
350
568#define MW(mw, me) ((mw) + me)
569#define DECREASEMONTH(m, y) \
570 if (--m == 0) { \
571 m = 12; \
572 y--; \
573 }
574#define INCREASEMONTH(m, y) \
575 if (++(m) == 13) { \
576 (m) = 1; \
577 (y)++; \
578 }
579#define M2Y(m) ((m) / 12)
580#define M2M(m) (1 + (m) % 12)
581
582/* Print all months for the period in the range [ before .. y-m .. after ]. */
583void
351void
584monthrangeb(int y, int m, int jd_flag, int before, int after)
352printmonth(int y, int m, int jd_flag)
585{
353{
586 struct monthlines year[12];
354 struct monthlines month;
587 struct weekdays wds;
355 struct weekdays wds;
588 char s[MAX_WIDTH], t[MAX_WIDTH];
589 wchar_t ws[MAX_WIDTH], ws1[MAX_WIDTH];
590 const char *wdss;
591 int i, j;
592 int mpl;
593 int mw;
594 int m1, m2;
595 int printyearheader;
596 int prevyear = -1;
356 int i;
597
357
598 mpl = jd_flag ? 2 : 3;
599 mw = jd_flag ? MONTH_WIDTH_B_J : MONTH_WIDTH_B;
600 wdss = (mpl == 2) ? " " : "";
358 mkmonth(y, m - 1, jd_flag, &month);
359 mkweekdays(&wds);
360 printf(" %s %d\n", month.name, y);
361 for (i = 0; i != 7; i++)
362 printf("%.2s%s\n", wds.names[i], month.lines[i]);
363 if (flag_weeks)
364 printf(" %s\n", month.weeks);
365}
601
366
602 while (before != 0) {
603 DECREASEMONTH(m, y);
604 before--;
605 after++;
606 }
607 m1 = y * 12 + m - 1;
608 m2 = m1 + after;
367void
368printmonthb(int y, int m, int jd_flag)
369{
370 struct monthlines month;
371 struct weekdays wds;
372 char s[MAX_WIDTH], t[MAX_WIDTH];
373 int i;
374 int mw;
609
375
376 mkmonthb(y, m - 1, jd_flag, &month);
610 mkweekdays(&wds);
611
377 mkweekdays(&wds);
378
612 /*
613 * The year header is printed when there are more than 'mpl' months
614 * and if the first month is a multitude of 'mpl'.
615 * If not, it will print the year behind every month.
616 */
617 printyearheader = (after >= mpl - 1) && (M2M(m1) - 1) % mpl == 0;
379 mw = jd_flag ? MONTH_WIDTH_B_J : MONTH_WIDTH_B;
618
380
619 m = m1;
620 while (m <= m2) {
621 int count = 0;
622 for (i = 0; i != mpl && m + i <= m2; i++) {
623 mkmonthb(M2Y(m + i), M2M(m + i) - 1, jd_flag, year + i);
624 count++;
625 }
381 sprintf(s, "%s %d", month.name, y);
382 printf("%s\n", center(t, s, mw));
626
383
627 /* Empty line between two rows of months */
628 if (m != m1)
629 printf("\n");
384 if (jd_flag)
385 printf(" %s %s %s %s %s %s %.2s\n", wds.names[6], wds.names[0],
386 wds.names[1], wds.names[2], wds.names[3],
387 wds.names[4], wds.names[5]);
388 else
389 printf("%s%s%s%s%s%s%.2s\n", wds.names[6], wds.names[0],
390 wds.names[1], wds.names[2], wds.names[3],
391 wds.names[4], wds.names[5]);
630
392
631 /* Year at the top. */
632 if (printyearheader && M2Y(m) != prevyear) {
633 sprintf(s, "%d", M2Y(m));
634 printf("%s\n", center(t, s, mpl * mw));
635 prevyear = M2Y(m);
636 }
393 for (i = 0; i != 6; i++)
394 printf("%s\n", month.lines[i]+1);
395}
637
396
638 /* Month names. */
639 for (i = 0; i < count; i++)
640 if (printyearheader)
641 wprintf(L"%-*ls ",
642 mw, wcenter(ws, year[i].name, mw));
643 else {
644 swprintf(ws, sizeof(ws), L"%-ls %d",
645 year[i].name, M2Y(m + i));
646 wprintf(L"%-*ls ", mw, wcenter(ws1, ws, mw));
647 }
648 printf("\n");
397void
398printyear(int y, int jd_flag)
399{
400 struct monthlines year[12];
401 struct weekdays wds;
402 char s[80], t[80];
403 int i, j;
404 int mpl;
405 int mw;
649
406
650 /* Day of the week names. */
651 for (i = 0; i < count; i++) {
652 wprintf(L"%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls%s%ls ",
653 wdss, wds.names[6], wdss, wds.names[0],
654 wdss, wds.names[1], wdss, wds.names[2],
655 wdss, wds.names[3], wdss, wds.names[4],
656 wdss, wds.names[5]);
657 }
658 printf("\n");
407 for (i = 0; i != 12; i++)
408 mkmonth(y, i, jd_flag, year + i);
409 mkweekdays(&wds);
410 mpl = jd_flag ? 3 : 4;
411 mw = jd_flag ? MONTH_WIDTH_J : MONTH_WIDTH;
659
412
660 /* And the days of the month. */
661 for (i = 0; i != 6; i++) {
662 for (j = 0; j < count; j++)
663 printf("%-*s ",
664 MW(mw, year[j].extralen[i]),
665 year[j].lines[i]+1);
666 printf("\n");
667 }
413 sprintf(s, "%d", y);
414 printf("%s\n", center(t, s, mpl * mw));
668
415
669 m += mpl;
416 for (j = 0; j != 12; j += mpl) {
417 printf(" %-*s%-*s",
418 mw, year[j].name,
419 mw, year[j + 1].name);
420 if (mpl == 3)
421 printf("%s\n", year[j + 2].name);
422 else
423 printf("%-*s%s\n",
424 mw, year[j + 2].name,
425 year[j + 3].name);
426 for (i = 0; i != 7; i++) {
427 printf("%.2s%-*s%-*s",
428 wds.names[i],
429 mw, year[j].lines[i],
430 mw, year[j + 1].lines[i]);
431 if (mpl == 3)
432 printf("%s\n", year[j + 2].lines[i]);
433 else
434 printf("%-*s%s\n",
435 mw, year[j + 2].lines[i],
436 year[j + 3].lines[i]);
437 }
438 if (flag_weeks)
439 if (mpl == 3)
440 printf(" %-*s%-*s%-s\n",
441 mw, year[j].weeks,
442 mw, year[j + 1].weeks,
443 year[j + 2].weeks);
444 else
445 printf(" %-*s%-*s%-*s%-s\n",
446 mw, year[j].weeks,
447 mw, year[j + 1].weeks,
448 mw, year[j + 2].weeks,
449 year[j + 3].weeks);
670 }
671}
672
673void
450 }
451}
452
453void
674monthranger(int y, int m, int jd_flag, int before, int after)
454printyearb(int y, int jd_flag)
675{
676 struct monthlines year[12];
677 struct weekdays wds;
455{
456 struct monthlines year[12];
457 struct weekdays wds;
678 char s[MAX_WIDTH], t[MAX_WIDTH];
458 char s[80], t[80];
679 int i, j;
680 int mpl;
681 int mw;
459 int i, j;
460 int mpl;
461 int mw;
682 int m1, m2;
683 int prevyear = -1;
684 int printyearheader;
685
462
686 mpl = jd_flag ? 3 : 4;
687 mw = jd_flag ? MONTH_WIDTH_R_J : MONTH_WIDTH_R;
688
689 while (before != 0) {
690 DECREASEMONTH(m, y);
691 before--;
692 after++;
693 }
694 m1 = y * 12 + m - 1;
695 m2 = m1 + after;
696
463 for (i = 0; i != 12; i++)
464 mkmonthb(y, i, jd_flag, year + i);
697 mkweekdays(&wds);
465 mkweekdays(&wds);
466 mpl = jd_flag ? 2 : 3;
467 mw = jd_flag ? MONTH_WIDTH_B_J : MONTH_WIDTH_B;
698
468
699 /*
700 * The year header is printed when there are more than 'mpl' months
701 * and if the first month is a multitude of 'mpl'.
702 * If not, it will print the year behind every month.
703 */
704 printyearheader = (after >= mpl - 1) && (M2M(m1) - 1) % mpl == 0;
469 sprintf(s, "%d", y);
470 printf("%s\n\n", center(t, s, mw * mpl + mpl));
705
471
706 m = m1;
707 while (m <= m2) {
708 int count = 0;
709 for (i = 0; i != mpl && m + i <= m2; i++) {
710 mkmonthr(M2Y(m + i), M2M(m + i) - 1, jd_flag, year + i);
711 count++;
712 }
472 for (j = 0; j != 12; j += mpl) {
473 printf("%-*s ", mw, center(s, year[j].name, mw));
474 if (mpl == 2)
475 printf("%s\n", center(s, year[j + 1].name, mw));
476 else
477 printf("%-*s %s\n", mw,
478 center(s, year[j + 1].name, mw),
479 center(t, year[j + 2].name, mw));
713
480
714 /* Empty line between two rows of months. */
715 if (m != m1)
716 printf("\n");
717
718 /* Year at the top. */
719 if (printyearheader && M2Y(m) != prevyear) {
720 sprintf(s, "%d", M2Y(m));
721 printf("%s\n", center(t, s, mpl * mw));
722 prevyear = M2Y(m);
723 }
724
725 /* Month names. */
726 wprintf(L" ");
727 for (i = 0; i < count; i++)
728 if (printyearheader)
729 wprintf(L"%-*ls", mw, year[i].name);
481 if (mpl == 2)
482 printf(" %s %s %s %s %s %s %s "
483 " %s %s %s %s %s %s %.2s\n",
484 wds.names[6], wds.names[0], wds.names[1],
485 wds.names[2], wds.names[3], wds.names[4],
486 wds.names[5],
487 wds.names[6], wds.names[0], wds.names[1],
488 wds.names[2], wds.names[3], wds.names[4],
489 wds.names[5]);
490 else
491 printf("%s%s%s%s%s%s%s "
492 "%s%s%s%s%s%s%s "
493 "%s%s%s%s%s%s%.2s\n",
494 wds.names[6], wds.names[0], wds.names[1],
495 wds.names[2], wds.names[3], wds.names[4],
496 wds.names[5],
497 wds.names[6], wds.names[0], wds.names[1],
498 wds.names[2], wds.names[3], wds.names[4],
499 wds.names[5],
500 wds.names[6], wds.names[0], wds.names[1],
501 wds.names[2], wds.names[3], wds.names[4],
502 wds.names[5]);
503 for (i = 0; i != 6; i++) {
504 if (mpl == 2)
505 printf("%-*s %s\n",
506 mw, year[j].lines[i]+1,
507 year[j + 1].lines[i]+1);
730 else
508 else
731 wprintf(L"%-ls %-*d", year[i].name,
732 mw - wcslen(year[i].name) - 1, M2Y(m + i));
733 printf("\n");
509 printf("%-*s %-*s %s\n",
510 mw, year[j].lines[i]+1,
511 mw, year[j + 1].lines[i]+1,
512 year[j + 2].lines[i]+1);
734
513
735 /* And the days of the month. */
736 for (i = 0; i != 7; i++) {
737 /* Week day */
738 wprintf(L"%.2ls", wds.names[i]);
739
740 /* Full months */
741 for (j = 0; j < count; j++)
742 printf("%-*s",
743 MW(mw, year[j].extralen[i]),
744 year[j].lines[i]);
745 printf("\n");
746 }
514 }
747
748 /* Week numbers. */
749 if (flag_weeks) {
750 printf(" ");
751 for (i = 0; i < count; i++)
752 printf("%-*s", mw, year[i].weeks);
753 printf("\n");
754 }
755
756 m += mpl;
757 }
515 }
758 return;
759}
760
761void
516}
517
518void
762mkmonthr(int y, int m, int jd_flag, struct monthlines *mlines)
519mkmonth(int y, int m, int jd_flag, struct monthlines *mlines)
763{
764
765 struct tm tm; /* for strftime printing local names of
766 * months */
767 date dt; /* handy date */
768 int dw; /* width of numbers */
769 int first; /* first day of month */
770 int firstm; /* first day of first week of month */
520{
521
522 struct tm tm; /* for strftime printing local names of
523 * months */
524 date dt; /* handy date */
525 int dw; /* width of numbers */
526 int first; /* first day of month */
527 int firstm; /* first day of first week of month */
771 int i, j, k, l; /* just indices */
528 int i, j, k; /* just indices */
772 int last; /* the first day of next month */
773 int jan1 = 0; /* the first day of this year */
774 char *ds; /* pointer to day strings (daystr or
775 * jdaystr) */
776
777 /* Set name of month. */
778 memset(&tm, 0, sizeof(tm));
779 tm.tm_mon = m;
529 int last; /* the first day of next month */
530 int jan1 = 0; /* the first day of this year */
531 char *ds; /* pointer to day strings (daystr or
532 * jdaystr) */
533
534 /* Set name of month. */
535 memset(&tm, 0, sizeof(tm));
536 tm.tm_mon = m;
780 wcsftime(mlines->name, sizeof(mlines->name) / sizeof(mlines->name[0]),
781 L"%OB", &tm);
782 mlines->name[0] = towupper(mlines->name[0]);
537 strftime(mlines->name, sizeof(mlines->name), "%B", &tm);
783
784 /*
785 * Set first and last to the day number of the first day of this
786 * month and the first day of next month respectively. Set jan1 to
538
539 /*
540 * Set first and last to the day number of the first day of this
541 * month and the first day of next month respectively. Set jan1 to
787 * the day number of the first day of this year.
542 * the day number of Jan 1st of this year.
788 */
543 */
789 first = firstday(y, m + 1);
790 if (m == 11)
791 last = firstday(y + 1, 1);
792 else
793 last = firstday(y, m + 2);
544 dt.y = y;
545 dt.m = m + 1;
546 dt.d = 1;
547 first = sndays(&dt);
548 if (m == 11) {
549 dt.y = y + 1;
550 dt.m = 1;
551 dt.d = 1;
552 } else {
553 dt.y = y;
554 dt.m = m + 2;
555 dt.d = 1;
556 }
557 last = sndays(&dt);
794
558
795 if (jd_flag)
796 jan1 = firstday(y, 1);
559 if (jd_flag) {
560 dt.y = y;
561 dt.m = 1;
562 dt.d = 1;
563 jan1 = sndays(&dt);
564 }
797
798 /*
799 * Set firstm to the day number of monday of the first week of
800 * this month. (This might be in the last month)
801 */
802 firstm = first - weekday(first);
803
565
566 /*
567 * Set firstm to the day number of monday of the first week of
568 * this month. (This might be in the last month)
569 */
570 firstm = first - weekday(first);
571
804 /* Set ds (daystring) and dw (daywidth) according to the jd_flag. */
572 /* Set ds (daystring) and dw (daywidth) according to the jd_flag */
805 if (jd_flag) {
806 ds = jdaystr;
807 dw = 4;
808 } else {
809 ds = daystr;
810 dw = 3;
811 }
812
813 /*
814 * Fill the lines with day of month or day of year (julian day)
815 * line index: i, each line is one weekday. column index: j, each
816 * column is one day number. print column index: k.
817 */
818 for (i = 0; i != 7; i++) {
573 if (jd_flag) {
574 ds = jdaystr;
575 dw = 4;
576 } else {
577 ds = daystr;
578 dw = 3;
579 }
580
581 /*
582 * Fill the lines with day of month or day of year (julian day)
583 * line index: i, each line is one weekday. column index: j, each
584 * column is one day number. print column index: k.
585 */
586 for (i = 0; i != 7; i++) {
819 l = 0;
820 for (j = firstm + i, k = 0; j < last; j += 7, k += dw) {
587 for (j = firstm + i, k = 0; j < last; j += 7, k += dw)
821 if (j >= first) {
822 if (jd_flag)
823 dt.d = j - jan1 + 1;
824 else
588 if (j >= first) {
589 if (jd_flag)
590 dt.d = j - jan1 + 1;
591 else
825 sdater(j, &dt);
826 if (j == highlightdate && !flag_nohighlight)
827 highlight(mlines->lines[i] + k,
828 ds + dt.d * dw, dw, &l);
829 else
830 memcpy(mlines->lines[i] + k + l,
831 ds + dt.d * dw, dw);
592 sdate(j, &dt);
593 memcpy(mlines->lines[i] + k,
594 ds + dt.d * dw, dw);
832 } else
595 } else
833 memcpy(mlines->lines[i] + k + l, " ", dw);
834 }
835 mlines->lines[i][k + l] = '\0';
836 mlines->extralen[i] = l;
596 memcpy(mlines->lines[i] + k, " ", dw);
597 mlines->lines[i][k] = '\0';
598
837 }
838
599 }
600
839 /* fill the weeknumbers. */
601 /* fill the weeknumbers */
840 if (flag_weeks) {
841 for (j = firstm, k = 0; j < last; k += dw, j += 7)
842 if (j <= nswitch)
843 memset(mlines->weeks + k, ' ', dw);
844 else
845 memcpy(mlines->weeks + k,
846 ds + week(j, &i)*dw, dw);
847 mlines->weeks[k] = '\0';

--- 5 unchanged lines hidden (view full) ---

853{
854
855 struct tm tm; /* for strftime printing local names of
856 * months */
857 date dt; /* handy date */
858 int dw; /* width of numbers */
859 int first; /* first day of month */
860 int firsts; /* sunday of first week of month */
602 if (flag_weeks) {
603 for (j = firstm, k = 0; j < last; k += dw, j += 7)
604 if (j <= nswitch)
605 memset(mlines->weeks + k, ' ', dw);
606 else
607 memcpy(mlines->weeks + k,
608 ds + week(j, &i)*dw, dw);
609 mlines->weeks[k] = '\0';

--- 5 unchanged lines hidden (view full) ---

615{
616
617 struct tm tm; /* for strftime printing local names of
618 * months */
619 date dt; /* handy date */
620 int dw; /* width of numbers */
621 int first; /* first day of month */
622 int firsts; /* sunday of first week of month */
861 int i, j, k, l; /* just indices */
623 int i, j, k; /* just indices */
862 int jan1 = 0; /* the first day of this year */
863 int last; /* the first day of next month */
864 char *ds; /* pointer to day strings (daystr or
865 * jdaystr) */
866
867 /* Set ds (daystring) and dw (daywidth) according to the jd_flag */
868 if (jd_flag) {
869 ds = jdaystr;
870 dw = 4;
871 } else {
872 ds = daystr;
873 dw = 3;
874 }
875
624 int jan1 = 0; /* the first day of this year */
625 int last; /* the first day of next month */
626 char *ds; /* pointer to day strings (daystr or
627 * jdaystr) */
628
629 /* Set ds (daystring) and dw (daywidth) according to the jd_flag */
630 if (jd_flag) {
631 ds = jdaystr;
632 dw = 4;
633 } else {
634 ds = daystr;
635 dw = 3;
636 }
637
876 /* Set name of month centered. */
638 /* Set name of month centered */
877 memset(&tm, 0, sizeof(tm));
878 tm.tm_mon = m;
639 memset(&tm, 0, sizeof(tm));
640 tm.tm_mon = m;
879 wcsftime(mlines->name, sizeof(mlines->name) / sizeof(mlines->name[0]),
880 L"%OB", &tm);
881 mlines->name[0] = towupper(mlines->name[0]);
641 strftime(mlines->name, sizeof(mlines->name), "%B", &tm);
882
883 /*
884 * Set first and last to the day number of the first day of this
885 * month and the first day of next month respectively. Set jan1 to
886 * the day number of Jan 1st of this year.
887 */
888 dt.y = y;
889 dt.m = m + 1;

--- 24 unchanged lines hidden (view full) ---

914 firsts = first - (weekday(first)+1) % 7;
915
916 /*
917 * Fill the lines with day of month or day of year (Julian day)
918 * line index: i, each line is one week. column index: j, each
919 * column is one day number. print column index: k.
920 */
921 for (i = 0; i != 6; i++) {
642
643 /*
644 * Set first and last to the day number of the first day of this
645 * month and the first day of next month respectively. Set jan1 to
646 * the day number of Jan 1st of this year.
647 */
648 dt.y = y;
649 dt.m = m + 1;

--- 24 unchanged lines hidden (view full) ---

674 firsts = first - (weekday(first)+1) % 7;
675
676 /*
677 * Fill the lines with day of month or day of year (Julian day)
678 * line index: i, each line is one week. column index: j, each
679 * column is one day number. print column index: k.
680 */
681 for (i = 0; i != 6; i++) {
922 l = 0;
923 for (j = firsts + 7 * i, k = 0; j < last && k != dw * 7;
682 for (j = firsts + 7 * i, k = 0; j < last && k != dw * 7;
924 j++, k += dw) {
683 j++, k += dw)
925 if (j >= first) {
926 if (jd_flag)
927 dt.d = j - jan1 + 1;
928 else
929 sdateb(j, &dt);
684 if (j >= first) {
685 if (jd_flag)
686 dt.d = j - jan1 + 1;
687 else
688 sdateb(j, &dt);
930 if (j == highlightdate && !flag_nohighlight)
931 highlight(mlines->lines[i] + k,
932 ds + dt.d * dw, dw, &l);
933 else
934 memcpy(mlines->lines[i] + k + l,
935 ds + dt.d * dw, dw);
689 memcpy(mlines->lines[i] + k,
690 ds + dt.d * dw, dw);
936 } else
691 } else
937 memcpy(mlines->lines[i] + k + l, " ", dw);
938 }
692 memcpy(mlines->lines[i] + k, " ", dw);
939 if (k == 0)
940 mlines->lines[i][1] = '\0';
941 else
693 if (k == 0)
694 mlines->lines[i][1] = '\0';
695 else
942 mlines->lines[i][k + l] = '\0';
943 mlines->extralen[i] = l;
696 mlines->lines[i][k] = '\0';
944 }
945}
946
697 }
698}
699
947/* Put the local names of weekdays into the wds. */
948void
949mkweekdays(struct weekdays *wds)
700/* Put the local names of weekdays into the wds */
701void mkweekdays(struct weekdays *wds)
950{
702{
951 int i, len, width = 0;
703 int i;
952 struct tm tm;
704 struct tm tm;
953 wchar_t buf[20];
954
955 memset(&tm, 0, sizeof(tm));
956
957 for (i = 0; i != 7; i++) {
958 tm.tm_wday = (i+1) % 7;
705
706 memset(&tm, 0, sizeof(tm));
707
708 for (i = 0; i != 7; i++) {
709 tm.tm_wday = (i+1) % 7;
959 wcsftime(buf, sizeof(buf), L"%a", &tm);
960 for (len = 2; len > 0; --len) {
961 if ((width = wcswidth(buf, len)) <= 2)
962 break;
963 }
964 wmemset(wds->names[i], L'\0', 4);
965 if (width == 1)
966 wds->names[i][0] = L' ';
967 wcsncat(wds->names[i], buf, len);
968 wcsncat(wds->names[i], L" ", 1);
710 strftime(wds->names[i], 4, "%a", &tm);
969 }
970}
971
972/*
711 }
712}
713
714/*
973 * Compute the day number of the first existing date after the first day in
974 * month. (the first day in month and even the month might not exist!)
975 */
976int
977firstday(int y, int m)
978{
979 date dt;
980 int nd;
981
982 dt.y = y;
983 dt.m = m;
984 dt.d = 1;
985 nd = sndaysr(&dt);
986 for (;;) {
987 sdater(nd, &dt);
988 if ((dt.m >= m && dt.y == y) || dt.y > y)
989 return (nd);
990 else
991 nd++;
992 }
993 /* NEVER REACHED */
994}
995
996/*
997 * Compute the number of days from date, obey the local switch from
998 * Julian to Gregorian if specified by the user.
999 */
1000int
715 * Compute the number of days from date, obey the local switch from
716 * Julian to Gregorian if specified by the user.
717 */
718int
1001sndaysr(struct date *d)
719sndays(struct date *d)
1002{
1003
1004 if (nswitch != 0)
1005 if (nswitch < ndaysj(d))
1006 return (ndaysg(d));
1007 else
1008 return (ndaysj(d));
1009 else

--- 9 unchanged lines hidden (view full) ---

1019{
1020
1021 if (nswitchb < ndaysj(d))
1022 return (ndaysg(d));
1023 else
1024 return (ndaysj(d));
1025}
1026
720{
721
722 if (nswitch != 0)
723 if (nswitch < ndaysj(d))
724 return (ndaysg(d));
725 else
726 return (ndaysj(d));
727 else

--- 9 unchanged lines hidden (view full) ---

737{
738
739 if (nswitchb < ndaysj(d))
740 return (ndaysg(d));
741 else
742 return (ndaysj(d));
743}
744
1027/* Inverse of sndays. */
745/* Inverse of sndays */
1028struct date *
746struct date *
1029sdater(int nd, struct date *d)
747sdate(int nd, struct date *d)
1030{
1031
1032 if (nswitch < nd)
1033 return (gdate(nd, d));
1034 else
1035 return (jdate(nd, d));
1036}
1037
748{
749
750 if (nswitch < nd)
751 return (gdate(nd, d));
752 else
753 return (jdate(nd, d));
754}
755
1038/* Inverse of sndaysb. */
756/* Inverse of sndaysb */
1039struct date *
1040sdateb(int nd, struct date *d)
1041{
1042
1043 if (nswitchb < nd)
1044 return (gdate(nd, d));
1045 else
1046 return (jdate(nd, d));
1047}
1048
757struct date *
758sdateb(int nd, struct date *d)
759{
760
761 if (nswitchb < nd)
762 return (gdate(nd, d));
763 else
764 return (jdate(nd, d));
765}
766
1049/* Center string t in string s of length w by putting enough leading blanks. */
767/* Center string t in string s of length w by putting enough leading blanks */
1050char *
1051center(char *s, char *t, int w)
1052{
768char *
769center(char *s, char *t, int w)
770{
1053 char blanks[MAX_WIDTH];
771 char blanks[80];
1054
1055 memset(blanks, ' ', sizeof(blanks));
1056 sprintf(s, "%.*s%s", (int)(w - strlen(t)) / 2, blanks, t);
1057 return (s);
1058}
772
773 memset(blanks, ' ', sizeof(blanks));
774 sprintf(s, "%.*s%s", (int)(w - strlen(t)) / 2, blanks, t);
775 return (s);
776}
1059
1060/* Center string t in string s of length w by putting enough leading blanks. */
1061wchar_t *
1062wcenter(wchar_t *s, wchar_t *t, int w)
1063{
1064 char blanks[MAX_WIDTH];
1065
1066 memset(blanks, ' ', sizeof(blanks));
1067 swprintf(s, MAX_WIDTH, L"%.*s%ls", (int)(w - wcslen(t)) / 2, blanks, t);
1068 return (s);
1069}
1070
1071int
1072parsemonth(const char *s, int *m, int *y)
1073{
1074 int nm, ny;
1075 char *cp;
1076 struct tm tm;
1077
1078 nm = (int)strtol(s, &cp, 10);
1079 if (cp != s) {
1080 ny = *y;
1081 if (*cp == '\0') {
1082 ; /* no special action */
1083 } else if (*cp == 'f' || *cp == 'F') {
1084 if (nm <= *m)
1085 ny++;
1086 } else if (*cp == 'p' || *cp == 'P') {
1087 if (nm >= *m)
1088 ny--;
1089 } else
1090 return (1);
1091 if (nm < 1 || nm > 12)
1092 return 1;
1093 *m = nm;
1094 *y = ny;
1095 return (0);
1096 }
1097 if (strptime(s, "%B", &tm) != NULL || strptime(s, "%b", &tm) != NULL) {
1098 *m = tm.tm_mon + 1;
1099 return (0);
1100 }
1101 return (1);
1102}
1103
1104void
1105highlight(char *dst, char *src, int len, int *extralen)
1106{
1107 static int first = 1;
1108 static const char *term_so, *term_se;
1109
1110 if (first) {
1111 char tbuf[1024], cbuf[512], *b;
1112
1113 term_se = term_so = NULL;
1114
1115 /* On how to highlight on this type of terminal (if any). */
1116 if (isatty(STDOUT_FILENO) && tgetent(tbuf, NULL) == 1) {
1117 b = cbuf;
1118 term_so = tgetstr("so", &b);
1119 term_se = tgetstr("se", &b);
1120 }
1121
1122 first = 0;
1123 }
1124
1125 /*
1126 * This check is not necessary, should have been handled before calling
1127 * this function.
1128 */
1129 if (flag_nohighlight) {
1130 memcpy(dst, src, len);
1131 return;
1132 }
1133
1134 /*
1135 * If it is a real terminal, use the data from the termcap database.
1136 */
1137 if (term_so != NULL && term_se != NULL) {
1138 /* separator. */
1139 dst[0] = ' ';
1140 dst++;
1141 /* highlight on. */
1142 memcpy(dst, term_so, strlen(term_so));
1143 dst += strlen(term_so);
1144 /* the actual text. (minus leading space) */
1145 len--;
1146 src++;
1147 memcpy(dst, src, len);
1148 dst += len;
1149 /* highlight off. */
1150 memcpy(dst, term_se, strlen(term_se));
1151 *extralen = strlen(term_so) + strlen(term_se);
1152 return;
1153 }
1154
1155 /*
1156 * Otherwise, print a _, backspace and the letter.
1157 */
1158 *extralen = 0;
1159 /* skip leading space. */
1160 src++;
1161 len--;
1162 /* separator. */
1163 dst[0] = ' ';
1164 dst++;
1165 while (len > 0) {
1166 /* _ and backspace. */
1167 memcpy(dst, "_\010", 2);
1168 dst += 2;
1169 *extralen += 2;
1170 /* the character. */
1171 *dst++ = *src++;
1172 len--;
1173 }
1174 return;
1175}