summaryrefslogtreecommitdiffstats
path: root/misc-utils/cal.c
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:26:24 +0100
committerKarel Zak2006-12-07 00:26:24 +0100
commitd162fcb550a77875c8f58fda0e0a0bd91f211c99 (patch)
treebd984959acd465b3058bd805f216d29dc0c3c1a6 /misc-utils/cal.c
parentImported from util-linux-2.12i tarball. (diff)
downloadkernel-qcow2-util-linux-d162fcb550a77875c8f58fda0e0a0bd91f211c99.tar.gz
kernel-qcow2-util-linux-d162fcb550a77875c8f58fda0e0a0bd91f211c99.tar.xz
kernel-qcow2-util-linux-d162fcb550a77875c8f58fda0e0a0bd91f211c99.zip
Imported from util-linux-2.12j tarball.
Diffstat (limited to 'misc-utils/cal.c')
-rw-r--r--misc-utils/cal.c432
1 files changed, 268 insertions, 164 deletions
diff --git a/misc-utils/cal.c b/misc-utils/cal.c
index 527b5bbc8..83015ea96 100644
--- a/misc-utils/cal.c
+++ b/misc-utils/cal.c
@@ -35,11 +35,11 @@
*/
/* 1999-02-01 Jean-Francois Bignolles: added option '-m' to display
- * monday as the first day of the week.
+ * monday as the first day of the week.
* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
*
- * 2000-09-01 Michael Charles Pruznick <dummy@netwiz.net>
+ * 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
@@ -68,6 +68,57 @@
#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 void
+my_setupterm(const char *term, int fildes, int *errret) {
+ setupterm((char*)term, fildes, errret);
+}
+
+static void
+my_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 void
+my_setupterm(const char *term, int fildes, int *errret) {
+ *errret = tgetent(tcbuffer, term);
+}
+
+static void
+my_putstring(char *s) {
+ tputs (s, 1, putchar);
+}
+
+static char *
+my_tgetstr(char *s, char *ss) {
+ return tgetstr(s, &strbuf);
+}
+
+#endif
+const char *term="";
+const char *Senter="", *Sexit="";/* enter and exit standout mode */
+
#ifdef HAVE_langinfo_h
# include <langinfo.h>
#else
@@ -77,7 +128,7 @@
#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
@@ -88,10 +139,10 @@
#endif
#define THURSDAY 4 /* for reformation */
-#define SATURDAY 6 /* 1 Jan 1 was a Saturday */
+#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 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 */
@@ -162,6 +213,8 @@ const char *full_month[12];
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
@@ -169,26 +222,27 @@ struct fmt_st
char s[FMT_ST_LINES][FMT_ST_CHARS];
};
-void ascii_day __P((char *, int));
-void center __P((const char *, int, int));
-void day_array __P((int, int, int *));
-int day_in_week __P((int, int, int));
-int day_in_year __P((int, int, int));
-void j_yearly __P((int));
-void do_monthly __P((int, int, struct fmt_st*));
-void monthly __P((int, int));
-void monthly3 __P((int, int));
-void trim_trailing_spaces __P((char *));
-void usage __P((void));
-void yearly __P((int));
-void headers_init(void);
+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;
int
main(int argc, char **argv) {
struct tm *local_time;
time_t now;
- int ch, month, year, yflag;
+ int ch, day, month, year, yflag;
char *progname, *p;
int num_months = NUM_MONTHS;
@@ -201,6 +255,17 @@ main(int argc, char **argv) {
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
@@ -214,7 +279,7 @@ main(int argc, char **argv) {
*
* 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.
*/
@@ -222,16 +287,16 @@ main(int argc, char **argv) {
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 '1':
+ num_months = 1; /* default */
+ break;
+ case '3':
+ num_months = 3;
+ break;
case 's':
week1stday = 0; /* default */
break;
@@ -255,7 +320,7 @@ main(int argc, char **argv) {
argc -= optind;
argv += optind;
- month = year = 0;
+ day = month = year = 0;
switch(argc) {
case 2:
if ((month = atoi(*argv++)) < 1 || month > 12)
@@ -266,8 +331,10 @@ main(int argc, char **argv) {
errx(1, _("illegal year value: use 1-9999"));
break;
case 0:
- (void)time(&now);
+ 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;
@@ -278,13 +345,13 @@ main(int argc, char **argv) {
headers_init();
if (month && num_months == 1)
- monthly(month, year);
+ monthly(day, month, year);
else if (month && num_months == 3)
- monthly3(month, year);
+ monthly3(day, month, year);
else if (julian)
- j_yearly(year);
+ j_yearly(day, year);
else
- yearly(year);
+ yearly(day, year);
exit(0);
}
@@ -316,7 +383,7 @@ void headers_init(void)
#else
# define weekday(wd) _time_info->abbrev_wkday[wd]
#endif
-
+
for(i = 0 ; i < 7 ; i++ ) {
wd = (i + week1stday) % 7;
#ifdef ENABLE_WIDECHAR
@@ -342,8 +409,10 @@ void headers_init(void)
wcstombs(j_day_headings,j_day_headings_wc,sizeof(j_day_headings));
#endif
+ trim_trailing_spaces(day_headings);
+ trim_trailing_spaces(j_day_headings);
#undef weekday
-
+
for (i = 0; i < 12; i++) {
#ifdef HAVE_langinfo_h
full_month[i] = nl_langinfo(MON_1+i);
@@ -354,62 +423,51 @@ void headers_init(void)
}
void
-do_monthly(month, year, out)
- int month, year;
- struct fmt_st* out;
-{
+do_monthly(int day, int month, int year, struct fmt_st *out) {
int col, row, len, days[MAXDAYS];
- char *p, lineout[300];
-#ifdef ENABLE_WIDECHAR
- wchar_t lineout_wc[300];
-#endif
-
- day_array(month, year, days);
- /* %s is the month name, %d the year number.
+ char *p, lineout[FMT_ST_CHARS];
+ int width = (julian ? J_WEEK_LEN : WEEK_LEN) - 1;
+
+ day_array(day, month, year, days);
+
+ /*
+ * %s is the month name, %d the year number.
* you can change the order and/or add something here; eg for
* Basque the translation should be: "%2$dko %1$s", and
* the Vietnamese should be "%s na(m %d", etc.
*/
len = sprintf(lineout, _("%s %d"), full_month[month - 1], year);
-#ifdef ENABLE_WIDECHAR
- if (mbstowcs(lineout_wc,lineout,len) > 0) {
- len = wcswidth(lineout_wc,len);
- } else {
- len = strlen(lineout);
- }
-#endif
- (void)sprintf(out->s[0],"%*s%s",
- ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "", lineout );
- (void)sprintf(out->s[1],"%s",
- julian ? j_day_headings : day_headings);
+ center_str(lineout, out->s[0], SIZE(out->s[0]), width);
+
+ sprintf(out->s[1],"%s",
+ julian ? j_day_headings : day_headings);
for (row = 0; row < 6; row++) {
- for (col = 0, p = lineout; col < 7; col++,
- p += julian ? J_DAY_LEN : DAY_LEN)
- ascii_day(p, days[row * 7 + col]);
+ for (col = 0, p = lineout; col < 7; col++)
+ p = ascii_day(p, days[row * 7 + col]);
*p = '\0';
trim_trailing_spaces(lineout);
- (void)sprintf(out->s[row+2],"%s", lineout);
+ sprintf(out->s[row+2], "%s", lineout);
}
}
void
-monthly(month, year)
- int month, year;
-{
+monthly(int day, int month, int year) {
int i;
struct fmt_st out;
- do_monthly(month, year, &out);
- for ( i = 0; i < FMT_ST_LINES; i++ )
- {
- printf("%s\n", out.s[i]);
+ do_monthly(day, month, year, &out);
+ for (i = 0; i < FMT_ST_LINES; i++) {
+#if defined(HAVE_ncurses) || defined(HAVE_termcap)
+ my_putstring(out.s[i]);putchar('\n');
+#else
+ puts(out.s[i]);
+#endif
}
}
void
-monthly3(month, year)
- int month, year;
-{
+monthly3(int day, int month, int year) {
+ char lineout[FMT_ST_CHARS];
int i;
int width;
struct fmt_st out_prev;
@@ -418,109 +476,117 @@ monthly3(month, year)
int prev_month, prev_year;
int next_month, next_year;
- if ( month == 1 )
- {
- prev_month = 12;
- prev_year = year - 1;
- }
- else
- {
- prev_month = month - 1;
- prev_year = year;
- }
- if ( month == 12 )
- {
- next_month = 1;
- next_year = year + 1;
+ if (month == 1) {
+ prev_month = 12;
+ prev_year = year - 1;
+ } else {
+ prev_month = month - 1;
+ prev_year = year;
}
- else
- {
- next_month = month + 1;
- next_year = year;
+ if (month == 12) {
+ next_month = 1;
+ next_year = year + 1;
+ } else {
+ next_month = month + 1;
+ next_year = year;
}
- do_monthly(prev_month, prev_year, &out_prev);
- do_monthly(month, year, &out_curm);
- do_monthly(next_month, next_year, &out_next);
- width = (julian ? J_WEEK_LEN : WEEK_LEN);
- for ( i = 0; i < FMT_ST_LINES; i++ )
- {
- printf("%-*.*s %-*.*s %-*.*s\n",
- width, width, out_prev.s[i],
- width, width, out_curm.s[i],
- width, width, out_next.s[i] );
+ do_monthly(day, prev_month, prev_year, &out_prev);
+ do_monthly(day, month, year, &out_curm);
+ do_monthly(day, next_month, next_year, &out_next);
+ width = (julian ? J_WEEK_LEN : WEEK_LEN) -1;
+ for (i = 0; i < 2; i++)
+ printf("%s %s %s\n", out_prev.s[i], out_curm.s[i], out_next.s[i]);
+ for (i = 2; i < FMT_ST_LINES; i++) {
+ snprintf(lineout, SIZE(lineout), "%-*s %-*s %-*s\n",
+ width, out_prev.s[i],
+ width, out_curm.s[i],
+ width, out_next.s[i]);
+#if defined(HAVE_ncurses) || defined(HAVE_termcap)
+ my_putstring(lineout);
+#else
+ fputs(lineout,stdout);
+#endif
}
}
void
-j_yearly(year)
- int year;
-{
+j_yearly(int day, int year) {
int col, *dp, i, month, row, which_cal;
int days[12][MAXDAYS];
char *p, lineout[80];
- (void)sprintf(lineout, "%d", year);
+ sprintf(lineout, "%d", year);
center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0);
- (void)printf("\n\n");
+ printf("\n\n");
+
for (i = 0; i < 12; i++)
- day_array(i + 1, year, days[i]);
- (void)memset(lineout, ' ', sizeof(lineout) - 1);
+ day_array(day, i + 1, year, days[i]);
+ memset(lineout, ' ', sizeof(lineout) - 1);
lineout[sizeof(lineout) - 1] = '\0';
for (month = 0; month < 12; month += 2) {
center(full_month[month], J_WEEK_LEN, J_HEAD_SEP);
center(full_month[month + 1], J_WEEK_LEN, 0);
- (void)printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "",
+ printf("\n%s%*s %s\n", j_day_headings, J_HEAD_SEP, "",
j_day_headings);
for (row = 0; row < 6; row++) {
+ p = lineout;
for (which_cal = 0; which_cal < 2; which_cal++) {
- p = lineout + which_cal * (J_WEEK_LEN + 2);
dp = &days[month + which_cal][row * 7];
- for (col = 0; col < 7; col++, p += J_DAY_LEN)
- ascii_day(p, *dp++);
+ for (col = 0; col < 7; col++)
+ p = ascii_day(p, *dp++);
+ p += sprintf(p, " ");
}
*p = '\0';
trim_trailing_spaces(lineout);
- (void)printf("%s\n", lineout);
+#if defined(HAVE_ncurses) || defined(HAVE_termcap)
+ my_putstring(lineout);putchar('\n');
+#else
+ puts(lineout);
+#endif
}
}
- (void)printf("\n");
+ printf("\n");
}
void
-yearly(year)
- int year;
-{
+yearly(int day, int year) {
int col, *dp, i, month, row, which_cal;
int days[12][MAXDAYS];
- char *p, lineout[80];
+ char *p, lineout[100];
- (void)sprintf(lineout, "%d", year);
+ sprintf(lineout, "%d", year);
center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0);
- (void)printf("\n\n");
+ printf("\n\n");
+
for (i = 0; i < 12; i++)
- day_array(i + 1, year, days[i]);
- (void)memset(lineout, ' ', sizeof(lineout) - 1);
+ day_array(day, i + 1, year, days[i]);
+ memset(lineout, ' ', sizeof(lineout) - 1);
lineout[sizeof(lineout) - 1] = '\0';
for (month = 0; month < 12; month += 3) {
center(full_month[month], WEEK_LEN, HEAD_SEP);
center(full_month[month + 1], WEEK_LEN, HEAD_SEP);
center(full_month[month + 2], WEEK_LEN, 0);
- (void)printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
+ printf("\n%s%*s %s%*s %s\n", day_headings, HEAD_SEP,
"", day_headings, HEAD_SEP, "", day_headings);
for (row = 0; row < 6; row++) {
+ p = lineout;
for (which_cal = 0; which_cal < 3; which_cal++) {
- p = lineout + which_cal * (WEEK_LEN + 2);
dp = &days[month + which_cal][row * 7];
- for (col = 0; col < 7; col++, p += DAY_LEN)
- ascii_day(p, *dp++);
+ for (col = 0; col < 7; col++)
+ p = ascii_day(p, *dp++);
+ p += sprintf(p, " ");
}
*p = '\0';
trim_trailing_spaces(lineout);
- (void)printf("%s\n", lineout);
+#if defined(HAVE_ncurses) || defined(HAVE_termcap)
+ my_putstring(lineout);putchar('\n');
+#else
+ puts(lineout);
+#endif
}
}
- (void)printf("\n");
+ printf("\n");
}
/*
@@ -531,11 +597,8 @@ yearly(year)
* builds that array for any month from Jan. 1 through Dec. 9999.
*/
void
-day_array(month, year, days)
- int month, year;
- int *days;
-{
- int day, dw, dm;
+day_array(int day, int month, int year, int *days) {
+ int julday, daynum, dw, dm;
int *d_sep1752;
if (month == 9 && year == 1752) {
@@ -546,9 +609,14 @@ day_array(month, year, days)
memcpy(days, empty, MAXDAYS * sizeof(int));
dm = days_in_month[leap_year(year)][month];
dw = (day_in_week(1, month, year) - week1stday + 7) % 7;
- day = julian ? day_in_year(1, month, year) : 1;
- while (dm--)
- days[dw++] = day++;
+ julday = day_in_year(1, month, year);
+ daynum = julian ? julday : 1;
+ while (dm--) {
+ days[dw] = daynum++;
+ if (julday++ == day)
+ days[dw] |= TODAY_FLAG;
+ dw++;
+ }
}
/*
@@ -556,15 +624,13 @@ day_array(month, year, days)
* return the 1 based day number within the year
*/
int
-day_in_year(day, month, year)
- int day, month, year;
-{
+day_in_year(int day, int month, int year) {
int i, leap;
leap = leap_year(year);
for (i = 1; i < month; i++)
day += days_in_month[leap][i];
- return (day);
+ return day;
}
/*
@@ -575,9 +641,7 @@ day_in_year(day, month, year)
* missing days.
*/
int
-day_in_week(day, month, year)
- int day, month, year;
-{
+day_in_week(int day, int month, int year) {
long temp;
temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
@@ -589,12 +653,10 @@ day_in_week(day, month, year)
return (THURSDAY);
}
-void
-ascii_day(p, day)
- char *p;
- int day;
-{
+char *
+ascii_day(char *p, int day) {
int display, val;
+ int highlight = 0;
static char *aday[] = {
"",
" 1", " 2", " 3", " 4", " 5", " 6", " 7",
@@ -605,8 +667,14 @@ ascii_day(p, day)
};
if (day == SPACE) {
- memset(p, ' ', julian ? J_DAY_LEN : DAY_LEN);
- return;
+ int len = julian ? J_DAY_LEN : DAY_LEN;
+ memset(p, ' ', len);
+ return p+len;
+ }
+ if (day & TODAY_FLAG) {
+ day &= ~TODAY_FLAG;
+ p += sprintf(p, Senter);
+ highlight = 1;
}
if (julian) {
if ((val = day / 100)) {
@@ -627,7 +695,10 @@ ascii_day(p, day)
*p++ = aday[day][0];
*p++ = aday[day][1];
}
- *p = ' ';
+ if (highlight)
+ p += sprintf(p, Sexit);
+ *p++ = ' ';
+ return p;
}
void
@@ -645,26 +716,59 @@ trim_trailing_spaces(s)
*p = '\0';
}
+/*
+ * Center string, handling multibyte characters appropriately.
+ * In addition if the string is too large for the width it's truncated.
+ */
+void
+center_str(const char* src, char* dest, size_t dest_size, int width)
+{
+#ifdef ENABLE_WIDECHAR
+ wchar_t str_wc[FMT_ST_CHARS];
+#endif
+ char str[FMT_ST_CHARS];
+ const char* str_to_print=src;
+ int len, spaces, wide_char_enabled=0;
+
+ len = strlen(src);
+
+#ifdef ENABLE_WIDECHAR
+ if (mbstowcs(str_wc, src, FMT_ST_CHARS) > 0) {
+ wide_char_enabled = 1;
+ len = wcswidth(str_wc, SIZE(str_wc));
+ }
+#endif
+ if (len > width) {
+ str_to_print=str;
+ if (wide_char_enabled) {
+#ifdef ENABLE_WIDECHAR
+ str_wc[width]=L'\0';
+ wcstombs(str, str_wc, SIZE(str));
+#endif
+ } else {
+ strncpy(str, src, SIZE(str));
+ str[width]='\0';
+ }
+ }
+
+ spaces = width - len;
+ spaces = ( spaces < 0 ? 0 : spaces );
+
+ snprintf(dest, dest_size, "%*s%s%*s",
+ spaces / 2, "",
+ str_to_print,
+ spaces / 2 + spaces % 2, "" );
+}
+
void
center(str, len, separate)
const char *str;
int len;
int separate;
{
-#ifdef ENABLE_WIDECHAR
- wchar_t str_wc[300];
- int str_len;
-
- if (mbstowcs(str_wc,str,300) > 0) {
- str_len = wcswidth(str_wc,300);
- } else {
- str_len = strlen(str);
- }
- len -= str_len;
-#else
- len -= strlen(str);
-#endif
- (void)printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, "");
+ char lineout[FMT_ST_CHARS];
+ center_str(str, lineout, SIZE(lineout), len);
+ fputs(lineout, stdout);
if (separate)
(void)printf("%*s", separate, "");
}