1 /*
2  * calendar.c -- calendar display program
3  *
4  * Copyright (C) 1988,1999,2003 by Yoshifumi Mori
5  *
6  *  2003/06/14 SAT          - UNIX defpathbuf[] �ɲ�
7  *	2003/04/08 TUE ver.2.5B - �ֹ�̱�ε����׼�ư����
8  *	1999/01/19 TUE ver.2.5A - holiday.tbl load proc move to misc.c
9  *	1997/05/25 SUN ver.2.5  - holiday.tbl format change
10  *	1993/08/19 THU ver.2.4A - human68k ESC output sequence change
11  *	1993/07/08 THU ver.2.4
12  *	1993/06/29 TUE          - holiday.tbl 10��ʬ ���º��
13  *	1993/06/27 SUN          - -& -> -r, schedule display support.
14  *	1993/06/20 SUN ver.2.3  - -@, -& option support.
15  *	1993/05/09 SUN ver.2.2  - minor change
16  *	1992/05/13 WED ver.2.1  - minor change
17  *	1992/04/23 THU ver.2.0  - kyureki, color config.
18  *	1991/03/03 SUN ver.1.7  - 3 month display support.
19  *	1990/04/07 SAT ver.1.6a
20  *	1990/03/31 SAT ver.1.6
21  *	1990/03/11 SUN ver.1.5a
22  *	1989/09/24 SUN ver.1.5
23  *	1989/09/12 TUE ver.1.4a
24  *	1989/09/11 MON ver.1.4  - X68000 version.
25  *	1989/06/05 MON ver.1.3a - help option add.
26  *	1989/06/01 THU ver.1.3  - ANSI escape sequence.
27  *	1989/04/11 TUE ver.1.2
28  *	1989/03/22 WED ver.1.1
29  *	1988/12/19 MON ver.1.0
30  *
31  * tab:4
32  */
33 
34 #include "cdefs.h"
35 #include "extern.h"
36 
37 #define MAXATTRBUF		24	/* ���������ץ�������Ÿ���Хåե� */
38 #define MAXLINEBUF		512	/* 1��Ÿ���Хåե��� */
39 #define MAXLINE			6
40 #define MAXWEEK			7
41 #define MAXMONTH		3
42 #define CENTER_MONTH	(MAXMONTH / 2)
43 #define MAXWEEKTBL		(MAXLINE * MAXWEEK)
44 #define MAXMONTHNAME	9
45 #define MAXROKUYOU		6
46 
47 enum WEEK {
48 	SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY,
49 };
50 
51 static const char	Copyright[] = "Copyright (C) 1988,1999,2003 by Yoshifumi Mori";
52 static const char	version[] = "calendar " __DATE__ " version 2.5B";
53 
54 const char	*fmt_sep1 = "/\t ";
55 const char	*fmt_sep2 = ",\t ";
56 const char	*fmt_sep3 = "\t ";
57 const char	*fmt_sep4 = "";
58 
59 const char	*todaycnf_file = "today.cnf";
60 
61 static char	cmdpathbuf[_T_MAXPATHNAME];
62 #if defined(_T_UNIX)
63 static char	defpathbuf[_T_MAXPATHBUF];
64 #endif
65 static char	linebuffer[MAXLINEBUF];
66 static int	daytbl[MAXMONTH][MAXWEEKTBL];
67 static int	attrtbl[MAXMONTH][MAXWEEKTBL];
68 static int	weekcolor[MAXWEEK];
69 static int	cal3_flag = FALSE;
70 static int	kyureki_flag = FALSE;
71 static int	kyureki_valid_flag = TRUE;
72 static int	schedule_flag = TRUE;
73 
74 static struct CALENDAR	nowdate;
75 
76 struct CALTBL	caltbl[MAXMONTH];
77 
78 #define CTBL_COLORMASK	0x0F	/* ���顼�ޥ��� */
79 #define CTBL_REVERSE	16		/* ��С���(ȿžʸ��) */
80 #define CTBL_BLINK		17		/* �֥��(����ʸ��) */
81 #define CTBL_HIGHLIGHT	18		/* �ϥ��饤��(��Ĵʸ��) */
82 #define CTBL_MAX		19		/* ���顼�����ɥơ��֥�� */
83 
84 /* ���顼���������ץ������� �ֹ�ơ��֥� */
85 static int	color[CTBL_MAX] = {
86 	30,						/* �� */
87 	34,						/* �� */
88 	31,						/* �� */
89 	35,						/* �� */
90 	32,						/* �� */
91 	36,						/* �忧 */
92 	33,						/* �� */
93 	37,						/* �� */
94 	0, 0, 0, 0, 0, 0, 0, 0,	/* ͽ���ΰ� */
95 	7,						/* ��С���(ȿžʸ��) */
96 	5,						/* �֥��(����ʸ��) */
97 	1,						/* �ϥ��饤��(��Ĵʸ��) */
98 };
99 
100 #define COL_NONE		-1
101 #define COL_WEEKDAY		0		/* ʿ�� */
102 #define COL_SUNDAY		1		/* ���� */
103 #define COL_SATDAY		2		/* ���� */
104 #define COL_HOLIDAY		3		/* ����/���� */
105 #define COL_ROKUYOU		4		/* ϻ�� */
106 #define COL_SCHEDULE	10		/* �������塼�뤢�� */
107 #define COL_TODAY		20		/* ���� */
108 #define COL_HEADER		40		/* �إå��� */
109 #define COL_MAX			41		/* ���顼�ơ��֥�� */
110 
111 #define ATTR_REVERSE	0x10	/* ��С���(ȿžʸ��) */
112 #define ATTR_BLINK		0x20	/* �֥��(����ʸ��) */
113 #define ATTR_HIGHLIGHT	0x40	/* �ϥ��饤��(��Ĵʸ��) */
114 
115 /* �������� �ƹ��ܥ��顼�ơ��֥� */
116 static int	calcolor[COL_MAX] = {
117 	0x07, 0x02, 0x05, 0x02, 0x04,  0x05, 0x03, 0x01, 0x02, 0x07,	/* 0~9 */
118 	0x06, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00,	/* 10~19 */
119 	0x67, 0x62, 0x65, 0x62, 0x64,  0x65, 0x63, 0x61, 0x62, 0x67,	/* 20~29 */
120 	0x66, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00,	/* 30~39 */
121 	0x07,
122 };
123 /* calcolor[n]
124  *      0 : ʿ��                   ��
125  *      1 : ����                   ��
126  *      2 : ����                   �忧
127  *      3 : ����/����              ��
128  *      4 : �辡                   ��
129  *      5 : ͧ��                   �忧
130  *      6 : ����                   ��
131  *      7 : ʩ��                   ��
132  *      8 : ���                   ��
133  *      9 : �ָ�                   ��
134  *     10 : �������塼�뤢��       ����
135  *  11~29 : ͽ���ΰ�
136  *  20~30 : ʿ�����ָ� �����ξ��  �ƿ�+�֥��+�ϥ��饤��
137  *  31~39 : ͽ���ΰ�
138  *     40 : �إå���               ��
139  */
140 
141 #define COLMAP_COLMASK(x)	((x) & 0x00FF)
142 #define COLMAP_NEWLINE		0x0100
143 #define COLMAP_TODAY		0x0200
144 #define COLMAP_ROKUYOU		0x0400
145 #define COLMAP_HEADER		0x0800
146 #define COLMAP_ATTRMASK(x)	((x) & (COLMAP_NEWLINE | COLMAP_TODAY | \
147 							COLMAP_ROKUYOU | COLMAP_HEADER))
148 
149 enum {
150 	COLMAP_FIRST,		/* ���� */
151 	COLMAP_SECOND,		/* ���� */
152 	COLMAP_ROKUYOU1,	/* ϻ�� ��6�� */
153 	COLMAP_ROKUYOU2,	/* ϻ�� ��3�� */
154 };
155 
156 static struct COLOR_MAP {
157 	const char	*name;
158 	const int	attr;
159 } colormap_tbl[] = {
160 	{ "�إå���",     COL_HEADER        | COLMAP_HEADER | COLMAP_NEWLINE },
161 	{ "ʿ��",         COL_WEEKDAY       | COLMAP_TODAY },
162 	{ "����",         COL_SUNDAY        | COLMAP_TODAY },
163 	{ "����",         COL_SATDAY        | COLMAP_TODAY },
164 	{ "����",         COL_HOLIDAY       | COLMAP_TODAY },
165 	{ "�������塼��", COL_SCHEDULE      | COLMAP_TODAY  | COLMAP_NEWLINE },
166 	{ "�辡",         (COL_ROKUYOU + 0) | COLMAP_TODAY  | COLMAP_ROKUYOU },
167 	{ "ͧ��",         (COL_ROKUYOU + 1) | COLMAP_TODAY  | COLMAP_ROKUYOU },
168 	{ "����",         (COL_ROKUYOU + 2) | COLMAP_TODAY  | COLMAP_ROKUYOU },
169 	{ "ʩ��",         (COL_ROKUYOU + 3) | COLMAP_TODAY  | COLMAP_ROKUYOU },
170 	{ "���",         (COL_ROKUYOU + 4) | COLMAP_TODAY  | COLMAP_ROKUYOU },
171 	{ "�ָ�",         (COL_ROKUYOU + 5) | COLMAP_TODAY  | COLMAP_ROKUYOU | COLMAP_NEWLINE },
172 	{ NULL,           0 }
173 };
174 
175 static const struct OPERAND_TABLE	op_mode[] = {
176 	{ "yes", TRUE  },
177 	{ "no",  FALSE },
178 	{ NULL,  0     },
179 };
180 
181 /* ����ե����졼����� �ѥ�᡼�� */
182 static struct CONFIG_VARIABLE_TABLE	conf_tbl[] = {
183 	{ "calcolor",        VAR_DIMINT, { (void *)COL_MAX         }, { calcolor         } },
184 	{ "color",           VAR_DIMINT, { (void *)CTBL_MAX        }, { color            } },
185 	{ "kyureki",         VAR_OP,     { op_mode                 }, { &kyureki_flag    } },
186 	{ "replace_pathenv", VAR_OP,     { op_mode                 }, { &replace_pathenv } },
187 	{ "schedule",        VAR_OP,     { op_mode                 }, { &schedule_flag   } },
188 	{ "schedule_file",   VAR_DIMSTR, { (void *)MAXSCHEDULEFILE }, { schedule_filetbl } },
189 #if defined(_T_HUMAN68K) || defined(_T_MSDOS) || defined(_T_WIN32CONSOLE)
190 	{ "table_path",      VAR_STR,    { NULL                    }, { &search_path     } },
191 #else /* _T_UNIX */
192 	{ "table_path",      VAR_PATH,   { NULL                    }, { &search_path     } },
193 #endif
194 	{ "three_months",    VAR_OP,     { op_mode                 }, { &cal3_flag       } },
195 	{ NULL,              VAR_NONE,   { NULL                    }, { NULL             } },
196 };
197 
198 static const char	*readblock[] = { "calendar", "common", NULL };
199 
200 static void calendar(int year, int month);
201 static void setup_weekcolor(void);
202 static void schedule_setup(int monindex);
203 static void kyureki_setup(int monindex);
204 static void output_header(void);
205 static void output_calendar(void);
206 static void add_spaces(int spcnt, int *attr);
207 static void output_footer(void);
208 static void output_colormap(void);
209 static void output_colorsample(int type);
210 static void holidayset(int monindex);
211 static const char *MakeAttr(int attr);
212 static void clear_buffer(void);
213 static void add_buffer(const char *fmt, ...);
214 static void flush_buffer(void);
215 
main(int argc,char ** argv)216 int main(int argc, char **argv)
217 {
218 	int	c_rtc;
219 	int	year, month;
220 	int	errflag;
221 	int	verflag;
222 	int	testflag;
223 	int	c;
224 
225 #if defined(_T_HUMAN68K) || defined(_T_MSDOS) || defined(_T_WIN32CONSOLE)
226 	{
227 		char	*p;
228 
229 		strncpy(cmdpathbuf, argv[0], sizeof(cmdpathbuf) - 1);
230 		p = strrchr(cmdpathbuf, _T_FS_CHR);
231 		if (p == NULL) {
232 			p = strrchr(cmdpathbuf, '/');
233 			if (p == NULL) {
234 				p = strrchr(cmdpathbuf, ':');
235 			}
236 		}
237 		if (p != NULL) {
238 			p[1] = '\0';
239 			search_cmdpath = cmdpathbuf;
240 		}
241 	}
242 #else /* _T_UNIX */
243 	if (readlink(_T_PROCSELFEXE_PATH, cmdpathbuf, sizeof(cmdpathbuf) - 1) > 0 &&
244 	    cmdpathbuf[0] == '/') {
245 		char	*p;
246 
247 		p = strrchr(cmdpathbuf, '/');
248 		if (p != NULL) {
249 			p[1] = '\0';
250 		}
251 		search_cmdpath = cmdpathbuf;
252 	}
253 
254 	(void)setlocale(LC_ALL, "");
255 	strncpy(defpathbuf, _T_SEARCH_DEFPATHS, sizeof(defpathbuf) - 1);
256 	search_defpath = defpathbuf;
257 #endif
258 
259 	search_envname = "TODAYTBL";
260 	replace_pathenv = TRUE;
261 
262 	c_rtc = config(todaycnf_file, &conf_tbl[0], &readblock[0]);
263 
264 #if defined(_T_UNIX)
265 /*
266  * unix �Ǥ� _T_SEARCH_DEFPATH �� today.cnf ���ɤ᤿�� HOME ��
267  * today.cnf ���ɤ߹���
268  *
269  * table_path �� & �� HOME �ˤ��� today.cnf �� table_path �����ꤷ�Ƥ�
270  * ��� & ����ʬ������Υѥ����֤�������
271  *
272  * �� table_path = &:/home/mori/tbl
273  */
274 	if (c_rtc == 0 && search_hitphase == 1) {	/* _T_SEARCH_DEFPATH ��ȯ���Ǥ��� */
275 		search_errignore = TRUE;
276 		search_gophase = 6;	/* _T_HOMEENV ��Ĵ�٤� */
277 		(void)config(todaycnf_file, &conf_tbl[0], &readblock[0]);
278 		search_gophase = 0;
279 		search_errignore = FALSE;
280 	}
281 #endif /* _T_UNIX */
282 
283 	rdcalendar(&nowdate);
284 	year = nowdate.year;
285 	month = nowdate.month;
286 
287 	errflag = FALSE;
288 	verflag = FALSE;
289 	testflag = FALSE;
290 
291 	while ((c = getopt(argc, argv, "13@::Kkr::Sstv?")) != EOF) {
292 		switch (c) {
293 		case '1':
294 			cal3_flag = FALSE;
295 			break;
296 		case '3':
297 			cal3_flag = TRUE;
298 			break;
299 		case 'k':
300 			kyureki_flag = TRUE;
301 			break;
302 		case 'K':
303 			kyureki_flag = FALSE;
304 			break;
305 		case 's':
306 			schedule_flag = TRUE;
307 			break;
308 		case 'S':
309 			schedule_flag = FALSE;
310 			break;
311 		case 'v':
312 			verflag = TRUE;
313 			break;
314 		case 't':
315 			testflag = TRUE;
316 			break;
317 		case 'r':	/* ���Ū���ѿ������� */
318 			if (optarg != NULL) {
319 				config_oneline("cmdline", &conf_tbl[0], optarg);
320 			}
321 			break;
322 		case '@':	/* ���Ū�� TODAY.CNF ���ɤ߹��� */
323 			config(optarg, &conf_tbl[0], &readblock[0]);
324 			break;
325 		case '?':
326 		default:
327 			errflag = TRUE;
328 			break;
329 		}
330 	}
331 
332 	argc -= optind;
333 	argv += optind;
334 
335 	switch (argc) {
336 	case 0:	/* no option */
337 		break;
338 	case 2:	/* month & year option */
339 		year = atoi(argv[1]);
340 	case 1:	/* month option */
341 		month = atoi(argv[0]);
342 		break;
343 	default:
344 		errflag = TRUE;
345 	}
346 
347 	if (verflag == TRUE) {
348 		puts(Copyright);
349 		puts(version);
350 	}
351 	if (testflag == TRUE) {
352 		output_colormap();
353 		return (0);
354 	}
355 	if (errflag == TRUE) {
356 		fprintf(stderr, "usage: calendar [options] [month [year]]\n"
357 				"options:"
358 				  " -1|-3\tɽ���������\t\t-1��1��ʬ\n"
359 				"\t -k|-K\tϻ�ˤ�ɽ������\t\t-k��ɽ��\n"
360 				"\t -s|-S\t�������塼���ɽ������\t-s��ɽ��\n"
361 				"\t -t\t�����������ɽ��\n"
362 				"\t -v\t�С������ɽ��\n\n"
363 				"\t -@file\t���Ū��%s(file)���ɤ߹���\n"
364 				"\t -rvarname=value ���Ū���ѿ����ѹ�\n", todaycnf_file);
365 		exit(3);
366 	}
367 
368 	calendar(year, month);
369 
370 	return (0);
371 }
372 
373 /*
374  * ��������ɽ���ᥤ��
375  */
376 static
calendar(int year,int month)377 void calendar(int year, int month)
378 {
379 	int	i;
380 
381 	if (year < 1 || year > 9999) {
382 		errprint(NULL, ERR_ERROR, "invalid year %d\n", year);
383 		exit(5);
384 	}
385 	if (month < 1 || month > 12) {
386 		errprint(NULL, ERR_ERROR, "invalid month %d\n", month);
387 		exit(5);
388 	}
389 
390 	if (Loading_GengoTbl() != LOAD_OK) {
391 		errprint(NULL, ERR_ERROR, "ǯ���Ѵ��ϤǤ��ޤ���");
392 	}
393 	if (Loading_HolidayTbl() != LOAD_OK) {
394 		errprint(NULL, ERR_ERROR, "������������ɽ���Ǥ��ޤ���");
395 	}
396 
397 	for (i = 0; i < MAXMONTH; i++) {
398 		int	nyear;
399 		int	nmonth;
400 		int	nday;
401 
402 		nyear = year;
403 		nmonth = month + (i - CENTER_MONTH);
404 		if (nmonth < 1) {
405 			nyear--;
406 			nmonth += 12;
407 		}
408 		if (nmonth > 12) {
409 			nyear++;
410 			nmonth -= 12;
411 		}
412 
413 		nday = GetDayofMonth(nyear, nmonth);
414 		caltbl[i].year = nyear;
415 		caltbl[i].month = nmonth;
416 		caltbl[i].dayofmonth = nday;
417 		caltbl[i].first_dayofweek = GetDayofWeek(nyear, nmonth, 1);
418 		caltbl[i].last_dayofweek = GetDayofWeek(nyear, nmonth, nday);
419 		caltbl[i].monthname = GetNameofMonth(1, nmonth);
420 	}
421 
422 	setup_weekcolor();
423 	/*
424 	 * ����λ��ϰ츫��̵�̤˸����뤬
425 	 * �������顼������Ǥ��ʤ����ˡ����̤�����
426 	 */
427 	for (i = 0; i < MAXMONTH; i++) {
428 		int	weekindex;
429 
430 		for (weekindex = 0; weekindex < MAXWEEKTBL; weekindex++) {
431 			daytbl[i][weekindex] = 0;
432 			attrtbl[i][weekindex] = weekcolor[weekindex % MAXWEEK];
433 		}
434 	}
435 
436 	if (schedule_flag == TRUE) {
437 		schedule_find();
438 	}
439 
440 	for (i = 0; i < MAXMONTH; i++) {
441 		int	weekindex;
442 		int	day;
443 
444 		weekindex = caltbl[i].first_dayofweek;
445 
446 		for (day = 1; day <= caltbl[i].dayofmonth; day++, weekindex++) {
447 			daytbl[i][weekindex] = day;
448 		}
449 
450 		if (kyureki_flag == FALSE) {
451 			holidayset(i);
452 			schedule_setup(i);
453 		} else {
454 			kyureki_setup(i);
455 #if 0
456 			schedule_setup(i);
457 #endif
458 		}
459 
460 		/* today mark */
461 		if (caltbl[i].year == nowdate.year &&
462 		    caltbl[i].month == nowdate.month) {
463 			weekindex = caltbl[i].first_dayofweek + nowdate.day - 1;
464 			attrtbl[i][weekindex] += COL_TODAY;
465 		}
466 	}
467 
468 	output_header();
469 	output_calendar();
470 	output_footer();
471 }
472 
473 /*
474  * ���ˤο������ꤹ��
475  */
476 static
setup_weekcolor(void)477 void setup_weekcolor(void)
478 {
479 	int	i;
480 
481 	for (i = 0; i < MAXWEEK; i++) {
482 		weekcolor[i] = COL_WEEKDAY;
483 	}
484 	weekcolor[SUNDAY] = COL_SUNDAY;
485 	weekcolor[SATURDAY] = COL_SATDAY;
486 }
487 
488 /*
489  * �������塼������ꤹ��
490  */
491 static
schedule_setup(int monindex)492 void schedule_setup(int monindex)
493 {
494 	int	i;
495 	int	day;
496 
497 	if (schedule_flag == FALSE) {
498 		return ;
499 	}
500 
501 	for (i = 0; i < MAXWEEKTBL; i++) {
502 		day = daytbl[monindex][i];
503 		if (day > 0 && schedule_daytbl[monindex][day - 1] == SCHEDULE_EXIST) {
504 			attrtbl[monindex][i] = COL_SCHEDULE;
505 		}
506 	}
507 }
508 
509 /*
510  * ϻ��(����)�����ꤹ��
511  */
512 static
kyureki_setup(int monindex)513 void kyureki_setup(int monindex)
514 {
515 	int	year, month, day;
516 	int	i;
517 
518 	if (kyureki_valid_flag == FALSE) {
519 		return ;
520 	}
521 
522 	year = caltbl[monindex].year;
523 	month = caltbl[monindex].month;
524 
525 	for (i = 0; i < MAXWEEKTBL; i++) {
526 		day = daytbl[monindex][i];
527 		if (day > 0) {
528 			const struct LUNAR_CALENDAR	*lc;
529 
530 			lc = GetLunarCalendar(year, month, day);
531 			if (lc == NULL) {
532 				errprint(NULL, ERR_ERROR, "�������뤳�Ȥ��Ǥ��ޤ���");
533 				kyureki_valid_flag = FALSE;
534 				return ;
535 			}
536 
537 			attrtbl[monindex][i] = lc->dayofweek + COL_ROKUYOU;
538 		}
539 	}
540 }
541 
542 /*
543  * �إå�������Ϥ���
544  */
545 static
output_header(void)546 void output_header(void)
547 {
548 	const char	*spbuf, *spbuf2;
549 	int	loop_limit;
550 	int	i;
551 
552 	clear_buffer();
553 	add_buffer(MakeAttr(COL_HEADER));
554 
555 	spbuf = "         ";	/* 9 */
556 	spbuf2 = "     ";		/* 5 */
557 	loop_limit = 1;
558 	if (cal3_flag == TRUE) {
559 		spbuf = "      ";	/* 6 */
560 		spbuf2 = "  ";		/* 2 */
561 		loop_limit = MAXMONTH;
562 	}
563 
564 	for (i = 0; i < MAXMONTH; i++) {
565 		const char	*nammonth;
566 		char	nambuf[MAXMONTHNAME + 1];
567 		int		spcnt;
568 
569 		if (cal3_flag == FALSE && i != CENTER_MONTH) {
570 			continue;
571 		}
572 
573 		nammonth = caltbl[i].monthname;
574 		spcnt = (MAXMONTHNAME - strlen(nammonth)) / 2;
575 		memset(nambuf, '\0', sizeof(nambuf));
576 		memset(nambuf, ' ', spcnt);
577 		strcat(nambuf, nammonth);
578 
579 		add_buffer("%s%-9s%s%4d", spbuf, nambuf, spbuf2, caltbl[i].year);
580 
581 		/* next month space */
582 		if (cal3_flag == TRUE && i < (MAXMONTH - 1)) {
583 			add_buffer("  ");
584 		}
585 	}
586 	add_buffer(MakeAttr(COL_NONE));
587 	flush_buffer();
588 
589 	add_buffer(MakeAttr(COL_HEADER));
590 	for (i = 0; i < loop_limit; i++) {
591 		if (cal3_flag == TRUE) {
592 			add_buffer("SunMonTueWedThuFriSat");
593 			/* next month space */
594 			if (i < (loop_limit - 1)) {
595 				add_buffer("  ");
596 			}
597 		} else {
598 			add_buffer("Sun Mon Tue Wed Thu Fri Sat");
599 		}
600 	}
601 	add_buffer(MakeAttr(COL_NONE));
602 	flush_buffer();
603 }
604 
605 /*
606  * �����������Τ���Ϥ���
607  */
608 static
output_calendar(void)609 void output_calendar(void)
610 {
611 	int	attr;
612 	int	linecount;
613 
614 	clear_buffer();
615 	attr = COL_NONE;
616 	add_buffer(MakeAttr(attr));
617 
618 	for (linecount = 0; linecount < MAXLINE; linecount++) {
619 		int	i;
620 
621 		for (i = 0; i < MAXMONTH; i++) {
622 			int	weekindex;
623 			int	weekcount;
624 
625 			if (cal3_flag == FALSE && i != CENTER_MONTH) {
626 				continue;
627 			}
628 
629 			weekindex = linecount * MAXWEEK;
630 			for (weekcount = 0; weekcount < MAXWEEK; weekcount++) {
631 				if (daytbl[i][weekindex] != 0) {
632 					add_spaces(1, &attr);
633 					if (attr != attrtbl[i][weekindex]) {
634 						attr = attrtbl[i][weekindex];
635 						add_buffer(MakeAttr(attr));
636 					}
637 					add_buffer("%2d", daytbl[i][weekindex]);
638 				} else {
639 					add_spaces(3, &attr);
640 				}
641 				if (cal3_flag == FALSE) {
642 					add_spaces(1, &attr);
643 				}
644 				weekindex++;
645 			}
646 
647 			/* next month space */
648 			if (cal3_flag == TRUE && i < (MAXMONTH - 1)) {
649 				add_spaces(2, &attr);
650 			}
651 		}
652 		if (attr != COL_NONE) {
653 			attr = COL_NONE;
654 			add_buffer(MakeAttr(attr));
655 		}
656 		flush_buffer();
657 	}
658 }
659 
660 /*
661  * ���ϥХåե��˥��ڡ������ɲä���
662  */
663 static
add_spaces(int spcnt,int * attr)664 void add_spaces(int spcnt, int *attr)
665 {
666 	if (*attr != COL_NONE) {
667 		*attr = COL_NONE;
668 		add_buffer(MakeAttr(*attr));
669 	}
670 	while (spcnt-- > 0) {
671 		add_buffer(" ");
672 	}
673 }
674 
675 /*
676  * �եå�������Ϥ���
677  */
678 static
output_footer(void)679 void output_footer(void)
680 {
681 	if (kyureki_flag == FALSE || kyureki_valid_flag == FALSE) {
682 		return ;
683 	}
684 
685 	if (cal3_flag == FALSE) {
686 		output_colorsample(COLMAP_ROKUYOU2);
687 	} else {
688 		output_colorsample(COLMAP_ROKUYOU1);
689 	}
690 }
691 
692 /*
693  * ���������γƿ���������֤�ɽ������
694  */
695 static
output_colormap(void)696 void output_colormap(void)
697 {
698 	clear_buffer();
699 	add_buffer("%s�������� �ƿ��������", MakeAttr(COL_NONE));
700 	flush_buffer();
701 
702 	output_colorsample(COLMAP_FIRST);
703 
704 	add_buffer("%s�����ξ��", MakeAttr(COL_NONE));
705 	flush_buffer();
706 
707 	output_colorsample(COLMAP_SECOND);
708 }
709 
710 /*
711  * �ƹ��ܤο������ɽ������
712  */
713 static
output_colorsample(int type)714 void output_colorsample(int type)
715 {
716 	int	i = 0;
717 	struct COLOR_MAP	*cmp;
718 
719 	clear_buffer();
720 
721 	for (cmp = colormap_tbl; cmp->name != NULL; cmp++) {
722 		int	attr = COLMAP_ATTRMASK(cmp->attr);
723 		int	dspflag = FALSE;
724 		int	base_no = 0;
725 		int	namcolor = COL_NONE;
726 
727 		switch (type) {
728 		case COLMAP_FIRST:
729 			dspflag = TRUE;
730 			break;
731 		case COLMAP_SECOND:
732 			if (attr & COLMAP_TODAY) {
733 				dspflag = TRUE;
734 				base_no = COL_TODAY;
735 			}
736 			break;
737 		case COLMAP_ROKUYOU1:
738 		case COLMAP_ROKUYOU2:
739 			if (attr & COLMAP_ROKUYOU) {
740 				dspflag = TRUE;
741 				namcolor = COL_HEADER;
742 				if (type == COLMAP_ROKUYOU2) {
743 					i++;
744 				}
745 			}
746 			break;
747 		}
748 
749 		if (dspflag == TRUE) {
750 			add_buffer("%s��", MakeAttr(COLMAP_COLMASK(cmp->attr) + base_no));
751 			add_buffer("%s..%s", MakeAttr(namcolor), cmp->name);
752 
753 			if (namcolor == COL_HEADER) {
754 				add_buffer(MakeAttr(COL_NONE));
755 			}
756 
757 			if (attr & COLMAP_NEWLINE || i == 3) {
758 				flush_buffer();
759 			} else {
760 				add_buffer("  ");
761 			}
762 		}
763 	}
764 
765 	flush_buffer();
766 }
767 
768 /*
769  * �����������������������ꤹ��(���ص�����Ԥ�)
770  */
771 static
holidayset(int monindex)772 void holidayset(int monindex)
773 {
774 	int	*tbl;
775 	int	i;
776 	int	day;
777 	int	week;
778 
779 	tbl = GetHolidayTbl(caltbl[monindex].year, caltbl[monindex].month);
780 	if (tbl != NULL) {
781 		for (i = 0; i < MAX_DAYOFMONTH; i++) {
782 			if (tbl[i] != 0) {
783 				day = i + 1;
784 				week = caltbl[monindex].first_dayofweek + day - 1;
785 				if ((week % MAXWEEK) == SUNDAY &&
786 				    checkTransferHoliday(caltbl[monindex].year, caltbl[monindex].month, day) == TRUE) {
787 					day++;
788 					week++;	/* ���ص��� */
789 				}
790 				if (day <= caltbl[monindex].dayofmonth) {
791 					attrtbl[monindex][week] = COL_HOLIDAY;
792 				} else if ((monindex + 1) < MAXMONTH) {
793 					attrtbl[monindex + 1][week % MAXWEEK] = COL_HOLIDAY;
794 				}
795 			}
796 			/* �ֹ�̱�ε�����Ŭ�����б� */
797 			if (i >= 2 &&
798 		        tbl[i - 2] != 0 &&
799 		        tbl[i - 1] == 0 &&
800 		        tbl[i + 0] != 0 &&
801 			    checkNationalHoliday(caltbl[monindex].year, caltbl[monindex].month, i) == TRUE) {
802 				week = caltbl[monindex].first_dayofweek + i - 1;
803 				if ((week % MAXWEEK) != SUNDAY) {
804 					attrtbl[monindex][week] = COL_HOLIDAY;
805 				}
806 			}
807 		}
808 		free(tbl);
809 	}
810 }
811 
812 /*
813  * ���������ץ�������ʸ�������
814  */
815 static
MakeAttr(int attr)816 const char *MakeAttr(int attr)
817 {
818 	static char	attrbuf[MAXATTRBUF];
819 	int	colno;
820 
821 	colno = calcolor[attr];
822 
823 	strcpy(attrbuf, "\033[");
824 	if (attr == COL_NONE) {
825 		strcat(attrbuf, "0m");
826 		return (attrbuf);
827 	}
828 #if defined(_T_HUMAN68K)
829 	sprintf(strlastp(attrbuf), "%d", color[colno & CTBL_COLORMASK]);
830 	if ((colno & ATTR_HIGHLIGHT) != 0 && color[CTBL_HIGHLIGHT] != 0) {
831 		sprintf(strlastp(attrbuf), ";%d", color[CTBL_HIGHLIGHT]);
832 	}
833 	if ((colno & ATTR_BLINK) != 0 && color[CTBL_BLINK] != 0) {
834 		sprintf(strlastp(attrbuf), ";%d", color[CTBL_BLINK]);
835 	}
836 	if ((colno & ATTR_REVERSE) != 0 && color[CTBL_REVERSE] != 0) {
837 		sprintf(strlastp(attrbuf), ";%d", color[CTBL_REVERSE]);
838 	}
839 	strcat(attrbuf, "m");
840 #else /* _T_MSDOS || _T_UNIX || _T_WIN32CONSOLE */
841 	if ((colno & ATTR_HIGHLIGHT) != 0 && color[CTBL_HIGHLIGHT] != 0) {
842 		sprintf(strlastp(attrbuf), "%d;", color[CTBL_HIGHLIGHT]);
843 	}
844 	if ((colno & ATTR_BLINK) != 0 && color[CTBL_BLINK] != 0) {
845 		sprintf(strlastp(attrbuf), "%d;", color[CTBL_BLINK]);
846 	}
847 	if ((colno & ATTR_REVERSE) != 0 && color[CTBL_REVERSE] != 0) {
848 		sprintf(strlastp(attrbuf), "%d;", color[CTBL_REVERSE]);
849 	}
850 	sprintf(strlastp(attrbuf), "%dm", color[colno & CTBL_COLORMASK]);
851 #endif
852 	return (attrbuf);
853 }
854 
855 /*
856  * ���ꥨ�顼����
857  */
memerr(const char * func)858 void memerr(const char *func)
859 {
860 	errprint(func, ERR_PANIC, "virtual memory exhausted, program stop.");
861 	terminate_program(TERM_MEMERROR);
862 }
863 
864 /*
865  * �¹���Υ��顼ɽ��
866  *
867  * func:  �¹Դؿ�̾
868  * level: ���顼��٥� (information, warning, debug, error, panic)
869  * fmt:   ���顼��å�����
870  */
errprint(const char * func,int level,const char * fmt,...)871 void errprint(const char *func, int level, const char *fmt, ...)
872 {
873 	static const char	*statname[] = {
874 		"warning", "debug", "error", "panic",
875 	};
876 	va_list	ap;
877 
878 	va_start(ap, fmt);
879 
880 	fprintf(stderr, "calendar: %s");
881 	if (level != ERR_INFO) {
882 		fprintf(stderr, "%s: ", statname[level - ERR_WARN]);
883 	}
884 	if (func != NULL) {
885 		fprintf(stderr, "%s: ", func);
886 	}
887 	vfprintf(stderr, fmt, ap);
888 	fprintf(stderr, "\n");
889 
890 	va_end(ap);
891 }
892 
893 /*
894  * �����ѥХåե��ν����
895  */
896 static
clear_buffer(void)897 void clear_buffer(void)
898 {
899 	memset(linebuffer, '\0', sizeof(linebuffer));
900 }
901 
902 /*
903  * ���ϥХåե���ʸ����(fmt)���ɲä���
904  */
905 static
add_buffer(const char * fmt,...)906 void add_buffer(const char *fmt, ...)
907 {
908 	char	*lp;
909 	va_list	ap;
910 
911 	lp = strlastp(linebuffer);
912 	va_start(ap, fmt);
913 	vsprintf(lp, fmt, ap);
914 	va_end(ap);
915 }
916 
917 /*
918  * ���ϥХåե������Ƥ����(stdout)�˽��Ϥ���
919  */
920 static
flush_buffer(void)921 void flush_buffer(void)
922 {
923 	if (linebuffer[0] == '\0') {
924 		return ;
925 	}
926 
927 	puts(linebuffer);
928 	clear_buffer();
929 }
930 
931 /*
932  * ���顼�ˤ��ץ�������ǽ���
933  */
terminate_program(int sig)934 void terminate_program(int sig)
935 {
936 	switch (sig) {
937 	case TERM_MEMERROR:
938 		exit(1);
939 		break;
940 	}
941 	exit(99);
942 }
943