1 /*
2 Copyright (c) 1991-1999 Thomas T. Wetmore IV
3
4 Permission is hereby granted, free of charge, to any person
5 obtaining a copy of this software and associated documentation
6 files (the "Software"), to deal in the Software without
7 restriction, including without limitation the rights to use, copy,
8 modify, merge, publish, distribute, sublicense, and/or sell copies
9 of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 /* modified 05 Jan 2000 by Paul B. McBride (pmcbride@tiac.net) */
25 /*=============================================================
26 * export.c -- Export GEDCOM file from LifeLines database
27 * Copyright(c) 1992-94 by T.T. Wetmore IV; all rights reserved
28 * 3.0.0 - 29 May 94 3.0.2 - 09 Nov 94
29 *===========================================================*/
30
31 #include "sys_inc.h"
32 #include <time.h>
33 #include "llstdlib.h"
34 #include "btree.h"
35 #include "table.h"
36 #include "translat.h"
37 #include "gedcom.h"
38 #include "liflines.h"
39 #include "llinesi.h"
40 #include "feedback.h"
41 #include "lloptions.h"
42 #include "codesets.h"
43 #include "impfeed.h"
44 #include "xlat.h"
45
46 /*********************************************
47 * external/imported variables
48 *********************************************/
49
50 extern BTREE BTR;
51
52 /*********************************************
53 * local types
54 *********************************************/
55
56 struct tag_trav_parm {
57 struct tag_export_feedback * efeed;
58 FILE * fp;
59 };
60
61 /*********************************************
62 * local function prototypes
63 *********************************************/
64
65 /* alphabetical */
66 static BOOLEAN archive(BTREE btree, BLOCK block, void * param);
67 static void copy_and_translate(FILE *fo, INT len, struct tag_trav_parm * travparm, char ctype, XLAT xlat);
68
69 /*********************************************
70 * local variables
71 *********************************************/
72
73 static XLAT xlat_gedout; /* TODO: could do away with this via param to traverse */
74 static char *mabbv[] = {
75 "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
76 "JUL", "AUG", "SEP", "OCT", "NOV", "DEC",
77 };
78
79 static INT nindi, nfam, neven, nsour, nothr;
80
81
82 /*********************************************
83 * local & exported function definitions
84 * body of module
85 *********************************************/
86
87 /*===================================================
88 * archive_in_file -- Archive database in GEDCOM file
89 *=================================================*/
90 BOOLEAN
archive_in_file(struct tag_export_feedback * efeed,FILE * fp)91 archive_in_file (struct tag_export_feedback * efeed, FILE *fp)
92 {
93 char dat[30]="", tim[20]="";
94 struct tm *pt=0;
95 time_t curtime;
96 STRING str=0;
97 struct tag_trav_parm travparm;
98 xlat_gedout = transl_get_predefined_xlat(MINGD); /* internal to GEDCOM */
99
100 curtime = time(NULL);
101 pt = localtime(&curtime);
102 sprintf(dat, "%d %s %d", pt->tm_mday, mabbv[pt->tm_mon],
103 1900 + pt->tm_year);
104 sprintf(tim, "%d:%.2d", pt->tm_hour, pt->tm_min);
105 fprintf(fp, "0 HEAD\n1 SOUR LIFELINES %s\n1 DEST ANY\n"
106 , get_lifelines_version(80));
107 /* header date & time */
108 fprintf(fp, "1 DATE %s\n2 TIME %s\n", dat, tim);
109 /* header submitter entry */
110 str = getlloptstr("HDR_SUBM", "1 SUBM");
111 fprintf(fp, "%s\n", str);
112 /* header gedcom version info */
113 str = getlloptstr("HDR_GEDC", "1 GEDC\n2 VERS 5.5\n2 FORM LINEAGE-LINKED");
114 fprintf(fp, "%s\n", str);
115 /* header character set info */
116 /* should be outcharset; that is what is being used */
117 str = getlloptstr("HDR_CHAR", 0);
118 if (str) {
119 fprintf(fp, "%s\n", str);
120 } else {
121 /* xlat_gedout is the actual conversion used, so
122 we should use the name of its output */
123 CNSTRING outcharset = xl_get_dest_codeset(xlat_gedout);
124 fprintf(fp, "1 CHAR %s\n", outcharset);
125 }
126 /* finished header */
127
128 nindi = nfam = neven = nsour = nothr = 0;
129 memset(&travparm, 0, sizeof(travparm));
130 travparm.efeed = efeed;
131 travparm.fp = fp;
132 traverse_index_blocks(BTR, bmaster(BTR), &travparm, NULL, archive);
133 fprintf(fp, "0 TRLR\n");
134 return TRUE;
135 }
136 /*========================================================
137 * archive -- Traverse function called on each btree block
138 *======================================================*/
139 static BOOLEAN
archive(BTREE btree,BLOCK block,void * param)140 archive (BTREE btree, BLOCK block, void * param)
141 {
142 INT i, n, l;
143 char scratch[100];
144 FILE *fo=0;
145 struct tag_trav_parm * travparm = (struct tag_trav_parm *)param;
146
147 sprintf(scratch, "%s/%s", bbasedir(btree), fkey2path(ixself(block)));
148 fo = fopen(scratch, LLREADBINARY);
149 ASSERT(fo);
150 n = nkeys(block);
151 for (i = 0; i < n; i++) {
152 STRING key = rkey2str(rkeys(block, i));
153 if (*key != 'I' && *key != 'F' && *key != 'E' &&
154 *key != 'S' && *key != 'X')
155 continue;
156 if (fseek(fo, (long)(offs(block, i) + BUFLEN), 0))
157 FATAL();
158 if ((l = lens(block, i)) > 6) /* filter deleted records */
159 copy_and_translate(fo, l, travparm, *key, xlat_gedout);
160 }
161 fclose(fo);
162 return TRUE;
163 }
164 /*===================================================
165 * copy_and_translate -- Copy record with translation
166 *=================================================*/
167 static void
copy_and_translate(FILE * fo,INT len,struct tag_trav_parm * travparm,char ctype,XLAT xlat)168 copy_and_translate (FILE *fo, INT len, struct tag_trav_parm * travparm, char ctype, XLAT xlat)
169 {
170 char in[BUFLEN]="";
171 char *inp=0;
172 int remlen=0, num=0;
173 FILE * fn = travparm->fp;
174 struct tag_export_feedback * efeed = travparm->efeed;
175
176 inp = in; /* location for next read */
177 remlen = BUFLEN; /* max for next read */
178 while (len > 0) {
179 BOOLEAN last=FALSE, ok=FALSE;
180 if(len < remlen) remlen = len;
181 ASSERT(fread(inp, remlen, 1, fo) == 1);
182 len -= remlen;
183 remlen = (inp + remlen) - in; /* amount in current buffer */
184 last = (len <= 0);
185 ok = translate_write(xlat, in, &remlen, fn, last);
186 ASSERT(ok);
187 inp = in + remlen; /* position for next read */
188 remlen = BUFLEN - remlen; /* max for next read */
189 }
190 num = 0;
191 switch (ctype) {
192 case 'I': num = ++nindi; break;
193 case 'F': num = ++nfam; break;
194 case 'E': num = ++neven; break;
195 case 'S': num = ++nsour; break;
196 case 'X': num = ++nothr; break;
197 default: FATAL();
198 }
199 if (efeed && efeed->added_rec_fnc)
200 efeed->added_rec_fnc(ctype, num);
201 }
202