You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
767 lines
22 KiB
767 lines
22 KiB
/*
|
|
***********************************************************************
|
|
* © 2016 and later: Unicode, Inc. and others.
|
|
* License & terms of use: http://www.unicode.org/copyright.html
|
|
***********************************************************************
|
|
**********************************************************************
|
|
* Copyright (C) 1998-2012, International Business Machines Corporation
|
|
* and others. All Rights Reserved.
|
|
**********************************************************************
|
|
*
|
|
* File date.c
|
|
*
|
|
* Modification History:
|
|
*
|
|
* Date Name Description
|
|
* 06/16/99 stephen Creation.
|
|
*******************************************************************************
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "unicode/uloc.h"
|
|
#include "unicode/udat.h"
|
|
#include "unicode/ucal.h"
|
|
#include "unicode/ustring.h"
|
|
#include "unicode/uclean.h"
|
|
|
|
#include "uprint.h"
|
|
|
|
#if UCONFIG_NO_FORMATTING
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
printf("%s: Sorry, UCONFIG_NO_FORMATTING was turned on (see uconfig.h). No formatting can be done. \n", argv[0]);
|
|
return 0;
|
|
}
|
|
#else
|
|
|
|
|
|
/* Protos */
|
|
static void usage(void);
|
|
|
|
static void version(void);
|
|
|
|
static void cal(int32_t month, int32_t year,
|
|
UBool useLongNames, UErrorCode *status);
|
|
|
|
static void get_symbols(const UDateFormat *fmt,
|
|
UDateFormatSymbolType type,
|
|
UChar *array[],
|
|
int32_t arrayLength,
|
|
int32_t lowestIndex,
|
|
int32_t firstIndex,
|
|
UErrorCode *status);
|
|
|
|
static void free_symbols(UChar *array[],
|
|
int32_t arrayLength);
|
|
|
|
static void get_days(const UDateFormat *fmt,
|
|
UChar *days [], UBool useLongNames,
|
|
int32_t fdow, UErrorCode *status);
|
|
|
|
static void free_days(UChar *days[]);
|
|
|
|
static void get_months(const UDateFormat *fmt,
|
|
UChar *months [], UBool useLongNames,
|
|
UErrorCode *status);
|
|
|
|
static void free_months(UChar *months[]);
|
|
|
|
static void indent(int32_t count, FILE *f);
|
|
|
|
static void print_days(UChar *days [], FILE *f, UErrorCode *status);
|
|
|
|
static void print_month(UCalendar *c,
|
|
UChar *days [],
|
|
UBool useLongNames, int32_t fdow,
|
|
UErrorCode *status);
|
|
|
|
static void print_year(UCalendar *c,
|
|
UChar *days [], UChar *months [],
|
|
UBool useLongNames, int32_t fdow,
|
|
UErrorCode *status);
|
|
|
|
/* The version of cal */
|
|
#define CAL_VERSION "1.0"
|
|
|
|
/* Number of days in a week */
|
|
#define DAY_COUNT 7
|
|
|
|
/* Number of months in a year (yes, 13) */
|
|
#define MONTH_COUNT 13
|
|
|
|
/* Separation between months in year view */
|
|
#define MARGIN_WIDTH 4
|
|
|
|
/* Size of stack buffers */
|
|
#define BUF_SIZE 64
|
|
|
|
/* Patterm string - "MMM yyyy" */
|
|
static const UChar sShortPat [] = { 0x004D, 0x004D, 0x004D, 0x0020,
|
|
0x0079, 0x0079, 0x0079, 0x0079 };
|
|
/* Pattern string - "MMMM yyyy" */
|
|
static const UChar sLongPat [] = { 0x004D, 0x004D, 0x004D, 0x004D, 0x0020,
|
|
0x0079, 0x0079, 0x0079, 0x0079 };
|
|
|
|
|
|
int
|
|
main(int argc,
|
|
char **argv)
|
|
{
|
|
int printUsage = 0;
|
|
int printVersion = 0;
|
|
UBool useLongNames = 0;
|
|
int optInd = 1;
|
|
char *arg;
|
|
int32_t month = -1, year = -1;
|
|
UErrorCode status = U_ZERO_ERROR;
|
|
|
|
|
|
/* parse the options */
|
|
for(optInd = 1; optInd < argc; ++optInd) {
|
|
arg = argv[optInd];
|
|
|
|
/* version info */
|
|
if(strcmp(arg, "-v") == 0 || strcmp(arg, "--version") == 0) {
|
|
printVersion = 1;
|
|
}
|
|
/* usage info */
|
|
else if(strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
|
|
printUsage = 1;
|
|
}
|
|
/* use long day names */
|
|
else if(strcmp(arg, "-l") == 0 || strcmp(arg, "--long") == 0) {
|
|
useLongNames = 1;
|
|
}
|
|
/* POSIX.1 says all arguments after -- are not options */
|
|
else if(strcmp(arg, "--") == 0) {
|
|
/* skip the -- */
|
|
++optInd;
|
|
break;
|
|
}
|
|
/* unrecognized option */
|
|
else if(strncmp(arg, "-", strlen("-")) == 0) {
|
|
printf("cal: invalid option -- %s\n", arg+1);
|
|
printUsage = 1;
|
|
}
|
|
/* done with options, display cal */
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Get the month and year to display, if specified */
|
|
if(optInd != argc) {
|
|
|
|
/* Month and year specified */
|
|
if(argc - optInd == 2) {
|
|
sscanf(argv[optInd], "%d", (int*)&month);
|
|
sscanf(argv[optInd + 1], "%d", (int*)&year);
|
|
|
|
/* Make sure the month value is legal */
|
|
if(month < 0 || month > 12) {
|
|
printf("icucal: Bad value for month -- %d\n", (int)month);
|
|
|
|
/* Display usage */
|
|
printUsage = 1;
|
|
}
|
|
|
|
/* Adjust because months are 0-based */
|
|
--month;
|
|
}
|
|
/* Only year specified */
|
|
else {
|
|
sscanf(argv[optInd], "%d", (int*)&year);
|
|
}
|
|
}
|
|
|
|
/* print usage info */
|
|
if(printUsage) {
|
|
usage();
|
|
return 0;
|
|
}
|
|
|
|
/* print version info */
|
|
if(printVersion) {
|
|
version();
|
|
return 0;
|
|
}
|
|
|
|
/* print the cal */
|
|
cal(month, year, useLongNames, &status);
|
|
|
|
/* ICU cleanup. Deallocate any memory ICU may be holding. */
|
|
u_cleanup();
|
|
|
|
return (U_FAILURE(status) ? 1 : 0);
|
|
}
|
|
|
|
/* Usage information */
|
|
static void
|
|
usage()
|
|
{
|
|
puts("Usage: icucal [OPTIONS] [[MONTH] YEAR]");
|
|
puts("");
|
|
puts("Options:");
|
|
puts(" -h, --help Print this message and exit.");
|
|
puts(" -v, --version Print the version number of cal and exit.");
|
|
puts(" -l, --long Use long names.");
|
|
puts("");
|
|
puts("Arguments (optional):");
|
|
puts(" MONTH An integer (1-12) indicating the month to display");
|
|
puts(" YEAR An integer indicating the year to display");
|
|
puts("");
|
|
puts("For an interesting calendar, look at October 1582");
|
|
}
|
|
|
|
/* Version information */
|
|
static void
|
|
version()
|
|
{
|
|
printf("icucal version %s (ICU version %s), created by Stephen F. Booth.\n",
|
|
CAL_VERSION, U_ICU_VERSION);
|
|
puts(U_COPYRIGHT_STRING);
|
|
}
|
|
|
|
static void
|
|
cal(int32_t month,
|
|
int32_t year,
|
|
UBool useLongNames,
|
|
UErrorCode *status)
|
|
{
|
|
UCalendar *c;
|
|
UChar *days [DAY_COUNT];
|
|
UChar *months [MONTH_COUNT];
|
|
int32_t fdow;
|
|
|
|
if(U_FAILURE(*status)) return;
|
|
|
|
/* Create a new calendar */
|
|
c = ucal_open(0, -1, uloc_getDefault(), UCAL_TRADITIONAL, status);
|
|
|
|
/* Determine if we are printing a calendar for one month or for a year */
|
|
|
|
/* Print an entire year */
|
|
if(month == -1 && year != -1) {
|
|
|
|
/* Set the year */
|
|
ucal_set(c, UCAL_YEAR, year);
|
|
|
|
/* Determine the first day of the week */
|
|
fdow = ucal_getAttribute(c, UCAL_FIRST_DAY_OF_WEEK);
|
|
|
|
/* Print the calendar for the year */
|
|
print_year(c, days, months, useLongNames, fdow, status);
|
|
}
|
|
|
|
/* Print only one month */
|
|
else {
|
|
|
|
/* Set the month and the year, if specified */
|
|
if(month != -1)
|
|
ucal_set(c, UCAL_MONTH, month);
|
|
if(year != -1)
|
|
ucal_set(c, UCAL_YEAR, year);
|
|
|
|
/* Determine the first day of the week */
|
|
fdow = ucal_getAttribute(c, UCAL_FIRST_DAY_OF_WEEK);
|
|
|
|
/* Print the calendar for the month */
|
|
print_month(c, days, useLongNames, fdow, status);
|
|
}
|
|
|
|
/* Clean up */
|
|
ucal_close(c);
|
|
}
|
|
/*
|
|
* Get a set of DateFormat symbols of a given type.
|
|
*
|
|
* lowestIndex is the index of the first symbol to fetch.
|
|
* (e.g. it will be one to fetch day names, since Sunday is
|
|
* day 1 *not* day 0.)
|
|
*
|
|
* firstIndex is the index of the symbol to place first in
|
|
* the output array. This is used when fetching day names
|
|
* in locales where the week doesn't start on Sunday.
|
|
*/
|
|
static void get_symbols(const UDateFormat *fmt,
|
|
UDateFormatSymbolType type,
|
|
UChar *array[],
|
|
int32_t arrayLength,
|
|
int32_t lowestIndex,
|
|
int32_t firstIndex,
|
|
UErrorCode *status)
|
|
{
|
|
int32_t count, i;
|
|
|
|
if (U_FAILURE(*status)) {
|
|
return;
|
|
}
|
|
|
|
count = udat_countSymbols(fmt, type);
|
|
|
|
if(count != arrayLength + lowestIndex) {
|
|
return;
|
|
}
|
|
|
|
for(i = 0; i < arrayLength; i++) {
|
|
int32_t idx = (i + firstIndex) % arrayLength;
|
|
int32_t size = 1 + udat_getSymbols(fmt, type, idx + lowestIndex, NULL, 0, status);
|
|
|
|
array[idx] = (UChar *) malloc(sizeof(UChar) * size);
|
|
|
|
*status = U_ZERO_ERROR;
|
|
udat_getSymbols(fmt, type, idx + lowestIndex, array[idx], size, status);
|
|
}
|
|
}
|
|
|
|
/* Free the symbols allocated by get_symbols(). */
|
|
static void free_symbols(UChar *array[],
|
|
int32_t arrayLength)
|
|
{
|
|
int32_t i;
|
|
|
|
for(i = 0; i < arrayLength; i++) {
|
|
free(array[i]);
|
|
}
|
|
}
|
|
|
|
/* Get the day names for the specified locale, in either long or short
|
|
form. Also, reorder the days so that they are in the proper order
|
|
for the locale (not all locales begin weeks on Sunday; in France,
|
|
weeks start on Monday) */
|
|
static void
|
|
get_days(const UDateFormat *fmt,
|
|
UChar *days [],
|
|
UBool useLongNames,
|
|
int32_t fdow,
|
|
UErrorCode *status)
|
|
{
|
|
UDateFormatSymbolType dayType = (useLongNames ? UDAT_WEEKDAYS : UDAT_SHORT_WEEKDAYS);
|
|
|
|
if(U_FAILURE(*status))
|
|
return;
|
|
|
|
/* fdow is 1-based */
|
|
--fdow;
|
|
|
|
get_symbols(fmt, dayType, days, DAY_COUNT, 1, fdow, status);
|
|
}
|
|
|
|
static void free_days(UChar *days[])
|
|
{
|
|
free_symbols(days, DAY_COUNT);
|
|
}
|
|
|
|
/* Get the month names for the specified locale, in either long or
|
|
short form. */
|
|
static void
|
|
get_months(const UDateFormat *fmt,
|
|
UChar *months [],
|
|
UBool useLongNames,
|
|
UErrorCode *status)
|
|
{
|
|
UDateFormatSymbolType monthType = (useLongNames ? UDAT_MONTHS : UDAT_SHORT_MONTHS);
|
|
|
|
if(U_FAILURE(*status))
|
|
return;
|
|
|
|
get_symbols(fmt, monthType, months, MONTH_COUNT - 1, 0, 0, status); /* some locales have 13 months, no idea why */
|
|
}
|
|
|
|
static void free_months(UChar *months[])
|
|
{
|
|
free_symbols(months, MONTH_COUNT - 1);
|
|
}
|
|
|
|
/* Indent a certain number of spaces */
|
|
static void
|
|
indent(int32_t count,
|
|
FILE *f)
|
|
{
|
|
char c [BUF_SIZE];
|
|
|
|
if(count <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(count < BUF_SIZE) {
|
|
memset(c, (int)' ', count);
|
|
fwrite(c, sizeof(char), count, f);
|
|
}
|
|
else {
|
|
int32_t i;
|
|
for(i = 0; i < count; ++i)
|
|
putc(' ', f);
|
|
}
|
|
}
|
|
|
|
/* Print the days */
|
|
static void
|
|
print_days(UChar *days [],
|
|
FILE *f,
|
|
UErrorCode *status)
|
|
{
|
|
int32_t i;
|
|
|
|
if(U_FAILURE(*status)) return;
|
|
|
|
/* Print the day names */
|
|
for(i = 0; i < DAY_COUNT; ++i) {
|
|
uprint(days[i], f, status);
|
|
putc(' ', f);
|
|
}
|
|
}
|
|
|
|
/* Print out a calendar for c's current month */
|
|
static void
|
|
print_month(UCalendar *c,
|
|
UChar *days [],
|
|
UBool useLongNames,
|
|
int32_t fdow,
|
|
UErrorCode *status)
|
|
{
|
|
int32_t width, pad, i, day;
|
|
int32_t lens [DAY_COUNT];
|
|
int32_t firstday, current;
|
|
UNumberFormat *nfmt;
|
|
UDateFormat *dfmt;
|
|
UChar s [BUF_SIZE];
|
|
const UChar *pat = (useLongNames ? sLongPat : sShortPat);
|
|
int32_t len = (useLongNames ? 9 : 8);
|
|
|
|
if(U_FAILURE(*status)) return;
|
|
|
|
|
|
/* ========== Generate the header containing the month and year */
|
|
|
|
/* Open a formatter with a month and year only pattern */
|
|
dfmt = udat_open(UDAT_PATTERN,UDAT_PATTERN,NULL,NULL,0,pat, len,status);
|
|
|
|
/* Format the date */
|
|
udat_format(dfmt, ucal_getMillis(c, status), s, BUF_SIZE, 0, status);
|
|
|
|
|
|
/* ========== Get the day names */
|
|
get_days(dfmt, days, useLongNames, fdow, status);
|
|
|
|
/* ========== Print the header */
|
|
|
|
/* Calculate widths for justification */
|
|
width = 6; /* 6 spaces, 1 between each day name */
|
|
for(i = 0; i < DAY_COUNT; ++i) {
|
|
lens[i] = u_strlen(days[i]);
|
|
width += lens[i];
|
|
}
|
|
|
|
/* Print the header, centered among the day names */
|
|
pad = width - u_strlen(s);
|
|
indent(pad / 2, stdout);
|
|
uprint(s, stdout, status);
|
|
putc('\n', stdout);
|
|
|
|
|
|
/* ========== Print the day names */
|
|
|
|
print_days(days, stdout, status);
|
|
putc('\n', stdout);
|
|
|
|
|
|
/* ========== Print the calendar */
|
|
|
|
/* Get the first of the month */
|
|
ucal_set(c, UCAL_DATE, 1);
|
|
firstday = ucal_get(c, UCAL_DAY_OF_WEEK, status);
|
|
|
|
/* The day of the week for the first day of the month is based on
|
|
1-based days of the week, which were also reordered when placed
|
|
in the days array. Account for this here by offsetting by the
|
|
first day of the week for the locale, which is also 1-based. */
|
|
firstday -= fdow;
|
|
|
|
/* Open the formatter */
|
|
nfmt = unum_open(UNUM_DECIMAL, NULL,0,NULL,NULL, status);
|
|
|
|
/* Indent the correct number of spaces for the first week */
|
|
current = firstday;
|
|
if(current < 0)
|
|
{
|
|
current += 7;
|
|
}
|
|
for(i = 0; i < current; ++i)
|
|
indent(lens[i] + 1, stdout);
|
|
|
|
/* Finally, print out the days */
|
|
day = ucal_get(c, UCAL_DATE, status);
|
|
do {
|
|
|
|
/* Format the current day string */
|
|
unum_format(nfmt, day, s, BUF_SIZE, 0, status);
|
|
|
|
/* Calculate the justification and indent */
|
|
pad = lens[current] - u_strlen(s);
|
|
indent(pad, stdout);
|
|
|
|
/* Print the day number out, followed by a space */
|
|
uprint(s, stdout, status);
|
|
putc(' ', stdout);
|
|
|
|
/* Update the current day */
|
|
++current;
|
|
current %= DAY_COUNT;
|
|
|
|
/* If we're at day 0 (first day of the week), insert a newline */
|
|
if(current == 0) {
|
|
putc('\n', stdout);
|
|
}
|
|
|
|
/* Go to the next day */
|
|
ucal_add(c, UCAL_DATE, 1, status);
|
|
day = ucal_get(c, UCAL_DATE, status);
|
|
|
|
} while(day != 1);
|
|
|
|
/* Output a trailing newline */
|
|
putc('\n', stdout);
|
|
|
|
/* Clean up */
|
|
free_days(days);
|
|
unum_close(nfmt);
|
|
udat_close(dfmt);
|
|
}
|
|
|
|
/* Print out a calendar for c's current year */
|
|
static void
|
|
print_year(UCalendar *c,
|
|
UChar *days [],
|
|
UChar *months [],
|
|
UBool useLongNames,
|
|
int32_t fdow,
|
|
UErrorCode *status)
|
|
{
|
|
int32_t width, pad, i, j;
|
|
int32_t lens [DAY_COUNT];
|
|
UNumberFormat *nfmt;
|
|
UDateFormat *dfmt;
|
|
UChar s [BUF_SIZE];
|
|
const UChar pat [] = { 0x0079, 0x0079, 0x0079, 0x0079 };
|
|
int32_t len = 4;
|
|
UCalendar *left_cal, *right_cal;
|
|
int32_t left_day, right_day;
|
|
int32_t left_firstday, right_firstday, left_current, right_current;
|
|
int32_t left_month, right_month;
|
|
|
|
if(U_FAILURE(*status)) return;
|
|
|
|
/* Alias */
|
|
left_cal = c;
|
|
|
|
/* ========== Generate the header containing the year (only) */
|
|
|
|
/* Open a formatter with a month and year only pattern */
|
|
dfmt = udat_open(UDAT_PATTERN,UDAT_PATTERN,NULL,NULL,0,pat, len, status);
|
|
|
|
/* Format the date */
|
|
udat_format(dfmt, ucal_getMillis(left_cal, status), s, BUF_SIZE, 0, status);
|
|
|
|
/* ========== Get the month and day names */
|
|
get_days(dfmt, days, useLongNames, fdow, status);
|
|
get_months(dfmt, months, useLongNames, status);
|
|
|
|
/* ========== Print the header, centered */
|
|
|
|
/* Calculate widths for justification */
|
|
width = 6; /* 6 spaces, 1 between each day name */
|
|
for(i = 0; i < DAY_COUNT; ++i) {
|
|
lens[i] = u_strlen(days[i]);
|
|
width += lens[i];
|
|
}
|
|
|
|
/* width is the width for 1 calendar; we are displaying in 2 cols
|
|
with MARGIN_WIDTH spaces between months */
|
|
|
|
/* Print the header, centered among the day names */
|
|
pad = 2 * width + MARGIN_WIDTH - u_strlen(s);
|
|
indent(pad / 2, stdout);
|
|
uprint(s, stdout, status);
|
|
putc('\n', stdout);
|
|
putc('\n', stdout);
|
|
|
|
/* Generate a copy of the calendar to use */
|
|
right_cal = ucal_open(0, -1, uloc_getDefault(), UCAL_TRADITIONAL, status);
|
|
ucal_setMillis(right_cal, ucal_getMillis(left_cal, status), status);
|
|
|
|
/* Open the formatter */
|
|
nfmt = unum_open(UNUM_DECIMAL,NULL, 0,NULL,NULL, status);
|
|
|
|
/* ========== Calculate and display the months, two at a time */
|
|
for(i = 0; i < MONTH_COUNT - 1; i += 2) {
|
|
|
|
/* Print the month names for the two current months */
|
|
pad = width - u_strlen(months[i]);
|
|
indent(pad / 2, stdout);
|
|
uprint(months[i], stdout, status);
|
|
indent(pad / 2 + MARGIN_WIDTH, stdout);
|
|
pad = width - u_strlen(months[i + 1]);
|
|
indent(pad / 2, stdout);
|
|
uprint(months[i + 1], stdout, status);
|
|
putc('\n', stdout);
|
|
|
|
/* Print the day names, twice */
|
|
print_days(days, stdout, status);
|
|
indent(MARGIN_WIDTH, stdout);
|
|
print_days(days, stdout, status);
|
|
putc('\n', stdout);
|
|
|
|
/* Setup the two calendars */
|
|
ucal_set(left_cal, UCAL_MONTH, i);
|
|
ucal_set(left_cal, UCAL_DATE, 1);
|
|
ucal_set(right_cal, UCAL_MONTH, i + 1);
|
|
ucal_set(right_cal, UCAL_DATE, 1);
|
|
|
|
left_firstday = ucal_get(left_cal, UCAL_DAY_OF_WEEK, status);
|
|
right_firstday = ucal_get(right_cal, UCAL_DAY_OF_WEEK, status);
|
|
|
|
/* The day of the week for the first day of the month is based on
|
|
1-based days of the week. However, the days were reordered
|
|
when placed in the days array. Account for this here by
|
|
offsetting by the first day of the week for the locale, which
|
|
is also 1-based. */
|
|
|
|
/* We need to mod by DAY_COUNT since fdow can be > firstday. IE,
|
|
if fdow = 2 = Monday (like in France) and the first day of the
|
|
month is a 1 = Sunday, we want firstday to be 6, not -1 */
|
|
left_firstday += (DAY_COUNT - fdow);
|
|
left_firstday %= DAY_COUNT;
|
|
|
|
right_firstday += (DAY_COUNT - fdow);
|
|
right_firstday %= DAY_COUNT;
|
|
|
|
left_current = left_firstday;
|
|
right_current = right_firstday;
|
|
|
|
left_day = ucal_get(left_cal, UCAL_DATE, status);
|
|
right_day = ucal_get(right_cal, UCAL_DATE, status);
|
|
|
|
left_month = ucal_get(left_cal, UCAL_MONTH, status);
|
|
right_month = ucal_get(right_cal, UCAL_MONTH, status);
|
|
|
|
/* Finally, print out the days */
|
|
while(left_month == i || right_month == i + 1) {
|
|
|
|
/* If the left month is finished printing, but the right month
|
|
still has days to be printed, indent the width of the days
|
|
strings and reset the left calendar's current day to 0 */
|
|
if(left_month != i && right_month == i + 1) {
|
|
indent(width + 1, stdout);
|
|
left_current = 0;
|
|
}
|
|
|
|
while(left_month == i) {
|
|
|
|
/* If the day is the first, indent the correct number of
|
|
spaces for the first week */
|
|
if(left_day == 1) {
|
|
for(j = 0; j < left_current; ++j)
|
|
indent(lens[j] + 1, stdout);
|
|
}
|
|
|
|
/* Format the current day string */
|
|
unum_format(nfmt, left_day, s, BUF_SIZE, 0, status);
|
|
|
|
/* Calculate the justification and indent */
|
|
pad = lens[left_current] - u_strlen(s);
|
|
indent(pad, stdout);
|
|
|
|
/* Print the day number out, followed by a space */
|
|
uprint(s, stdout, status);
|
|
putc(' ', stdout);
|
|
|
|
/* Update the current day */
|
|
++left_current;
|
|
left_current %= DAY_COUNT;
|
|
|
|
/* Go to the next day */
|
|
ucal_add(left_cal, UCAL_DATE, 1, status);
|
|
left_day = ucal_get(left_cal, UCAL_DATE, status);
|
|
|
|
/* Determine the month */
|
|
left_month = ucal_get(left_cal, UCAL_MONTH, status);
|
|
|
|
/* If we're at day 0 (first day of the week), break and go to
|
|
the next month */
|
|
if(left_current == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* If the current day isn't 0, indent to make up for missing
|
|
days at the end of the month */
|
|
if(left_current != 0) {
|
|
for(j = left_current; j < DAY_COUNT; ++j)
|
|
indent(lens[j] + 1, stdout);
|
|
}
|
|
|
|
/* Indent between the two months */
|
|
indent(MARGIN_WIDTH, stdout);
|
|
|
|
while(right_month == i + 1) {
|
|
|
|
/* If the day is the first, indent the correct number of
|
|
spaces for the first week */
|
|
if(right_day == 1) {
|
|
for(j = 0; j < right_current; ++j)
|
|
indent(lens[j] + 1, stdout);
|
|
}
|
|
|
|
/* Format the current day string */
|
|
unum_format(nfmt, right_day, s, BUF_SIZE, 0, status);
|
|
|
|
/* Calculate the justification and indent */
|
|
pad = lens[right_current] - u_strlen(s);
|
|
indent(pad, stdout);
|
|
|
|
/* Print the day number out, followed by a space */
|
|
uprint(s, stdout, status);
|
|
putc(' ', stdout);
|
|
|
|
/* Update the current day */
|
|
++right_current;
|
|
right_current %= DAY_COUNT;
|
|
|
|
/* Go to the next day */
|
|
ucal_add(right_cal, UCAL_DATE, 1, status);
|
|
right_day = ucal_get(right_cal, UCAL_DATE, status);
|
|
|
|
/* Determine the month */
|
|
right_month = ucal_get(right_cal, UCAL_MONTH, status);
|
|
|
|
/* If we're at day 0 (first day of the week), break out */
|
|
if(right_current == 0) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/* Output a newline */
|
|
putc('\n', stdout);
|
|
}
|
|
|
|
/* Output a trailing newline */
|
|
putc('\n', stdout);
|
|
}
|
|
|
|
/* Clean up */
|
|
free_months(months);
|
|
free_days(days);
|
|
udat_close(dfmt);
|
|
unum_close(nfmt);
|
|
ucal_close(right_cal);
|
|
}
|
|
|
|
#endif
|