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 /*=============================================================
25 * init.c -- Initialize LifeLines data structures
26 * Copyright(c) 1991-95 by T.T. Wetmore IV; all rights reserved
27 * 2.3.4 - 24 Jun 93 2.3.5 - 29 Aug 93
28 * 3.0.0 - 05 Oct 94 3.0.2 - 09 Nov 94
29 * 3.0.3 - 21 Sep 95
30 *===========================================================*/
31
32 #include "sys_inc.h"
33 #include "llstdlib.h"
34 #include "arch.h"
35 #include "btree.h"
36 #include "table.h"
37 #include "translat.h"
38 #include "gedcom.h"
39 #include "gedcomi.h"
40 #include "lloptions.h"
41 #include "codesets.h"
42 #include "menuitem.h"
43 #include "zstr.h"
44 #include "icvt.h"
45 #include "date.h"
46 #include "mychar.h"
47 #include "charprops.h"
48 #include "xlat.h"
49 #include "dbcontext.h"
50
51 /*********************************************
52 * global/exported variables
53 *********************************************/
54
55 TABLE tagtable=NULL; /* table for tag strings */
56 TABLE placabbvs=NULL; /* table for place abbrevs */
57 STRING editstr=NULL; /* edit command to run to edit (has editfile inside of it) */
58 STRING editfile=NULL; /* file used for editing, name obtained via mktemp */
59
60 /*********************************************
61 * external/imported variables
62 *********************************************/
63
64 extern BOOLEAN writeable;
65 extern STRING readpath,readpath_file;
66 extern STRING illegal_char;
67 extern INT opt_finnish, opt_mychar;
68
69 /*********************************************
70 * local function prototypes
71 *********************************************/
72
73 static void check_installation_path(void);
74 static BOOLEAN load_configs(STRING configfile, STRING * pmsg);
75 static void post_codesets_hook(void);
76 static void pre_codesets_hook(void);
77 static void update_db_options(void);
78
79 /*********************************************
80 * local variables
81 *********************************************/
82
83 static BOOLEAN suppress_reload=FALSE;
84 static char global_conf_path[MAXPATHLEN]="";
85
86 /*********************************************
87 * local & exported function definitions
88 * body of module
89 *********************************************/
90
91 /*=================================
92 * init_lifelines_global -- Initialization options & misc. stuff
93 * This is called before first (or later) database opened
94 *===============================*/
95 BOOLEAN
init_lifelines_global(STRING configfile,STRING * pmsg,void (* notify)(STRING db,BOOLEAN opening))96 init_lifelines_global (STRING configfile, STRING * pmsg, void (*notify)(STRING db, BOOLEAN opening))
97 {
98 STRING e;
99 STRING dirvars[] = { "LLPROGRAMS", "LLREPORTS", "LLARCHIVES"
100 , "LLDATABASES", };
101 INT i;
102
103 check_installation_path();
104
105 /* request notification when options change */
106 register_notify(&update_useropts);
107 suppress_reload = TRUE;
108
109 dbnotify_set(notify);
110
111 if (!load_configs(configfile, pmsg)) {
112 suppress_reload = FALSE;
113 update_useropts(NULL);
114 return FALSE;
115 }
116
117 pre_codesets_hook(); /* For MS-Windows user config of console codepages */
118
119 /* now that codeset variables are set from config file, lets initialize codesets */
120 /* although int_codeset can't be determined yet, we need GUI codeset for gettext */
121 init_codesets();
122
123 post_codesets_hook(); /* For Windows, link dynamically to gettext & iconv if available */
124
125
126 /* until we have an internal codeset (which is until we open a database)
127 we want output in display codeset */
128 llgettext_init(PACKAGE, gui_codeset_out);
129
130 /* read available translation tables */
131 transl_load_all_tts();
132 /* set up translations (for first time, will do it again after
133 loading config table, and then again after loading database */
134 transl_load_xlats();
135
136 /* check if any directories not specified, and try environment
137 variables, and default to "." */
138 for (i=0; i<ARRSIZE(dirvars); ++i) {
139 STRING str = getenv(dirvars[i]);
140 if (!str)
141 str = ".";
142 setoptstr_fallback(dirvars[i], str);
143 }
144 /* also check environment variable for editor */
145 {
146 STRING str = getenv("LLEDITOR");
147 if (!str)
148 str = environ_determine_editor(PROGRAM_LIFELINES);
149 setoptstr_fallback("LLEDITOR", str);
150 }
151 /* editor falls back to platform-specific default */
152 e = getlloptstr("LLEDITOR", NULL);
153 /* configure tempfile & edit command */
154 editfile = environ_determine_tempfile();
155 if (!editfile) {
156 *pmsg = strsave("Error creating temp file");
157 return FALSE;
158 }
159 editfile = strsave(editfile );
160 editstr = (STRING) stdalloc(strlen(e) + strlen(editfile) + 2);
161 sprintf(editstr, "%s %s", e, editfile);
162 set_usersort(custom_sort);
163 suppress_reload = FALSE;
164 update_useropts(0);
165
166 /* Finnish always uses custom character sets */
167 if (opt_finnish ) {
168 opt_mychar = TRUE;
169 mych_set_table(ISO_Latin1);
170 }
171
172
173 return TRUE;
174 }
175 /*=================================
176 * init_lifelines_postdb --
177 * Initialize stuff maintained in-memory
178 * which requires the database to already be opened
179 *===============================*/
180 BOOLEAN
init_lifelines_postdb(void)181 init_lifelines_postdb (void)
182 {
183 STRING emsg;
184 TABLE dbopts = create_table_str();
185
186 tagtable = create_table_str(); /* values are same as keys */
187 placabbvs = create_table_str();
188
189 init_valtab_from_rec("VPLAC", placabbvs, ':', &emsg);
190 init_valtab_from_rec("VUOPT", dbopts, '=', &emsg);
191 set_db_options(dbopts);
192 release_table(dbopts);
193 init_caches();
194 init_browse_lists();
195 if (!openxref(readonly))
196 return FALSE;
197
198
199 transl_load_xlats();
200
201 return TRUE;
202 }
203 /*===================================
204 * close_lifelines -- Close LifeLines
205 * Close entire lifelines engine - not just
206 * database (see close_lldb below).
207 *=================================*/
208 void
close_lifelines(void)209 close_lifelines (void)
210 {
211 lldb_close(&def_lldb); /* make sure database closed */
212 if (editfile) {
213 unlink(editfile);
214 stdfree(editfile);
215 editfile=NULL;
216 }
217 if (editstr) {
218 stdfree(editstr);
219 editstr=NULL;
220 }
221 term_lloptions();
222 term_date();
223 term_codesets();
224 strfree(&int_codeset);
225 xlat_shutdown();
226 }
227 /*===================================================
228 * is_codeset_utf8 -- Is this the name of UTF-8 ?
229 *=================================================*/
230 BOOLEAN
is_codeset_utf8(CNSTRING codename)231 is_codeset_utf8 (CNSTRING codename)
232 {
233 if (!codename || !codename[0]) return FALSE;
234 if (eqstr("UTF-8", codename)||eqstr("utf-8", codename)||eqstr("65001", codename))
235 return TRUE;
236 return FALSE;
237 }
238 /*===================================================
239 * update_useropts -- Set any global variables
240 * dependent on user options
241 *=================================================*/
242 void
update_useropts(VPTR uparm)243 update_useropts (VPTR uparm)
244 {
245 uparm = uparm; /* unused */
246 if (suppress_reload)
247 return;
248 /* deal with db-specific options */
249 /* includes setting int_codeset */
250 if (def_lldb)
251 update_db_options();
252 /* in case user changed any codesets */
253 init_codesets();
254 /* in case user changed locale (need int_codeset already set) */
255 uilocale();
256 /* in case user changed codesets */
257 /* TODO: Isn't this superfluous, as it was called in update_db_options above ? */
258 transl_load_xlats();
259
260 strupdate(&illegal_char, getlloptstr("IllegalChar", 0));
261
262 nodechk_enable(!!getlloptint("nodecheck", 0));
263 }
264 /*==================================================
265 * update_db_options --
266 * check database-specific options for updates
267 *================================================*/
268 static void
update_db_options(void)269 update_db_options (void)
270 {
271 TABLE opttab = create_table_str();
272 CNSTRING str=0;
273 get_db_options(opttab);
274
275 str = valueof_str(opttab, "codeset");
276 if (!str || !str[0]) {
277 /*
278 no specified database/internal codeset
279 so default to user's default codeset, which
280 should be from locale
281 */
282 str = get_defcodeset();
283 }
284 if (!int_codeset)
285 strupdate(&int_codeset, "");
286 if (!eqstr_ex(int_codeset, str)) {
287 /* database encoding changed */
288 strupdate(&int_codeset, str);
289
290 /* Here is where the global uu8 variable is set
291 This is a flag if the internal (database) encoding is UTF-8 */
292 uu8 = is_codeset_utf8(int_codeset);
293
294 /* always translate to internal codeset */
295 set_gettext_codeset(PACKAGE, int_codeset);
296 /* need to reload all predefined codeset conversions */
297 transl_load_xlats();
298 if (uu8) {
299 charprops_load_utf8();
300 } else {
301 charprops_load(int_codeset);
302 }
303 }
304
305 destroy_table(opttab);
306 }
307 /*==================================================
308 * pre_codesets_hook -- code to run just before initializing codesets
309 * For MS-Windows user config of console codepages
310 *================================================*/
311 static void
pre_codesets_hook(void)312 pre_codesets_hook (void)
313 {
314 #ifdef WIN32
315 /* On MS-Windows, attempt to set any requested non-standard codepage */
316 /* Do this now, before init_codesets below */
317 INT i = getlloptint("ConsoleCodepage", 0);
318 if (i) {
319 w_set_oemout_codepage(i);
320 w_set_oemin_codepage(i);
321 }
322 #endif
323 }
324 /*==================================================
325 * post_codesets_hook -- code to run just after initializing codesets
326 * For Windows, link dynamically to gettext & iconv if available
327 *================================================*/
328 static void
post_codesets_hook(void)329 post_codesets_hook (void)
330 {
331 init_win32_gettext_shim();
332 init_win32_iconv_shim(getlloptstr("iconv.path",""));
333 }
334 /*==================================================
335 * load_configs -- Load global config file(s)
336 * returns FALSE if error, with message in pmsg
337 *================================================*/
338 static BOOLEAN
load_configs(STRING configfile,STRING * pmsg)339 load_configs (STRING configfile, STRING * pmsg)
340 {
341 INT rtn=0;
342 STRING str=0;
343 char cfg_name[MAXPATHLEN];
344
345 /* TODO: Should read a system-wide config file */
346
347 if (!configfile)
348 configfile = getenv("LLCONFIGFILE");
349
350 *pmsg = NULL;
351
352
353 if (configfile && configfile[0]) {
354
355 rtn = load_global_options(configfile, pmsg);
356 if (rtn == -1) return FALSE;
357
358 } else {
359
360 /* No config file specified, so load config_file(s) from
361 the standard places */
362
363 /* look for global config file */
364 llstrncpy(cfg_name, global_conf_path, sizeof(cfg_name), 0);
365 llstrapps(cfg_name, sizeof(cfg_name), 0, "/lifelines.conf");
366 rtn = load_global_options(cfg_name, pmsg);
367 if (rtn == -1) return FALSE;
368
369 /* look for one in user's home directory */
370 /* TODO: Shouldn't Win32 use getenv("USERPROFILE") ? */
371 llstrncpy(cfg_name, getenv("HOME") , sizeof(cfg_name), 0);
372 /*llstrappc(cfg_name, sizeof(cfg_name), '/');*/
373 llstrapps(cfg_name, sizeof(cfg_name), 0, "/" LINES_CONFIG_FILE);
374
375 rtn = load_global_options(cfg_name, pmsg);
376 if (rtn == -1) return FALSE;
377
378 rtn = load_global_options(LINES_CONFIG_FILE, pmsg);
379 if (rtn == -1) return FALSE;
380 }
381
382 /* allow chaining to one more config file
383 * if one was defined for the database
384 */
385 str = getlloptstr("LLCONFIGFILE", NULL);
386 if (str && str[0]) {
387 rtn = load_global_options(str, pmsg);
388 if (rtn == -1) return FALSE;
389 }
390 return TRUE;
391 }
392 /*==================================================
393 * check_installation_path -- Figure out installed path
394 *================================================*/
395 static void
check_installation_path(void)396 check_installation_path (void)
397 {
398 INT maxlen = sizeof(global_conf_path)-1;
399 #ifdef WIN32
400 /* TODO: Installation should set value in registry
401 and we should read it here */
402 strncpy(global_conf_path, "C:\\Program Files\\lifelines", maxlen);
403 #else
404 /* SYS_CONF_DIR was passed to make in src/gedlib/Makefile.am */
405 strncpy(global_conf_path, SYS_CONF_DIR, maxlen);
406 #endif
407 global_conf_path[maxlen] = 0;
408 }
409