1 /*
2  * history.c -- history manage
3  *
4  * Copyright (C) 1991,1997,1998,1999,2003 by Yoshifumi Mori
5  *
6  * remake 2003/06/27
7  *
8  * tab:4
9  */
10 
11 #include "cdefs.h"
12 #include "extern.h"
13 
14 /* #define ROUGH_PERIOD_YEAR */
15 
16 #define HISTORY_FOLDTYPE_DEFAULT	(MSG_FOLDTYPE_BASE + 1)	/* type1 */
17 
18 #ifdef MSG_STYLE
19 #define PERIOD	"��"
20 #else
21 #define PERIOD	"."
22 #endif
23 
24 enum {
25 	TYPE_EVENT = 0,	/* ��˾�ν���� */
26 	TYPE_BIRTH,		/* ��ʪ�������� */
27 	TYPE_DEATH,		/* ��ʪ��̿�� */
28 };
29 
30 enum {
31 	DATE_HEADER = 0,	/* �إå��������� */
32 	DATE_ADDDT_BIRTH,	/* ���������ɲþ�������� */
33 	DATE_ADDDT_DEATH,	/* ̿�����ɲþ�������� */
34 };
35 
36 struct HDATA {
37 	struct DATE_T	edate;	/* ��������� */
38 	struct DATE_T	edate2;	/* ���������2 */
39 	struct DATE_T	bdate;	/* ���������� */
40 	struct DATE_T	ddate;	/* ̿������ */
41 	int	flags;
42 	const char	*msg;
43 };
44 #define FLAG_HD_EVENT_W		01	/* ���������:���� */
45 #define FLAG_HD_EVENT2_W	02	/* �����2����:���� */
46 #define FLAG_HD_BIRTH_W		010	/* ����������:���� */
47 #define FLAG_HD_DEATH_W		020	/* ̿������:���� */
48 
49 /* history_addinfo */
50 #define FLAG_AI_BIRTH	01	/* ���������ɲþ��� */
51 #define FLAG_AI_DEATH	02	/* ̿�����ɲþ��� */
52 
53 /* history_year_commnet */
54 #define FLAG_Y_TIMES	01	/* ��������̿���β����ɽ�� */
55 #define FLAG_Y_DIEDAGE	02	/* ��ǯ��ɽ�� */
56 
57 char	*history_filetbl[MAXHISTORYFILE];
58 int		history_sort = SORT_UP_ORDER;
59 int		history_foldtype = HISTORY_FOLDTYPE_DEFAULT;
60 int		history_addinfo = FLAG_AI_BIRTH | FLAG_AI_DEATH;
61 int		history_year_comment = FLAG_Y_TIMES | FLAG_Y_DIEDAGE;
62 int		history_both_date = TRUE;
63 
64 static int	history_listup_flag;
65 static const int	mesg_start_tbl[4][2] = {	/* �ޤ��֤��Կ� */
66 	{ 13, 13 },	/* type0 1st:13, 2nd:13 */
67 	{ 14, 12 },	/* type1 1st:14, 2nd:12 */
68 	{ 14, 14 },	/* type2 1st:14, 2nd:14 */
69 	{ 16, 14 },	/* type3 1st:16, 2nd:14 */
70 };
71 
72 static void history_main(const char *infile);
73 static void history_listup(void);
74 static void history_makemsg(int type, const struct DATE_T basedate, const struct HDATA hdata, int jdatefmt, int jdatefmt2);
75 static int period_year(struct DATE_T start, struct DATE_T end);
76 static void add_date(int type, struct DATE_T date, int jdatefmt);
77 static void history_listadd(struct DATE_T date);
78 static void history_output(const char *msg, ...);
79 
80 /*
81  * �ƥե����뤴�Ȥ���˾�ν����(��ʪ��������/̿����ޤ�)���������
82  */
history(void)83 void history(void)
84 {
85 	int	i;
86 
87 	history_listup_flag = FALSE;
88 
89 	if (history_foldtype < MSG_FOLDTYPE_BASE + 0 ||
90 	    history_foldtype > MSG_FOLDTYPE_BASE + 3) {
91 		history_foldtype = HISTORY_FOLDTYPE_DEFAULT;
92 		errprint("history", ERR_WARN, "history_foldtype error, default %d set", history_foldtype);
93 	}
94 
95 	list_init();
96 
97 	for (i = 0; i < MAXHISTORYFILE; i++) {
98 		if (history_filetbl[i] != NULL) {
99 			history_main(make_filename(history_filetbl[i]));
100 		}
101 	}
102 
103 	history_listup();
104 
105 	list_free();
106 }
107 
108 /*
109  * ��ˤ�ꥹ�ȥ��å�
110  */
111 static
history_listup(void)112 void history_listup(void)
113 {
114 	void	(*output_func)(const char *msg, ...);
115 
116 	if (history_listup_flag == FALSE) {
117 		return ;
118 	}
119 
120 	pager_output_skip();
121 #ifdef MSG_STYLE
122 	pager_output("======== ���礦����� ========");
123 #else
124 	pager_output("����� ���礦����� �����");
125 #endif
126 
127 	if (history_foldtype == 0) {
128 		output_func = pager_output;
129 	} else {
130 		output_func = history_output;
131 	}
132 	list_output(0, output_func);
133 }
134 
135 /*
136  * �ƥե�������ɤ߹��ߡ���˾�ν�������������
137  *
138  * file format:
139  *   year/month/day {e|E} message
140  *   year/month/day {b|B} year/month/day message
141  *   year/month/day {d|D} year/month/day message
142  */
143 static
history_main(const char * infile)144 void history_main(const char *infile)
145 {
146 	char	*bp;
147 	char	*lasts;
148 	int		type;
149 	int		type2;
150 	int		wflag;
151 	int		jdate_format;
152 	struct DATE_T	date;
153 	struct HDATA	hdata;
154 
155 	if (openfile(infile)) {
156 		return ;
157 	}
158 
159 	while ((bp = getfile()) != NULL) {
160 		lasts = NULL;
161 		bp = strtok_r(bp, fmt_sep3, &lasts);
162 		if (bp == NULL ||
163 		    read_date(0x99, bp, &date, &wflag) == DATE_NG) {
164 			continue;
165 		}
166 
167 		memset(&hdata, 0, sizeof(hdata));
168 		hdata.edate = date;	/* ���������������̿�� ���� */
169 		if (wflag != FALSE) {
170 			hdata.flags |= FLAG_HD_EVENT_W;
171 		}
172 
173 		bp = strtok_r(NULL, fmt_sep3, &lasts);
174 		if (bp == NULL) {
175 			continue;
176 		}
177 		switch (*bp) {
178 		case 'B': case 'b':	/* ������ */
179 			hdata.bdate = date;
180 			if (wflag != FALSE) {
181 				hdata.flags |= FLAG_HD_BIRTH_W;
182 			}
183 			type = TYPE_BIRTH;
184 			break;
185 		case 'D': case 'd':	/* ̿�� */
186 			hdata.ddate = date;
187 			if (wflag != FALSE) {
188 				hdata.flags |= FLAG_HD_DEATH_W;
189 			}
190 			type = TYPE_DEATH;
191 			break;
192 		case 'E': case 'e':	/* ����� */
193 			type = TYPE_EVENT;
194 			break;
195 		default:
196 			continue;
197 		}
198 
199 		jdate_format = isupper(*bp) ? TRUE : FALSE;
200 
201 		switch (type) {
202 		case TYPE_BIRTH:
203 		case TYPE_DEATH:
204 			bp = strtok_r(NULL, fmt_sep3, &lasts);
205 			if (bp == NULL ||
206 			    read_date(0x99, bp, &date, &wflag) == DATE_NG) {
207 				continue;
208 			}
209 			hdata.edate2 = date;
210 			if (wflag != FALSE) {
211 				hdata.flags |= FLAG_HD_EVENT2_W;
212 			}
213 			switch (type) {
214 			case TYPE_BIRTH:	/* ̿������ */
215 				hdata.ddate = date;
216 				if (wflag != FALSE) {
217 					hdata.flags |= FLAG_HD_DEATH_W;
218 				}
219 				type2 = TYPE_DEATH;
220 				break;
221 			case TYPE_DEATH:	/* ���������� */
222 				hdata.bdate = date;
223 				if (wflag != FALSE) {
224 					hdata.flags |= FLAG_HD_BIRTH_W;
225 				}
226 				type2 = TYPE_BIRTH;
227 				break;
228 			}
229 			break;
230 		}
231 
232 		bp = strtok_r(NULL, fmt_sep4, &lasts);
233 		if (bp == NULL) {
234 			continue;
235 		}
236 
237 		hdata.msg = xstrescape(strip(bp));
238 
239 		if ((hdata.edate.year == 0 || hdata.edate.year <= calendar.year) &&
240 		    (hdata.edate.month == calendar.month && hdata.edate.day == calendar.day)) {
241 			if ((hdata.flags & FLAG_HD_EVENT_W) != 0 ||
242 			    jdate_format != FALSE) {
243 				wflag = TRUE;
244 			} else {
245 				wflag = FALSE;
246 			}
247 			history_makemsg(type, hdata.edate, hdata, wflag, jdate_format);
248 		}
249 		if (history_both_date != FALSE &&
250 		    (type == TYPE_BIRTH || type == TYPE_DEATH) &&
251 		    (hdata.edate2.year == 0 || hdata.edate2.year <= calendar.year) &&
252 		    (hdata.edate2.month == calendar.month && hdata.edate2.day == calendar.day)) {
253 			if ((hdata.flags & FLAG_HD_EVENT2_W) != 0 ||
254 			    jdate_format != FALSE) {
255 				wflag = TRUE;
256 			} else {
257 				wflag = FALSE;
258 			}
259 			history_makemsg(type2, hdata.edate2, hdata, wflag, jdate_format);
260 		}
261 	}
262 
263 	closefile();
264 }
265 
266 /*
267  * ɽ��������˾�ν�����Υ�å����������
268  */
269 static
history_makemsg(int type,const struct DATE_T basedate,const struct HDATA hdata,int jdatefmt,int jdatefmt2)270 void history_makemsg(int type, const struct DATE_T basedate, const struct HDATA hdata, int jdatefmt, int jdatefmt2)
271 {
272 	int	age;
273 	int	ayear;
274 	int	jdf;
275 	struct DATE_T	nowdate;
276 
277 	history_listup_flag = TRUE;
278 
279 	msgbuf[0] = '\0';	/* add_date ���Хåե��κǸ���ɲä��뤿�� */
280 	add_date(DATE_HEADER, basedate, jdatefmt);
281 	strcpy(&msgbuf[mesg_start_tbl[history_foldtype][0]], hdata.msg);
282 
283 	nowdate.year = calendar.year;
284 	nowdate.month = calendar.month;
285 	nowdate.day = calendar.day;
286 
287 	switch (type) {
288 	case TYPE_BIRTH:	/* ������ */
289 		age = period_year(hdata.bdate, nowdate);	/* ǯ�� */
290 		if ((history_year_comment & FLAG_Y_TIMES) != 0 && age >= 0) {
291 			sprintf(strlastp(msgbuf), "��%d����", age);
292 		}
293 		strcat(msgbuf, "��������");
294 		if ((history_addinfo & FLAG_AI_BIRTH) != 0) {	/* �ɲþ��� */
295 			if ((hdata.flags & FLAG_HD_DEATH_W) != 0 ||
296 			    jdatefmt2 != FALSE) {
297 				jdf = TRUE;
298 			} else {
299 				jdf = FALSE;
300 			}
301 			strcat(msgbuf, PERIOD);
302 			add_date(DATE_ADDDT_BIRTH, hdata.ddate, jdf);
303 		}
304 		break;
305 	case TYPE_DEATH:	/* ̿�� */
306 		ayear = period_year(hdata.ddate, nowdate);	/* �׸�ǯ */
307 		if ((history_year_comment & FLAG_Y_TIMES) != 0 && ayear >= 0) {
308 			sprintf(strlastp(msgbuf), "��%d����", ayear);
309 		}
310 		strcat(msgbuf, "��̿��");
311 		age = period_year(hdata.bdate, hdata.ddate);	/* ��ǯ */
312 		if ((history_year_comment & FLAG_Y_DIEDAGE) != 0 && age >= 0) {
313 			sprintf(strlastp(msgbuf), PERIOD "��ǯ%d��", age);
314 		}
315 		if ((history_addinfo & FLAG_AI_DEATH) != 0) {	/* �ɲþ��� */
316 			if ((hdata.flags & FLAG_HD_BIRTH_W) != 0 ||
317 			    jdatefmt2 != FALSE) {
318 				jdf = TRUE;
319 			} else {
320 				jdf = FALSE;
321 			}
322 			strcat(msgbuf, PERIOD);
323 			add_date(DATE_ADDDT_DEATH, hdata.bdate, jdf);
324 		}
325 		break;
326 	}
327 
328 #if 0
329 	strcat(msgbuf, PERIOD);
330 #endif
331 
332 	history_listadd(basedate);
333 }
334 
335 /*
336  * ����(ǯ)�����
337  *
338  * �Ϥ�����դ�꽪�������դ�ɬ���礭������
339  * #ifdef ROUGH_PERIOD_YEAR
340  * �ɤ��餫�����դ� 00/00 �ξ���ñ��� end.year - start.year ���֤�
341  * #endif
342  *
343  * ǯ����˴����ǯ����˴���Ƥ���δ���(ǯ)
344  */
345 static
period_year(struct DATE_T start,struct DATE_T end)346 int period_year(struct DATE_T start, struct DATE_T end)
347 {
348 	int	period;
349 
350 	if (start.year == 0 || end.year == 0 || start.year > end.year) {
351 		return (-1);	/* �Ϥᡢ������ǯ�β������� 0 �ξ��Ϸ׻����ʤ� */
352 	}
353 
354 #ifndef ROUGH_PERIOD_YEAR
355 	if (start.month == 0 || start.day == 0 ||
356 	    end.month == 0 || end.day == 0) {
357 		return (-1);	/* ����(����)�������ξ��ϴ���(ǯ)����ʤ� */
358 	}
359 #endif
360 
361 	period = end.year - start.year;
362 	if (start.year < 0 && end.year > 0) {	/* �������������ޤ��� */
363 		period--;
364 	}
365 	if (start.month != 0 && end.month != 0 &&
366 	    (end.month < start.month ||
367 	     (end.month == start.month && end.day < start.day))) {
368 		period--;
369 	}
370 	return (period);
371 }
372 
373 /*
374  * ǯ������դ�Хåե��˽�����
375  *
376  * type:
377  *   DATE_HEADER      �إå���������(��˥�å�������Ƭ��)
378  *   DATE_ADDDT_BIRTH ���������ɲþ��������
379  *   DATE_ADDDT_DEATH ̿�����ɲþ��������
380  */
381 static
add_date(int type,struct DATE_T date,int jdatefmt)382 void add_date(int type, struct DATE_T date, int jdatefmt)
383 {
384 	const char	*msg1;
385 	const char	*msg2;
386 	const char	*msgfmt;
387 	const char	*nameofera;
388 	const char	*temp_name;
389 	char	*msg_w;
390 	int	date_flag = 0;
391 	int	disp_year;
392 	int	temp_year;
393 #define FLAG_DISP_YY		01
394 #define FLAG_DISP_MMDD		02
395 #define FLAG_DISP_YYMMDD	(FLAG_DISP_YY|FLAG_DISP_MMDD)
396 
397 	msg_w = strlastp(msgbuf);
398 
399 	switch (type) {
400 	case DATE_HEADER:
401 		if (date.year == 0) {
402 			sprintf(msg_w, "       %02d/%02d    ", date.month, date.day);
403 		} else {
404 			if (jdatefmt != FALSE &&
405 			    (nameofera = GetNameofEra(LANG_J, date.year, date.month, date.day, &disp_year)) != NULL) {
406 				msgfmt = "%s%02d/%02d/%02d    ";
407 			} else {
408 				msgfmt  = "%s%04d/%02d/%02d    ";
409 				nameofera = (date.year < 0) ? "BC" : "  ";
410 				disp_year = abs(date.year);
411 			}
412 			sprintf(msg_w, msgfmt, nameofera, disp_year, date.month, date.day);
413 		}
414 		break;
415 	case DATE_ADDDT_BIRTH:
416 		msg1 = "��";
417 		msg2 = "̿������";
418 		goto add_info_date;
419 	case DATE_ADDDT_DEATH:
420 		msg1 = "���ޤ�";
421 		msg2 = "����������";
422 add_info_date:
423 		if (date.year != 0) {
424 			date_flag |= FLAG_DISP_YY;
425 			nameofera = (date.year < 0) ? "BC" : "";
426 			disp_year = abs(date.year);
427 		}
428 		if (date.month != 0 && date.day != 0) {
429 			date_flag |= FLAG_DISP_MMDD;
430 		}
431 
432 		switch (date_flag) {
433 		case 0:
434 			sprintf(msg_w, "(%s)", msg2);
435 			break;
436 		case FLAG_DISP_YY:
437 			sprintf(msg_w, "(%s%04d%s)", nameofera, disp_year, msg1);
438 			break;
439 		case FLAG_DISP_MMDD:
440 			sprintf(msg_w, "(%02d/%02d%s)", date.month, date.day, msg1);
441 			break;
442 		case FLAG_DISP_YY | FLAG_DISP_MMDD:
443 			if (jdatefmt != 0 &&
444 				(temp_name = GetNameofEra(LANG_E, date.year, date.month, date.day, &temp_year)) != NULL) {
445 				msgfmt = "(%s%02d/%02d/%02d%s)";
446 				nameofera = temp_name;
447 				disp_year = temp_year;
448 			} else {
449 				msgfmt = "(%s%04d/%02d/%02d%s)";
450 			}
451 			sprintf(msg_w, msgfmt, nameofera, disp_year, date.month, date.day, msg1);
452 			break;
453 		}
454 		break;
455 	}
456 }
457 
458 /*
459  * ��˾�ν���������Ȥ��뤿�ᡢ�ꥹ�ȹ�¤�˳�Ǽ����
460  */
461 static
history_listadd(struct DATE_T date)462 void history_listadd(struct DATE_T date)
463 {
464 	switch (history_sort) {
465 	case SORT_UP_ORDER:
466 		list_insert(0, date.year, 0, 0, msgbuf);
467 		break;
468 	case SORT_DOWN_ORDER:
469 		list_insert(0, -date.year, 0, 0, msgbuf);
470 		break;
471 	case SORT_NO_ORDER:
472 		list_add(0, date.year, 0, 0, msgbuf);
473 		break;
474 	}
475 }
476 
477 /*
478  * ��˾�ν������ɽ������(pager �˽��Ϥ���)
479  *
480  * 1�Ԥ˼��ޤ�ʤ��Ȥ��ϡ�ʣ���Ԥ�ʬ�䤷��ɽ��
481  * �ޤ���ʸ�Ϥζ�§������Ԥ�
482  */
483 static
history_output(const char * msg,...)484 void history_output(const char *msg, ...)
485 {
486 	int	second_start;
487 
488 	second_start = mesg_start_tbl[history_foldtype][1];
489 	message_fold((const unsigned char *)msg, screen_max_columns - 3, 0, second_start);
490 }
491