/*================================ * load_gedcom -- have user select gedcom file & import it *==============================*/ void load_gedcom (BOOLEAN picklist) { FILE *fp=NULL; struct tag_import_feedback ifeed; STRING srcdir=NULL; STRING fullpath=0; time_t begin = time(NULL); time_t beginui = get_uitime(); srcdir = getlloptstr("InputPath", "."); if (!ask_for_gedcom(LLREADTEXT, _(qSwhatgedc), 0, &fullpath, srcdir, ".ged", picklist) || !(fp = fopen(fullpath, LLREADBINARY))) { strfree(&fullpath); return; } /* Note: we read the file in binary mode, so ftell & fseek will work correctly. Microsoft's ftell/fseek do not work correctly if the file has simple unix (\n) line terminations! -- Perry, 2003-02-11 */ memset(&ifeed, 0, sizeof(ifeed)); ifeed.validating_fnc = import_validating; ifeed.validated_rec_fnc = import_validated_rec; ifeed.beginning_import_fnc = import_beginning_import; ifeed.error_invalid_fnc = import_error_invalid; ifeed.error_readonly_fnc = import_readonly; ifeed.adding_unused_keys_fnc = import_adding_unused_keys; ifeed.added_rec_fnc = import_added_rec; ifeed.validation_error_fnc = import_validation_error; ifeed.validation_warning_fnc = import_validation_warning; import_from_gedcom_file(&ifeed, fp); fclose(fp); strfree(&fullpath); if (1) { INT duration = time(NULL) - begin; INT uitime = get_uitime() - beginui; ZSTR zt1=approx_time(duration-uitime), zt2=approx_time(uitime); /* TRANSLATORS: how long Import ran, and how much of that was UI delay */ ZSTR zout = zs_newf(_("Import time %s (ui %s)\n") , zs_str(zt1), zs_str(zt2)); wfield(8,0, zs_str(zout)); zs_free(&zt1); zs_free(&zt2); zs_free(&zout); } /* position cursor further down stdout so check_stdout doesn't overwrite our messages from above */ wpos(15,0); }
/*============================ * mvcwaddnstr -- convert to GUI codeset & call mvwaddstr with length limit * Created: 2002/12/13 (Perry Rapp) *==========================*/ int mvccwaddnstr (WINDOW *wp, int y, int x, const char *cp, int n) { ZSTR zstr = zs_news(cp); int rtn=0; int_to_disp(zstr); if (zs_len(zstr) < (unsigned int)n) { rtn = mvwaddstr(wp, y, x, zs_str(zstr)); } else { if (output_width(zstr) > (size_t)n) { STRING str = zs_str(zstr); /* We need to do length truncation correctly for UTF-8 output */ /* #1) We need to not break UTF-8 multibytes */ INT width=0; STRING prev = find_prev_char(&str[n-1], &width, str, gui8); width += (prev - str); zs_chop(zstr, width); /* #2) We should account for zero-width characters, eg, use wcwidth */ /* Unfortunately, lifelines doesn't yet use wcwidth or config test it */ /* TODO: config test for wcswidth and substitute Markus Kuhn's http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c */ } rtn = mvwaddnstr(wp, y, x, zs_str(zstr), n); } zs_free(&zstr); return rtn; }
static void zram_free_page(struct zram *zram, size_t index) { struct zram_meta *meta = zram->meta; unsigned long handle = meta->table[index].handle; u16 size = meta->table[index].size; if (unlikely(!handle)) { /* * No memory is allocated for zero filled pages. * Simply clear zero page flag. */ if (zram_test_flag(meta, index, ZRAM_ZERO)) { zram_clear_flag(meta, index, ZRAM_ZERO); zram->stats.pages_zero--; } return; } if (unlikely(size > max_zpage_size)) zram->stats.bad_compress--; zs_free(meta->mem_pool, handle); if (size <= PAGE_SIZE / 2) zram->stats.good_compress--; zram_stat64_sub(zram, &zram->stats.compr_size, meta->table[index].size); zram->stats.pages_stored--; meta->table[index].handle = 0; meta->table[index].size = 0; }
/*==================================================== * format_dbgsymtab_val -- Display one entry in symbol table * This is part of the report language debugger * key: [IN] name of current symbol * val: [IN] value of current symbol * sdata: [I/O] structure holding array of values & strings to display *==================================================*/ static void format_dbgsymtab_val (STRING key, PVALUE val, struct dbgsymtab_s * sdata) { ZSTR zval = describe_pvalue(val); STRING valstr = zs_str(zval); format_dbgsymtab_str(key, valstr, val, sdata); zs_free(&zval); }
/*============================ * mvcwaddstr -- convert to GUI codeset & call mvwaddstr * Created: 2002/12/03 (Perry Rapp) * TODO: Convert all calls of this to call mvccuwaddstr (or mvccwaddnstr) ! *==========================*/ int mvccwaddstr (WINDOW *wp, int y, int x, const char *cp) { ZSTR zstr = zs_news(cp); int rtn; int_to_disp(zstr); rtn = mvwaddstr(wp, y, x, zs_str(zstr)); zs_free(&zstr); return rtn; }
/*============================ * vccprintf -- vprintf with codeset convert from internal to GUI * Created: 2002/12/03 (Perry Rapp) *==========================*/ int vccprintf (const char *fmt, va_list args) { int rtn; ZSTR zstr = zs_newvf(fmt, args); int_to_disp(zstr); rtn = printf(zs_str(zstr)); zs_free(&zstr); return rtn; }
/*============================ * vccwprintw -- vwprintw with codeset convert from internal to GUI * Created: 2002/12/03 (Perry Rapp) *==========================*/ int vccwprintw (WINDOW *wp, const char *fmt, va_list args) { ZSTR zstr = zs_newvf(fmt, args); int rtn; int_to_disp(zstr); rtn = waddstr(wp, zs_str(zstr)); zs_free(&zstr); return rtn; }
/*=============================================+ * vprog_error -- Report a run time program error * node: current parsed node * fmt, args: printf style message * ...: printf style varargs * Prints error to the stdout-style curses window * and to the report log (if one was specified in config file) * Always includes line number of node, if available * Only includes file name if not same as previous error * Returns static buffer with one-line description *============================================*/ static STRING vprog_error (PNODE node, STRING fmt, va_list args) { INT num; STRING rptfile; ZSTR zstr=zs_newn(256); static char msgbuff[100]; if (rpt_cancelled) return _("Report cancelled"); rptfile = getlloptstr("ReportLog", NULL); if (node) { STRING fname = irptinfo(node)->fullpath; INT lineno = iline(node)+1; /* Display filename if not same as last error */ if (!eqstr(vprog_prevfile, fname)) { llstrsets(vprog_prevfile, sizeof(vprog_prevfile), uu8, fname); zs_apps(zstr, _("Report file: ")); zs_apps(zstr, fname); zs_appc(zstr, '\n'); vprog_prevline = -1; /* force line number display */ } /* Display line number if not same as last error */ if (vprog_prevline != lineno) { vprog_prevline = lineno; if (progparsing) zs_appf(zstr, _("Parsing Error at line %d: "), lineno); else zs_appf(zstr, _("Runtime Error at line %d: "), lineno); } } else { zs_apps(zstr, _("Aborting: ")); } zs_appvf(zstr, fmt, args); llwprintf("\n"); llwprintf(zs_str(zstr)); ++progerror; /* if user specified a report error log (in config file) */ if (rptfile && rptfile[0]) { FILE * fp = fopen(rptfile, LLAPPENDTEXT); if (fp) { if (progerror == 1) { LLDATE creation; get_current_lldate(&creation); fprintf(fp, "\n%s\n", creation.datestr); } fprintf(fp, "%s", zs_str(zstr)); fprintf(fp, "\n"); fclose(fp); } } if ((num = getlloptint("PerErrorDelay", 0))) sleep(num); zs_free(&zstr); return msgbuff; }
/*==================================================== * format_dbgsymtab_val -- Display one entry in symbol table * This is part of the report language debugger * key: [IN] name of current symbol * valstr: [IN] string to display for current value * val: [IN] value of current symbol (or NULL if none applicable) * sdata: [I/O] structure holding array of values & strings to display *==================================================*/ static void format_dbgsymtab_str (STRING key, STRING valstr, PVALUE val, struct dbgsymtab_s * sdata) { ZSTR zline = zs_newn(80); ASSERT(sdata->current < sdata->count); zs_setf(zline, "%s: %s", key, valstr); sdata->displays[sdata->current] = strsave(zs_str(zline)); sdata->values[sdata->current] = val; ++sdata->current; zs_free(&zline); }
/*========================================== * do_format_date -- Do general date formatting * str - raw string containing a date * dfmt; [IN] day format code (see format_day function below) * mfmt: [IN] month format code (see format_month function below) * yfmt: [IN] year format code (see format_year function below) * sfmt: [IN] combining code (see format_ymd function below) * efmt: [IN] era format (see format_eratime function below) * cmplx - 0 is year only, 1 is complex, including * date modifiers, ranges, and/or double-dating * Returns static buffer *========================================*/ STRING do_format_date (STRING str, INT dfmt, INT mfmt, INT yfmt, INT sfmt, INT efmt, INT cmplx) { /* TODO: get rid of this function, and have callers call do_zformat_date */ ZSTR zstr = do_zformat_date(str, dfmt, mfmt, yfmt, sfmt, efmt, cmplx); static char buffer[100]; llstrsets(buffer, sizeof(buffer), uu8, zs_str(zstr)); zs_free(&zstr); return buffer; }
/*=================================================== * translate_string -- Translate string via XLAT * ttm: [IN] tranmapping * in: [IN] in string * out: [OUT] string * maxlen: [OUT] max len of out string * Output string is limited to max length via use of * add_char & add_string. *=================================================*/ void translate_string (XLAT ttm, CNSTRING in, STRING out, INT maxlen) { ZSTR zstr=0; if (!in || !in[0]) { out[0] = 0; return; } zstr = translate_string_to_zstring(ttm, in); llstrsets(out, maxlen, uu8, zs_str(zstr)); zs_free(&zstr); }
/*============================ * wgetccnstr -- wgetnstr with codeset convert from GUI to internal * Created: 2002/12/03 (Perry Rapp) *==========================*/ int wgetccnstr (WINDOW *wp, char *cp, int n) { ZSTR zstr=0; /* TODO: Need Win32-specific code here to handle Unicode input on NT family */ int rtn = wgetnstr(wp, (char *)cp, n); zstr = zs_news(cp); disp_to_int(zstr); llstrsets(cp, n, uu8, zs_str(zstr)); zs_free(&zstr); return rtn; }
/*========================================================== * transl_get_description -- Fetch description of a translation * eg, "3 steps with iconv(UTF-8, CP1252)" * Created: 2002/12/13 (Perry Rapp) *========================================================*/ ZSTR transl_get_description (XLAT xlat) { ZSTR zstr = xlat_get_description(xlat); INT index = xl_get_uparam(xlat)-1; struct legacytt_s * legtt = (index>=0 ? &legacytts[index] : NULL); if (legtt && legtt->tt) { ZSTR zdesc = get_trantable_desc(legtt->tt); /* TRANSLATORS: db internal translation table note for tt menu */ zs_appf(zstr, _(" (dbint tt: %s)"), zs_str(zdesc)); zs_free(&zdesc); } return zstr; }
/*======================================================= * annotate_node -- Alter a node by * expanding refns (eg, "@S25@" to "<1850.Census>") * annotating pointers (eg, "@I1@" to "@I1@ {{ John/SMITH }}") * Used during editing *=====================================================*/ static void annotate_node (NODE node, BOOLEAN expand_refns, BOOLEAN annotate_pointers, RFMT rfmt) { STRING key=0; RECORD rec=0; key = value_to_xref(nval(node)); if (!key) return; rec = key_possible_to_record(key, *key); if (!rec) return; if (expand_refns) { NODE refn = REFN(nztop(rec)); char buffer[60]; /* if there is a REFN, and it fits in our buffer, and it doesn't have any (confusing) > in it */ if (refn && nval(refn) && !strchr(nval(refn), '>') && strlen(nval(refn))<=sizeof(buffer)-3) { /* then replace, eg, @S25@, with, eg, <1850.Census> */ buffer[0]=0; strcpy(buffer, "<"); strcat(buffer, nval(refn)); strcat(buffer, ">"); stdfree(nval(node)); nval(node) = strsave(buffer); } } if (annotate_pointers) { STRING str = generic_to_list_string(nztop(rec), key, 60, ", ", rfmt, FALSE); ZSTR zstr = zs_news(nval(node)); zs_apps(zstr, " {{"); zs_apps(zstr, str); zs_apps(zstr, " }}"); stdfree(nval(node)); nval(node) = strsave(zs_str(zstr)); zs_free(&zstr); } }
/*=============================================+ * prog_var_error_zstr -- Report a run time program error * node: [IN] current parse node * stab: [IN] current symbol table (lexical scope) * arg: [IN] if non-null, parse node of troublesome argument * val: [IN] if non-null, PVALUE of troublesome argument * zstr: [IN] message * * Inline debugger is implemented here * See vprog_error * Created: 2002/02/17, Perry Rapp *============================================*/ static void prog_var_error_zstr (PNODE node, SYMTAB stab, PNODE arg, PVALUE val, ZSTR zstr) { STRING choices[5]; INT rtn=0; SYMTAB curstab = stab; /* currently displayed symbol table */ INT nlevels=0; /* number frames on callstack */ INT curlevel=0; /* 0 is lowest */ ASSERT(zstr); if (val) { ZSTR zval = describe_pvalue(val); zs_appf(zstr, " (value: %s)", zs_str(zval)); } else if (arg) { INT max=40 + zs_len(zstr); /* not too much argument description */ /* arg isn't evaluated, but describe will at least give its type */ zs_apps(zstr, " (arg: "); describe_pnode(arg, zstr, max); zs_apps(zstr, ")"); } prog_error(node, zs_str(zstr)); zs_free(&zstr); if (dbg_mode != -99 && dbg_mode != 3) { INT ch = 0; while (!(ch=='d' || ch=='q')) ch = rptui_prompt_stdout(_("Enter d for debugger, q to quit")); if (ch == 'q') dbg_mode = -99; } /* call stack size & location */ nlevels = count_symtab_ancestors(stab) + 1; curlevel = 0; /* report debugger loop */ while (dbg_mode != -99) { ZSTR zstr=zs_new(); INT n=0; /* 0: display local variable(s) */ n = (curstab->tab ? get_table_count(curstab->tab) : 0); zs_setf(zstr, _pl("Display local (%d var)", "Display locals (%d vars)", n), n); zs_appf(zstr, " [%s]", curstab->title); choices[0] = strsave(zs_str(zstr)); /* 1: display global variables */ n = (globtab->tab ? get_table_count(globtab->tab) : 0); zs_setf(zstr, _pl("Display global (%d var)", "Display globals (%d vars)", n), n); choices[1] = strsave(zs_str(zstr)); /* 2: up call stack */ n = nlevels - curlevel - 1; zs_setf(zstr, _pl("Call stack has %d higher level", "Call stack has %d higher levels", n), n); zs_apps(zstr, ". "); if (n > 0) { zs_apps(zstr, _(" Go up one level")); zs_appf(zstr, "(%s)", curstab->parent->title); } choices[2] = strsave(zs_str(zstr)); /* 3: down call stack */ n = curlevel; zs_setf(zstr, _pl("Call stack has %d lower level", "Call stack has %d lower levels", n), n); zs_apps(zstr, ". "); if (n > 0) { CNSTRING title = get_symtab_ancestor(stab, n-1)->title; zs_apps(zstr, _(" Go down one level")); zs_appf(zstr, "(%s)", title); } choices[3] = strsave(zs_str(zstr)); /* quit */ choices[4] = strsave(_("Quit debugger")); dbgloop: rtn = rptui_choose_from_array(_("Report debugger"), ARRSIZE(choices), choices); if (rtn == 4 || rtn == -1) { dbg_mode = -99; } else if (rtn == 0) { disp_symtab(_("Local variables"), curstab); goto dbgloop; } else if (rtn == 1) { disp_symtab(_("Global variables"), globtab); goto dbgloop; } else if (rtn == 2) { if (curlevel+1 < nlevels) { curstab = curstab->parent; ++curlevel; ASSERT(curstab); } } else if (rtn == 3) { if (curlevel > 0) { curstab = get_symtab_ancestor(stab, curlevel-1); --curlevel; ASSERT(curstab); } } zs_free(&zstr); free_array_strings(ARRSIZE(choices), choices); } }
int main (int argc, char *argv[]) { ZIPstream *zstream = NULL; ZIPentry *zentry = NULL; uint64_t buffersize = 0; ssize_t writestatus; time_t now; int method = ZS_DEFLATE; int fd; int idx; if ( argc < 2 ) { fprintf (stderr, "zipexample: write a ZIP archive to stdout from memory buffer\n"); fprintf (stderr, "Usage: zipexample [-S] [-D] > output.zip\n"); fprintf (stderr, " -S Store archive entries\n"); fprintf (stderr, " -D Deflate archive entries\n"); fprintf (stderr, "\n"); fprintf (stderr, "One of -S or -D is required, make sure to redirect stdout."); fprintf (stderr, "\n"); return 0; } /* Loop through input arguments and process options */ for ( idx=1; idx < argc; idx++ ) { if ( ! strncmp (argv[idx], "-S", 2) ) { method = ZS_STORE; fprintf (stderr, "Storing archive entries, no compression\n"); continue; } else if ( ! strncmp (argv[idx], "-D", 2) ) { method = ZS_DEFLATE; fprintf (stderr, "Deflating archive entries, no compression\n"); continue; } } /* Set output stream to stdout */ fd = fileno (stdout); /* Initialize ZIP container, skip options */ if ( (zstream = zs_init (fd, NULL)) == NULL ) { fprintf (stderr, "Error initializing ZIP archive\n"); return 1; } buffersize = strlen (buffer); now = time(NULL); /* Write entry containing buffer contents */ zentry = zs_writeentry (zstream, (unsigned char *)buffer, buffersize, "Leon.txt", now, method, &writestatus); if ( zentry == NULL ) { fprintf (stderr, "Error adding entry to output ZIP (writestatus: %lld)\n", (long long int) writestatus); return 1; } fprintf (stderr, "Added %s: %lld -> %lld (%.1f%%)\n", zentry->Name, (long long int) zentry->UncompressedSize, (long long int) zentry->CompressedSize, (100.0 * zentry->CompressedSize / zentry->UncompressedSize)); /* Write another entry containing the same buffer contents */ zentry = zs_writeentry (zstream, (unsigned char *)buffer, buffersize, "Deckard.txt", now, method, &writestatus); if ( zentry == NULL ) { fprintf (stderr, "Error adding entry to output ZIP (writestatus: %lld)\n", (long long int) writestatus); return 1; } fprintf (stderr, "Added %s: %lld -> %lld (%.1f%%)\n", zentry->Name, (long long int) zentry->UncompressedSize, (long long int) zentry->CompressedSize, (100.0 * zentry->CompressedSize / zentry->UncompressedSize)); /* Many more files/entries can be added to the ZIP archive ... */ /* Finish ZIP archive */ if ( zs_finish (zstream, &writestatus) ) { fprintf (stderr, "Error finishing ZIP archive (writestatus: %lld)\n", (long long int) writestatus); return 1; } fprintf (stderr, "Success, created archive with %d entries\n", zstream->EntryCount); /* Cleanup */ zs_free (zstream); return 0; }
/*========================================+ * poutput -- Output string in current mode *=======================================*/ void poutput (STRING str, BOOLEAN *eflg) { STRING p; ZSTR zstr = 0; INT c, len; XLAT ttmr = transl_get_predefined_xlat(MINRP); if (!str || (len = strlen(str)) <= 0) return; zstr = translate_string_to_zstring(ttmr, str); str = zs_str(zstr); if ((len = strlen(str)) <= 0) goto exit_poutput; if (!Poutfp) { if (!request_file(eflg)) goto exit_poutput; setbuf(Poutfp, NULL); } switch (outputmode) { case UNBUFFERED: fwrite(str, len, 1, Poutfp); adjust_cols(str); goto exit_poutput; case BUFFERED: if (len >= 1024) { fwrite(linebuffer, linebuflen, 1, Poutfp); fwrite(str, len, 1, Poutfp); linebuflen = 0; bufptr = (STRING)linebuffer; adjust_cols(str); goto exit_poutput; } if (len + linebuflen >= 1024) { fwrite(linebuffer, linebuflen, 1, Poutfp); linebuflen = 0; bufptr = (STRING)linebuffer; } linebuflen += len; while ((c = *bufptr++ = *str++)) { if (c == '\n') curcol = 1; else curcol++; } --bufptr; goto exit_poutput; case PAGEMODE: p = pagebuffer + (currow - 1)*__cols + curcol - 1; while ((c = *str++)) { if (c == '\n') { curcol = 1; currow++; p = pagebuffer + (currow - 1)*__cols; } else { if (curcol <= __cols && currow <= __rows) *p++ = c; curcol++; } } goto exit_poutput; default: FATAL(); } exit_poutput: zs_free(&zstr); }
/*========================================== * do_zformat_date * See description above for do_format_date * (Except this returns alloc'd ZSTR *========================================*/ static ZSTR do_zformat_date (STRING str, INT dfmt, INT mfmt, INT yfmt, INT sfmt, INT efmt, INT cmplx) { STRING smo, syr; static char daystr[3]; GDATEVAL gdv = 0; ZSTR zstr=zs_newn(40); if (!str) return zstr; initialize_if_needed(); if (sfmt==12) { /* This is what used to be the shrt flag */ zs_free(&zstr); return zshorten_date(str); } if (sfmt==14) { zs_sets(zstr, str); return zstr; } if (!cmplx) { /* simple */ gdv = extract_date(str); if (gdv->valid == GDV_V_PHRASE) { /* GEDCOM date phrases (parenthesized) shown "as is" */ return zs_news(gdv->text); } format_day(gdv->date1.day, dfmt, daystr); smo = format_month(gdv->date1.calendar, gdv->date1.month, mfmt); syr = format_year(gdv->date1.year, yfmt); format_ymd(zstr, syr, smo, daystr, sfmt); format_eratime(zstr, gdv->date1.eratime, efmt); if (gdv->date1.calendar) { format_cal(zstr, gdv->date1.calendar); } free_gdateval(gdv); return zstr; } else { ZSTR zstr2 = zs_newn(40); ZSTR zstr3=0; /* complex (include modifier words) */ gdv = extract_date(str); if (gdv->valid == GDV_V_PHRASE) { /* GEDCOM date phrases (parenthesized) shown "as is" */ return zs_news(gdv->text); } format_day(gdv->date1.day, dfmt, daystr); smo = format_month(gdv->date1.calendar, gdv->date1.month, mfmt); syr = (gdv->date1.year.str ? gdv->date1.year.str : format_year(gdv->date1.year, yfmt)); format_ymd(zstr, syr, smo, daystr, sfmt); format_eratime(zstr, gdv->date1.eratime, efmt); if (gdv->date1.calendar) { format_cal(zstr, gdv->date1.calendar); } if (gdateval_isdual(gdv)) { /* build 2nd date string into ymd2 */ format_day(gdv->date2.day, dfmt, daystr); smo = format_month(gdv->date2.calendar, gdv->date2.month, mfmt); syr = (gdv->date2.year.str ? gdv->date2.year.str : format_year(gdv->date2.year, yfmt)); format_ymd(zstr2, syr, smo, daystr, sfmt); format_eratime(zstr2, gdv->date2.eratime, efmt); if (gdv->date2.calendar) { format_cal(zstr2, gdv->date2.calendar); } } zstr3 = format_complex(gdv, cmplx, zs_str(zstr), zs_str(zstr2)); zs_free(&zstr); zs_free(&zstr2); free_gdateval(gdv); return zstr3; } }
/*================================================= * do_import -- Read GEDCOM file to database * ifeed: [IN] output methods * fp: [I/O] GEDCOM file whence to load data *===============================================*/ static BOOLEAN do_import (IMPORT_FEEDBACK ifeed, FILE *fp) { NODE node, conv; XLAT ttm = 0; STRING msg; BOOLEAN emp; INT nindi = 0, nfam = 0, neven = 0; INT nsour = 0, nothr = 0, type, num = 0; INT totkeys = 0, totused = 0; char msgbuf[80]; BOOLEAN succeeded=FALSE; STRING str,unistr=0; ZSTR zerr=0; TABLE metadatatab = create_table_str(); STRING gdcodeset=0; INT warnings=0; /* start by assuming default */ strupdate(&gdcodeset, gedcom_codeset_in); /* rptui_init(); *//* clear ui time counter */ /* Open and validate GEDCOM file */ if ((unistr=check_file_for_unicode(fp)) && !eqstr(unistr, "UTF-8")) { msg_error(_(qSunsupuniv), unistr); goto end_import; } if (eqstr_ex(unistr, "UTF-8")) { strupdate(&gdcodeset, "UTF-8"); } if (!scan_header(fp, metadatatab, &zerr)) { msg_error(zs_str(zerr)); goto end_import; } if ((str = valueof_str(metadatatab, "GEDC.FORM"))!= NULL) { if (!eqstr(str, "LINEAGE-LINKED")) { if (!ask_yes_or_no_msg( _("This is not a lineage linked GEDCOM file.") , _("Proceed anyway?") )) goto end_import; } } if (!unistr && (str = valueof_str(metadatatab, "CHAR"))!= NULL) { /* if no BOM, use file's declared encoding if present */ strupdate(&gdcodeset, str); } /* TODO: Push this codeset question down to after the validation, where we can know if the incoming file happened to really be all ASCII */ if (!int_codeset[0]) { /* TODO: ask if user would like to adopt codeset of incoming file, if we found it */ if (!ask_yes_or_no_msg( _("No current internal codeset, so no codeset conversion can be done") , _("Proceed without codeset conversion?") )) goto end_import; } /* Warn if lossy code conversion likely */ if (gdcodeset[0] && int_codeset[0]) { if (is_lossy_conversion(gdcodeset, int_codeset)) { ZSTR zstr=zs_new(); zs_setf(zstr, _("Lossy codeset conversion (from <%s> to <%s>) likely") , gdcodeset, int_codeset); if (!ask_yes_or_no_msg( zs_str(zstr) , _("Proceed anyway?") )) goto end_import; } } /* validate */ if (ifeed && ifeed->validating_fnc) (*ifeed->validating_fnc)(); if (!validate_gedcom(ifeed, fp)) { if (ifeed && ifeed->error_invalid_fnc) (*ifeed->error_invalid_fnc)(_(qSgdnadd)); goto end_import; } warnings = validate_get_warning_count(); if (warnings) { ZSTR zstr=zs_new(); zs_setf(zstr, _pl("%d warning during import", "%d warnings during import", warnings), warnings); if (!ask_yes_or_no_msg(zs_str(zstr), _(qSproceed))) { goto end_import; } } if (gdcodeset[0] && int_codeset[0]) { retry_input_codeset: ttm = transl_get_xlat(gdcodeset, int_codeset); if (!transl_is_xlat_valid(ttm)) { ZSTR zstr=zs_new(); char csname[64]; BOOLEAN b; transl_release_xlat(ttm); ttm = 0; zs_setf(zstr, _("Cannot convert codeset (from <%s> to <%s>)") , gdcodeset, int_codeset); b = ask_for_string(zs_str(zstr) , _("Enter codeset to assume (* for none)") , csname, sizeof(csname)) && csname[0]; zs_free(&zstr); if (!b) goto end_import; if (!eqstr(csname, "*")) { strupdate(&gdcodeset, csname); goto retry_input_codeset; } } } if((num_indis() > 0) || (num_fams() > 0) || (num_sours() > 0) || (num_evens() > 0) || (num_othrs() > 0)) gd_reuse = FALSE; else if((gd_reuse = check_stdkeys())) { totused = gd_itot + gd_ftot + gd_stot + gd_etot + gd_xtot; totkeys = gd_imax + gd_fmax + gd_smax + gd_emax + gd_xmax; if((totkeys-totused) > 0) { INT delkeys = totkeys-totused; snprintf(msgbuf, sizeof(msgbuf) , _pl("Using original keys, %d deleted record will be in the database." , "Using original keys, %d deleted records will be in the database." , delkeys) , delkeys ); } else strcpy(msgbuf, " "); gd_reuse = ask_yes_or_no_msg(msgbuf, _(qScfoldk)); /* TODO: why were these here ? touchwin(uiw_win(stdout_win)); wrefresh(uiw_win(stdout_win)); */ } /* start loading the file */ rewind(fp); /* test for read-only database here */ if(readonly) { if (ifeed && ifeed->error_readonly_fnc) (*ifeed->error_readonly_fnc)(); goto end_import; } /* tell user we are beginning real part of import */ if (ifeed && ifeed->beginning_import_fnc) { if(gd_reuse) (*ifeed->beginning_import_fnc)(_(qSdboldk)); else (*ifeed->beginning_import_fnc)(_(qSdbnewk)); } /* Add records to database */ node = convert_first_fp_to_node(fp, FALSE, ttm, &msg, &emp); while (node) { if (!(conv = node_to_node(node, &type))) { free_nodes(node); node = next_fp_to_node(fp, FALSE, ttm, &msg, &emp); continue; } switch (type) { case INDI_REC: num = ++nindi; break; case FAM_REC: num = ++nfam; break; case EVEN_REC: num = ++neven; break; case SOUR_REC: num = ++nsour; break; case OTHR_REC: num = ++nothr; break; default: FATAL(); } restore_record(conv, type, num); if (ifeed && ifeed->added_rec_fnc) ifeed->added_rec_fnc(nxref(conv)[1], ntag(conv), num); free_nodes(node); node = next_fp_to_node(fp, FALSE, ttm, &msg, &emp); } if (msg) { msg_error(msg); } if(gd_reuse && ((totkeys - totused) > 0)) { if (ifeed && ifeed->adding_unused_keys_fnc) (*ifeed->adding_unused_keys_fnc)(); addmissingkeys(INDI_REC); addmissingkeys(FAM_REC); addmissingkeys(EVEN_REC); addmissingkeys(SOUR_REC); addmissingkeys(OTHR_REC); } succeeded = TRUE; end_import: validate_end_import(); zs_free(&zerr); destroy_table(metadatatab); strfree(&gdcodeset); return succeeded; }