📄 cal.c
字号:
/* * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Kim Letkeman. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *//* 1999-02-01 Jean-Francois Bignolles: added option '-m' to display * monday as the first day of the week. * 1999-02-22 Arkadiusz Mi秌iewicz <misiek@pld.ORG.PL> * - added Native Language Support * * 2000-09-01 Michael Charles Pruznick <dummy@netwiz.net> * Added "-3" option to print prev/next month with current. * Added over-ridable default NUM_MONTHS and "-1" option to * get traditional output when -3 is the default. I hope that * enough people will like -3 as the default that one day the * product can be shipped that way. * * 2001-05-07 Pablo Saratxaga <pablo@mandrakesoft.com> * Fixed the bugs with multi-byte charset (zg: cjk, utf-8) * displaying. made the 'month year' ("%s %d") header translatable * so it can be adapted to conventions used by different languages * added support to read "first_weekday" locale information * still to do: support for 'cal_direction' (will require a major * rewrite of the displaying) and proper handling of RTL scripts */#include <sys/types.h>#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <locale.h>#include "errs.h"#include "nls.h"#include "../defines.h"#if defined(HAVE_ncurses)#if NCH#include <ncurses.h>#else#include <curses.h>#endif#include <term.h> /* include after <curses.h> */static voidmy_setupterm(const char *term, int fildes, int *errret) { setupterm((char*)term, fildes, errret);}static voidmy_putstring(char *s) { putp(s);}static char *my_tgetstr(char *s, char *ss) { return tigetstr(ss);}#elif defined(HAVE_termcap)#include <termcap.h>char termbuffer[4096];char tcbuffer[4096];char *strbuf = termbuffer;static voidmy_setupterm(const char *term, int fildes, int *errret) { *errret = tgetent(tcbuffer, term);}static voidmy_putstring(char *s) { tputs (s, 1, putchar);}static char *my_tgetstr(char *s, char *ss) { return tgetstr(s, &strbuf);}#endifconst char *term="";const char *Senter="", *Sexit="";/* enter and exit standout mode */#ifdef HAVE_langinfo_h# include <langinfo.h>#else# include <localeinfo.h> /* libc4 only */#endif#include "widechar.h"#define SIZE(a) (sizeof(a)/sizeof((a)[0]))/* allow compile-time define to over-ride default */#ifndef NUM_MONTHS#define NUM_MONTHS 1#endif#if ( NUM_MONTHS != 1 && NUM_MONTHS !=3 )#error NUM_MONTHS must be 1 or 3#endif#define THURSDAY 4 /* for reformation */#define SATURDAY 6 /* 1 Jan 1 was a Saturday */#define FIRST_MISSING_DAY 639799 /* 3 Sep 1752 */#define NUMBER_MISSING_DAYS 11 /* 11 day correction */#define MAXDAYS 43 /* max slots in a month array */#define SPACE -1 /* used in day array */static int days_in_month[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},};int sep1752[MAXDAYS] = { SPACE, SPACE, 1, 2, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE}, j_sep1752[MAXDAYS] = { SPACE, SPACE, 245, 246, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE}, empty[MAXDAYS] = { SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE};#define DAY_LEN 3 /* 3 spaces per day */#define J_DAY_LEN 4 /* 4 spaces per day */#define WEEK_LEN 21 /* 7 days * 3 characters */#define J_WEEK_LEN 28 /* 7 days * 4 characters */#define HEAD_SEP 2 /* spaces between day headings */#define J_HEAD_SEP 2/* utf-8 can have up to 6 bytes per char; and an extra byte for ending \0 */char day_headings[WEEK_LEN*6+1];/* week1stday = 1 => " M Tu W Th F S S " */char j_day_headings[J_WEEK_LEN*6+1];/* week1stday = 1 => " M Tu W Th F S S " */const char *full_month[12];/* leap year -- account for gregorian reformation in 1752 */#define leap_year(yr) \ ((yr) <= 1752 ? !((yr) % 4) : \ (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400))/* number of centuries since 1700, not inclusive */#define centuries_since_1700(yr) \ ((yr) > 1700 ? (yr) / 100 - 17 : 0)/* number of centuries since 1700 whose modulo of 400 is 0 */#define quad_centuries_since_1700(yr) \ ((yr) > 1600 ? ((yr) - 1600) / 400 : 0)/* number of leap years between year 1 and this year, not inclusive */#define leap_years_since_year_1(yr) \ ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))/* 0 => sunday (default), 1 => monday */int week1stday=0;int julian;#define TODAY_FLAG 0x400 /* flag day for highlighting */#define FMT_ST_LINES 8#define FMT_ST_CHARS 300 /* 90 suffices in most locales */struct fmt_st{ char s[FMT_ST_LINES][FMT_ST_CHARS];};char * ascii_day(char *, int);void center_str(const char* src, char* dest, size_t dest_size, int width);void center(const char *, int, int);void day_array(int, int, int, int *);int day_in_week(int, int, int);int day_in_year(int, int, int);void yearly(int, int);void j_yearly(int, int);void do_monthly(int, int, int, struct fmt_st*);void monthly(int, int, int);void monthly3(int, int, int);void trim_trailing_spaces(char *);void usage(void);void headers_init(void);extern char *__progname;intmain(int argc, char **argv) { struct tm *local_time; time_t now; int ch, day, month, year, yflag; char *progname, *p; int num_months = NUM_MONTHS; progname = argv[0]; if ((p = strrchr(progname, '/')) != NULL) progname = p+1; __progname = progname; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE);#if defined(HAVE_ncurses) || defined(HAVE_termcap) if ((term = getenv("TERM"))) { int ret; my_setupterm(term, 1, &ret); if (ret > 0) { Senter = my_tgetstr("so","smso"); Sexit = my_tgetstr("se","rmso"); } }#endif#if 0 /* setting week1stday is against man page *//* * What *is* the first day of the week? Note that glibc does not * provide any information today, it (almost) always answers Monday. * Sunday is the Jewish and Christian tradition. * Sometimes an answer is built into the language: * German calls Wednesday "Mittwoch", so starts at Sunday. * Portuguese calls Monday "segunda-feira", so starts at Sunday. * Russian calls Friday "pyatnitsa", so starts at Monday. * ISO 8601 decided to start at Monday. * * The traditional Unix cal utility starts at Sunday. * We start at Sunday and have an option -m for starting at Monday. * * At some future time this may become -s for Sunday, -m for Monday, * no option for glibc-determined locale-dependent version. */#ifdef HAVE_langinfo_h week1stday = (int)(nl_langinfo(_NL_TIME_FIRST_WEEKDAY))[0];#endif#endif yflag = 0; while ((ch = getopt(argc, argv, "13mjsyV")) != -1) switch(ch) { case '1': num_months = 1; /* default */ break; case '3': num_months = 3; break; case 's': week1stday = 0; /* default */ break; case 'm': week1stday = 1; break; case 'j': julian = 1; break; case 'y': yflag = 1; break; case 'V': printf(_("%s from %s\n"), progname, util_linux_version); return 0; case '?': default: usage(); } argc -= optind; argv += optind; day = month = year = 0; switch(argc) { case 2: if ((month = atoi(*argv++)) < 1 || month > 12) errx(1, _("illegal month value: use 1-12")); /* FALLTHROUGH */ case 1: if ((year = atoi(*argv)) < 1 || year > 9999) errx(1, _("illegal year value: use 1-9999")); break; case 0: time(&now); local_time = localtime(&now); if (isatty(1)) day = local_time->tm_yday + 1; year = local_time->tm_year + 1900; if (!yflag) month = local_time->tm_mon + 1; break; default: usage(); } headers_init(); if (month && num_months == 1) monthly(day, month, year); else if (month && num_months == 3) monthly3(day, month, year); else if (julian) j_yearly(day, year); else yearly(day, year); exit(0);}#ifndef ENABLE_WIDECHARstatic char *eos(char *s) { while (s && *s) s++; return s;}#endifvoid headers_init(void){ int i, wd;#ifdef ENABLE_WIDECHAR wchar_t day_headings_wc[22],j_day_headings_wc[29]; wchar_t wd_wc[10];#endif strcpy(day_headings,""); strcpy(j_day_headings,"");#ifdef ENABLE_WIDECHAR wcscpy(day_headings_wc,L""); wcscpy(j_day_headings_wc,L"");#endif#ifdef HAVE_langinfo_h# define weekday(wd) nl_langinfo(ABDAY_1+wd)#else# define weekday(wd) _time_info->abbrev_wkday[wd]#endif for(i = 0 ; i < 7 ; i++ ) { wd = (i + week1stday) % 7;#ifdef ENABLE_WIDECHAR mbstowcs(wd_wc,weekday(wd),10); if (wcswidth(wd_wc,10) < 3) wcscat(j_day_headings_wc,L" ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -