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 * gstrings.c -- Routines to creates child strings
27 * Copyright(c) 1992-94 by T.T. Wetmore IV; all rights reserved
28 * 2.3.4 - 24 Jun 93 2.3.5 - 25 Aug 93
29 * 3.0.0 - 02 May 94 3.0.2 - 24 Nov 94
30 * 3.0.3 - 15 Aug 95
31 *===========================================================*/
32
33 #include "llstdlib.h"
34 #include "table.h"
35 #include "translat.h"
36 #include "gedcom.h"
37 #include "lloptions.h"
38
39 /*********************************************
40 * external/imported variables
41 *********************************************/
42
43 extern STRING qSdspa_mar,qSdspa_bir,qSdspa_chr,qSdspa_dea,qSdspa_bur;
44 extern STRING qSunksps;
45
46 /*********************************************
47 * local variables
48 *********************************************/
49
50 static INT nchil = 0, maxchil = 0;
51 static STRING *chstrings = NULL, *chkeys = NULL;
52
53 static BOOLEAN displaykeys=TRUE;
54
55 /*********************************************
56 * local function definitions
57 * body of module
58 *********************************************/
59
60 /*===================================================================
61 * get_child_strings -- Return children strings; each string has name
62 * and event info, if avail
63 * fam: [in] family of interest
64 * rfmt: [in] reformatting functions
65 * pnum: [out] number of output strings
66 * pkeys: [out] array of output strings (children descriptions)
67 *=================================================================*/
68 STRING *
get_child_strings(NODE fam,RFMT rfmt,INT * pnum,STRING ** pkeys)69 get_child_strings (NODE fam, RFMT rfmt, INT *pnum, STRING **pkeys)
70 {
71 NODE chil;
72 INT i;
73
74 for (i = 0; i < nchil; i++) {
75 stdfree(chstrings[i]);
76 stdfree(chkeys[i]);
77 }
78 nchil = *pnum = 0;
79 if (!fam || !(chil = CHIL(fam))) return NULL;
80 nchil = length_nodes(chil);
81 if (nchil == 0) return NULL;
82 if (nchil > (maxchil - 1)) {
83 if (maxchil) {
84 stdfree(chstrings);
85 stdfree(chkeys);
86 }
87 chstrings = (STRING *) stdalloc((nchil+5)*sizeof(STRING));
88 chkeys = (STRING *) stdalloc((nchil+5)*sizeof(STRING));
89 maxchil = nchil + 5;
90 }
91 FORCHILDRENx(fam,child,i)
92 chstrings[i-1] = indi_to_list_string(child, NULL, 66, rfmt, TRUE);
93 chkeys[i-1] = strsave(rmvat(nxref(child)));
94 ENDCHILDRENx
95 *pnum = nchil;
96 *pkeys = chkeys;
97 return chstrings;
98 }
99 /*================================================
100 * indi_to_list_string -- Return menu list string.
101 * returns heap-alloc'd string
102 * indi: [IN] source person
103 * fam: [IN] relevant family (used in spouse lists)
104 * len: [IN] max length desired
105 * rfmt: [IN] reformating functions (may be NULL)
106 * appkey: [IN] allow appending key ?
107 *==============================================*/
108 STRING
indi_to_list_string(NODE indi,NODE fam,INT len,RFMT rfmt,BOOLEAN appkey)109 indi_to_list_string (NODE indi, NODE fam, INT len, RFMT rfmt, BOOLEAN appkey)
110 {
111 char scratch[MAXLINELEN];
112 STRING name, evt = NULL, p = scratch;
113 int hasparents;
114 int hasfamily;
115 if (len>(INT)sizeof(scratch))
116 len = sizeof(scratch);
117 if (indi) {
118 ASSERT(name = indi_to_name(indi, len));
119 } else
120 name = _(qSunksps);
121 sprintf(p, "%s", name);
122 /* TODO: Shouldn't we len -= strlen(p) first ? Perry, 2007-09-29 */
123 p += strlen(p);
124 if (fam) evt = fam_to_event(fam, "MARR", _(qSdspa_mar), len, rfmt);
125 if (!evt) evt = indi_to_event(indi, "BIRT", _(qSdspa_bir), len, rfmt);
126 if (!evt) evt = indi_to_event(indi, "CHR", _(qSdspa_chr), len, rfmt);
127 if (!evt) evt = indi_to_event(indi, "DEAT", _(qSdspa_dea), len, rfmt);
128 if (!evt) evt = indi_to_event(indi, "BURI", _(qSdspa_bur), len, rfmt);
129 if (evt) {
130 sprintf(p, ", %s", evt);
131 p += strlen(p);
132 }
133 if (appkey && indi && displaykeys) {
134 if (getlloptint("DisplayKeyTags", 0) > 0) {
135 sprintf(p, " (i%s)", key_of_record(indi));
136 } else {
137 sprintf(p, " (%s)", key_of_record(indi));
138 }
139 p += strlen(p);
140 }
141 if (appkey && fam && displaykeys) {
142 if (getlloptint("DisplayKeyTags", 0) > 0) {
143 sprintf(p, " (f%s)", key_of_record(fam));
144 } else {
145 sprintf(p, " (%s)", key_of_record(fam));
146 }
147 p += strlen(p);
148 }
149 if(indi) {
150 if(FAMC(indi)) hasparents = 1;
151 else hasparents = 0;
152 if(FAMS(indi)) hasfamily = 1;
153 else hasfamily = 0;
154 if(hasfamily || hasparents) {
155 *p++ = ' ';
156 *p++ = '[';
157 if(hasparents) *p++ = 'P';
158 if(hasfamily) *p++ = 'S';
159 *p++ = ']';
160 *p = '\0';
161 }
162 }
163 limit_width(scratch, len, uu8);
164 return strsave(scratch);
165 }
166 /*================================================
167 * sour_to_list_string -- Return menu list string.
168 * Created: 2000/11/29, Perry Rapp
169 *==============================================*/
170 STRING
sour_to_list_string(NODE sour,INT len,STRING delim)171 sour_to_list_string (NODE sour, INT len, STRING delim)
172 {
173 char scratch[1024];
174 STRING name, p=scratch;
175 INT mylen=len;
176 if (mylen>(INT)sizeof(scratch))
177 mylen=sizeof(scratch);
178 p[0]=0;
179 llstrcatn(&p, "(S", &mylen);
180 llstrcatn(&p, rmvat(nxref(sour))+1, &mylen);
181 llstrcatn(&p, ") ", &mylen);
182 name = node_to_tag(sour, "REFN", len);
183 if (name)
184 llstrcatn(&p, name, &mylen);
185 name = node_to_tag(sour, "TITL", len);
186 if (name && mylen > 20)
187 {
188 llstrcatn(&p, delim, &mylen);
189 llstrcatn(&p, name, &mylen);
190 }
191 name = node_to_tag(sour, "AUTH", len);
192 if (name && mylen > 20)
193 {
194 llstrcatn(&p, delim, &mylen);
195 llstrcatn(&p, name, &mylen);
196 }
197 limit_width(scratch, len, uu8);
198 return strsave(scratch);
199 }
200 /*================================================
201 * even_to_list_string -- Return menu list string.
202 * Created: 2001/12/16, Perry Rapp
203 *==============================================*/
204 STRING
even_to_list_string(NODE even,INT len,STRING delim)205 even_to_list_string (NODE even, INT len, STRING delim)
206 {
207 char scratch[1024];
208 STRING name, p=scratch;
209 INT mylen=len;
210 delim=delim; /* unused */
211 if (mylen>(INT)sizeof(scratch))
212 mylen=sizeof(scratch);
213 p[0]=0;
214 llstrcatn(&p, "(E", &mylen);
215 llstrcatn(&p, rmvat(nxref(even))+1, &mylen);
216 llstrcatn(&p, ") ", &mylen);
217 name = node_to_tag(even, "NAME", len);
218 if (name)
219 llstrcatn(&p, name, &mylen);
220 name = node_to_tag(even, "REFN", len);
221 if (name) {
222 llstrcatn(&p, " (", &mylen);
223 llstrcatn(&p, name, &mylen);
224 llstrcatn(&p, ")", &mylen);
225 }
226 limit_width(scratch, len, uu8);
227 return strsave(scratch);
228 }
229 /*================================================
230 * fam_to_list_string -- Return menu list string.
231 * Created: 2001/02/17, Perry Rapp
232 *==============================================*/
233 STRING
fam_to_list_string(NODE fam,INT len,STRING delim)234 fam_to_list_string (NODE fam, INT len, STRING delim)
235 {
236 char scratch[1024];
237 STRING name, p=scratch;
238 STRING tempname;
239 INT mylen=len;
240 char counts[32];
241 INT husbands=0, wives=0, children=0;
242 INT templen=0;
243 NODE refn, husb, wife, chil, rest, node;
244 if (mylen>(INT)sizeof(scratch))
245 mylen=sizeof(scratch);
246 p[0]=0;
247 llstrcatn(&p, "(F", &mylen);
248 llstrcatn(&p, rmvat(nxref(fam))+1, &mylen);
249 llstrcatn(&p, ")", &mylen);
250 name = node_to_tag(fam, "REFN", len);
251 if (name) {
252 llstrcatn(&p, " ", &mylen);
253 llstrcatn(&p, name, &mylen);
254 }
255 split_fam(fam, &refn, &husb, &wife, &chil, &rest);
256 for (node=husb; node; node=nsibling(node))
257 husbands++;
258 for (node=wife; node; node=nsibling(node))
259 wives++;
260 for (node=chil; node; node=nsibling(node))
261 children++;
262 sprintf(counts, "%ldh,%ldw,%ldch", husbands, wives, children);
263 llstrcatn(&p, " ", &mylen);
264 llstrcatn(&p, counts, &mylen);
265 if (husbands) {
266 node = qkey_to_indi(rmvat(nval(husb)));
267 if (node) {
268 llstrcatn(&p, delim, &mylen);
269 if (wives)
270 templen = (mylen-4)/2;
271 else
272 templen = mylen;
273 tempname = indi_to_name(node, templen);
274 limit_width(tempname, templen, uu8);
275 llstrcatn(&p, tempname, &mylen);
276 if (wives)
277 llstrcatn(&p, " m. ", &mylen);
278 }
279 }
280 if (wives) {
281 node = qkey_to_indi(rmvat(nval(wife)));
282 if (node) {
283 if (!templen)
284 templen = mylen;
285 /* othewise we set templen above */
286 llstrcatn(&p, indi_to_name(node, templen), &mylen);
287 }
288 }
289 join_fam(fam, refn, husb, wife, chil, rest);
290 /* TO DO - print a husband and a wife out */
291 limit_width(scratch, len, uu8);
292 return strsave(scratch);
293 }
294 /*================================================
295 * other_to_list_string -- Return menu list string.
296 * Created: 2000/11/29, Perry Rapp
297 *==============================================*/
298 STRING
other_to_list_string(NODE node,INT len,STRING delim)299 other_to_list_string(NODE node, INT len, STRING delim)
300 {
301 char scratch[1024];
302 STRING name, p=scratch;
303 INT mylen=len;
304 NODE child;
305 delim=delim; /* unused */
306 if (mylen>(INT)sizeof(scratch))
307 mylen=sizeof(scratch);
308 p[0]=0;
309 llstrcatn(&p, "(X", &mylen);
310 llstrcatn(&p, rmvat(nxref(node))+1, &mylen);
311 llstrcatn(&p, ") (", &mylen);
312 llstrcatn(&p, ntag(node), &mylen);
313 llstrcatn(&p, ") ", &mylen);
314 name = node_to_tag(node, "REFN", mylen);
315 if (name)
316 llstrcatn(&p, name, &mylen);
317 if (nval(node)) {
318 llstrcatn(&p, nval(node), &mylen);
319 }
320 /* append any CONC/CONT nodes that fit */
321 child = nchild(node);
322 while (mylen>5 && child) {
323 if (!strcmp(ntag(child), "CONC")
324 || !strcmp(ntag(child), "CONT")) {
325 /* skip empty CONC/CONT nodes */
326 if (nval(child)) {
327 llstrcatn(&p, " ", &mylen);
328 llstrcatn(&p, nval(child), &mylen);
329 }
330 } else {
331 break;
332 }
333 if (nchild(child))
334 break;
335 else if (nsibling(child))
336 child = nsibling(child);
337 else
338 break;
339 }
340 limit_width(scratch, len, uu8);
341 return strsave(scratch);
342 }
343 /*===========================================
344 * generic_to_list_string -- Format a print line from
345 * a top-level node of any type
346 * Caller may specify either node or key (& leave other NULL)
347 * returns heap-alloc'd string
348 * Caller must specify either node or key (or both)
349 * Used in lists and in extended gedcom view
350 * Created: 2001/02/12, Perry Rapp
351 * node: [IN] node tree of indi or fam ... to be described
352 * key: [IN] key of record specified by node
353 * len: [IN] max description desired
354 * delim: [IN] separator to use between events
355 * rfmt: [IN] reformatting information
356 * appkey: [IN] allow appending key ?
357 *=========================================*/
358 STRING
generic_to_list_string(NODE node,STRING key,INT len,STRING delim,RFMT rfmt,BOOLEAN appkey)359 generic_to_list_string (NODE node, STRING key, INT len, STRING delim, RFMT rfmt, BOOLEAN appkey)
360 {
361 STRING str;
362 str=NULL; /* set to appropriate format */
363 if (!node && key)
364 node = qkey_to_type(key);
365 if (!key && node)
366 key = rmvat(nxref(node));
367 if (node) {
368 switch (key[0])
369 {
370 case 'I':
371 str = indi_to_list_string(node, NULL, len, rfmt, appkey);
372 break;
373 case 'S':
374 str = sour_to_list_string(node, len, delim);
375 break;
376 case 'F':
377 str = fam_to_list_string(node, len, delim);
378 break;
379 case 'E':
380 str = even_to_list_string(node, len, delim);
381 break;
382 case 'X':
383 str = other_to_list_string(node, len, delim);
384 break;
385 }
386 }
387 if (!str) {
388 if (key)
389 str = strsave(key);
390 else
391 str = strsave("??");
392 }
393 return str;
394 }
395 /*=======================================================
396 * set_displaykeys -- Enable/disable keys in list strings
397 * That is, whether or not to show key numbers in items
398 * Created: 2001/01/01, Perry Rapp
399 *=====================================================*/
400 void
set_displaykeys(BOOLEAN keyflag)401 set_displaykeys (BOOLEAN keyflag)
402 {
403 displaykeys = keyflag;
404 }
405