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