]> cygwin.com Git - cygwin-apps/cygutils.git/blob - src/cal/cal.c
Fixes for cygstart; bump version number and documentation
[cygwin-apps/cygutils.git] / src / cal / cal.c
1 /* && HAVE_NL_LANGINFO
2 * Copyright (c) 1989, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kim Letkeman.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 /* 2001-12-04 Charles Wilson: modified license to the 'BSD no advert'
34 * license, as required by the Director of the Office of
35 * Technology Licensing of the University of California on
36 * July 22, 1999.
37 * See http://www.opensource.org/licenses/bsd-license.html
38 * 1999-02-01 Jean-Francois Bignolles: added option '-m' to display
39 * monday as the first day of the week.
40 * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
41 * - added Native Language Support
42 *
43 * 2000-09-01 Michael Charles Pruznick <dummy@netwiz.net>
44 * Added "-3" option to print prev/next month with current.
45 * Added over-ridable default NUM_MONTHS and "-1" option to
46 * get traditional output when -3 is the default. I hope that
47 * enough people will like -3 as the default that one day the
48 * product can be shipped that way.
49 *
50 * 2001-05-07 Pablo Saratxaga <pablo@mandrakesoft.com>
51 * Fixed the bugs with multi-byte charset (zg: cjk, utf-8)
52 * displaying. made the 'month year' ("%s %d") header translatable
53 * so it can be adapted to conventions used by different languages
54 * added support to read "first_weekday" locale information
55 * still to do: support for 'cal_direction' (will require a major
56 * rewrite of the displaying) and proper handling of RTL scripts
57 */
58
59 #if HAVE_CONFIG_H
60 # include "config.h"
61 #endif
62
63 #include "common.h"
64 #include "errs.h"
65
66 /* Determine if the C(++) compiler requires complete function prototype */
67 #ifndef __P
68 #if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
69 #define __P(x) x
70 #else
71 #define __P(x) ()
72 #endif
73 #endif
74
75 int main __P((int argc, char *argv[]));
76
77 #ifndef PACKAGE
78 #define PACKAGE "cygutils"
79 #endif
80
81 #ifndef LOCALEDIR
82 #define LOCALEDIR "/usr/share/locale"
83 #endif
84
85 #ifdef HAVE_LOCALE_H
86 # include <locale.h>
87 #endif
88 #if !HAVE_SETLOCALE
89 # undef setlocale(a, b)
90 # define setlocale(a, b) /* empty */
91 #endif
92
93 #ifdef ENABLE_NLS
94 # include <libintl.h>
95 # define _(Text) gettext (Text)
96 # ifdef gettext_noop
97 # define N_(String) gettext_noop (String)
98 # else
99 # define N_(String) (String)
100 # endif
101 #else
102 # undef bindtextdomain
103 # define bindtextdomain(Domain, Directory) /* empty */
104 # undef textdomain
105 # define textdomain(Domain) /* empty */
106 # define _(Text) (Text)
107 # define N_(Text) (Text)
108 #endif
109
110 #if defined HAVE_LANGINFO_H && HAVE_NL_LANGINFO
111 # include <langinfo.h>
112 #else
113 struct time_info_struct {
114 char *abbrev_wkday[7];
115 char *full_month[12];
116 };
117 struct time_info_struct time_info = {
118 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
119 {"January", "February", "March", "April",
120 "May", "June", "July", "August",
121 "September", "October", "November", "December"}
122 };
123 struct time_info_struct * _time_info = &time_info;
124 #endif
125
126 #include "widechar.h"
127
128 /* allow compile-time define to over-ride default */
129 #ifndef NUM_MONTHS
130 #define NUM_MONTHS 1
131 #endif
132
133 #if ( NUM_MONTHS != 1 && NUM_MONTHS !=3 )
134 #error NUM_MONTHS must be 1 or 3
135 #endif
136
137 #define THURSDAY 4 /* for reformation */
138 #define SATURDAY 6 /* 1 Jan 1 was a Saturday */
139
140 #define FIRST_MISSING_DAY 639799 /* 3 Sep 1752 */
141 #define NUMBER_MISSING_DAYS 11 /* 11 day correction */
142
143 #define MAXDAYS 43 /* max slots in a month array */
144 #define SPACE -1 /* used in day array */
145
146 static int days_in_month[2][13] = {
147 {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
148 {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
149 };
150
151 int sep1752[MAXDAYS] = {
152 SPACE, SPACE, 1, 2, 14, 15, 16,
153 17, 18, 19, 20, 21, 22, 23,
154 24, 25, 26, 27, 28, 29, 30,
155 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
156 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
157 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
158 SPACE
159 }, j_sep1752[MAXDAYS] = {
160 SPACE, SPACE, 245, 246, 258, 259, 260,
161 261, 262, 263, 264, 265, 266, 267,
162 268, 269, 270, 271, 272, 273, 274,
163 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
164 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
165 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
166 SPACE
167 }, empty[MAXDAYS] = {
168 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
169 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
170 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
171 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
172 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
173 SPACE, SPACE, SPACE, SPACE, SPACE, SPACE, SPACE,
174 SPACE
175 };
176
177 #define DAY_LEN 3 /* 3 spaces per day */
178 #define J_DAY_LEN 4 /* 4 spaces per day */
179 #define WEEK_LEN 21 /* 7 days * 3 characters */
180 #define J_WEEK_LEN 28 /* 7 days * 4 characters */
181 #define HEAD_SEP 2 /* spaces between day headings */
182 #define J_HEAD_SEP 2
183
184 /* utf-8 can have up to 6 bytes per char; and an extra byte for ending \0 */
185 char day_headings[WEEK_LEN*6+1];
186 /* week1stday = 1 => " M Tu W Th F S S " */
187 char j_day_headings[J_WEEK_LEN*6+1];
188 /* week1stday = 1 => " M Tu W Th F S S " */
189 const char *full_month[12];
190
191 /* leap year -- account for gregorian reformation in 1752 */
192 #define leap_year(yr) \
193 ((yr) <= 1752 ? !((yr) % 4) : \
194 (!((yr) % 4) && ((yr) % 100)) || !((yr) % 400))
195
196 /* number of centuries since 1700, not inclusive */
197 #define centuries_since_1700(yr) \
198 ((yr) > 1700 ? (yr) / 100 - 17 : 0)
199
200 /* number of centuries since 1700 whose modulo of 400 is 0 */
201 #define quad_centuries_since_1700(yr) \
202 ((yr) > 1600 ? ((yr) - 1600) / 400 : 0)
203
204 /* number of leap years between year 1 and this year, not inclusive */
205 #define leap_years_since_year_1(yr) \
206 ((yr) / 4 - centuries_since_1700(yr) + quad_centuries_since_1700(yr))
207
208 /* 0 => sunday (default), 1 => monday */
209 int week1stday=0;
210 int julian;
211
212 #define FMT_ST_LINES 8
213 #define FMT_ST_CHARS 300 /* 90 suffices in most locales */
214 struct fmt_st
215 {
216 char s[FMT_ST_LINES][FMT_ST_CHARS];
217 };
218
219 void ascii_day __P((char *, int));
220 void center __P((const char *, int, int));
221 void day_array __P((int, int, int *));
222 int day_in_week __P((int, int, int));
223 int day_in_year __P((int, int, int));
224 void j_yearly __P((int));
225 void do_monthly __P((int, int, struct fmt_st*));
226 void monthly __P((int, int));
227 void monthly3 __P((int, int));
228 void trim_trailing_spaces __P((char *));
229 void usage __P((void));
230 void yearly __P((int));
231 void headers_init(void);
232 extern char *__progname;
233
234 int
235 main(int argc, char **argv) {
236 struct tm *local_time;
237 time_t now;
238 int ch, month, year, yflag;
239 char *progname, *p;
240 int num_months = NUM_MONTHS;
241
242 progname = argv[0];
243 if ((p = strrchr(progname, '/')) != NULL)
244 progname = p+1;
245 __progname = progname;
246
247 setlocale(LC_ALL, "");
248 bindtextdomain(PACKAGE, LOCALEDIR);
249 textdomain(PACKAGE);
250
251 #if 0 /* setting week1stday is against man page */
252 #if defined HAVE_LANGINFO_H && HAVE_NL_LANGINFO
253 week1stday = (int)(nl_langinfo(_NL_TIME_FIRST_WEEKDAY))[0];
254 #endif
255 #endif
256
257 yflag = 0;
258 while ((ch = getopt(argc, argv, "13mjyV")) != EOF)
259 switch(ch) {
260 case '1':
261 num_months = 1;
262 break;
263 case '3':
264 num_months = 3;
265 break;
266 case 'm':
267 week1stday = 1;
268 break;
269 case 'j':
270 julian = 1;
271 break;
272 case 'y':
273 yflag = 1;
274 break;
275 case 'V':
276 printf(_("%s from %s version %s\n"),
277 progname, PACKAGE, VERSION);
278 return 0;
279 case '?':
280 default:
281 usage();
282 }
283 argc -= optind;
284 argv += optind;
285
286 month = year = 0;
287 switch(argc) {
288 case 2:
289 if ((month = atoi(*argv++)) < 1 || month > 12)
290 errx(1, _("illegal month value: use 1-12"));
291 /* FALLTHROUGH */
292 case 1:
293 if ((year = atoi(*argv)) < 1 || year > 9999)
294 errx(1, _("illegal year value: use 1-9999"));
295 break;
296 case 0:
297 (void)time(&now);
298 local_time = localtime(&now);
299 year = local_time->tm_year + 1900;
300 if (!yflag)
301 month = local_time->tm_mon + 1;
302 break;
303 default:
304 usage();
305 }
306 headers_init();
307
308 if (month && num_months == 1)
309 monthly(month, year);
310 else if (month && num_months == 3)
311 monthly3(month, year);
312 else if (julian)
313 j_yearly(year);
314 else
315 yearly(year);
316 exit(0);
317 }
318
319 #ifndef ENABLE_WIDECHAR
320 static char *eos(char *s) {
321 while (s && *s)
322 s++;
323 return s;
324 }
325 #endif
326
327 void headers_init(void)
328 {
329 int i, wd;
330 #ifdef ENABLE_WIDECHAR
331 wchar_t day_headings_wc[22],j_day_headings_wc[29];
332 wchar_t wd_wc[10];
333 #endif
334
335 strcpy(day_headings,"");
336 strcpy(j_day_headings,"");
337 #ifdef ENABLE_WIDECHAR
338 wcscpy(day_headings_wc,L"");
339 wcscpy(j_day_headings_wc,L"");
340 #endif
341
342 #if defined HAVE_LANGINFO_H && HAVE_NL_LANGINFO
343 # define weekday(wd) nl_langinfo(ABDAY_1+wd)
344 #else
345 # define weekday(wd) _time_info->abbrev_wkday[wd]
346 #endif
347
348 for(i = 0 ; i < 7 ; i++ ) {
349 wd = (i + week1stday) % 7;
350 #ifdef ENABLE_WIDECHAR
351 mbstowcs(wd_wc,weekday(wd),10);
352 if (wcslen(wd_wc) < 3)
353 wcscat(j_day_headings_wc,L" ");
354 if (wcslen(wd_wc) < 2) {
355 wcscat(day_headings_wc, L" ");
356 wcscat(j_day_headings_wc, L" ");
357 }
358 wcsncat(day_headings_wc,wd_wc,2);
359 wcsncat(j_day_headings_wc,wd_wc,3);
360 wcscat(day_headings_wc, L" ");
361 wcscat(j_day_headings_wc, L" ");
362 #else
363 sprintf(eos(day_headings), "%2.2s ", weekday(wd));
364 sprintf(eos(j_day_headings), "%3.3s ", weekday(wd));
365 #endif
366 }
367
368 #ifdef ENABLE_WIDECHAR
369 wcstombs(day_headings,day_headings_wc,sizeof(day_headings));
370 wcstombs(j_day_headings,j_day_headings_wc,sizeof(j_day_headings));
371 #endif
372
373 #undef weekday
374
375 for (i = 0; i < 12; i++) {
376 #if defined HAVE_LANGINFO_H && HAVE_NL_LANGINFO
377 full_month[i] = nl_langinfo(MON_1+i);
378 #else
379 full_month[i] = _time_info->full_month[i];
380 #endif
381 }
382 }
383
384 void
385 do_monthly(month, year, out)
386 int month, year;
387 struct fmt_st* out;
388 {
389 int col, row, len, days[MAXDAYS];
390 char *p, lineout[300];
391 #ifdef ENABLE_WIDECHAR
392 wchar_t lineout_wc[300];
393 #endif
394
395 day_array(month, year, days);
396 /* %s is the month name, %d the year number.
397 * you can change the order and/or add something her; eg for
398 * Basque the translation should be: "%2$dko %1$s", and
399 * the Vietnamese should be "%s na(m %d", etc.
400 */
401 len = sprintf(lineout, _("%s %d"), full_month[month - 1], year);
402 #ifdef ENABLE_WIDECHAR
403 len = mbstowcs(lineout_wc,lineout,len);
404 #endif
405 (void)sprintf(out->s[0],"%*s%s",
406 ((julian ? J_WEEK_LEN : WEEK_LEN) - len) / 2, "", lineout );
407 (void)sprintf(out->s[1],"%s",
408 julian ? j_day_headings : day_headings);
409 for (row = 0; row < 6; row++) {
410 for (col = 0, p = lineout; col < 7; col++,
411 p += julian ? J_DAY_LEN : DAY_LEN)
412 ascii_day(p, days[row * 7 + col]);
413 *p = '\0';
414 trim_trailing_spaces(lineout);
415 (void)sprintf(out->s[row+2],"%s", lineout);
416 }
417 }
418
419 void
420 monthly(month, year)
421 int month, year;
422 {
423 int i;
424 struct fmt_st out;
425
426 do_monthly(month, year, &out);
427 for ( i = 0; i < FMT_ST_LINES; i++ )
428 {
429 printf("%s\n", out.s[i]);
430 }
431 }
432
433 void
434 monthly3(month, year)
435 int month, year;
436 {
437 int i;
438 int width;
439 struct fmt_st out_prev;
440 struct fmt_st out_curm;
441 struct fmt_st out_next;
442 int prev_month, prev_year;
443 int next_month, next_year;
444
445 if ( month == 1 )
446 {
447 prev_month = 12;
448 prev_year = year - 1;
449 }
450 else
451 {
452 prev_month = month - 1;
453 prev_year = year;
454 }
455 if ( month == 12 )
456 {
457 next_month = 1;
458 next_year = year + 1;
459 }
460 else
461 {
462 next_month = month + 1;
463 next_year = year;
464 }
465
466 do_monthly(prev_month, prev_year, &out_prev);
467 do_monthly(month, year, &out_curm);
468 do_monthly(next_month, next_year, &out_next);
469 width = (julian ? J_WEEK_LEN : WEEK_LEN);
470 for ( i = 0; i < FMT_ST_LINES; i++ )
471 {
472 printf("%-*.*s %-*.*s %-*.*s\n",
473 width, width, out_prev.s[i],
474 width, width, out_curm.s[i],
475 width, width, out_next.s[i] );
476 }
477 }
478
479 void
480 j_yearly(year)
481 int year;
482 {
483 int col, *dp, i, month, row, which_cal;
484 int days[12][MAXDAYS];
485 char *p, lineout[80];
486
487 (void)sprintf(lineout, "%d", year);
488 center(lineout, J_WEEK_LEN * 2 + J_HEAD_SEP, 0);
489 (void)printf("\n\n");
490 for (i = 0; i < 12; i++)
491 day_array(i + 1, year, days[i]);
492 (void)memset(lineout, ' ', sizeof(lineout) - 1);
493 lineout[sizeof(lineout) - 1] = '\0';
494 for (month = 0; month < 12; month += 2) {
495 center(full_month[month], J_WEEK_LEN, J_HEAD_SEP);
496 center(full_month[month + 1], J_WEEK_LEN, 0);
497 (void)printf("\n%s%*s%s\n", j_day_headings, J_HEAD_SEP, "",
498 j_day_headings);
499 for (row = 0; row < 6; row++) {
500 for (which_cal = 0; which_cal < 2; which_cal++) {
501 p = lineout + which_cal * (J_WEEK_LEN + 2);
502 dp = &days[month + which_cal][row * 7];
503 for (col = 0; col < 7; col++, p += J_DAY_LEN)
504 ascii_day(p, *dp++);
505 }
506 *p = '\0';
507 trim_trailing_spaces(lineout);
508 (void)printf("%s\n", lineout);
509 }
510 }
511 (void)printf("\n");
512 }
513
514 void
515 yearly(year)
516 int year;
517 {
518 int col, *dp, i, month, row, which_cal;
519 int days[12][MAXDAYS];
520 char *p, lineout[80];
521
522 (void)sprintf(lineout, "%d", year);
523 center(lineout, WEEK_LEN * 3 + HEAD_SEP * 2, 0);
524 (void)printf("\n\n");
525 for (i = 0; i < 12; i++)
526 day_array(i + 1, year, days[i]);
527 (void)memset(lineout, ' ', sizeof(lineout) - 1);
528 lineout[sizeof(lineout) - 1] = '\0';
529 for (month = 0; month < 12; month += 3) {
530 center(full_month[month], WEEK_LEN, HEAD_SEP);
531 center(full_month[month + 1], WEEK_LEN, HEAD_SEP);
532 center(full_month[month + 2], WEEK_LEN, 0);
533 (void)printf("\n%s%*s%s%*s%s\n", day_headings, HEAD_SEP,
534 "", day_headings, HEAD_SEP, "", day_headings);
535 for (row = 0; row < 6; row++) {
536 for (which_cal = 0; which_cal < 3; which_cal++) {
537 p = lineout + which_cal * (WEEK_LEN + 2);
538 dp = &days[month + which_cal][row * 7];
539 for (col = 0; col < 7; col++, p += DAY_LEN)
540 ascii_day(p, *dp++);
541 }
542 *p = '\0';
543 trim_trailing_spaces(lineout);
544 (void)printf("%s\n", lineout);
545 }
546 }
547 (void)printf("\n");
548 }
549
550 /*
551 * day_array --
552 * Fill in an array of 42 integers with a calendar. Assume for a moment
553 * that you took the (maximum) 6 rows in a calendar and stretched them
554 * out end to end. You would have 42 numbers or spaces. This routine
555 * builds that array for any month from Jan. 1 through Dec. 9999.
556 */
557 void
558 day_array(month, year, days)
559 int month, year;
560 int *days;
561 {
562 int day, dw, dm;
563 int *d_sep1752;
564
565 if (month == 9 && year == 1752) {
566 d_sep1752 = julian ? j_sep1752 : sep1752;
567 memcpy(days, d_sep1752 + week1stday, MAXDAYS * sizeof(int));
568 return;
569 }
570 memcpy(days, empty, MAXDAYS * sizeof(int));
571 dm = days_in_month[leap_year(year)][month];
572 dw = (day_in_week(1, month, year) - week1stday + 7) % 7;
573 day = julian ? day_in_year(1, month, year) : 1;
574 while (dm--)
575 days[dw++] = day++;
576 }
577
578 /*
579 * day_in_year --
580 * return the 1 based day number within the year
581 */
582 int
583 day_in_year(day, month, year)
584 int day, month, year;
585 {
586 int i, leap;
587
588 leap = leap_year(year);
589 for (i = 1; i < month; i++)
590 day += days_in_month[leap][i];
591 return (day);
592 }
593
594 /*
595 * day_in_week
596 * return the 0 based day number for any date from 1 Jan. 1 to
597 * 31 Dec. 9999. Assumes the Gregorian reformation eliminates
598 * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all
599 * missing days.
600 */
601 int
602 day_in_week(day, month, year)
603 int day, month, year;
604 {
605 long temp;
606
607 temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1)
608 + day_in_year(day, month, year);
609 if (temp < FIRST_MISSING_DAY)
610 return ((temp - 1 + SATURDAY) % 7);
611 if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS))
612 return (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7);
613 return (THURSDAY);
614 }
615
616 void
617 ascii_day(p, day)
618 char *p;
619 int day;
620 {
621 int display, val;
622 static char *aday[] = {
623 "",
624 " 1", " 2", " 3", " 4", " 5", " 6", " 7",
625 " 8", " 9", "10", "11", "12", "13", "14",
626 "15", "16", "17", "18", "19", "20", "21",
627 "22", "23", "24", "25", "26", "27", "28",
628 "29", "30", "31",
629 };
630
631 if (day == SPACE) {
632 memset(p, ' ', julian ? J_DAY_LEN : DAY_LEN);
633 return;
634 }
635 if (julian) {
636 if ((val = day / 100)) {
637 day %= 100;
638 *p++ = val + '0';
639 display = 1;
640 } else {
641 *p++ = ' ';
642 display = 0;
643 }
644 val = day / 10;
645 if (val || display)
646 *p++ = val + '0';
647 else
648 *p++ = ' ';
649 *p++ = day % 10 + '0';
650 } else {
651 *p++ = aday[day][0];
652 *p++ = aday[day][1];
653 }
654 *p = ' ';
655 }
656
657 void
658 trim_trailing_spaces(s)
659 char *s;
660 {
661 char *p;
662
663 for (p = s; *p; ++p)
664 continue;
665 while (p > s && isspace(*--p))
666 continue;
667 if (p > s)
668 ++p;
669 *p = '\0';
670 }
671
672 void
673 center(str, len, separate)
674 const char *str;
675 int len;
676 int separate;
677 {
678 #ifdef ENABLE_WIDECHAR
679 wchar_t str_wc[300];
680 int str_len;
681
682 str_len = mbstowcs(str_wc,str,300);
683 len -= str_len;
684 #else
685 len -= strlen(str);
686 #endif
687 (void)printf("%*s%s%*s", len / 2, "", str, len / 2 + len % 2, "");
688 if (separate)
689 (void)printf("%*s", separate, "");
690 }
691
692 void
693 usage()
694 {
695
696 (void)fprintf(stderr, _("usage: cal [-mjyV] [[month] year]\n"));
697 exit(1);
698 }
This page took 0.064293 seconds and 5 git commands to generate.