1 /*
2  * schedule.c -- schedule manage
3  *
4  * Copyright (C) 1993,1997,1999,2003 by Yoshifumi Mori
5  *
6  * tab:4
7  */
8 
9 #include "cdefs.h"
10 #include "extern.h"
11 
12 #define SCHEDULE_FOLDTYPE_DEFAULT	(MSG_FOLDTYPE_BASE + 1)	/* type1 */
13 #define SCHEDULE_DEFAULT_RANGE		4	/* notify max 4 days */
14 
15 char	*schedule_filetbl[MAXSCHEDULEFILE];
16 
17 #ifndef INCLUDE_CALENDAR
18 char	*schedule_sortorder;
19 int		schedule_sort = SORT_UP_ORDER;
20 int		schedule_foldtype = SCHEDULE_FOLDTYPE_DEFAULT;
21 int		schedule_limit = SCHEDULE_DEFAULT_RANGE;
22 
23 static int	schedule_sortflag;
24 static int	schedule_sortorder_tbl[MAXSORTITEM];	/* ����_����_���� */
25 static int	schedule_listup_flag;
26 static const int	mesg_start_tbl[4][2] = {	/* �ޤ��֤��Կ� */
27 	{ 13, 13 },	/* type0 1st:13, 2nd:13 */
28 	{ 14, 12 },	/* type1 1st:14, 2nd:12 */
29 	{ 14, 14 },	/* type2 1st:14, 2nd:14 */
30 	{ 16, 14 }	/* type3 1st:16, 2nd:14 */
31 };
32 static int	sc_range;
33 #else /* INCLUDE_CALENDAR */
34 char	schedule_daytbl[MAXMONTH_SCHEDULE][MAXDAY_SCHEDULE];
35 #endif /* INCLUDE_CALENDAR */
36 
37 #ifndef INCLUDE_CALENDAR
38 static int schedule_search(int index, const char *infile);
39 static int schedule_make_msg(int month, int day, int diffday, const char *comment, const char *msg);
40 static void schedule_listup(int diffday, int tm);
41 static void schedule_listadd(int sortorder_no, int diffday, int tm);
42 static void schedule_output(const char *msg, ...);
43 static int schedule_range(void);
44 #endif /* !INCLUDE_CALENDAR */
45 
46 #ifndef INCLUDE_CALENDAR
47 /*
48  * �������塼���ɽ������
49  */
schedule(void)50 void schedule(void)
51 {
52 	int	i;
53 	int	j;
54 	void	(*output_func)(const char *msg, ...);
55 
56 	schedule_sortflag = TRUE;
57 	schedule_sortorder_tbl[0] = 0;
58 	schedule_sortorder_tbl[1] = 1;
59 	schedule_sortorder_tbl[2] = 2;
60 	schedule_listup_flag = FALSE;
61 
62 	if (schedule_foldtype < MSG_FOLDTYPE_BASE + 0 ||
63 	    schedule_foldtype > MSG_FOLDTYPE_BASE + 3) {
64 		schedule_foldtype = SCHEDULE_FOLDTYPE_DEFAULT;
65 		errprint("schedule", ERR_WARN, "schedule_foldtype error, default %d set", schedule_foldtype);
66 	}
67 	if (schedule_limit < -MAX_DAYOFMONTH || schedule_limit > MAX_DAYOFMONTH) {
68 		schedule_limit = SCHEDULE_DEFAULT_RANGE;
69 		errprint("schedule", ERR_WARN, "schedule_limit error, default %d set", schedule_limit);
70 	}
71 
72 	schedule_sortflag = analysis_sortorder("schedule", schedule_sortorder, schedule_sortorder_tbl, schedule_sortflag);
73 
74 	sc_range = schedule_range();
75 
76 	list_init();
77 
78 	for (i = 0; i < MAXSCHEDULEFILE; i++) {
79 		if (schedule_filetbl[i] != NULL) {
80 			for (j = CENTER_MONTH; j < MAX_MONTH_TBL; j++) {
81 				if (schedule_search(j, schedule_filetbl[i]) == FALSE &&
82 				    (mkfile_status & (SET_MKF_CC | SET_MKF_YY | SET_MKF_MM)) == 0) {
83 					break;
84 				}
85 			}
86 		}
87 	}
88 
89 	if (schedule_foldtype == 0) {
90 		output_func = pager_output;
91 	} else {
92 		output_func = schedule_output;
93 	}
94 	if (schedule_sortflag == FALSE) {
95 		list_output(0, output_func);
96 	} else {
97 		for (i = 0; i < MAXSORTITEM; i++) {
98 			if (schedule_sortorder_tbl[i] >= 0) {
99 				list_output(schedule_sortorder_tbl[i], output_func);
100 			}
101 		}
102 	}
103 
104 	list_free();
105 }
106 
107 /*
108  * �ե����뤫�饹�����塼�����Ф�ɽ������
109  *
110  * return value:
111  *   TRUE  ���ェλ
112  *   FALSE ���顼ȯ��(�ե����륪���ץ��)
113  *
114  * file format:
115  *   year/month/day [*comment] message
116  */
117 static
schedule_search(int index,const char * infile)118 int schedule_search(int index, const char *infile)
119 {
120 	char	*bp;
121 	char	*lasts;
122 	char	*comment, *msg;
123 	struct DATE_T	date;
124 	int		pyear, pmonth, pmaxday;
125 	div_t	c;
126 	int		hitday;
127 	int		mindif;
128 	int		diffday;
129 	int		tm;
130 
131 	pyear = monthtbl[index].year;
132 	pmonth = monthtbl[index].month;
133 	pmaxday = monthtbl[index].dayofmonth;
134 
135 	if (openfile(make_filename2(infile, pyear, pmonth, 0))) {
136 		return (FALSE);
137 	}
138 
139 	while ((bp = getfile()) != NULL) {
140 		lasts = NULL;
141 		bp = strtok_r(bp, fmt_sep3, &lasts);
142 		if (bp == NULL ||
143 		    read_date(0x0177, bp, &date, NULL) == DATE_NG) {
144 			continue;
145 		}
146 
147 		bp = strtok_r(NULL, fmt_sep4, &lasts);
148 		if (bp == NULL) {	/* ���դ����ιԤ�̵�� */
149 			continue;
150 		}
151 
152 		if (date.year == 0) {
153 			date.year = pyear;
154 		} else if (pyear != date.year) {
155 			continue;
156 		}
157 		if (date.month == 0) {
158 			date.month = pmonth;
159 		} else if (pmonth != date.month) {
160 			continue;
161 		}
162 
163 		if (date.day == 0) {
164 			if (index == CENTER_MONTH) {
165 				date.day = calendar.day;
166 			} else {
167 				date.day = 1;
168 			}
169 		} else {
170 			if (date.day < 0) {	/* ��������,�������� */
171 				date.day = -date.day;
172 				if (date.day < 100) {
173 					date.day = pmaxday - (date.day - 1);
174 				} else {
175 					c = div(date.day - 100, 10);
176 					date.day = ((c.rem - 1) - monthtbl[index].first_dayofweek) + 1;
177 					if (date.day < 1) {
178 						date.day += 7;
179 					}
180 					if (c.quot > 5) {	/* ��-n���� */
181 						date.day = (c.rem - 1) - monthtbl[index].last_dayofweek;
182 						if (date.day > 0) {
183 							date.day -= 7;
184 						}
185 						date.day += pmaxday - (c.quot - 6) * 7;
186 					} else if (c.quot > 0) {	/* ��n���� */
187 						date.day += (c.quot - 1) * 7;
188 					} else {
189 						hitday = -1;
190 						mindif = 999;
191 						/* ���ֶᤤ������1��õ�� */
192 						while (date.day <= pmaxday) {
193 							diffday = (int)(Julian(date.year, date.month, date.day) - calendar.julian_day);
194 							if (diffday >= 0 && diffday < mindif) {
195 								mindif = diffday;
196 								hitday = date.day;
197 							}
198 							date.day += 7;
199 						}
200 						date.day = hitday;
201 					}
202 				}
203 			}
204 			if (date.day < 1 || date.day > pmaxday) {
205 				continue;
206 			}
207 		}
208 
209 		diffday = (int)(Julian(date.year, date.month, date.day) - calendar.julian_day);
210 		if (diffday < 0 || diffday > sc_range) {
211 			continue;
212 		}
213 
214 		if (*bp == '*') {
215 			comment = xstrescape(undertospace(strtok_r(bp, fmt_sep3, &lasts) + 1));
216 			bp = strtok_r(NULL, fmt_sep4, &lasts);
217 			if (bp == NULL) {	/* �����Ȥ����ιԤ�̵�� */
218 				continue;
219 			}
220 		} else {
221 			comment = " --:--      ";
222 		}
223 		msg = xstrescape(strip(bp));
224 		tm = schedule_make_msg(date.month, date.day, diffday, comment, msg);
225 		schedule_listup(diffday, tm);
226 	}
227 
228 	closefile();
229 
230 	return (TRUE);
231 }
232 
233 /*
234  * �������塼���å���������
235  *
236  * �������塼���������
237  */
238 static
schedule_make_msg(int month,int day,int diffday,const char * comment,const char * msg)239 int schedule_make_msg(int month, int day, int diffday, const char *comment, const char *msg)
240 {
241 	int	tm;
242 	int	h, m;
243 
244 	tm = 9999;
245 	if (sscanf(comment, "%d:%d", &h, &m) == 2) {
246 		if ((h >= 0 && h <= 23) && (m >= 0 && m <= 59)) {
247 			tm = h * 100 + m;
248 		}
249 	}
250 	if (diffday == 0) {
251 		sprintf(msgbuf, "%-12.12s    ", comment);
252 	} else {
253 		if (month == 0) {
254 			strcpy(msgbuf, " --");
255 		} else {
256 			sprintf(msgbuf, " %02d", month);
257 		}
258 		if (day == 0) {
259 			strcpy(&msgbuf[3], "/--");
260 		} else {
261 			sprintf(&msgbuf[3], "/%02d", day);
262 		}
263 		if (tm == 9999) {
264 			strcpy(&msgbuf[6], " --:--    ");
265 		} else {
266 			sprintf(&msgbuf[6], " %02d:%02d    ", h, m);
267 		}
268 	}
269 	strcpy(&msgbuf[mesg_start_tbl[schedule_foldtype][0]], msg);
270 	return (tm);
271 }
272 
273 /*
274  * �������塼���ɽ������
275  */
276 static
schedule_listup(int diffday,int tm)277 void schedule_listup(int diffday, int tm)
278 {
279 	int	sortorder_no;
280 	int	i;
281 
282 	sortorder_no = 0;		/* ���� */
283 	if (diffday < 0) {
284 		sortorder_no = 1;	/* ���� */
285 	} else if (diffday > 0) {
286 		sortorder_no = 2;	/* ���� */
287 	}
288 	for (i = 0; i < MAXSORTITEM; i++) {
289 		if (schedule_sortorder_tbl[i] == sortorder_no) {
290 			break;
291 		}
292 	}
293 	if (i >= MAXSORTITEM) {
294 		return ;
295 	}
296 
297 	if (schedule_listup_flag == FALSE) {
298 		schedule_listup_flag = TRUE;
299 		pager_output_skip();
300 #ifdef MSG_STYLE
301 		pager_output("#### ���礦�Υ������塼�� ####");
302 #else
303 		pager_output("���� ���礦�Υ������塼�� ����");
304 #endif
305 	}
306 
307 	schedule_listadd(sortorder_no, diffday, tm);
308 }
309 
310 /*
311  * �������塼������Ȥ��뤿�ᡢ�ꥹ�ȹ�¤�˳�Ǽ����
312  *
313  * �ꥹ�ȹ�¤��Ǽ��ˡ(�����Ȥ��ʤ��Ȥ������� No.0)
314  *   No.0: ����
315  *   No.1: ����
316  *   No.2: ����
317  */
318 static
schedule_listadd(int sortorder_no,int diffday,int tm)319 void schedule_listadd(int sortorder_no, int diffday, int tm)
320 {
321 	if (schedule_sortflag == FALSE) {
322 		list_add(0, 0, 0, 0, msgbuf);
323 	} else {
324 		switch (schedule_sort) {
325 		case SORT_UP_ORDER:
326 			list_insert(sortorder_no, diffday, tm, 0, msgbuf);
327 			break;
328 		case SORT_DOWN_ORDER:
329 			list_insert(sortorder_no, diffday, -tm, 0, msgbuf);
330 			break;
331 		case SORT_NO_ORDER:
332 			list_add(sortorder_no, diffday, tm, 0, msgbuf);
333 			break;
334 		}
335 	}
336 }
337 
338 /*
339  * �������塼���ɽ������(pager �˽��Ϥ���)
340  *
341  * 1�Ԥ˼��ޤ�ʤ��Ȥ��ϡ�ʣ���Ԥ�ʬ�䤷��ɽ��
342  * �ޤ���ʸ�Ϥζ�§������Ԥ�
343  */
344 static
schedule_output(const char * msg,...)345 void schedule_output(const char *msg, ...)
346 {
347 	int	second_start;
348 
349 	second_start = mesg_start_tbl[schedule_foldtype][1];
350 	message_fold((const unsigned char *)msg, screen_max_columns - 3, 0, second_start);
351 }
352 
353 /*
354  * �������塼���ɽ��������֤����
355  */
356 static
schedule_range(void)357 int schedule_range(void)
358 {
359 	int	base_day;
360 	int	limit_day;
361 	int	n;
362 
363 	base_day = calendar.day + monthtbl[CENTER_MONTH].offset_day - 1;
364 	limit_day = base_day;
365 	n = schedule_limit;
366 
367 	if (n < 0) {
368 		return (-n);
369 	}
370 
371 	while (--n >= 0) {
372 		limit_day++;
373 		if ((holiday_tbl[limit_day] & (SET_SUNID | SET_SATID | SET_HOLID | SET_OVRID)) == 0) {
374 			break;	/* ʿ�� */
375 		}
376 	}
377 
378 	return (limit_day - base_day);
379 }
380 
381 #else /* INCLUDE_CALENDAR */
382 
383 /*
384  * calendar.c, calfw.c �� �������塼��롼����
385  */
386 
387 /*
388  * �ե����뤫�饹�����塼�����/��Ф���schedule_daytbl �����ꤹ��
389  *
390  * return value:
391  *   TRUE  ���ェλ
392  *   FALSE ���顼ȯ��(�ե����륪���ץ��)
393  *
394  * file format:
395  *   year/month/day [*comment] message
396  */
397 static
schedule_find_sub(int index,const char * infile)398 int schedule_find_sub(int index, const char *infile)
399 {
400 	char	*bp;
401 	char	*lasts;
402 	struct DATE_T	date;
403 	int		pyear, pmonth, pmaxday;
404 	int		last_dayofweek;
405 	int		i;
406 	div_t	c;
407 
408 	pyear = caltbl[index].year;
409 	pmonth = caltbl[index].month;
410 	pmaxday = caltbl[index].dayofmonth;
411 	last_dayofweek = GetDayofWeek(pyear, pmonth, pmaxday);
412 
413 	if (openfile(make_filename2(infile, pyear, pmonth, 0))) {
414 		return (FALSE);
415 	}
416 
417 	while ((bp = getfile()) != NULL) {
418 		lasts = NULL;
419 		bp = strtok_r(bp, fmt_sep3, &lasts);
420 		if (bp == NULL ||
421 		    read_date(0x0177, bp, &date, NULL) == DATE_NG) {
422 			continue;
423 		}
424 
425 		bp = strtok_r(NULL, fmt_sep4, &lasts);
426 		if (bp == NULL) {	/* ���դ����ιԤ�̵�� */
427 			continue;
428 		}
429 
430 		if (date.year != 0 && pyear != date.year) {
431 			continue;
432 		}
433 		if (date.month != 0 && pmonth != date.month) {
434 			continue;
435 		}
436 
437 		if (date.day == 0) {
438 			for (i = 0; i < pmaxday; i++) {
439 				schedule_daytbl[index][i] = SCHEDULE_EXIST;
440 			}
441 		} else {
442 			if (date.day < 0) {	/* ��������,�������� */
443 				date.day = -date.day;
444 				if (date.day < 100) {
445 					date.day = pmaxday - (date.day - 1);
446 				} else {
447 					c = div(date.day - 100, 10);
448 					date.day = ((c.rem - 1) - caltbl[index].first_dayofweek) + 1;
449 					if (date.day < 1) {
450 						date.day += 7;
451 					}
452 					if (c.quot > 5) {	/* ��-n���� */
453 						date.day = (c.rem - 1) - last_dayofweek;
454 						if (date.day > 0) {
455 							date.day -= 7;
456 						}
457 						date.day += pmaxday - (c.quot - 6) * 7;
458 					} else if (c.quot > 0) {	/* ��n���� */
459 						date.day += (c.quot - 1) * 7;
460 					} else {
461 						while (date.day <= pmaxday) {
462 							schedule_daytbl[index][date.day - 1] = SCHEDULE_EXIST;
463 							date.day += 7;
464 						}
465 						continue;
466 					}
467 				}
468 			}
469 			if (date.day > 0 && date.day <= pmaxday) {
470 				schedule_daytbl[index][date.day - 1] = SCHEDULE_EXIST;
471 			}
472 		}
473 	}
474 
475 	closefile();
476 
477 	return (TRUE);
478 }
479 
480 /*
481  * �������塼�����/��Ф���schedule_daytbl �����ꤹ��
482  */
schedule_find(void)483 void schedule_find(void)
484 {
485 	int	i, j;
486 
487 	memset(schedule_daytbl, (char)SCHEDULE_NONE, sizeof(schedule_daytbl));
488 
489 	for (i = 0; i < MAXSCHEDULEFILE; i++) {
490 		if (schedule_filetbl[i] != NULL) {
491 			for (j = 0; j < MAXMONTH_SCHEDULE; j++) {
492 				if (schedule_find_sub(j, schedule_filetbl[i]) == FALSE &&
493 				    (mkfile_status & (SET_MKF_CC | SET_MKF_YY | SET_MKF_MM)) == 0) {
494 					break;
495 				}
496 			}
497 		}
498 	}
499 }
500 
501 #if defined(_T_WINDOWS)
502 /*
503  * used calfw.c
504  *
505  * �ե����뤫�饹�����塼�����Ф���å������ơ��֥����
506  */
507 static
schedule_loadmsg_sub(const char * infile,int year,int month,int day,int * msgcount,char ** msgtbl)508 char **schedule_loadmsg_sub(const char *infile, int year, int month, int day, int *msgcount, char **msgtbl)
509 {
510 	char	*bp;
511 	char	*lasts;
512 	char	*comment, *msg;
513 	struct DATE_T	sdate;
514 	int		pmaxday;
515 	int		first_dayofweek;
516 	int		last_dayofweek;
517 	div_t	c;
518 	char	*msgbuf;
519 
520 	if (openfile(make_filename2(infile, year, month, 0))) {
521 		return (msgtbl);
522 	}
523 
524 	pmaxday = GetDayofMonth(year, month);
525 	first_dayofweek = GetDayofWeek(year, month, 1);
526 	last_dayofweek = GetDayofWeek(year, month, pmaxday);
527 
528 	while ((bp = getfile()) != NULL) {
529 		lasts = NULL;
530 		bp = strtok_r(bp, fmt_sep3, &lasts);
531 		if (bp == NULL ||
532 		    read_date(0x0177, bp, &sdate, NULL) == DATE_NG) {
533 			continue;
534 		}
535 
536 		bp = strtok_r(NULL, fmt_sep4, &lasts);
537 		if (bp == NULL) {	/* ���դ����ιԤ�̵�� */
538 			continue;
539 		}
540 
541 		if (sdate.year != 0 && sdate.year != year) {
542 			continue;
543 		}
544 		if (sdate.month != 0 && sdate.month != month) {
545 			continue;
546 		}
547 		if (sdate.day < 0) {	/* �������� */
548 			sdate.day = -sdate.day;
549 			if (sdate.day < 100) {
550 				sdate.day = pmaxday - (sdate.day - 1);
551 			} else {
552 				c = div(sdate.day - 100, 10);
553 				sdate.day = ((c.rem - 1) - first_dayofweek) + 1;
554 				if (sdate.day < 1) {
555 					sdate.day += 7;
556 				}
557 				if (c.quot > 5) {	/* ��-n���� */
558 					sdate.day = (c.rem - 1) - last_dayofweek;
559 					if (sdate.day > 0) {
560 						sdate.day -= 7;
561 					}
562 					sdate.day += pmaxday - (c.quot - 6) * 7;
563 				} else if (c.quot > 0) {	/* ��n���� */
564 					sdate.day += (c.quot - 1) * 7;
565 				} else {
566 					while (sdate.day <= MAX_DAYOFMONTH) {
567 						if (sdate.day == day) {
568 							break;
569 						}
570 						sdate.day += 7;
571 					}
572 				}
573 			}
574 		}
575 		if (sdate.day != 0 && sdate.day != day) {
576 			continue;
577 		}
578 
579 		if (*bp == '*') {
580 			comment = xstrescape(undertospace(strtok_r(bp, fmt_sep3, &lasts) + 1));
581 			bp = strtok_r(NULL, fmt_sep4, &lasts);
582 			if (bp == NULL) {	/* �����Ȥ����ιԤ�̵�� */
583 				continue;
584 			}
585 		} else {
586 			comment = " --:--      ";
587 		}
588 		msg = xstrescape(strip(bp));
589 
590 		msgbuf = XMALLOC(12 + 1 + strlen(msg) + 1);
591 		sprintf(msgbuf, "%-12.12s %s", comment, msg);
592 
593 		msgtbl = realloc(msgtbl, sizeof(char *) * (*msgcount + 1));
594 		if (msgtbl == NULL) {
595 			memerr("schedule_loadmsg_sub");
596 		}
597 		msgtbl[*msgcount] = msgbuf;
598 		(*msgcount)++;
599 	}
600 
601 	closefile();
602 
603 	return (msgtbl);
604 }
605 
606 /*
607  * �������դΥ������塼����ɼ�ꡢ��å������ơ��֥�(msgtbl)���������
608  *
609  * return value:
610  *   NULL �������塼��ʤ�
611  */
schedule_loadmsg(int year,int month,int day,int * count)612 char **schedule_loadmsg(int year, int month, int day, int *count)
613 {
614 	int		i;
615 	int		msgcount;
616 	char	**msgtbl;
617 
618 	msgcount = 0;
619 	msgtbl = NULL;
620 
621 	for (i = 0; i < MAXSCHEDULEFILE; i++) {
622 		if (schedule_filetbl[i] != NULL) {
623 			msgtbl = schedule_loadmsg_sub(schedule_filetbl[i], year, month, day, &msgcount, msgtbl);
624 		}
625 	}
626 
627 	*count = msgcount;
628 	return (msgtbl);
629 }
630 #endif /* _T_WINDOWS */
631 #endif /* INCLUDE_CALENDAR */
632