1 /*
2 * event.c -- event manage
3 *
4 * Copyright (C) 1989,1997,1999,2001,2003 by Yoshifumi Mori
5 *
6 * tab:4
7 */
8
9 #include "cdefs.h"
10 #include "extern.h"
11
12 #define total_weekofyear 53 /* ǯ��53�� */
13 #define PARAM_COUNT 32 /* �ȡ��������ʬ��� */
14 #define SET_DAY '\xFF'
15 #define CLEAR_DAY '\0'
16 #define MAXHIT 8
17 #define MAXFLAG 64
18
19 #define WEEK(x) (((x) - 1) / 7 + 1)
20 #define LVAR(x) event_level_var[(x)-'a']
21
22 #define EV_YEAR_ERR 0
23 #define EV_YEAR_YEAR 1
24 #define EV_YEAR_DATE 2
25
26 struct DATE_MD {
27 int month;
28 int day;
29 };
30
31 char *event_filetbl[MAXEVENTFILE];
32 char *week_filetbl[MAXWEEKFILE];
33 char *event_sortorder;
34 int event_notice_range = NOTICE_DEFAULT_RANGE;
35 int event_notice_flag = NOTICE_MARK_ONLY;
36 int event_range_flag = TRUE;
37 char *event_level_str;
38
39 static char pbuff[PARAM_COUNT * 8];
40 static char *param[PARAM_COUNT];
41 static struct SRANGE_T rangetbl[PARAM_COUNT];
42
43 static int event_sortflag;
44 static int event_sortorder_tbl[MAXSORTITEM]; /* ����_����_���� */
45 static int message_counter;
46 static int event_msg_level_default;
47 static int event_msg_level;
48 static char event_level_var[MAXLVAR];
49
50 static int endofmonth;
51 static int endofyear;
52 static int start_dayofyear, end_dayofyear;
53 static int start_weekofyear, end_weekofyear;
54 static int start_dayofweek, end_dayofweek;
55 static long start_julian, end_julian;
56
57 static int current_year;
58 static int current_month;
59 static int current_day;
60 static int current_leap;
61 static int current_offsetday;
62 static int current_mode;
63 static int current_weekcount;
64
65 static int focus_flag;
66
67 enum {
68 EVENT_MODE,
69 LC_EVENT_MODE,
70 };
71
72 static int dayshift_direction;
73 static int dayshift_skip_saturday;
74
75 static char pinpoint_daytbl[MAX_DAYOFMONTH], pinpoint_masktbl[MAX_DAYOFMONTH];
76 static int pinpoint_hittbl[MAXHIT];
77
78 static unsigned char evflag[(MAXFLAG + 7) / 8];
79
80 static void setup_event_level(void);
81 static void event_out(const char *msg, ...);
82 static void event_main(void);
83 static void setup_eventmode(int index);
84 static void setup_lc_eventmode(int index);
85 static void call_eventsearch(void);
86 static int eventSearch(const char *filename);
87 static void ctrl_msg_proc(char *bp);
88 static int analysis_ev_day(char *bp);
89 static int analysis_ev_whatday(char *bp);
90 static int analysis_ev_week(char *bp);
91 static int analysis_ev_month(char *bp);
92 static int analysis_ev_year(char *bp);
93 static int analysis_year_date(const char *p, int *year, long *jul);
94 static int pickup_event(int notice_range);
95 static int pickup_lc_event(int notice_range);
96 static void pinpoint_dayclear(void);
97 static void pinpoint_maskclear(void);
98 static int pinpoint_day(void);
99
100 static void event_week(void);
101 static int weekSearch(const char *filename);
102 static int check_week(struct DATE_MD *begin, struct DATE_MD *end);
103
104 static void output_eventlist(int type, char *msg, int diffday, int rangeflag);
105
106 static int skipHoliday(int day);
107 static void makerange(char *msg);
108
109 /*
110 * ���٥�Ȥ�ɽ��
111 *
112 * �ƥե�������˽�������
113 */
event(void)114 void event(void)
115 {
116 unsigned int hol_attr;
117 char *hol_name;
118
119 event_sortflag = TRUE;
120 event_sortorder_tbl[0] = 0;
121 event_sortorder_tbl[1] = 1;
122 event_sortorder_tbl[2] = 2;
123 message_counter = 0;
124
125 if (event_notice_range < 0 || event_notice_range > MAX_DAYOFMONTH) {
126 event_notice_range = NOTICE_DEFAULT_RANGE;
127 errprint("event", ERR_WARN, "event_notice_range error, default %d set", event_notice_range);
128 }
129
130 event_sortflag = analysis_sortorder("event", event_sortorder, event_sortorder_tbl, event_sortflag);
131
132 setup_event_level();
133
134 list_init();
135
136 hol_attr = holiday_tbl[calendar.day + monthtbl[CENTER_MONTH].offset_day - 1];
137 if ((hol_attr & SET_HOLID) == SET_HOLID) {
138 hol_name = GetHolidayName(GET_HOLNAMEI(hol_attr));
139 if (hol_name != NULL) {
140 event_msg_level = LVAR('a');
141 event_out(hol_name);
142 free(hol_name);
143 }
144 }
145
146 event_msg_level = LVAR('b');
147 memset(evflag, '\0', sizeof(evflag));
148 rekichu(evflag, event_out);
149
150 event_main();
151 event_week();
152
153 output_eventlist(0, NULL, 0, FALSE);
154 list_free();
155 }
156
157 /*
158 * ��٥��ѿ�������
159 */
160 static
setup_event_level(void)161 void setup_event_level(void)
162 {
163 char *p;
164 int i, n;
165
166 memset(event_level_var, 99, sizeof(event_level_var));
167 if (event_level_str != NULL) {
168 p = event_level_str;
169 i = 0;
170 while (*p != '\0' && i < MAXLVAR) {
171 if (sscanf(p, "%02d", &n) != 1) {
172 break;
173 }
174 event_level_var[i++] = (char)n;
175 p += 2;
176 }
177 }
178 }
179
180 /*
181 * ���٥�ȥ�å�����ɽ�������θƤӽФ�
182 */
183 static
event_out(const char * msg,...)184 void event_out(const char *msg, ...)
185 {
186 char msgtmp[64];
187 va_list ap;
188
189 va_start(ap, msg);
190 vsprintf(msgtmp, msg, ap);
191 va_end(ap);
192 output_eventlist(1, msgtmp, 0, FALSE);
193 }
194
195 /*
196 * ����3����ʬ�Υ��٥�Ƚ�����ư(�ᥤ��)
197 */
198 static
event_main(void)199 void event_main(void)
200 {
201 int i;
202
203 for (i = 0; i < MAX_MONTH_TBL; i++) {
204 focus_flag = (i == CENTER_MONTH) ? TRUE : FALSE;
205
206 setup_eventmode(i);
207 call_eventsearch();
208 if (calendar.lc_valid == TRUE && calendar.lc_tbl == TRUE) {
209 setup_lc_eventmode(i);
210 call_eventsearch();
211 }
212 }
213 }
214
215 /*
216 * ���٥�ȸ���/����ѥǡ����ν����
217 */
218 static
setup_eventmode(int index)219 void setup_eventmode(int index)
220 {
221 endofyear = GetDayofYear(calendar.year, 12, 31);
222 endofmonth = monthtbl[index].dayofmonth;
223
224 start_dayofyear = GetDayofYear(monthtbl[index].year, monthtbl[index].month, 1);
225 end_dayofyear = GetDayofYear(monthtbl[index].year, monthtbl[index].month, monthtbl[index].dayofmonth);
226
227 start_weekofyear = WEEK(start_dayofyear);
228 end_weekofyear = WEEK(end_dayofyear);
229
230 start_dayofweek = monthtbl[index].first_dayofweek;
231 end_dayofweek = monthtbl[index].last_dayofweek;
232
233 start_julian = Julian(monthtbl[index].year, monthtbl[index].month, 1);
234 end_julian = Julian(monthtbl[index].year, monthtbl[index].month, monthtbl[index].dayofmonth);
235
236 current_year = monthtbl[index].year;
237 current_month = monthtbl[index].month;
238 current_day = calendar.day;
239 current_leap = monthtbl[index].leap;
240 current_offsetday = monthtbl[index].offset_day;
241 current_mode = EVENT_MODE;
242 current_weekcount = 7;
243 }
244
245 /*
246 * ���٥�ȸ���/����ѥǡ����ν����
247 */
248 static
setup_lc_eventmode(int index)249 void setup_lc_eventmode(int index)
250 {
251 endofyear = 0;
252 endofmonth = monthtbl[index].lc.dayofmonth;
253
254 start_dayofyear = 0;
255 end_dayofyear = 0;
256
257 start_weekofyear = 0;
258 end_weekofyear = 0;
259
260 start_dayofweek = monthtbl[index].lc.first_dayofweek;
261 end_dayofweek = monthtbl[index].lc.last_dayofweek;
262
263 start_julian = 0L;
264 end_julian = 0L;
265
266 current_year = monthtbl[index].lc.year;
267 current_month = monthtbl[index].lc.month;
268 current_day = calendar.lc_day;
269 current_leap = monthtbl[index].lc.leap;
270 current_offsetday = monthtbl[index].lc.offset_day;
271 current_mode = LC_EVENT_MODE;
272 current_weekcount = 6;
273 }
274
275 /*
276 * �ƥ��٥����Ͽ�ե�������������
277 */
278 static
call_eventsearch(void)279 void call_eventsearch(void)
280 {
281 int i;
282 const char *filename;
283
284 event_msg_level_default = LVAR('i');
285 for (i = 0; i < MAXEVENTFILE; i++) {
286 if (event_filetbl[i] != NULL) {
287 filename = make_filename2(event_filetbl[i], current_year, current_month, current_day);
288 eventSearch(filename);
289 }
290 }
291 }
292
293 /*
294 * �ե����뤫�饤�٥�Ȥ�/��Ф���
295 *
296 * return value:
297 * TRUE ���ェλ
298 * FALSE ���顼ȯ��(�ե����륪���ץ��)
299 *
300 * file format:
301 * [+n] [<>|&]day whatday week month [year] message
302 */
303 static
eventSearch(const char * infile)304 int eventSearch(const char *infile)
305 {
306 char *bp;
307 char *lasts;
308
309 if (openfile(infile)) {
310 return (FALSE);
311 }
312
313 event_msg_level = event_msg_level_default;
314
315 while ((bp = getfile()) != NULL) {
316 char *eventmessage;
317 int flag_day, flag_whatday, flag_week;
318 int notice_range;
319 int notice_force_range;
320 int rangeflag;
321 int hitcnt;
322 int i;
323 int diffday;
324
325 if (*bp == '$') {
326 ctrl_msg_proc(bp);
327 continue;
328 }
329
330 notice_range = 0; /* notice off */
331 notice_force_range = FALSE;
332 if (*bp == '+') {
333 lasts = NULL;
334 bp = strtok_r(bp, fmt_sep3, &lasts);
335 if (bp == NULL) {
336 continue;
337 }
338 bp++; /* skip '+' */
339 notice_range = event_notice_range;
340 if (isdigit((unsigned char)*bp) != 0) {
341 notice_range = (int)strtol(bp, &bp, 10);
342 notice_force_range = TRUE;
343 }
344 bp = NULL;
345 }
346
347 if (event_notice_flag == NOTICE_NO) {
348 notice_range = 0; /* notice off */
349 } else if (event_notice_flag == NOTICE_ALL) {
350 if (notice_range == 0 && notice_force_range == FALSE) {
351 notice_range = event_notice_range;
352 }
353 }
354
355 bp = strtok_r(bp, fmt_sep3, &lasts);
356 if (bp == NULL) {
357 continue;
358 }
359
360 dayshift_direction = 0;
361 dayshift_skip_saturday = FALSE;
362 switch (*bp) {
363 case '&': /* ������� */
364 if (current_mode == EVENT_MODE) {
365 continue;
366 }
367 if (notice_range == 0 && focus_flag == FALSE) {
368 continue;
369 }
370 bp++;
371 break;
372 case '<':
373 dayshift_direction = -1;
374 goto dayshift_check;
375 case '>':
376 dayshift_direction = 1;
377 dayshift_check:
378 if (current_mode == LC_EVENT_MODE) {
379 continue;
380 }
381 bp++;
382 if (bp[0] == bp[-1]) {
383 dayshift_skip_saturday = TRUE;
384 bp++;
385 }
386 break;
387 default:
388 if (current_mode == LC_EVENT_MODE) {
389 continue;
390 }
391 if (notice_range == 0 && focus_flag == FALSE) {
392 continue;
393 }
394 break;
395 }
396
397 pinpoint_dayclear();
398
399 flag_day = analysis_ev_day(bp);
400
401 bp = strtok_r(NULL, fmt_sep3, &lasts);
402 if (bp == NULL) {
403 continue;
404 }
405 flag_whatday = analysis_ev_whatday(bp);
406
407 bp = strtok_r(NULL, fmt_sep3, &lasts);
408 if (bp == NULL) {
409 continue;
410 }
411 flag_week = analysis_ev_week(bp);
412
413 if (flag_day == FALSE && flag_whatday == FALSE && flag_week == FALSE) {
414 continue;
415 }
416
417 bp = strtok_r(NULL, fmt_sep3, &lasts);
418 if (bp == NULL) {
419 continue;
420 }
421 if (analysis_ev_month(bp) == FALSE) {
422 continue;
423 }
424
425 bp = strtok_r(NULL, fmt_sep3, &lasts);
426 if (bp == NULL) {
427 continue;
428 }
429 if (analysis_ev_year(bp) == FALSE) {
430 continue;
431 }
432
433 bp = strtok_r(NULL, fmt_sep4, &lasts);
434 if (bp == NULL) {
435 continue;
436 }
437 eventmessage = strip(bp);
438
439 rangeflag = FALSE;
440 if (flag_day == TRUE && flag_whatday == FALSE && flag_week == FALSE &&
441 rangetbl[0].start != 0) {
442 rangeflag = TRUE;
443 }
444
445 if (current_mode == EVENT_MODE) {
446 hitcnt = pickup_event(notice_range);
447 } else {
448 hitcnt = pickup_lc_event(notice_range);
449 }
450 for (i = 0; i < hitcnt; i++) {
451 diffday = pinpoint_hittbl[i];
452 if (diffday == 0) {
453 output_eventlist(1, eventmessage, 0, rangeflag);
454 } else {
455 output_eventlist(3, eventmessage, diffday, rangeflag);
456 }
457 }
458 }
459
460 closefile();
461
462 return (TRUE);
463 }
464
465 /*
466 * ��å���������ȥ������
467 *
468 * ${ctrl}
469 *
470 * ctrl: Lnn ��å�������٥� 0-99
471 * Lx ��å�������٥��ѿ� a-z, A-Z
472 * L@,L ��å�������٥�ꥻ�å�
473 */
474 static
ctrl_msg_proc(char * bp)475 void ctrl_msg_proc(char *bp)
476 {
477 char *ep;
478
479 bp++;
480 while (*bp != '\0') {
481 switch (*bp) {
482 case 'L':
483 bp++;
484 if (isdigit(*bp) != 0) {
485 event_msg_level = strtol(bp, &ep, 10);
486 bp = ep;
487 } else if (isalpha(*bp) != 0) {
488 event_msg_level = LVAR(tolower(*bp));
489 bp++;
490 } else if (*bp == '@' || *bp == '\0') {
491 event_msg_level = event_msg_level_default;
492 }
493 break;
494 default:
495 bp++;
496 break;
497 }
498 }
499 }
500
501 /*
502 * ���դβ���(�����б�)
503 *
504 * ������� !nn �ϻ��ѤǤ��ʤ�
505 * %n ��ͽ������ˤ���ư���Ǥ��ʤ�
506 *
507 * return value:
508 * TRUE pinpoint_daytbl[] ��
509 * FALSE ̤���� '0' �����ꤵ�줿���ᡢ����̵��
510 */
511 static
analysis_ev_day(char * bp)512 int analysis_ev_day(char *bp)
513 {
514 int change_masktbl = FALSE;
515 int pcnt;
516 int pc;
517
518 pcnt = separate_param(bp, pbuff, param, PARAM_COUNT, rangetbl);
519 pinpoint_maskclear();
520
521 for (pc = 0; pc < pcnt; pc++) {
522 const char *pp;
523 int pday;
524 int pf;
525
526 pp = param[pc];
527 if (*pp == '%') { /* �ü����� */
528 pf = atoi(pp + 1);
529 if (pf < 1 || pf > MAXFLAG) {
530 continue;
531 }
532 pf--;
533 if (focus_flag == TRUE && CHKBIT(pf, evflag) != 0) {
534 pday = calendar.day;
535 } else {
536 continue;
537 }
538 } else if (*pp == '!') { /* ǯƬ������̻��� */
539 pday = atoi(pp + 1);
540 if (pday < 0) {
541 pday += endofyear + 1;
542 }
543 if (pday < start_dayofyear || pday > end_dayofyear) {
544 continue;
545 }
546 pday -= start_dayofyear - 1;
547 } else { /* ���̤��� */
548 pday = atoi(pp);
549 if (pday < 0) {
550 pday += endofmonth + 1;
551 }
552 }
553 if (pday > 0 && pday <= endofmonth) {
554 pinpoint_masktbl[pday - 1] = SET_DAY;
555 change_masktbl = TRUE;
556 }
557 }
558
559 if (change_masktbl == FALSE) {
560 return (FALSE);
561 }
562 return (pinpoint_day());
563 }
564
565 /*
566 * �����β���(�����б�)
567 *
568 * return value:
569 * TRUE pinpoint_daytbl[] ��
570 * FALSE ̤���� '0' �����ꤵ�줿���ᡢ������̵��
571 */
572 static
analysis_ev_whatday(char * bp)573 int analysis_ev_whatday(char *bp)
574 {
575 int change_masktbl = FALSE;
576 int pcnt;
577 int pc;
578
579 pcnt = separate_param(bp, pbuff, param, PARAM_COUNT, NULL);
580 pinpoint_maskclear();
581
582 for (pc = 0; pc < pcnt; pc++) {
583 const char *pp;
584 int pwhatday;
585
586 pp = param[pc];
587 pwhatday = atoi(pp);
588 if (pwhatday != 0) {
589 int i;
590
591 i = pwhatday - (start_dayofweek + 1) + 1;
592 if (i < 1) {
593 i += current_weekcount;
594 }
595 while (i > 0 && i <= endofmonth) {
596 pinpoint_masktbl[i - 1] = SET_DAY;
597 i += current_weekcount;
598 change_masktbl = TRUE;
599 }
600 }
601 }
602
603 if (change_masktbl == FALSE) {
604 return (FALSE);
605 }
606 return (pinpoint_day());
607 }
608
609 /*
610 * ���β���(�����б�)
611 *
612 * ������ϡ� !nn, %nn, .nn �ϻ��ѤǤ��ʤ�
613 *
614 * return value:
615 * TRUE pinpoint_daytbl[] ��
616 * FALSE ̤���� '0' �����ꤵ�줿���ᡢ����̵��
617 */
618 static
analysis_ev_week(char * bp)619 int analysis_ev_week(char *bp)
620 {
621 int change_masktbl = FALSE;
622 int pcnt;
623 int pc;
624
625 pcnt = separate_param(bp, pbuff, param, PARAM_COUNT, NULL);
626 pinpoint_maskclear();
627
628 for (pc = 0; pc < pcnt; pc++) {
629 const char *pp;
630 int pweek;
631 int previously_change_masktbl = FALSE;
632 int start_day_range = 0;
633
634 pp = param[pc];
635 if (*pp == '!') { /* ǯƬ������̻��� */
636 pweek = atoi(pp + 1);
637 if (pweek < 0) {
638 pweek += total_weekofyear + 1;
639 }
640 if (pweek < start_weekofyear || pweek > end_weekofyear) {
641 continue;
642 }
643 start_day_range = (pweek - 1) * current_weekcount + 1 - start_dayofyear + 1;
644 } else if (*pp == '%') { /* �ֽ� */
645 pweek = atoi(pp + 1);
646 if (pweek != 0) {
647 int i;
648 int mod_week;
649
650 mod_week = pweek % 2;
651 previously_change_masktbl = TRUE;
652 for (i = 0; i < MAX_DAYOFMONTH; i++) {
653 pweek = (start_dayofyear + i - 1) / current_weekcount + 1;
654 if ((pweek % 2) == mod_week) {
655 pinpoint_masktbl[i] = SET_DAY;
656 change_masktbl = TRUE;
657 }
658 }
659 }
660 } else if (*pp == '.') { /* ���������β��ν� */
661 pweek = atoi(pp + 1);
662 if (pweek == 0) {
663 ;
664 } else if (pweek < 0) {
665 start_day_range = endofmonth - end_dayofweek + (pweek - 1) * current_weekcount;
666 } else {
667 start_day_range = 1 - start_dayofweek + (pweek - 1) * current_weekcount;
668 }
669 } else { /* ���̤ν� */
670 pweek = atoi(pp);
671 if (pweek == 0) {
672 ;
673 } else if (pweek < 0) {
674 start_day_range = endofmonth + pweek * current_weekcount + 1;
675 } else {
676 start_day_range = 1 + (pweek - 1) * current_weekcount;
677 }
678 }
679
680 if (pweek != 0 && previously_change_masktbl == FALSE) {
681 int i;
682 int end_day_range;
683
684 end_day_range = start_day_range + current_weekcount;
685 for (i = start_day_range; i < end_day_range; i++) {
686 if (i > 0 && i <= endofmonth) {
687 pinpoint_masktbl[i - 1] = SET_DAY;
688 change_masktbl = TRUE;
689 }
690 }
691 }
692 }
693
694 if (change_masktbl == FALSE) {
695 return (FALSE);
696 }
697 return (pinpoint_day());
698 }
699
700 /*
701 * used analysis_ev_month(), analysis_ev_year()
702 */
703 #define MASKBIT(x) (1 << (x))
704
705 /*
706 * ��β���(�����б�)
707 *
708 * %1,%2 �� ��,%4,%5 ��Ʊ���˻��ꤷ������ AND �����Ȥʤ�
709 * %1,%2 ��Ʊ���˻��ꤹ��� %0 �������Ȥʤ�
710 * 0,1,2,5 �Ȼ��ꤹ��� 0 ��̵�뤹��
711 *
712 * return value:
713 * TRUE �оݷ�
714 * FALSE ̤�о�
715 */
716 static
analysis_ev_month(char * bp)717 int analysis_ev_month(char *bp)
718 {
719 int pcnt;
720 int pc;
721 int monthmap = 0; /* ��ͭ���ӥåȥޥå� bit0:1 - bit11:12 */
722 int leaptype = 0; /* bit0:��ǯ/��Ǥʤ�, bit1:��ǯ/�� */
723
724 pcnt = separate_param(bp, pbuff, param, PARAM_COUNT, NULL);
725 for (pc = 0; pc < pcnt; pc++) {
726 const char *p;
727 int pmon;
728
729 p = param[pc];
730 if (*p == '%') {
731 pmon = atoi(p + 1);
732 switch (pmon) {
733 case 1: /* %1 ��ǯ/��Ǥʤ� */
734 leaptype |= 1;
735 break;
736 case 2: /* %2 ��ǯ/�� */
737 leaptype |= 2;
738 break;
739 case 4: /* %4 ������ */
740 monthmap |= 0x0AAA;
741 break;
742 case 5: /* %5 ����� */
743 monthmap |= 0x0555;
744 break;
745 }
746 } else {
747 pmon = atoi(p);
748 if (pmon >= 1 && pmon <= 12) {
749 monthmap |= MASKBIT(pmon - 1);
750 }
751 }
752 }
753
754 if (monthmap == 0 || (monthmap & MASKBIT(current_month - 1)) != 0) {
755 if (leaptype == 0 || leaptype == 3 || (leaptype == (current_leap + 1))) {
756 return (TRUE);
757 }
758 }
759 return (FALSE);
760 }
761
762 /*
763 * ǯ(����)�β���(�����б�)
764 *
765 * ���դ���ꤷ�ƴ��֤����Ǥ���
766 * ����������դϻ��ѤǤ��ʤ�
767 *
768 * %1,%2 �� ǯ,%4,%5 ��Ʊ���˻��ꤷ������ AND �����Ȥʤ�
769 * %1,%2 ��Ʊ���˻��ꤹ��ȱ�ǯɾ���Ϥ��ʤ�
770 * %4,%5 ��Ʊ���˻��ꤹ��ȴ����ɾ���Ϥ��ʤ�
771 * 0,1995,1997 �Ȼ��ꤹ��� 0 ��̵�뤹��
772 *
773 * return value:
774 * TRUE �о�ǯ(����)
775 * FALSE ̤�о�
776 */
777 static
analysis_ev_year(char * bp)778 int analysis_ev_year(char *bp)
779 {
780 int change_masktbl = FALSE;
781 int pcnt;
782 int pc;
783 int leaptype = 0; /* bit0:��ǯ�Ǥʤ�, bit1:��ǯ */
784 int monthtype = 0; /* bit0:����ǯ, bit1:���ǯ */
785
786 pcnt = separate_param2(bp, param, PARAM_COUNT);
787 pinpoint_maskclear();
788
789 for (pc = 0; pc < pcnt; pc++) {
790 const char *p;
791 const char *q;
792 int pyear;
793 int pyear2;
794 long pjul;
795 long pjul2;
796
797 p = param[pc];
798 if (*p == '%') {
799 pyear = atoi(p + 1);
800 switch (pyear) {
801 case 1: /* %1 ��ǯ�Ǥʤ� */
802 leaptype |= 1;
803 break;
804 case 2: /* %2 ��ǯ */
805 leaptype |= 2;
806 break;
807 case 4: /* %4 ����ǯ */
808 monthtype |= 1;
809 break;
810 case 5: /* %5 ���ǯ */
811 monthtype |= 2;
812 break;
813 }
814 } else if (*p == '-') {
815 switch (analysis_year_date(p + 1, &pyear, &pjul)) {
816 case EV_YEAR_ERR:
817 default:
818 continue;
819 case EV_YEAR_YEAR: /* -n ����ǯ���� */
820 pyear2 = pyear;
821 pyear = INT_MIN;
822 goto year_check;
823 case EV_YEAR_DATE: /* -yy/mm/dd �������հ��� */
824 pjul2 = pjul;
825 pjul = LONG_MIN;
826 goto date_check;
827 }
828 } else {
829 switch (analysis_year_date(p, &pyear, &pjul)) {
830 case EV_YEAR_ERR:
831 default:
832 continue;
833 case EV_YEAR_YEAR:
834 q = strchr(p, '-');
835 if (q == NULL) { /* n ����ǯ�Τ� */
836 pyear2 = pyear;
837 } else if (q[1] == '\0') { /* n- ����ǯ�ʹ� */
838 pyear2 = INT_MAX;
839 } else { /* n-m �ϰϻ��� */
840 if (analysis_year(q + 1, &pyear2, NULL) == YEAR_NG) {
841 continue;
842 }
843 }
844 year_check:
845 if (pyear == 0) {
846 continue;
847 }
848 if (pyear == INT_MIN) {
849 pjul = LONG_MIN;
850 } else {
851 pjul = Julian(pyear, 1, 1);
852 }
853 if (pyear2 == INT_MAX) {
854 pjul2 = LONG_MAX;
855 } else {
856 pjul2 = Julian(pyear2, 12, 31);
857 }
858 goto date_check;
859 case EV_YEAR_DATE:
860 q = strchr(p, '-');
861 if (q == NULL) { /* yy/mm/dd �������դΤ� */
862 pjul2 = pjul;
863 } else if (q[1] == '\0') { /* yy/mm/dd- �������հʹ� */
864 pjul2 = LONG_MAX;
865 } else { /* yy/mm/dd-yy/mm/dd �ϰϻ��� */
866 switch (analysis_year_date(q + 1, &pyear2, &pjul2)) {
867 case EV_YEAR_ERR:
868 case EV_YEAR_YEAR:
869 default:
870 continue;
871 case EV_YEAR_DATE:
872 break;
873 }
874 }
875 date_check:
876 change_masktbl = TRUE;
877 if (start_julian <= pjul2 && pjul <= end_julian) {
878 int js;
879 int je;
880
881 if (pjul <= start_julian) {
882 js = 0;
883 } else {
884 js = (int)(pjul - start_julian);
885 }
886
887 if (pjul2 > end_julian) {
888 je = endofmonth - 1;
889 } else {
890 je = (int)(pjul2 - start_julian);
891 }
892
893 while (js <= je) {
894 pinpoint_masktbl[js++] = SET_DAY;
895 }
896 }
897 break;
898 }
899 }
900 }
901
902 /* change_masktbl == FALSE ���� 0 �����ꤵ��Ƥ��� */
903 if (change_masktbl == FALSE || pinpoint_day() != FALSE) {
904 if (monthtype == 0 || monthtype == 3 ||
905 ((monthtype - 1) == (current_year & 1))) {
906 if (leaptype == 0 || leaptype == 3 ||
907 (leaptype == (current_leap + 1))) {
908 return (TRUE);
909 }
910 }
911 }
912 return (FALSE);
913 }
914
915 /*
916 * ǯ(����)�����(����̤�б�)
917 *
918 * return value:
919 * EV_YEAR_ERR ��ʸ���顼
920 * EV_YEAR_YEAR ǯ�Τ���
921 * EV_YEAR_DATE ���ջ���
922 */
923 static
analysis_year_date(const char * p,int * year,long * jul)924 int analysis_year_date(const char *p, int *year, long *jul)
925 {
926 char *q;
927 int yy;
928 int mm;
929 int dd;
930
931 if (analysis_year(p, &yy, NULL) == YEAR_NG) {
932 return (EV_YEAR_ERR);
933 }
934
935 /* AD, BC, �����ά���楹���å� */
936 while (isalpha(*p) != 0) {
937 p++;
938 }
939 /* ����(ǯ)�����å� */
940 while (isdigit(*p) != 0) {
941 p++;
942 }
943
944 *year = yy;
945 if (*p != '/') {
946 return (EV_YEAR_YEAR);
947 }
948
949 mm = (int)strtol(p + 1, &q, 10);
950 if (*q != '/') {
951 return (EV_YEAR_ERR);
952 }
953 dd = (int)strtol(q + 1, &q, 10);
954 #if 0
955 if (current_mode == LC_EVENT_MODE) {
956 int leap = 0;
957 const struct DATE_T *nowcal;
958
959 if (*q == '.') {
960 leap = 1;
961 }
962 nowcal = LunarToNowCalendar(yy, mm, dd, leap);
963 yy = nowcal->year;
964 mm = nowcal->month;
965 dd = nowcal->day;
966 }
967 #endif
968 *jul = Julian(yy, mm, dd);
969
970 return (EV_YEAR_DATE);
971 }
972
973 /*
974 * ���٥�Ȥ��о�����õ���Ф�
975 *
976 * return value:
977 * �оݿ�
978 *
979 * pinpoint_hittbl[n] = diffday - ���٥�ȤޤǤδ���(����1�����)
980 */
981 static
pickup_event(int notice_range)982 int pickup_event(int notice_range)
983 {
984 int cday;
985 int hitcnt;
986 int i;
987
988 cday = calendar.day + monthtbl[CENTER_MONTH].offset_day;
989 hitcnt = 0;
990
991 for (i = 0; i < endofmonth; i++) {
992 int cmpday;
993 int diffdays;
994
995 if (pinpoint_daytbl[i] == CLEAR_DAY) {
996 continue;
997 }
998 cmpday = i + current_offsetday + 1;
999 if (dayshift_direction != 0) {
1000 cmpday = skipHoliday(cmpday);
1001 }
1002 diffdays = cmpday - cday;
1003 if (diffdays == 0 || (notice_range != 0 && diffdays >= -1 && diffdays <= notice_range)) {
1004 if (diffdays >= 28) {
1005 if (diffdays > monthtbl[CENTER_MONTH].dayofmonth) {
1006 continue;
1007 }
1008 if (cmpday == calendar.day) {
1009 diffdays = NOTICE_MONTH(1);
1010 }
1011 }
1012 pinpoint_hittbl[hitcnt++] = diffdays;
1013 if (hitcnt >= MAXHIT) {
1014 break;
1015 }
1016 }
1017 }
1018
1019 return (hitcnt);
1020 }
1021
1022 /*
1023 * ���٥�Ȥ��о�����õ���Ф�(������)
1024 *
1025 * return value:
1026 * �оݿ�
1027 *
1028 * pinpoint_hittbl[n] = diffday - ���٥�ȤޤǤδ���(����1�����)
1029 */
1030 static
pickup_lc_event(int notice_range)1031 int pickup_lc_event(int notice_range)
1032 {
1033 int cday;
1034 int hitcnt;
1035 int i;
1036
1037 cday = calendar.lc_day + monthtbl[CENTER_MONTH].lc.offset_day;
1038 hitcnt = 0;
1039
1040 for (i = 0; i < endofmonth; i++) {
1041 int cmpday;
1042 int diffdays;
1043
1044 if (pinpoint_daytbl[i] == CLEAR_DAY) {
1045 continue;
1046 }
1047 cmpday = i + current_offsetday + 1;
1048 diffdays = cmpday - cday;
1049 if (diffdays == 0 || (notice_range != 0 && diffdays >= -1 && diffdays <= notice_range)) {
1050 if (diffdays >= 28) { /* ������ɤ������� */
1051 const struct DATE_T *date;
1052 int cmpyear, cmpmonth, cmpleap;
1053
1054 if (diffdays > monthtbl[CENTER_MONTH].dayofmonth) {
1055 continue;
1056 }
1057 cmpday -= monthtbl[CENTER_MONTH].lc.offset_day;
1058 cmpyear = calendar.lc_year;
1059 cmpmonth = calendar.lc_month;
1060 cmpleap = calendar.lc_leap;
1061 if (cmpday < 1) {
1062 cmpyear = monthtbl[CENTER_MONTH - 1].lc.year;
1063 cmpmonth = monthtbl[CENTER_MONTH - 1].lc.month;
1064 cmpday += monthtbl[CENTER_MONTH - 1].lc.dayofmonth;
1065 cmpleap = monthtbl[CENTER_MONTH - 1].lc.leap;
1066 } else if (cmpday > monthtbl[CENTER_MONTH].lc.dayofmonth) {
1067 cmpyear = monthtbl[CENTER_MONTH + 1].lc.year;
1068 cmpmonth = monthtbl[CENTER_MONTH + 1].lc.month;
1069 cmpday -= monthtbl[CENTER_MONTH].lc.dayofmonth;
1070 cmpleap = monthtbl[CENTER_MONTH + 1].lc.leap;
1071 }
1072 date = LunarToNowCalendar(cmpyear, cmpmonth, cmpday, cmpleap);
1073 if (date == NULL) {
1074 continue;
1075 }
1076 if (date->day == calendar.day) {
1077 diffdays = NOTICE_MONTH(1);
1078 }
1079 }
1080 pinpoint_hittbl[hitcnt++] = diffdays;
1081 if (hitcnt >= MAXHIT) {
1082 break;
1083 }
1084 }
1085 }
1086
1087 return (hitcnt);
1088 }
1089
1090 /*
1091 * ���٥���о��������٤Υơ��֥����������
1092 */
1093 static
pinpoint_dayclear(void)1094 void pinpoint_dayclear(void)
1095 {
1096 memset(pinpoint_daytbl, SET_DAY, sizeof(pinpoint_daytbl));
1097 }
1098
1099 /*
1100 * ���٥���о�����ʤ���ि��Υޥ����ơ��֥����������
1101 */
1102 static
pinpoint_maskclear(void)1103 void pinpoint_maskclear(void)
1104 {
1105 memset(pinpoint_masktbl, CLEAR_DAY, sizeof(pinpoint_masktbl));
1106 }
1107
1108 /*
1109 * ���٥���о�����ʤ���� (and)
1110 *
1111 * return:
1112 * FALSE: �оݥ��٥��̵��
1113 * TRUE : �оݥ��٥�Ȥ���
1114 */
1115 static
pinpoint_day(void)1116 int pinpoint_day(void)
1117 {
1118 int i;
1119 int flag = 0;
1120
1121 for (i = 0; i < MAX_DAYOFMONTH; i++) {
1122 pinpoint_daytbl[i] &= pinpoint_masktbl[i];
1123 flag |= pinpoint_daytbl[i];
1124 }
1125
1126 return ((flag == 0) ? FALSE : TRUE);
1127 }
1128
1129 /*
1130 * ���־���ν���
1131 *
1132 * �ƽ�����Ͽ�ե���������
1133 */
1134 static
event_week(void)1135 void event_week(void)
1136 {
1137 int i;
1138 const char *filename;
1139
1140 event_msg_level_default = LVAR('r');
1141 for (i = 0; i < MAXWEEKFILE; i++) {
1142 if (week_filetbl[i] != NULL) {
1143 filename = make_filename(week_filetbl[i]);
1144 weekSearch(filename);
1145 }
1146 }
1147 }
1148 /*
1149 * �ե����뤫�齵�־����/��Ф���
1150 *
1151 * return value:
1152 * FALSE ���顼ȯ��(�ե����륪���ץ��)
1153 * TRUE ���ェλ
1154 *
1155 * file format:
1156 * month/day month/day message
1157 */
1158 static
weekSearch(const char * infile)1159 int weekSearch(const char *infile)
1160 {
1161 char *bp;
1162 char *lasts;
1163 char *weekmessage;
1164 struct DATE_MD begin, end;
1165
1166 if (openfile(infile)) {
1167 return (FALSE);
1168 }
1169
1170 current_mode = EVENT_MODE; /* makerange */
1171 event_msg_level = event_msg_level_default;
1172
1173 while ((bp = getfile()) != NULL) {
1174 if (*bp == '$') {
1175 ctrl_msg_proc(bp);
1176 continue;
1177 }
1178
1179 lasts = NULL;
1180 bp = strtok_r(bp, fmt_sep1, &lasts);
1181 if (bp == NULL) {
1182 continue;
1183 }
1184 begin.month = atoi(bp);
1185
1186 bp = strtok_r(NULL, fmt_sep3, &lasts);
1187 if (bp == NULL) {
1188 continue;
1189 }
1190 begin.day = atoi(bp);
1191
1192 bp = strtok_r(NULL, fmt_sep1, &lasts);
1193 if (bp == NULL) {
1194 continue;
1195 }
1196 end.month = atoi(bp);
1197
1198 bp = strtok_r(NULL, fmt_sep3, &lasts);
1199 if (bp == NULL) {
1200 continue;
1201 }
1202 end.day = atoi(bp);
1203
1204 if (begin.month == 0 || begin.day == 0 || end.month == 0 || end.day == 0) {
1205 continue;
1206 }
1207
1208 weekmessage = strtok_r(NULL, fmt_sep4, &lasts);
1209 if (weekmessage == NULL) {
1210 continue;
1211 }
1212
1213 if (check_week(&begin, &end) == FALSE) {
1214 continue;
1215 }
1216
1217 rangetbl[0].bmonth = begin.month;
1218 rangetbl[0].start = begin.day;
1219 rangetbl[0].emonth = end.month;
1220 rangetbl[0].end = end.day;
1221 rangetbl[1].bmonth = rangetbl[1].emonth = 0;
1222 rangetbl[1].start = rangetbl[1].end = 0;
1223 output_eventlist(2, strip(weekmessage), 0, TRUE);
1224 }
1225
1226 closefile();
1227
1228 return (TRUE);
1229 }
1230
1231 /*
1232 * ���־������⤫��ǧ����
1233 *
1234 * return value:
1235 * TRUE ������
1236 * FALSE ���ֳ�
1237 */
1238 static
check_week(struct DATE_MD * begin,struct DATE_MD * end)1239 int check_week(struct DATE_MD *begin, struct DATE_MD *end)
1240 {
1241 long jd1, jd2;
1242
1243 jd1 = Julian(calendar.year, begin->month, begin->day);
1244 jd2 = Julian(calendar.year, end->month, end->day);
1245
1246 if (jd1 > jd2) {
1247 if (jd1 <= calendar.julian_day) {
1248 jd2 = Julian(calendar.year + 1, end->month, end->day);
1249 } else if (jd2 >= calendar.julian_day) {
1250 jd1 = Julian(calendar.year - 1, begin->month, begin->day);
1251 }
1252 }
1253
1254 if (jd1 <= calendar.julian_day && calendar.julian_day <= jd2) {
1255 return (TRUE);
1256 }
1257 return (FALSE);
1258 }
1259
1260 /*
1261 * ���٥�ȥ�å�������ꥹ�ȹ�¤�˳�Ǽ����
1262 * �ꥹ�ȹ�¤�����å�������ڡ����㡼�˽��Ϥ���
1263 *
1264 * type:
1265 * 0: ��å�������ڡ����㡼�˽��Ϥ���
1266 * 1: ���٥�ȥ�å�������ꥹ�ȹ�¤�˳�Ǽ����
1267 * 2: ���־����å�������ꥹ�ȹ�¤�˳�Ǽ����
1268 * 3: ͽ���å�������ꥹ�ȹ�¤�˳�Ǽ����
1269 *
1270 * �ꥹ�ȹ�¤��Ǽ��ˡ(�����Ȥ��ʤ��Ȥ������� No.0)
1271 * No.0: ����
1272 * No.1: ����
1273 * No.2: ����
1274 */
1275 static
output_eventlist(int type,char * msg,int diffday,int rangeflag)1276 void output_eventlist(int type, char *msg, int diffday, int rangeflag)
1277 {
1278 static const char *title_message[2] = {
1279 #ifdef MSG_STYLE
1280 "****** ���礦�ϲ���������? ******",
1281 "****** ���礦�ϲ������Ǥ⤢��ޤ��� ******"
1282 #else
1283 "������ ���礦�ϲ��������ʡ� ������",
1284 "������ ���礦�ϲ������Ǥ⤢��ޤ���. ������"
1285 #endif
1286 };
1287 const char *notice_msg;
1288 char *end_msg;
1289 char *ep;
1290 int sortorder_no;
1291 int period = FALSE;
1292 int i;
1293
1294 switch (type) {
1295 case 0: /* messages flush */
1296 if (event_sortflag == FALSE) {
1297 list_output(0, pager_output);
1298 } else {
1299 for (i = 0; i < MAXSORTITEM; i++) {
1300 if (event_sortorder_tbl[i] >= 0) {
1301 list_output(event_sortorder_tbl[i], pager_output);
1302 }
1303 }
1304 }
1305 if (message_counter > 0) {
1306 #ifdef MSG_STYLE
1307 pager_output("--- %d�� ---", message_counter);
1308 #else
1309 pager_output("--- %2d�� ---", message_counter);
1310 #endif
1311 } else {
1312 pager_output_skip();
1313 pager_output("%s", title_message[1]);
1314 }
1315 break;
1316 case 1: /* event */
1317 case 2: /* week */
1318 case 3: /* event notice */
1319 sortorder_no = 0; /* ���� */
1320 if (diffday < 0) {
1321 sortorder_no = 1; /* ���� */
1322 } else if (diffday > 0) {
1323 sortorder_no = 2; /* ���� */
1324 }
1325 for (i = 0; i < MAXSORTITEM; i++) {
1326 if (event_sortorder_tbl[i] == sortorder_no) {
1327 break;
1328 }
1329 }
1330 if (i >= MAXSORTITEM) {
1331 return ;
1332 }
1333
1334 if (message_counter == 0) {
1335 pager_output_skip();
1336 pager_output("%s", title_message[0]);
1337 }
1338 message_counter++;
1339 for (; *msg == ' ' || *msg == '\t'; msg++)
1340 ;
1341 ep = strlastp(msg);
1342 if (ep[-1] == '.') {
1343 ep[-1] = '\0';
1344 period = TRUE;
1345 }
1346 (void)xstrescape(msg);
1347 notice_msg = Notice_Message(msg, diffday, &end_msg);
1348 if (type != 3) {
1349 strcpy(msgbuf, msg);
1350 } else {
1351 strcpy(msgbuf, notice_msg);
1352 strcat(msgbuf, msg);
1353 }
1354 if (rangeflag == TRUE) {
1355 makerange(msgbuf);
1356 }
1357 if (period == FALSE) {
1358 strcat(msgbuf, end_msg);
1359 }
1360 strcat(msgbuf, MSG_PERIOD);
1361 if (event_sortflag == FALSE) {
1362 list_add(0, 0, 0, event_msg_level, msgbuf);
1363 } else {
1364 list_insert(sortorder_no, diffday, 0, event_msg_level, msgbuf);
1365 }
1366 break;
1367 }
1368 }
1369
1370 /*
1371 * ���դΰ�ư
1372 *
1373 * ���դ����ˡ������ξ�硢��������ˤ��餹
1374 * ����ˤ�äƤϡ����������оݤˤ���
1375 *
1376 * ���餹����: dayshift_direction < 0: �� > 0: ��
1377 * �������о�: dayshift_skip_saturday == TRUE
1378 *
1379 * return value:
1380 * ��ư�������(holiday_tbl �ΰ��� + 1)
1381 * �ơ��֥뤫���줿��� 0 ���֤�
1382 */
1383 static
skipHoliday(int day)1384 int skipHoliday(int day)
1385 {
1386 day--; /* day:1-31 �� holiday_tbl ���ϰ� 0-30 ���Ѵ� */
1387
1388 while (day >= 0 && day < (MAX_DAYOFMONTH * MAX_MONTH_TBL)) {
1389 if (holiday_tbl[day] == 0 ||
1390 ((holiday_tbl[day] & SET_SATID) != 0 &&
1391 (holiday_tbl[day] & SET_HOLID) == 0 && dayshift_skip_saturday == FALSE)) {
1392 return (day + 1);
1393 }
1394 day += dayshift_direction;
1395 }
1396
1397 return (0);
1398 }
1399
1400 /*
1401 * ���٥�ȴ��֤��դ���
1402 *
1403 * rangetbl[] ����Ѥ��� msgbuff �κǸ�� (mm/dd��mm/dd) ���դ���
1404 * msgbuff �Υ����С��Ϲ�θ���Ƥ��ʤ��Τǡ���ʬ���礭������
1405 */
1406 static
makerange(char * msgbuff)1407 void makerange(char *msgbuff)
1408 {
1409 char *lastp;
1410 int modify_flag = FALSE;
1411 int i;
1412
1413 if (event_range_flag == FALSE) {
1414 return ;
1415 }
1416
1417 lastp = strlastp(msgbuff);
1418 lastp[0] = '(';
1419 lastp[1] = '\0';
1420 if (current_mode == LC_EVENT_MODE) {
1421 strcat(lastp, "����:");
1422 }
1423
1424 for (i = 0; i < PARAM_COUNT; i++) {
1425 int bmonth, emonth;
1426
1427 if (rangetbl[i].start == 0) {
1428 break;
1429 }
1430 bmonth = rangetbl[i].bmonth;
1431 if (bmonth == 0) {
1432 bmonth = current_month;
1433 }
1434 emonth = rangetbl[i].emonth;
1435 if (emonth == 0) {
1436 emonth = current_month;
1437 }
1438 if (rangetbl[i].start < 0) {
1439 rangetbl[i].start = endofmonth + rangetbl[i].start + 1;
1440 }
1441 if (rangetbl[i].end < 0) {
1442 rangetbl[i].end = endofmonth + rangetbl[i].end + 1;
1443 }
1444
1445 sprintf(strlastp(msgbuff), "%d/%d��%d/%d,", bmonth, rangetbl[i].start, emonth, rangetbl[i].end);
1446 modify_flag = TRUE;
1447 }
1448
1449 if (modify_flag == TRUE) {
1450 lastp = strlastp(msgbuff);
1451 lastp[-1] = ')';
1452 } else {
1453 *lastp = '\0';
1454 }
1455 }
1456