1 /*
2  * birthday.c -- birthday manage
3  *
4  * Copyright (C) 1989,1997,1999,2000,2003 by Yoshifumi Mori
5  *
6  * tab:4
7  */
8 
9 #include "cdefs.h"
10 #include "extern.h"
11 
12 /* #define ROUGH_PERIOD_YEAR */
13 /* #define BIRTHDAY_ENDMSG_CUT */
14 
15 #define LIST_DEATHDAY_BASE	3	/* 0,1,2 ����������3,4,5 ��̿���ǻ��� */
16 
17 struct BDATA {
18 	char	*name;			/* ̾�� */
19 	struct DATE_T	birth;	/* ������ */
20 	struct DATE_T	death;	/* ̿�� */
21 	int	flags;				/* �ե饰 */
22 	int	age;				/* ǯ��/��ǯ */
23 	int	ayear;				/* �׸�ǯ */
24 	int	sex;				/* ���̡�̤������ */
25 };
26 #define FLAG_BD_BIRTH	001	/* ������ͭ�� */
27 #define FLAG_BD_DEATH	002	/* ̿��ͭ�� */
28 #define FLAG_BD_BIRTH_W	004	/* ���������� */
29 #define FLAG_BD_DEATH_W	010	/* ̿������ */
30 
31 #define MASK_SEX		01	/* ���� mask */
32 #define MASK_MARRIED	02	/* �뺧 mask */
33 #define MASK_UNKNOWN	04	/* �������� mask */
34 #define SET_MALE		00	/* ���� */
35 #define SET_FEMALE		01	/* ���� */
36 #define SET_UNMARRIED	00	/* ̤�� */
37 #define SET_MARRIED		02	/* ���� */
38 #define SET_UNKNOWN		04	/* �������� */
39 
40 /* birthday_addinfo */
41 #define FLAG_AI_BIRTH	01	/* ���������ɲþ���ɽ�� */
42 #define FLAG_AI_DEATH	02	/* ̿�����ɲþ���ɽ�� */
43 #define FLAG_AI_MASK	(FLAG_AI_BIRTH|FLAG_AI_DEATH)
44 
45 /* birthday_agelevel */
46 #define FLAG_B_MASK		03
47 
48 /* deathday_agelevel */
49 #define FLAG_D_AYEAR	01	/* �׸�ǯɽ�� */
50 #define FLAG_D_AGE		02	/* ǯ��ɽ�� */
51 #define FLAG_D_MASK		(FLAG_D_AYEAR|FLAG_D_AGE)
52 
53 enum AGE_DISPMODE {
54 	INVISIBLE,	/* ǯ����ɽ�� */
55 	VISIBLE,	/* ǯ��ɽ�� */
56 	AGECHECK,	/* ǯ���ǧ */
57 };
58 
59 enum {
60 	DATE_ADDDT_BIRTH,	/* ���������ɲþ�������� */
61 	DATE_ADDDT_DEATH,	/* ̿�����ɲþ�������� */
62 };
63 
64 char	*birthday_filetbl[MAXBIRTHFILE];
65 char	*birthday_sortorder;
66 int		birthday_agesort = SORT_DOWN_ORDER;
67 int		birthday_addinfo = 0;
68 
69 int		birthday_agelevel = BIRTHDAY_AGE_NO;
70 int		birthday_notice_range = NOTICE_DEFAULT_RANGE;
71 int		birthday_notice_flag = NOTICE_ALL;
72 int		birthday_flower = FALSE;
73 
74 int		deathday_flag = TRUE;	/* TRUE: ̿����ɽ�� */
75 int		deathday_agelevel = 0;
76 int		deathday_notice_range = NOTICE_DEFAULT_RANGE;
77 int		deathday_notice_flag = NOTICE_NO;
78 
79 static int	birthday_sortflag;
80 static int	birthday_sortorder_tbl[MAXSORTITEM];
81 static int	birthday_effect_addinfo;
82 
83 static int	birthday_title_flag;
84 static int	birthday_listup_flag;
85 static int	birthday_todayhit_flag;
86 static int	birthday_effect_agelevel;
87 
88 static int	deathday_listup_flag;
89 static int	deathday_effect_agelevel;
90 
91 static void birthday_main(void);
92 static void birthday_filemain(const char *infile);
93 static int birthday_check_sex(const char *sex, int *flag_sex);
94 static int birthday_check_noticerange(struct DATE_T date, int notice_range, int *diffday, int *age);
95 static int period_year(struct DATE_T start, struct DATE_T end);
96 
97 static void birthday_display(int diffday, struct BDATA bdata);
98 static void birthday_listadd(int sortorder_no, int diffday, int age);
99 static void birthday_title(void);
100 static void birthday_listup(void);
101 static void birthday_message(void);
102 
103 static void deathday_display(int diffday, struct BDATA bdata);
104 static void deathday_listadd(int sortorder_no, int diffday, int ayear, int age);
105 static void deathday_listup(void);
106 
107 static void add_dateinfo(int type, struct DATE_T date, int wflag);
108 
109 static void ctrl_msg_proc(char *bp);
110 
111 /*
112  * ��������ɽ��
113  *
114  * �ƥե�������˽�������
115  */
birthday(void)116 void birthday(void)
117 {
118 	birthday_sortflag = TRUE;
119 	birthday_sortorder_tbl[0] = 0;
120 	birthday_sortorder_tbl[1] = 1;
121 	birthday_sortorder_tbl[2] = 2;
122 	birthday_sortflag = analysis_sortorder("birthday", birthday_sortorder, birthday_sortorder_tbl, birthday_sortflag);
123 
124 	birthday_title_flag = FALSE;
125 	birthday_listup_flag = FALSE;
126 	birthday_todayhit_flag = FALSE;
127 	if (birthday_notice_range < 0 || birthday_notice_range > MAX_DAYOFMONTH) {
128 		birthday_notice_range = NOTICE_DEFAULT_RANGE;
129 		errprint("birthday", ERR_WARN, "birthday_notice_range error, default %d set", birthday_notice_range);
130 	}
131 
132 	deathday_listup_flag = FALSE;
133 	if (deathday_notice_range < 0 || deathday_notice_range > MAX_DAYOFMONTH) {
134 		deathday_notice_range = NOTICE_DEFAULT_RANGE;
135 		errprint("birthday", ERR_WARN, "deathday_notice_range error, default %d set", deathday_notice_range);
136 	}
137 
138 	list_init();
139 
140 	birthday_main();
141 	birthday_listup();
142 	birthday_message();
143 
144 	deathday_listup();
145 
146 	list_free();
147 }
148 
149 /*
150  * �������ե�������������
151  */
152 static
birthday_main(void)153 void birthday_main(void)
154 {
155 	int	i;
156 	int	offs;
157 	int	mm;
158 
159 	for (i = 0; i < MAXBIRTHFILE; i++) {
160 		if (birthday_filetbl[i] != NULL) {
161 			for (offs = -1; offs <= 1; offs++) {
162 				mm = calendar.month + offs;
163 				if (mm < 1) {
164 					mm = 12;
165 				} else if (mm > 12) {
166 					mm = 1;
167 				}
168 				birthday_filemain(make_filename2(birthday_filetbl[i], 0, mm, 0));
169 				if ((mkfile_status & SET_MKF_MM) == 0) {
170 					break;
171 				}
172 			}
173 		}
174 	}
175 }
176 
177 /*
178  * �ե�����������������������
179  *
180  * file format:
181  *   [+n] year/month/day sm name1 name2
182  */
183 static
birthday_filemain(const char * infile)184 void birthday_filemain(const char *infile)
185 {
186 	char	*bp;
187 	char	*lasts;
188 	char	*name[2];
189 	char	*sex;
190 	struct BDATA	bdata;
191 	int		wflag;
192 	int		notice_range;
193 	int		notice_force_range;
194 	int		d_notice_range;
195 	int		diffday;
196 	char	*sp;
197 
198 	if (openfile(infile)) {
199 		return ;
200 	}
201 
202 	birthday_effect_addinfo = birthday_addinfo;
203 	birthday_effect_agelevel = birthday_agelevel;
204 	deathday_effect_agelevel = deathday_agelevel;
205 
206 	while ((bp = getfile()) != NULL) {
207 		if (*bp == '$') {
208 			ctrl_msg_proc(bp);
209 			continue;
210 		}
211 
212 		lasts = NULL;
213 		bp = strtok_r(bp, fmt_sep3, &lasts);
214 		if (bp == NULL) {
215 			continue;
216 		}
217 
218 		memset(&bdata, 0, sizeof(bdata));
219 
220 		notice_range = 0;	/* notice off */
221 		notice_force_range = FALSE;
222 		if (*bp == '+') {
223 			bp++;	/* skip '+' */
224 			notice_range = birthday_notice_range;
225 			if (isdigit((unsigned char)*bp) != 0) {
226 				notice_range = (int)strtol(bp, &bp, 10);
227 				notice_force_range = TRUE;
228 			}
229 			bp = strtok_r(NULL, fmt_sep3, &lasts);
230 		}
231 
232 		if (birthday_notice_flag == NOTICE_NO) {
233 			notice_range = 0;	/* notice off */
234 		} else if (birthday_notice_flag == NOTICE_ALL) {
235 			if (notice_range == 0 && notice_force_range == FALSE) {
236 				notice_range = birthday_notice_range;
237 			}
238 		}
239 
240 		if (bp == NULL ||
241 		    read_date(0x99, bp, &bdata.birth, &wflag) == DATE_NG) {
242 			continue;
243 		}
244 		if (bdata.birth.month != 0 && bdata.birth.day != 0) {
245 			/* 0000/00/00, yyyy/00/00 �λ�����������̵���Τޤ� */
246 			bdata.flags |= FLAG_BD_BIRTH;
247 		}
248 		if (wflag != FALSE) {
249 			bdata.flags |= FLAG_BD_BIRTH_W;
250 		}
251 
252 		sex = strtok_r(NULL, fmt_sep3, &lasts);
253 		if (sex == NULL) {
254 			continue;
255 		}
256 
257 		bp = strtok_r(NULL, fmt_sep3, &lasts);
258 		if (bp == NULL) {
259 			continue;
260 		}
261 
262 		d_notice_range = 0;	/* notice off */
263 		notice_force_range = FALSE;
264 		if (*bp == '+') {
265 			bp++;	/* skip '+' */
266 			d_notice_range = deathday_notice_range;
267 			if (isdigit((unsigned char)*bp) != 0) {
268 				d_notice_range = (int)strtol(bp, &bp, 10);
269 				notice_force_range = TRUE;
270 			}
271 			bp = strtok_r(NULL, fmt_sep3, &lasts);
272 		}
273 		if (deathday_notice_flag == NOTICE_NO) {
274 			d_notice_range = 0;	/* notice off */
275 		} else if (deathday_notice_flag == NOTICE_ALL) {
276 			if (d_notice_range == 0 && notice_force_range == FALSE) {
277 				d_notice_range = deathday_notice_range;
278 			}
279 		}
280 
281 		if (bp == NULL) {
282 			continue;
283 		}
284 
285 		sp = xstrdup(bp);
286 		if (read_date(0x99, sp, &bdata.death, &wflag) == DATE_OK) {
287 			bdata.flags |= FLAG_BD_DEATH;
288 			if (wflag != FALSE) {
289 				bdata.flags |= FLAG_BD_DEATH_W;
290 			}
291 			bp = strtok_r(NULL, fmt_sep3, &lasts);
292 		}
293 		free(sp);
294 
295 		name[0] = bp;
296 		if (name[0] == NULL) {
297 			continue;
298 		}
299 		name[1] = strtok_r(NULL, fmt_sep3, &lasts);
300 		if (name[1] == NULL) {
301 			name[1] = name[0];
302 		}
303 
304 		if (birthday_check_sex(sex, &bdata.sex) == FALSE) {
305 			errprint("birthday", ERR_WARN, "%s: %d: sex type %s for %s", infile, lines, sex, name[0]);
306 		}
307 
308 		bdata.name = undertospace(name[0]);
309 
310 		if ((bdata.flags & FLAG_BD_BIRTH) != 0 &&
311 		    birthday_check_noticerange(bdata.birth, notice_range, &diffday, &bdata.age) == TRUE) {
312 			birthday_display(diffday, bdata);
313 		}
314 
315 		if ((bdata.flags & FLAG_BD_DEATH) != 0 &&
316 		    deathday_flag == TRUE &&
317 		    birthday_check_noticerange(bdata.death, d_notice_range, &diffday, &bdata.ayear) == TRUE) {
318 			bdata.age = period_year(bdata.birth, bdata.death);
319 			deathday_display(diffday, bdata);
320 		}
321 	}
322 
323 	closefile();
324 }
325 
326 /*
327  * ���̡�̤��/�������̤���
328  *
329  * return value:
330  *   TRUE  : ��������
331  *   FALSE : ���顼ȯ��
332  */
333 static
birthday_check_sex(const char * sex,int * flag_sex)334 int birthday_check_sex(const char *sex, int *flag_sex)
335 {
336 	static const struct SEX_T {
337 		const char	*string;
338 		const int	type;
339 	} sextbl[] = {
340 		{ "ms", SET_MALE   | SET_UNMARRIED },
341 		{ "mu", SET_MALE   | SET_UNMARRIED },
342 		{ "mm", SET_MALE   | SET_MARRIED   },
343 		{ "fs", SET_FEMALE | SET_UNMARRIED },
344 		{ "fu", SET_FEMALE | SET_UNMARRIED },
345 		{ "fm", SET_FEMALE | SET_MARRIED   },
346 		{ "m?", SET_MALE   | SET_UNMARRIED },
347 		{ "f?", SET_FEMALE | SET_UNMARRIED },
348 		{ "?s", SET_MALE   | SET_UNMARRIED | SET_UNKNOWN },
349 		{ "?u", SET_MALE   | SET_UNMARRIED | SET_UNKNOWN },
350 		{ "?m", SET_MALE   | SET_MARRIED   | SET_UNKNOWN },
351 		{ "??", SET_MALE   | SET_UNMARRIED | SET_UNKNOWN },
352 	};
353 	int	i;
354 
355 	*flag_sex = SET_MALE | SET_UNMARRIED | SET_UNKNOWN;
356 
357 	for (i = 0; i < (sizeof(sextbl) / sizeof(struct SEX_T)); i++) {
358 		if (stricmp(sex, sextbl[i].string) == 0) {
359 			*flag_sex = sextbl[i].type;
360 			return (TRUE);
361 		}
362 	}
363 
364 	return (FALSE);
365 }
366 
367 /*
368  * ��������̿���ޤǤδ��֤��ᡢͽ������⤫Ĵ�٤�
369  * ǯ��/�׸�ǯ�����
370  *
371  * return value:
372  *   TRUE  ͽ�������
373  *   FALSE ͽ���ϰϳ�
374  */
375 static
birthday_check_noticerange(struct DATE_T date,int notice_range,int * diffday,int * age)376 int birthday_check_noticerange(struct DATE_T date, int notice_range, int *diffday, int *age)
377 {
378 	int	cmpyear;
379 	int	diffmonth;
380 	int	diffdays;
381 	struct DATE_T	nowdate;
382 
383 	if (date.month == 0 && date.day == 0) {
384 		return (FALSE);
385 	}
386 
387 	if (date.month == 2 && date.day == 29 && isleap(calendar.year) == 0) {
388 		/* 2/29 -> 3/1 translation */
389 		date.month = 3;
390 		date.day = 1;
391 	}
392 
393 	cmpyear = calendar.year;
394 	diffmonth = calendar.month - date.month;
395 	if (diffmonth >= 6) {
396 		cmpyear++;
397 	} else if (diffmonth <= -6) {
398 		cmpyear--;
399 	}
400 	diffdays = (int)(Julian(cmpyear, date.month, date.day) - calendar.julian_day);
401 	if (diffdays != 0) {
402 		if (notice_range == 0 || diffdays > notice_range || diffdays < -1) {
403 			return (FALSE);
404 		}
405 		if (diffdays >= 28) {
406 			if (diffdays > monthtbl[CENTER_MONTH].dayofmonth) {
407 				return (FALSE);
408 			}
409 			if (date.day == calendar.day) {
410 				diffdays = NOTICE_MONTH(1);
411 			}
412 		}
413 	}
414 
415 	*diffday = diffdays;
416 
417 	/* ǯ��/�׸�ǯ�׻� */
418 	nowdate = date;
419 	nowdate.year = cmpyear;
420 	*age = period_year(date, nowdate);
421 	if (date.year != 0 && *age < 0) {
422 		return (FALSE);	/* �ޤ����ޤ�Ƥ��ʤ�/˴���ʤäƤ��ʤ� */
423 	}
424 
425 	return (TRUE);
426 }
427 
428 /*
429  * ����(ǯ)�����
430  *
431  * �Ϥ�����դ�꽪�������դ�ɬ���礭������
432  * #ifdef ROUGH_PERIOD_YEAR
433  * �ɤ��餫�����դ� 00/00 �ξ���ñ��� end.year - start.year ���֤�
434  * #endif
435  *
436  * ǯ����˴����ǯ����˴���Ƥ���δ���(ǯ)
437  */
438 static
period_year(struct DATE_T start,struct DATE_T end)439 int period_year(struct DATE_T start, struct DATE_T end)
440 {
441 	int	period;
442 
443 	if (start.year == 0 || end.year == 0 || start.year > end.year) {
444 		return (-1);	/* �Ϥᡢ������ǯ�β������� 0 �ξ��Ϸ׻����ʤ� */
445 	}
446 
447 #ifndef ROUGH_PERIOD_YEAR
448 	if (start.month == 0 || start.day == 0 ||
449 	    end.month == 0 || end.day == 0) {
450 		return (-1);	/* ����(����)�������ξ��ϴ���(ǯ)����ʤ� */
451 	}
452 #endif
453 
454 	if (start.month == 2 && start.day == 29 && isleap(start.year) == 0) {
455 		/* 2/29 -> 3/1 translation */
456 		start.month = 3;
457 		start.day = 1;
458 	}
459 
460 	if (end.month == 2 && end.day == 29 && isleap(end.year) == 0) {
461 		/* 2/29 -> 3/1 translation */
462 		end.month = 3;
463 		end.day = 1;
464 	}
465 
466 	period = end.year - start.year;
467 	if (start.year < 0 && end.year > 0) {	/* �������������ޤ��� */
468 		period--;
469 	}
470 	if (start.month != 0 && end.month != 0 &&
471 	    (end.month < start.month ||
472 	     (end.month == start.month && end.day < start.day))) {
473 		period--;
474 	}
475 
476 	return (period);
477 }
478 
479 /*
480  * ����������Ϥ���(ͽ����)
481  */
482 static
birthday_display(int diffday,struct BDATA bdata)483 void birthday_display(int diffday, struct BDATA bdata)
484 {
485 	static const char	tbl_show_age[2][4] = {
486 		{ VISIBLE, VISIBLE,   AGECHECK,  INVISIBLE },	/* male */
487 		{ VISIBLE, INVISIBLE, INVISIBLE, INVISIBLE },	/* female */
488 	};
489 #ifdef BIRTHDAY_ENDMSG_CUT
490 	char	*ep;
491 #endif
492 	char	*end_msg;
493 	int		sortorder_no;
494 	int		show_age;
495 	int		period = FALSE;
496 	int		i;
497 
498 	sortorder_no = 0;		/* ���� */
499 	if (diffday < 0) {
500 		sortorder_no = 1;	/* ���� */
501 	} else if (diffday > 0) {
502 		sortorder_no = 2;	/* ���� */
503 	} else {
504 		birthday_todayhit_flag = TRUE;
505 	}
506 	for (i = 0; i < MAXSORTITEM; i++) {
507 		if (birthday_sortorder_tbl[i] == sortorder_no) {
508 			break;
509 		}
510 	}
511 	if (i >= MAXSORTITEM) {
512 		return ;
513 	}
514 
515 	if (bdata.birth.year == 0) {
516 		show_age = INVISIBLE;
517 	} else {
518 		show_age = (int)tbl_show_age[bdata.sex & MASK_SEX][birthday_effect_agelevel];
519 		if (show_age == AGECHECK) {
520 			if (bdata.age < 25) {	/* 25��̤����ǯ��ɽ�� */
521 				show_age = VISIBLE;
522 			} else {
523 				show_age = INVISIBLE;
524 			}
525 		}
526 	}
527 
528 #ifdef BIRTHDAY_ENDMSG_CUT
529 	ep = strlastp(bdata.name);
530 	if (ep[-1] == '.') {
531 		ep[-1] = '\0';
532 		period = TRUE;
533 	}
534 #endif
535 
536 	sprintf(msgbuf, "%s %s �����", Notice_Message(bdata.name, diffday, &end_msg), bdata.name);
537 	if (show_age == VISIBLE) {
538 		sprintf(strlastp(msgbuf), "%d���ܤ�", bdata.age);
539 	}
540 	strcat(msgbuf, "������");
541 	if (period == FALSE) {
542 		strcat(msgbuf, end_msg);
543 	}
544 	strcat(msgbuf, MSG_PERIOD);
545 
546 	/* ���������ɲþ��� */
547 	if ((birthday_effect_addinfo & FLAG_AI_BIRTH) != 0 &&
548 	    (bdata.flags & FLAG_BD_DEATH) != 0) {
549 		add_dateinfo(DATE_ADDDT_BIRTH, bdata.death, bdata.flags & FLAG_BD_DEATH_W);
550 	}
551 
552 	birthday_listadd(sortorder_no, diffday, bdata.age);
553 }
554 
555 /*
556  * �����������Ȥ��뤿�ᡢ�ꥹ�ȹ�¤�˳�Ǽ����
557  *
558  * �ꥹ�ȹ�¤��Ǽ��ˡ(�����Ȥ��ʤ��Ȥ������� No.0)
559  *   No.0: ����
560  *   No.1: ����
561  *   No.2: ����
562  */
563 static
birthday_listadd(int sortorder_no,int diffday,int age)564 void birthday_listadd(int sortorder_no, int diffday, int age)
565 {
566 	(void)xstrescape(msgbuf);
567 
568 	if (birthday_sortflag == FALSE) {
569 		list_add(0, 0, 0, 0, msgbuf);
570 	} else {
571 		switch (birthday_agesort) {
572 		case SORT_NO_ORDER:
573 			list_add(sortorder_no, diffday, age, 0, msgbuf);
574 			break;
575 		case SORT_UP_ORDER:
576 			list_insert(sortorder_no, diffday, age, 0, msgbuf);
577 			break;
578 		case SORT_DOWN_ORDER:
579 			list_insert(sortorder_no, diffday, -age, 0, msgbuf);
580 			break;
581 		}
582 	}
583 
584 	birthday_listup_flag = TRUE;
585 }
586 
587 /*
588  * �������Υ����ȥ�ɽ��
589  */
590 static
birthday_title(void)591 void birthday_title(void)
592 {
593 	if (birthday_title_flag == FALSE) {
594 		birthday_title_flag = TRUE;
595 
596 		pager_output_skip();
597 #ifdef MSG_STYLE
598 		pager_output("----------- ������ -----------");
599 #else
600 		pager_output("�ݡݡݡݡݡ����������ݡݡݡݡ�");
601 #endif
602 	}
603 }
604 
605 /*
606  * ��������ꥹ�ȥ��å�
607  */
608 static
birthday_listup(void)609 void birthday_listup(void)
610 {
611 	int	i;
612 
613 	if (birthday_listup_flag == FALSE) {
614 		return ;
615 	}
616 
617 	birthday_title();
618 
619 	if (birthday_sortflag == FALSE) {
620 		list_output(0, pager_output);
621 	} else {
622 		for (i = 0; i < MAXSORTITEM; i++) {
623 			if (birthday_sortorder_tbl[i] >= 0) {
624 				list_output(birthday_sortorder_tbl[i], pager_output);
625 			}
626 		}
627 	}
628 }
629 
630 /*
631  * ���¡������С�������β֡��������β֡��ָ��դ�ɽ��
632  */
633 static
birthday_message(void)634 void birthday_message(void)
635 {
636 	const char	*defSuffix;
637 	const struct FLOWER_T	*flower;
638 
639 	if (birthday_flower == TRUE || birthday_todayhit_flag == TRUE) {
640 		birthday_title();
641 
642 		defSuffix = GetDefaultSuffix(0);
643 		flower = GetLanguageofFlower(calendar.month, calendar.day);
644 
645 		if (birthday_todayhit_flag == TRUE) {
646 			pager_output("���¤� %s %s" MSG_PERIOD, GetNameofConstellation(calendar.month, calendar.day), defSuffix);
647 			pager_output("�����Ф� %s %s" MSG_PERIOD, GetNameofBirthstone(calendar.month), defSuffix);
648 		}
649 		pager_output("%s��β֤� %s %s" MSG_PERIOD, (birthday_todayhit_flag != FALSE) ? "����" : "��", GetNameofBirthflowers(calendar.month), defSuffix);
650 		pager_output("%s�֤� %s���֤��ȤФϡ�%s��%s" MSG_PERIOD, (birthday_todayhit_flag != FALSE) ? "��������" : "����������", flower->name, flower->language, defSuffix);
651 	}
652 }
653 
654 /*
655  * ̿������Ϥ���(ͽ����)
656  */
657 static
deathday_display(int diffday,struct BDATA bdata)658 void deathday_display(int diffday, struct BDATA bdata)
659 {
660 #ifdef BIRTHDAY_ENDMSG_CUT
661 	char	*ep;
662 #endif
663 	char	*end_msg;
664 	int		sortorder_no;
665 	int		period = FALSE;
666 	int		i;
667 
668 	sortorder_no = 0;		/* ���� */
669 	if (diffday < 0) {
670 		sortorder_no = 1;	/* ���� */
671 	} else if (diffday > 0) {
672 		sortorder_no = 2;	/* ���� */
673 	}
674 	for (i = 0; i < MAXSORTITEM; i++) {
675 		if (birthday_sortorder_tbl[i] == sortorder_no) {
676 			break;
677 		}
678 	}
679 	if (i >= MAXSORTITEM) {
680 		return ;
681 	}
682 
683 #ifdef BIRTHDAY_ENDMSG_CUT
684 	ep = strlastp(bdata.name);
685 	if (ep[-1] == '.') {
686 		ep[-1] = '\0';
687 		period = TRUE;
688 	}
689 #endif
690 
691 	sprintf(msgbuf, "%s %s �����", Notice_Message(bdata.name, diffday, &end_msg), bdata.name);
692 	if ((deathday_effect_agelevel & FLAG_D_AYEAR) != 0 && bdata.ayear > 0) {
693 		sprintf(strlastp(msgbuf), "%d���ܤ�", bdata.ayear);
694 	}
695 	strcat(msgbuf, "̿��");
696 	if (period == FALSE) {
697 		strcat(msgbuf, end_msg);
698 	}
699 	strcat(msgbuf, MSG_PERIOD);
700 
701 	if ((deathday_effect_agelevel & FLAG_D_AGE) != 0 && bdata.age >= 0) {
702 		sprintf(strlastp(msgbuf), "��ǯ%d��" MSG_PERIOD, bdata.age);
703 	}
704 
705 	/* ̿�����ɲþ��� */
706 	if ((birthday_effect_addinfo & FLAG_AI_DEATH) != 0) {
707 		add_dateinfo(DATE_ADDDT_DEATH, bdata.birth, bdata.flags & FLAG_BD_BIRTH_W);
708 	}
709 
710 	deathday_listadd(sortorder_no, diffday, bdata.ayear, bdata.age);
711 }
712 
713 /*
714  * ̿�������Ȥ��뤿�ᡢ�ꥹ�ȹ�¤�˳�Ǽ����
715  *
716  * �ꥹ�ȹ�¤��Ǽ��ˡ(�����Ȥ��ʤ��Ȥ������� No.0)
717  *   No.0: ����
718  *   No.1: ����
719  *   No.2: ����
720  */
721 static
deathday_listadd(int sortorder_no,int diffday,int ayear,int age)722 void deathday_listadd(int sortorder_no, int diffday, int ayear, int age)
723 {
724 	(void)xstrescape(msgbuf);
725 
726 	if (birthday_sortflag == FALSE) {
727 		list_add(LIST_DEATHDAY_BASE, 0, 0, 0, msgbuf);
728 	} else {
729 		switch (birthday_agesort) {
730 		case SORT_NO_ORDER:
731 			list_add(sortorder_no + LIST_DEATHDAY_BASE, diffday, ayear, age, msgbuf);
732 			break;
733 		case SORT_UP_ORDER:
734 			list_insert(sortorder_no + LIST_DEATHDAY_BASE, diffday, ayear, age, msgbuf);
735 			break;
736 		case SORT_DOWN_ORDER:
737 			list_insert(sortorder_no + LIST_DEATHDAY_BASE, diffday, -ayear, -age, msgbuf);
738 			break;
739 		}
740 	}
741 
742 	deathday_listup_flag = TRUE;
743 }
744 
745 /*
746  * ̿����ꥹ�ȥ��å�
747  */
deathday_listup(void)748 void deathday_listup(void)
749 {
750 	int	i;
751 
752 	if (deathday_listup_flag == FALSE) {
753 		return ;
754 	}
755 
756 	pager_output_skip();
757 #ifdef MSG_STYLE
758 	pager_output("----------- ̿�� -----------");
759 #else
760 	pager_output("�ݡݡݡݡݡ�̿�����ݡݡݡݡ�");
761 #endif
762 
763 	if (birthday_sortflag == FALSE) {
764 		list_output(LIST_DEATHDAY_BASE, pager_output);
765 	} else {
766 		for (i = 0; i < MAXSORTITEM; i++) {
767 			if (birthday_sortorder_tbl[i] >= 0) {
768 				list_output(birthday_sortorder_tbl[i] + LIST_DEATHDAY_BASE, pager_output);
769 			}
770 		}
771 	}
772 }
773 
774 /*
775  * �ɲþ�����ɲä���
776  */
777 static
add_dateinfo(int type,struct DATE_T date,int wflag)778 void add_dateinfo(int type, struct DATE_T date, int wflag)
779 {
780 	const char	*msg1;
781 	const char	*msg2;
782 	const char	*msgfmt;
783 	const char	*nameofera;
784 	const char	*temp_name;
785 	char	*msg_w;
786 	int	date_flag = 0;
787 	int	disp_year;
788 	int	temp_year;
789 #define FLAG_DISP_YY		01
790 #define FLAG_DISP_MMDD		02
791 #define FLAG_DISP_YYMMDD	(FLAG_DISP_YY|FLAG_DISP_MMDD)
792 
793 	switch (type) {
794 	case DATE_ADDDT_BIRTH:
795 		msg1 = "��";
796 		msg2 = "̿������";
797 		break;
798 	case DATE_ADDDT_DEATH:
799 		msg1 = "���ޤ�";
800 		msg2 = "����������";
801 		break;
802 	}
803 
804 	if (date.year != 0) {
805 		date_flag |= FLAG_DISP_YY;
806 		nameofera = (date.year < 0) ? "BC" : "";
807 		disp_year = abs(date.year);
808 	}
809 	if (date.month != 0 && date.day != 0) {
810 		date_flag |= FLAG_DISP_MMDD;
811 	}
812 
813 	msg_w = strlastp(msgbuf);
814 
815 	switch (date_flag) {
816 	case 0:
817 		sprintf(msg_w, "(%s)", msg2);
818 		break;
819 	case FLAG_DISP_YY:
820 		sprintf(msg_w, "(%s%04d%s)", nameofera, disp_year, msg1);
821 		break;
822 	case FLAG_DISP_MMDD:
823 		sprintf(msg_w, "(%02d/%02d%s)", date.month, date.day, msg1);
824 		break;
825 	case FLAG_DISP_YY | FLAG_DISP_MMDD:
826 		if (wflag != 0 &&
827 			(temp_name = GetNameofEra(LANG_E, date.year, date.month, date.day, &temp_year)) != NULL) {
828 			msgfmt = "(%s%02d/%02d/%02d%s)";
829 			nameofera = temp_name;
830 			disp_year = temp_year;
831 		} else {
832 			msgfmt = "(%s%04d/%02d/%02d%s)";
833 		}
834 		sprintf(msg_w, msgfmt, nameofera, disp_year, date.month, date.day, msg1);
835 		break;
836 	}
837 }
838 
839 /*
840  * ��å���������ȥ������
841  *
842  * ${ctrl}
843  *
844  * ctrl: An  ǯ��ɽ����٥� 0-3
845  *       Dn  �׸�ǯ����ǯɽ����٥� 0-3
846  *       In  ��������̿�����ɲþ���ɽ����٥� 0-3
847  */
848 static
ctrl_msg_proc(char * bp)849 void ctrl_msg_proc(char *bp)
850 {
851 	int	n;
852 
853 	bp++;
854 	while (*bp != '\0') {
855 		switch (*bp) {
856 		case 'A':
857 			bp++;
858 			if (isdigit(*bp) != 0) {
859 				n = *bp - '0';
860 				if (0 <= n && n <= FLAG_B_MASK) {
861 					birthday_effect_agelevel = n;
862 				}
863 				bp++;
864 			} else {
865 				/* RESET */
866 				birthday_effect_agelevel = birthday_agelevel;
867 			}
868 			break;
869 		case 'D':
870 			bp++;
871 			if (isdigit(*bp) != 0) {
872 				n = *bp - '0';
873 				if (0 <= n && n <= FLAG_D_MASK) {
874 					deathday_effect_agelevel = n;
875 				}
876 				bp++;
877 			} else {
878 				/* RESET */
879 				deathday_effect_agelevel = deathday_agelevel;
880 			}
881 			break;
882 		case 'I':
883 			bp++;
884 			if (isdigit(*bp) != 0) {
885 				n = *bp - '0';
886 				if (0 <= n && n <= FLAG_AI_MASK) {
887 					birthday_effect_addinfo = n;
888 				}
889 				bp++;
890 			} else {
891 				/* RESET */
892 				birthday_effect_addinfo = birthday_addinfo;
893 			}
894 			break;
895 		default:
896 			bp++;
897 			break;
898 		}
899 	}
900 }
901