From 062241ade5091964826cf05cc4026f4ae9ba6164 Mon Sep 17 00:00:00 2001 From: guy Date: Wed, 16 Dec 2015 15:54:37 +0000 Subject: [PATCH] Ricorretto cambio ditta che non permetteva conversione git-svn-id: svn://10.65.10.50/branches/R_10_00@23153 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- include/array.h | 1 + include/assoc.cpp | 22 + include/controls.cpp | 19 +- include/currency.cpp | 13 +- include/isam.cpp | 8694 +++++++++++++++++++++--------------------- include/prefix.cpp | 33 +- include/prefix.h | 15 +- include/relapp.cpp | 2 +- include/validate.cpp | 6 +- 9 files changed, 4425 insertions(+), 4380 deletions(-) diff --git a/include/array.h b/include/array.h index 069e0fbb5..b07881b14 100755 --- a/include/array.h +++ b/include/array.h @@ -1,3 +1,4 @@ +#pragma once #ifndef __ARRAY_H #define __ARRAY_H diff --git a/include/assoc.cpp b/include/assoc.cpp index 16c1a86f8..43757d7a3 100755 --- a/include/assoc.cpp +++ b/include/assoc.cpp @@ -189,6 +189,11 @@ bool TAssoc_array::add( delete o->_obj; o->_obj = obj; } + else + { + NFCHECK("deleting duplicate hash object"); + delete obj; + } return true; } o->_obj = obj; @@ -197,12 +202,29 @@ bool TAssoc_array::add( bool TAssoc_array::add(const char* key, const TObject& obj, bool force) { + /* // Non inserire l'Hash_object se non lo trovi (ci pensa la add sotto) bool isnew = false; _lookup(key,isnew,false); if (!isnew && !force) return true; return add(key,obj.dup(),force); + */ + bool isnew = false; + THash_object* o = _lookup(key, isnew, true); + if (!isnew) + { + if (force) + { + if (o->_obj != NULL) + delete o->_obj; + o->_obj = obj.dup(); + } + return true; + } + o->_obj = obj.dup(); + return false; + } // @doc EXTERNAL diff --git a/include/controls.cpp b/include/controls.cpp index bf222f3c5..f2787f885 100755 --- a/include/controls.cpp +++ b/include/controls.cpp @@ -1366,10 +1366,7 @@ TGroupbox_control::TGroupbox_control(WINDOW win, short cid, { XI_OBJ* itf = get_interface(win); XI_RCT rct = coord2rct(itf, left, top, width, height); - - //rct.top = _obj->v.text->xi_rct.bottom - 2; rct.top += XI_FU_MULTIPLE; - rct.bottom -= XI_FU_MULTIPLE / 2; XI_OBJ_DEF* def = xi_add_rect_def(NULL, cid, &rct, XI_ATR_VISIBLE, 0, 0); // Ignore colors @@ -1391,13 +1388,15 @@ TGroupbox_control::TGroupbox_control(WINDOW win, short cid, _rct = xi_create(itf, def); CHECKD(_rct, "Can't create Groupbox_control ", cid); - XI_RCT& rt = _obj->v.text->rct; - //rt.top--; rt.bottom--; - const int txt_height = rt.bottom-rt.top; - rt.bottom = _rct->v.rect->rct.top - 1; - rt.top = rt.bottom - txt_height + 2; - rt.left = _rct->v.rect->rct.left; - rt.right = _rct->v.rect->rct.right; + XI_RCT& rt = _obj->v.text->rct; // Rettangolo testo + XI_RCT& rr = _rct->v.rect->rct; // Rettangolo box + rr.top -= 2; + + //const int txt_height = rt.bottom-rt.top; + rt.bottom = rr.top - 1; + //rt.top = rt.bottom - txt_height + 2; + rt.left = rr.left; + rt.right = rr.right; xi_dequeue(); xi_tree_free(def); diff --git a/include/currency.cpp b/include/currency.cpp index aa1216b7d..0f460503c 100755 --- a/include/currency.cpp +++ b/include/currency.cpp @@ -132,12 +132,15 @@ void TDowJones::test_cache() } if (_euro_val.empty()) // Si son dimenticati dell'EURO? - { - TExchangeData* euro = new TExchangeData; - euro->_chg = UNO; euro->_dec = euro->_dec_prices = 2; - euro->_is_euro = true; + { _euro_val = "EUR"; - _cache.add(_euro_val, euro); + if (!_cache.is_key(_euro_val)) + { + TExchangeData* euro = new TExchangeData; + euro->_chg = UNO; euro->_dec = euro->_dec_prices = 2; + euro->_is_euro = true; + _cache.add(_euro_val, euro); + } } if (_firm_val.empty()) _firm_val = _euro_val; diff --git a/include/isam.cpp b/include/isam.cpp index e45fa0d70..270163727 100755 --- a/include/isam.cpp +++ b/include/isam.cpp @@ -1,4336 +1,4358 @@ -#define __ISAM_CPP -#define _CRT_SECURE_NO_WARNINGS 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -#include -#include -#include -#endif - -#include -#include -#include - -#include -#include - -#define RECLOCKTYPES 0xFF00 -#define READTYPES 0x00FF -#define INVFLD 255 - -bool __field_changed = FALSE; - -#define NOALLOC (char **) -1 - -HIDDEN bool __autoload = TRUE; - -// @doc INTERNAL - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Funzioni C -//////////////////////////////////////////////////////////////////////////////////////////////////// - -int hashfun(const char *s) -{ - int l = strlen(s); - unsigned short temp = 0, *pw = (unsigned short *) s; - - const unsigned short * end = (unsigned short *) (s + (l - 1)); - while ((char *) pw < (char *) end) - { - temp ^= *pw; - pw++; - } - if (l & 1) - temp ^= (unsigned short ) (8192 + s[l - 1]); - l = (short) (temp % (MaxFields - 3)); - CHECKS(l >= 0, "Negative remainder on ", s); - return(l); -} - -int findfld(const RecDes *recd, const char *s) -{ - short stp = hashfun(s); - - for (byte i = 0 ; i < MaxFields; i++) - { - if (stp + i >= MaxFields) - stp -= MaxFields; - byte p = stp + i; - const int fp = recd->SortFd[p]; - if (fp == INVFLD) - return(FIELDERR); - - const int cmp = strcmp(recd->Fd[fp].Name, s); - if (cmp == 0) - return (int) fp; - else - if (cmp > 0) - return(FIELDERR); - } - return(FIELDERR); -} - -void __getfieldbuff(byte l, byte t, const char * recin, TString& s) -{ - CHECK(recin, "Can't read from a Null record"); - - if (t != _alfafld && t != _datefld) - { - if (t == _intzerofld || t == _longzerofld) - { - byte i = 0; - for (char* c = (char*)recin; *c == ' ' && i < l; c++, i++) - *c = '0'; - if (i == l) - l = 0; - } - else - { - while ((*recin == ' ') && (l)) - { - recin++; - l--; - } - if ((t != _realfld) && (t != _charfld)) - { - while ((*recin == '0') && (l)) - { - recin++; - l--; - } - } - } - } - - if (l) - { - while(l > 0 && recin[l - 1] == ' ') l--; - if (l) - s.strncpy(recin, l); - } - s.cut(l); - if (l) - { - if (t == _datefld) - { - const TDate dt(s); - s = dt.string(full); - } - else - { - if (t == _boolfld) - { - const char ok = toupper(*s); - if (ok == 'T' || ok == 'Y' || ok == 'S' || ok == 'X') - s = "X"; - else - s.spaces(1); - } - } - } -} - -void __putfieldbuff(byte l, byte d, byte t, const char* s, char* recout) -{ - CHECK(recout, "Can't write null record" ); - - TString80 s2; - if (t == _datefld) - { - if (s && *s && strlen(s) != 8) - { - const TDate dt(s); - s2 << dt.date2ansi(); - s = s2.get_buffer(); - } - } - else - if (t == _boolfld) - { - s2 = (*s && strchr("1STXY", toupper(*s)) != NULL) ? "T" : "F"; - s = s2.get_buffer(); - } - else - if (t == _realfld) - { - real r(s); - s2 = r.string(l, d); - s = s2.get_buffer(); - } - - int len = strlen(s); - const bool exceeded = len > l; - - if ((t == _intfld) || - (t == _longfld) || - (t == _wordfld) || - (t == _realfld) || - (t == _intzerofld) || - (t == _longzerofld) - ) - { - if (len == 0 || exceeded) - { - s2 = "0"; - s = s2.get_buffer(); - len = 1; - } - - __field_changed = FALSE; - const char c = (t == _intzerofld || t == _longzerofld) ? '0' : ' '; - for (int i = l - len - 1; i >= 0; i--) - { - __field_changed |= (recout[i] != c); - recout[i] = c; - } - if (!__field_changed) - { - __field_changed = memcmp(s, recout, l) != 0; - if (!__field_changed) - return; - } - strncpy(&recout[l-len], s, len) ; - } - else - { - if (exceeded) - len = l; - -/* - // Il codice seguente e' completamente errato in quanto tutti i prefissi ingannano il test! - // La stringa vuota e' prefisso di qualsiasi stringa - // per cui l'azzeramento di un campo risulta sempre impossibile! - - __field_changed = memcmp(s, recout, len) != 0; - if (!__field_changed) - return; -*/ - __field_changed = TRUE; // Per ora e' meglio cosi' - - strncpy(recout, s, len) ; - for (int i = l - 1; i >= len; i--) - recout[i] = ' '; - } -} - -struct TCallbackFileinfo -{ - TString16 _var; - TFilename _app; -}; - -HIDDEN int find_relapp(TConfig& cfg, void* jolly) -{ - TCallbackFileinfo& info = *((TCallbackFileinfo*)jolly); - if (cfg.exist(info._var)) - { - info._app = cfg.get(info._var); - return info._app.not_empty(); - } - return FALSE; -} - -bool get_relapp(int logicnum, TString& app) -{ - TConfig ini(CONFIG_GENERAL); - TCallbackFileinfo fi; - fi._var.format("Edit_%d", logicnum); - ini.for_each_paragraph(find_relapp, &fi); - if (fi._app.not_empty()) - app = fi._app; - return app.not_empty(); -} - -struct TCallbackTableinfo -{ - TString16 _var1, _var2, _var3; - TString4 _module; - TFilename _tabapp, _relapp; -}; - -HIDDEN int find_tabapp(TConfig& cfg, void* jolly) -{ - TCallbackTableinfo& info = *((TCallbackTableinfo*)jolly); - - if (cfg.exist(info._var1)) - { - info._tabapp = cfg.get(info._var1); - if (info._tabapp.not_empty()) - return 1; - } - if (cfg.get_paragraph().compare(info._module, 2, TRUE) == 0) - { - if (cfg.exist(info._var2)) - { - info._relapp = cfg.get(info._var2); - if (info._relapp.not_empty()) - return 2; - } - if (info._var3.full() && cfg.exist(info._var3)) - { - info._relapp = cfg.get(info._var3); - if (info._relapp.not_empty()) - return 3; - } - } - return 0; -} - -bool get_tabapp(const char* tabname, TString& app) -{ - TConfig ini(CONFIG_GENERAL, "Main"); - TCallbackTableinfo fi; - TTable t(tabname); - fi._var1.format("Edit_%s", t.name()); - fi._var2.format("Edit_%d", t.num()); - fi._var3.format("Edit_%d", t.num() == LF_TABCOM ? LF_TAB : LF_TABCOM); - fi._module = t.module(); - ini.for_each_paragraph(find_tabapp, &fi); - - app = fi._tabapp; - if (app.empty()) - app = fi._relapp; - - if (app.empty()) - { - app = "ba3 -0"; - if (!fi._module.starts_with("ba")) // Compatibility mode :-( - { - const TString& tp = ini_get_string(CONFIG_STUDIO, fi._module, "TabPrg"); - if (tp.full()) - app = tp; - } - } - app << ' ' << tabname; - return tabname && *tabname > ' '; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Funzioni implementate per la gestione file dati tramite Codebase -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Inizio(@) - -// @doc INTERNAL - -// @func Ritorna una Token_string con in nome dell'indice -int get_table_names( - int logicnum, // @parm Numero logico del file di cui riconoscere l'indice - TToken_string& i_names, // @parm Token_string in cui inserire il nome dell'indice - int mode) - -// @comm Ritorna il nome con il prefisso corrente -{ - TFilename f = prefix().get_filename(logicnum); - i_names.cut(0); - - if (mode & 1) - i_names = f; - - if (mode & 2) - { - f.ext("cdx"); - i_names.add(f); - } - - if (mode & 4) - { - f.ext("fpt"); - if (f.exist()) - i_names.add(f); - } - - return i_names.items(); -} - -// Converte un errore di codebase in un errore isam -#ifdef DBG -HIDDEN int cb_error = NOERR; -#endif - -int get_error(int err) -{ -// Codici negativi -HIDDEN int error_codes_g[] = {-1,_isnotopen,-1,-1,-1,_islocked,-1,-1,-1,-1,-1,-1,_isfilefull, - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,_iskeynotfound,_ispatherr,-1,-1,_isdupkey}; -// Codici da 0 a 9 -HIDDEN int error_codes_ra[] = {NOERR,NOERR,_iskeynotfound,_iseof,_isbof,_isnrecerr} ; -// Codici da 10 a ... -HIDDEN int error_codes_rb[] = {-1,-1,_isreinsert,-1,-1,_islocked,-1,_isalropen,_iskeyerr } ; - - int isamerr = NOERR; - -#ifdef DBG - if (err <= 200 || err >= 230) - cb_error = err; -#endif - - if (err > 0) - { - if (err >= 10) - { - if (err > 80 || error_codes_rb[err/10]==-1) - isamerr = err; - else - isamerr = error_codes_rb[err/10]; - } - else - isamerr = error_codes_ra[err]; - } - else - if (err < 0) - { - if (err == -1) - { -#ifdef DBG - int ierr = DB_get_error(); -#endif - isamerr = _isnotopen; - } - else - { - int ierr = DB_get_error(); - if (ierr == 0) ierr = -err; // DB_get_error already called - if (ierr < 0) ierr = -ierr; - if (ierr > 340 || error_codes_g[ierr/10]==-1) - isamerr = -ierr; - else - isamerr = error_codes_g[ierr/10]; - } - } - DB_zero_error(); - return isamerr; -} - -// Used also by varrec -bool rec_has_memo(const RecDes& rd) -{ - for( int i = rd.NFields - 1; i >= 0; i--) - if (rd.Fd[i].TypeF == _memofld) - return true; - return false; -} - -HIDDEN bool lf_has_memo(int lffile) -{ - return rec_has_memo(prefix().get_recdes(lffile)); -} - -HIDDEN void browse_null(char *start, int nc) -{ - for (int i = nc - 1; i >= 0 ; i--) // Anche il primo byte(deletion flag) deve essere cambiato. nc comprende il primo byte - if (start[i] == '\0') start[i] = ' '; -} - -// Traduce l'espressione chiave di CodeBase - -HIDDEN int __build_key(const RecDes& recd, int numkey, const RecType recin, char *key, bool build_x_cb) - /* *recd; descrittore record */ - /* numkey; numero chiave */ - /* recin; buffer contenente il record */ - /* *key; valore della chiave */ - /* build_x_cb flag di costruzione per codebase */ -{ - CHECKD(numkey > 0, "Can't build key ", numkey); - - const char null_char = -1; - key[0] = '\0'; - if (numkey-- <= recd.NKeys) - { - int l = 0; - for (int i = 0; i < recd.Ky[numkey].NkFields; i++) - { - const KeyDes& kd = recd.Ky[numkey]; - const bool upp = kd.FieldSeq[i] > MaxFields; - const int nf = upp ? kd.FieldSeq[i] - MaxFields : kd.FieldSeq[i]; - const RecFieldDes& rf = recd.Fd[nf]; - const TFieldtypes f = (TFieldtypes) rf.TypeF; - - int off, len; - if (kd.FromCh[i] == 255) - { - off = rf.RecOff; - len = rf.Len; - } - else - { - off = rf.RecOff + kd.FromCh[i]; - len = kd.ToCh[i] - kd.FromCh[i] + 1; - } - if ((l + len) > 255) - { - key[0] = '\0'; - return(_iskeylenerr); - } - if (f == _boolfld) - { - const bool on = *(recin + off) > ' ' && strchr("STXY", *(recin + off)) != NULL; - key[l] = on ? 'T' : 'F'; - } - else - strncpy((key + l), (recin + off), len); - - if (recin[off] == '\0') - { - memset(key + l, ' ', len); - if ((f == _intfld) || (f == _longfld) || (f == _wordfld) || - (f == _intzerofld) || (f == _longzerofld)) - key[l + len - 1] = build_x_cb ? '0' : null_char; - } - else - if ((f == _intfld) || (f == _longfld) || (f == _wordfld) || (f == _intzerofld) || (f == _longzerofld)) - { - int w = l, j = l + len; - while (w < j && key[w] == ' ') w++; - while (w < j && key[w] == '0') key[w++] = ' '; - if (w == j) key[w-1] = build_x_cb ? '0' : null_char; - } - if (upp) - for (int i = l+len-1; i >= l; i--) - key[i] = toupper(key[i]); - - l += len; - } - - // rtrim - if (build_x_cb) - { - for (l--; l>=0 && key[l] == ' '; l--); - key[l + 1] = '\0'; - } - else - { - for (l--; l>=0 && (key[l] == ' ' || key[l] == null_char); l--); - key[l + 1] = '\0'; - for (;l >= 0; l--) - if (key[l] == null_char) - key[l] = '0'; - } - - return(NOERR); - } - return(_ispatherr); -} - - -HIDDEN int cisread(int fhnd, int knum, TRectype& record, int mode, TRecnotype& curr_recno) -{ - CHECKD(fhnd >= 0, "Can't use codebase handle ", fhnd); - - const int rmode = (mode & READTYPES); - const int lmode = (mode & RECLOCKTYPES); - - // Non usare mai _isnextn o _isprevn, usare il metodo skip! - CHECK (rmode !=_isnextn && rmode !=_isprevn, "_isnextn and _isprevn not supported in cisread"); - - TString256 keystr; - char* key = keystr.get_buffer(); - - int err = NOERR; - do - { - if (rmode>=_isequal && rmode<=_isgteq) - { - const RecDes& r = record.rec_des(); - err=__build_key(r, knum, record.string(),key,TRUE); - if (err == NOERR) - { - err = DB_seek(fhnd,key); - if (err == NOERR && rmode == _isgreat) - err = DB_next(fhnd); - if (err != NOERR) - err = get_error(err); - } - if (rmode != _isequal && err == _iskeynotfound) - err = NOERR; - } - else - { - if (rmode==_isfirst) - err=DB_first(fhnd); - else - if (rmode==_islast) - err=DB_last(fhnd); - else - if (rmode==_isnext) - { - if (curr_recno != DB_recno(fhnd)) - { - const RecDes& r = record.rec_des(); - err = __build_key(r, knum, record.string(),key,TRUE); - if (err == NOERR) - { - err = DB_seek(fhnd,key); - err = get_error(err); - if (err != NOERR && err != _iskeynotfound && err != _iseof) - fatal_box("Errore nella next %d : non posso riposizionarmi", err); - else - if (err == NOERR) - err=DB_next(fhnd); - } - } - else - err=DB_next(fhnd); - } - else - if (rmode==_isprev) - { - if (curr_recno != DB_recno(fhnd)) - { - const RecDes& r = record.rec_des(); - err = __build_key(r, knum, record.string(),key,TRUE); - if (err == NOERR) - { - err = DB_seek(fhnd,key); - err = get_error(err); - if (err != NOERR && err != _iskeynotfound && err != _iseof) - fatal_box("Errore nella prev %d : non posso riposizionarmi", err); - else - if (err == NOERR) - err=DB_prev(fhnd); - } - } - else - err=DB_prev(fhnd); - } - else - if (rmode==_iscurr) - err=DB_go(fhnd,DB_recno(fhnd)); - if (err != NOERR) - err=get_error(err); - } - - if (err == _iseof) - DB_last(fhnd); - if (err == NOERR && (lmode == _lock || lmode == _testandlock)) // _lock e _testandlock - { - err=DB_lock(fhnd); - if (err != NOERR) - err = get_error(err); - if (err == _islocked && lmode == _testandlock) - break; - } - if (err == _islocked) - { - const RecDes& r = record.rec_des(); - record = (const char*)DB_getrecord(fhnd); - __build_key(r, knum, record.string(), key, TRUE); - message_box("Codice %s in uso da parte\ndi un altro utente.", key); - if (lmode != _lock) - break; - } - } while (err ==_islocked); - - if (err == NOERR && lmode == _unlock) - { - err=DB_unlock(fhnd); - if (err != NOERR) - err = get_error(err); - } - - curr_recno = DB_recno(fhnd); - record = (const char *)DB_getrecord(fhnd); - - return err; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Funzioni implementate per la gestione file dati tramite Codebase -//////////////////////////////////////////////////////////////////////////////////////////////////// -// Fine(@) - -// @doc EXTERNAL - -// @func Setta il valore della variabile

-void set_autoload_new_files( - bool on) // @parm Valore da assegnare - -// @comm Il valore di

indica il caricamento dei valori standard dei file - -{ - __autoload = on; -} - -/////////////////////////////////////////////////////////// -// TBaseisamfile -/////////////////////////////////////////////////////////// - -TBaseisamfile::TBaseisamfile(int logicnum) -{ - _logicnum = logicnum; - _isam_handle = 0; - _curr_key = 0; - _lasterr = NOERR; - _current = new TRectype(logicnum); -} - -// @doc EXTERNAL - -// @mfunc Reperisce il tracciato dal file stesso. -// -TBaseisamfile::TBaseisamfile( - const char* name, // @parm Indica il nome del file - const char* descname) // @parm Indica la descrizione del file -// @comm Esiste la possibilita' di codificare i valori di pathpref e prefix in

-// % si riferisce ai dati comuni -// $ si riferisce ai dati di ditta corrente -// # si riferisce al direttorio indicato da PATHPREF.INI -{ - if (descname && *descname) - { - TTrec r; - ifstream f(descname); - f >> r; - const int err=DB_build(name, &r.rec()) ; - if (err != NOERR) - fatal_box("Non posso creare il file %s : errore n.ro %d", name, err); - } - _lasterr = NOERR; - TFilename filename(name); - CHECK(filename.full(),"Must define the file to open!"); - _logicnum = prefix().get_handle(filename); - _current = new TRectype(this); - -} - -TBaseisamfile::~TBaseisamfile() -{ - if (_current) - delete _current; -} - -TCodeb_handle TBaseisamfile::handle(int key) const -{ - return prefix().get_handle(_isam_handle, key > 0 ? key : _curr_key); -} - -TRecnotype TBaseisamfile::items() const -{ - return DB_reccount(handle()); -} - -const char* TBaseisamfile::name() const -{ - TString& tmp = get_tmp_string(); - tmp.format("%d", num()); - return tmp; -} - -const char* TBaseisamfile::module() const -{ - TFilename app; - curr().get_relapp(app); - if (app.full()) - return app.left(2); - return "ba"; -} - -const char* TBaseisamfile::filename() const -{ - const int n = _isam_handle > 0 ? _isam_handle : num(); - TString& tmp = get_tmp_string(); - tmp = prefix().get_filename(n); - tmp << ".dbf"; - return tmp; -} - -const char* TBaseisamfile::description() -{ - const int n = _isam_handle > 0 ? _isam_handle : num(); - const FileDes& d = prefix().get_filedes(n); - return d.Des; -} - -TRecnotype TBaseisamfile::eod() const -{ - return items(); -} - -void TBaseisamfile::set_curr(TRectype * curr) -{ - CHECK(curr != NULL, "You must set a valid current record"); - CHECK(num() == curr->num(), "You must set a coherent current record"); - if (_current != NULL) - delete _current; - _current = curr; -} - -void TBaseisamfile::setkey(int nkey) -{ - _curr_key = nkey; -} - -int TBaseisamfile::getkey() const -{ - return _curr_key; -} - -int TBaseisamfile::first(word lockop) -{ - return TBaseisamfile::read(curr(), _isfirst, lockop); -} - -int TBaseisamfile::last(word lockop) -{ - return TBaseisamfile::read(curr(), _islast, lockop); -} - -int TBaseisamfile::next(word lockop) -{ - return TBaseisamfile::read(curr(), _isnext, lockop); -} - -int TBaseisamfile::prev(word lockop) -{ - return TBaseisamfile::read(curr(), _isprev, lockop); -} - -int TBaseisamfile::reread(word lockop) -{ - return TBaseisamfile::reread(curr(), lockop); -} - -int TBaseisamfile::reread(TRectype& rec, word lockop) -{ - return rec.read(*this, _iscurr, lockop); -} - -int TBaseisamfile::skip(TRecnotype nrec, word lockop) -{ - if (nrec == 0) - return NOERR; - - curr().setdirty(); - const int fhnd = handle(); - - // controllo se mi sono spostato dall'ultima lettura - if (_recno != DB_recno(fhnd)) - { - _lasterr = DB_go(fhnd, _recno); - if (_lasterr != NOERR) - { - _lasterr = get_error(_lasterr); - if (_lasterr != _islocked) - fatal_box("Errore nella skip %d : non posso riposizionarmi", _lasterr); - } - } - _lasterr=DB_skip(fhnd, nrec); - if (_lasterr != NOERR) - _lasterr = get_error(_lasterr); - while (_lasterr ==_islocked) - { - const RecDes& r = prefix().get_recdes(num()); - TString256 key; - __build_key(r, _curr_key, curr().string(), key.get_buffer(), TRUE); - message_box("Codice %s in uso da parte\ndi un altro utente.\nSkipping", (const char*)key); - _lasterr = cisread(fhnd, getkey(), curr(),_iscurr + lockop, _recno); - } - _recno = DB_recno(fhnd); - if (curr().has_memo()) - curr().init_memo(_recno, _isam_handle); - - return _lasterr; -} - -// funzione di lettura dei file -int TBaseisamfile::_read(TRectype& rec, word op, word lockop) -{ - const TCodeb_handle fhnd = handle(); - rec.setdirty(); - - _lasterr = cisread(fhnd, getkey(), rec, op + lockop, _recno); - - // _recno = DB_recno(fhnd); // Gia' fatto nella cisread - - if(rec.has_memo()) - rec.init_memo(_recno, _isam_handle); - - if (_lasterr == NOERR) - { - if (lockop == _lock || lockop == _testandlock) - prefix().lock_record(_isam_handle, _recno); else - if (lockop == _unlock) - prefix().unlock_record(_isam_handle, _recno); - } - - return _lasterr; -} - -int TBaseisamfile::read(TRectype& rec, word op, word lockop) -{ - _lasterr=rec.read(*this, op, lockop); - return _lasterr; -} - -int TBaseisamfile::read(word op, word lockop) -{ - return TBaseisamfile::read(curr(), op, lockop); -} - -int TBaseisamfile::readat(TRectype& rec, TRecnotype nrec, word lockop) -{ - return rec.readat(*this, nrec, lockop); -} - -int TBaseisamfile::readat(TRecnotype nrec, word lockop) -{ - return TBaseisamfile::readat(curr(), nrec, lockop); -} - -int TBaseisamfile::_readat(TRectype& rec, TRecnotype nrec, word lockop) -{ - const int fhnd = handle(); - rec.setdirty(); - _lasterr = DB_go(fhnd, nrec); - if (_lasterr != NOERR) - _lasterr = get_error(_lasterr); - else - rec = (const char*)DB_getrecord(fhnd); - _recno = DB_recno(fhnd); - if (rec.has_memo()) - rec.init_memo(_recno, _isam_handle); - return _lasterr; -} - -int TBaseisamfile::_write(const TRectype& rec) -{ - CHECK(!rec.empty(), "Can't write an empty record"); - - // Controlla che la chiave sia piena - TString256 key; - - __build_key(rec.rec_des(), 1, rec.string(), key.get_buffer(), true); - if (key.blank()) - return _iskeyerr; - - if (dongle().demo() && items() > 979L) - return _isfilefull; - - // Forza l'uso della chiave principale (per chiavi duplicate?) - const int fhnd = handle(_curr_key > 0 ? 1 : 0); - - const int dst_len = DB_reclen(fhnd); - if (dst_len != rec.len()) - NFCHECK("Record size mismatch on file %d: RecDes=%d, DB_reclen=%d", - _logicnum, rec.len(), dst_len); - - browse_null(rec.string(), dst_len); - memcpy(DB_getrecord(fhnd), rec.string(), dst_len); - _lasterr = DB_add(fhnd); - _recno = DB_recno(fhnd); - - if (_lasterr == NOERR) - { - if (rec.has_memo()) - ((TRectype&)rec).write_memo(_isam_handle, _recno ); - } - else - _lasterr = get_error(_lasterr); - - return _lasterr; -} - -int TBaseisamfile::write(const TRectype& rec) -{ - return rec.write(*this); -} - -int TBaseisamfile::write() -{ - return TBaseisamfile::write(curr()); -} - -int TBaseisamfile::write_rewrite(const TRectype& rec) -{ - return rec.write_rewrite(*this); -} - -int TBaseisamfile::write_rewrite() -{ - return TBaseisamfile::write_rewrite(curr()); -} - -int TBaseisamfile::rewrite_write(const TRectype& rec) -{ - return rec.rewrite_write(*this); -} - -int TBaseisamfile::rewrite_write() -{ - return TBaseisamfile::rewrite_write(curr()); -} - -int TBaseisamfile::_rewrite(const TRectype& rec) -{ - CHECK(!rec.empty(), "Can't write an empty record"); - - TRectype save_rec(rec); - - // Forza l'uso della chiave principale (per chiavi duplicate?) - const int fhnd = handle(1); - _lasterr = cisread(fhnd, 1, save_rec, _isequal + _nolock, _recno); // Si Posiziona per sicurezza... - - if (_lasterr == NOERR) - { - const int len = DB_reclen(fhnd); - if (len != save_rec.len()) - NFCHECK("Record size mismatch on file %d: RecDes=%d, DB_reclen=%d", - _logicnum, save_rec.len(), len); - - browse_null(rec.string(), len); - if (memcmp(rec.string(), save_rec.string(), len) != 0) - { - memcpy(DB_getrecord(fhnd), rec.string(), len); - _lasterr = DB_rewrite(fhnd); - if (_lasterr == NOERR) - rec_cache(_logicnum).notify_change(); - else - _lasterr = get_error(_lasterr); - } - else - DB_unlock(fhnd); // non vale la pena farlo sempre ? - _recno = DB_recno(fhnd); - prefix().unlock_record(_isam_handle, _recno); - - if (_lasterr == NOERR) - { - if (curr().has_memo()) - ((TRectype&)rec).write_memo(_isam_handle, _recno); - } - } - - return _lasterr; -} - -int TBaseisamfile::rewrite(const TRectype& rec) -{ - return rec.rewrite(*this); -} - -int TBaseisamfile::rewrite() -{ - return TBaseisamfile::rewrite(curr()); -} - -int TBaseisamfile::rewriteat(const TRectype& rec, TRecnotype nrec) -{ - const int fhnd = handle(); - - if ((_lasterr=DB_go(fhnd,nrec))== NOERR) - { - browse_null(rec.string(),DB_reclen(fhnd)); - memcpy(DB_getrecord(fhnd),rec.string(),DB_reclen(fhnd)); - _lasterr=DB_rewrite(fhnd); - if (_lasterr != NOERR) _lasterr = get_error(_lasterr); - } - else - _lasterr = get_error(_lasterr); - _recno = DB_recno(fhnd); - - if(_lasterr == NOERR) - { - if (curr().has_memo()) - ((TRectype &)rec).write_memo(_isam_handle, _recno); - rec_cache(_logicnum).notify_change(); - } - - return _lasterr; -} - -int TBaseisamfile::rewriteat(TRecnotype nrec) -{ - return TBaseisamfile::rewriteat(curr(),nrec); -} - -int TBaseisamfile::_remove(const TRectype& rec) -{ - CHECK(!rec.empty(), "Can't remove an empty record"); - - const int fhnd = handle(1); // Forza l'uso della chiave principale (per chiavi duplicate?) - - TRectype save_rec(rec); - _lasterr = cisread(fhnd, 1, save_rec, _isequal + _nolock, _recno); // Si Posiziona per sicurezza... - - if (_lasterr == NOERR) - { - _lasterr = DB_delete(fhnd); // Put only deletion flag on record, must remove keys too! - if (_lasterr == NOERR) - { - if (curr().has_memo( )) - curr().init_memo(); - rec_cache(_logicnum).notify_change(); - DB_flush(fhnd); - } - else - _lasterr = get_error(_lasterr); - } - - if (_lasterr != NOERR) - DB_recall(fhnd); - - return _lasterr; -} - -int TBaseisamfile::remove(const TRectype& rec) -{ - return rec.remove(*this); -} - -int TBaseisamfile::remove() -{ - return TBaseisamfile::remove(curr()); -} - -int TBaseisamfile::lock() -{ - const int fhnd = handle(); - _lasterr = DB_lockfile(fhnd); - if (_lasterr != NOERR) - _lasterr = get_error(_lasterr); - return _lasterr; -} - -int TBaseisamfile::unlock() -{ - const int fhnd = handle(); - _lasterr = DB_unlock(fhnd); - if (_lasterr != NOERR) - _lasterr = get_error(_lasterr); - return (_lasterr); -} - -void TBaseisamfile::indexon() -{ -} - -void TBaseisamfile::indexoff() -{ -} - -bool TBaseisamfile::empty() -{ - return items() <= 0; -} - -// @doc EXTERNAL - -// @mfunc Apre il file isam di base con lock -// -// @rdesc Ritorna NOERR se e' riuscita ad aprire il file, altrimenti ritorna il numero di errore -// generato (vedi ). -int TBaseisamfile::_open( - unsigned int mode, // @parm Indica il modo di apertura del file (default _manulock) - bool index) // @parm Indica se aprire con indici o meno (default TRUE) - -// @comm Il parametro

puo' assumere i valori: -// -// @flag _manulock | Il lock dei record viene fatto manualmente -// @flag _exclock | Il file viene aperte in modo esclusivo -// @flag _autolock | Il lock dei record viene fatto in modo automatico -// @comm Il parametro

puo' assumere i valori: -// -// @flag TRUE | Il file viene aperto con indici -// @flag FALSE | Il file viene aperto senza indici - -{ - CHECKD(_isam_handle == 0, "Can't reopen file ", _logicnum); - _curr_key = index ? 1 : 0; - - TFilename filename; - _isam_handle = prefix().open_isamfile(_logicnum, filename, mode==_excllock, index); - if (_isam_handle > 0) - { - TCodeb_handle cb_handle = prefix().get_handle(_isam_handle, _curr_key); - const int dbfreclen = DB_reclen(cb_handle); - const int trcreclen = prefix().get_reclen(_logicnum); - const TRecnotype n = DB_reccount(cb_handle); - - if (dbfreclen != trcreclen) - { - TString msg; - msg.format("Lunghezza record incoerente sul file %d (%s): file=%d trc=%d", - num(), (const char*)filename, dbfreclen, trcreclen); - if (n <= 0) - { - msg << "\nSi consiglia di eliminare il file ed i suoi indici."; - error_box(msg); - } - else - fatal_box(msg); - } - if (prefix().get_recdes(_logicnum).NKeys <= 0) - fatal_box("Il file %d (%s) e' senza indici", num(), (const char*)filename); - _recno = RECORD_NON_FISICO; - setkey(_curr_key); - _lasterr = NOERR; - } - else - { - TString e_msg; - _lasterr = get_error(_isam_handle); - if (_lasterr == -60) - { - if (!filename.exist()) - e_msg.format("Il file %d(%s) non esiste, errore %d",num(),(const char*)filename,_lasterr); - else - e_msg.format("Il file %d(%s) e' aperto in modo esclusivo da un'altra applicazione", - num(), (const char*)filename); - } - if (e_msg.empty()) - e_msg.format("Il file %d(%s) non puo' essere aperto, errore %d",num(),(const char*)filename,_lasterr); - fatal_box((const char*) e_msg); - } - return _lasterr; -} - -int TBaseisamfile::_open_ex( - unsigned int mode, // @parm Indica il modo di apertura del file (default _manulock) - bool index) // @parm Indica se aprire con indici o meno (default TRUE) - -// @comm Il parametro

puo' assumere i valori: -// -// @flag _manulock | Il lock dei record viene fatto manualmente -// @flag _exclock | Il file viene aperte in modo esclusivo -// @flag _autolock | Il lock dei record viene fatto in modo automatico -// @comm Il parametro

puo' assumere i valori: -// -// @flag TRUE | Il file viene aperto con indici -// @flag FALSE | Il file viene aperto senza indici - -{ - CHECKD(_isam_handle == 0, "Can't reopen file ", _logicnum); - _curr_key = index ? 1 : 0; - - TFilename filename; - _isam_handle = prefix().open_isamfile(_logicnum, filename, mode==_excllock, index); - if (_isam_handle > 0) - { - if (prefix().get_reclen(_logicnum) > 0) - { - const int fhnd = handle(); - if (fhnd >= 0) - { - _recno = RECORD_NON_FISICO; - _lasterr = NOERR; - } - else - _lasterr = get_error(fhnd); - } - else - _lasterr = _isbadtrc; - } - else - { - _lasterr = get_error(_isam_handle); - _isam_handle = 0; - } - return _lasterr; -} - -int TBaseisamfile::_close() -{ - int err = NOERR; - if (prefix_valid()) - { - err = prefix().close_isamfile(_isam_handle); - setstatus(err); - } - return err; -} - -int TBaseisamfile::is_valid(bool exclusive) -{ // Ritorna NOERR se il file puo' essere aperto senza errori - CHECKD(_isam_handle == 0, "Can't reopen file ", _logicnum); - TFilename filename; - TIsam_handle isam_handle = prefix().open_isamfile(_logicnum, filename, exclusive, TRUE); - TCodeb_handle fhnd = isam_handle > 0 ? prefix().get_handle(isam_handle,1) : isam_handle; - - int err = NOERR; - if (fhnd < 0) - err = get_error(fhnd); - else - { - const int trcreclen = prefix().get_reclen(_logicnum); - if (trcreclen > 0) - { - if (DB_tagget(fhnd) == -1) - err = _ispatherr; - else - { - const int dbfreclen = DB_reclen(fhnd); - if (dbfreclen != trcreclen) - err = _istrcerr; - } - } - else - err = _isbadtrc; - } - if (isam_handle > 0) - prefix().close_isamfile(isam_handle); - return err; -} - -bool TBaseisamfile::get_relapp(TString& app) const -{ - return curr().get_relapp(app); -} - -bool TBaseisamfile::is_changed_since(long& last) const -{ - bool yes = false; - -#ifdef WIN32 - int fh = 0; - ::_sopen_s(&fh, filename(), _O_RDONLY, _SH_DENYNO, _S_IREAD); - if (fh > 0) - { - struct stat stat; - if (::fstat(fh, &stat) == 0) - { - const long tim = long(stat.st_mtime) ^ long(stat.st_size); - yes = tim != last; - last = tim; - } - ::_close(fh); - } -#else - struct stat stat; - if (lstat(filename(), &stat) == 0) - { - const long tim = long(stat.st_mtime) ^ long(stat.st_size); - yes = tim != last; - last = tim; - } -#endif - - return yes; -} - -/////////////////////////////////////////////////////////// -// TLocalisamfile -/////////////////////////////////////////////////////////// - -// @doc EXTERNAL - -// @mfunc Costruttore -// -// @rdesc Ritorna l'oggetto -TLocalisamfile::TLocalisamfile( - int logicnum) // @parm Numero del logico del file - : TBaseisamfile(logicnum) -{ - if (open() != NOERR) - fatal_box("Impossibile aprire il file %d", logicnum); -} - -// @mfunc Costruttore -// -// @rdesc Ritorna l'oggetto -TLocalisamfile::TLocalisamfile( - const char* name, // @parm Nome del file esterno da aprire - const char* descname) // @parm Indica la descrizione del file -: TBaseisamfile(name, descname) -{ -} - -TLocalisamfile::TLocalisamfile(int logicnum, bool tmpfile) - : TBaseisamfile(logicnum) -{ - CHECK(tmpfile == TRUE, "Protected constructor badly used"); -} - - -TLocalisamfile::~TLocalisamfile() -{ - close(); -} - -int TLocalisamfile::close() -{ - return TBaseisamfile::_close(); -} - -int TLocalisamfile::open(unsigned int mode) -{ - return TBaseisamfile::_open(mode); -} - -int TLocalisamfile::operator +=(const TRecnotype npos) -{ - skip(npos); - return status(); -} - - -int TLocalisamfile::operator -=(const TRecnotype npos) -{ - skip(-npos); - return status(); -} - - -int TLocalisamfile::operator ++() -{ - next(); - return status(); -} - - -int TLocalisamfile::operator --() -{ - prev(); - return status(); -} - - - -TIsamfile::TIsamfile(int logicnum) - : TBaseisamfile(logicnum) -{ } - - -TIsamfile::~TIsamfile() -{ - close(); -} - -/////////////////////////////////////////////////////////// -// TIsamtempfile -/////////////////////////////////////////////////////////// - -TIsamtempfile::TIsamtempfile(int logicnum, const char* radix, bool create, bool autodel) - : TLocalisamfile(logicnum, TRUE) -{ - TRecnotype eod = 0; - TRecnotype eox = 100; - - TFilename n; - - if (radix && *radix) - { - if (*radix == '%') - n = radix + 1; - else - { - n.tempdir(); - n.add(radix); - } - n.ext("dbf"); - } - else - n.temp(NULL, "dbf"); - - if (!create) - { - const long sz = fsize(n); - if (sz <= 64) - fatal_box("Impossibile aprire il file %s", (const char*)n); - - const long len = curr().len(); - eod = eox = sz / len; - } - - CHECK(create == FALSE || create == TRUE, "Il flag di autodel ora si setta con il terzo parametro del costruttore"); - _autodel = autodel || (create != FALSE && create != TRUE); - - n.insert("%", 0); - - open(n, create, eod, eox); -} - - -TIsamtempfile::~TIsamtempfile() -{ - close(); -} - -// @doc EXTERNAL - -// @mfunc Apre il file -// -// @rdesc Ritorna NOERR se e' riuscita ad aprire il file, altrimenti ritorna il numero di errore -// generato (vedi ). -int TIsamtempfile::open( - const char* radix, // @parm Radice del path del file - bool create, // @parm Indica se va creato un nuovo file (se FALSE il file esiste gia') - TRecnotype eod, // @parm Numero di record presenti nel file - TRecnotype eox) // @parm Numero di record da aggiungere al file - -// @comm Nel case

sia TRUE allora viene settato automaticamente il valore di

-// a TRUE, cioe' viene abilitata l'eliminazione del file in chiusura. - -{ - int err = NOERR; - - TFilename filename; - if (radix[0] == '%') - filename = radix+1; - else - filename.temp(radix); - filename.ext(""); - - CHECKS(_isam_handle == 0, "File already open ", (const char*)filename); - - if (create) - { - RecDes* r = (RecDes*)&prefix().get_recdes(num()); - err = DB_build(filename, r) ; - if (err != NOERR) - { - err = get_error(err); - fatal_box("Can't create temp file '%s' num. %d: Error n. %d", (const char*)filename, num(), err); - } - } - else - { - TFilename test = filename; test.ext("dbf"); - for (int t = 0; t < 2; t++) - { - test.ext(t == 0 ? "dbf" : "cdx"); - if (!test.exist()) - { - err = -60; - break; - } - } - } - - if (err == NOERR) - { - _isam_handle = prefix().open_isamfile(_logicnum, filename, true); - TCodeb_handle fhnd = handle(_curr_key = 1); - if (fhnd < 0) - err = get_error(fhnd); - } - - if (err != NOERR) - { - filename.ext("dbf"); - if (err == -60) - { - if (!filename.exist()) - fatal_box("Apertura file %s : errore n. %d. File non esistente.",(const char*)filename,err); - else - fatal_box("Apertura file %s : errore n. %d. File aperto in uso esclusivo da un'altra applicazione.",(const char*)filename,err); - } - else - fatal_box("Apertura file %s : errore n. %d ",(const char*)filename,err); - } - - _recno = RECORD_NON_FISICO; - setstatus(err); - return err; -} - - -int TIsamtempfile::close() -{ - TFilename f = filename(); - int err = prefix().close_isamfile(_isam_handle); - if (err == NOERR && _autodel) - { - const long c = DB_getconf(); - - f.ext("dbf"); - ::remove(f); - - if (c & 1) - f.ext("fpt"); - else - f.ext("dbt"); - ::remove(f); - - if (c & 1) // FOXPRO format - f.ext("cdx"); - if (c & 4) // DBIV format - f.ext("mdx"); - if (c & 8 || c & 2) // CLIPPER and DBIII format - { - f.ext("cgp"); - FILE* fp=NULL; fopen_s(&fp, f, "r"); - char in[16]; - while (fgets(in,16,fp)!=NULL) - { - TFilename a(in); - if (c & 8) // DBIII format - a.ext("ndx"); - else - a.ext("ntx"); // CLIPPER format - ::remove((const char *)a); - } - fclose(fp); - } - ::remove(f); - - if (curr().has_memo()) // Cancella eventuale file dei memo - { - f.ext("fpt"); - ::remove(f); - } - } - - setstatus(err); - return err; -} - -/////////////////////////////////////////////////////////// -// TExternisamfile -/////////////////////////////////////////////////////////// -TExternisamfile::TExternisamfile(const char* name, bool exclusive, bool index) -: TLocalisamfile(name) -{ - init(name, exclusive, index); -} - -TExternisamfile::TExternisamfile(const char* name, const char* descname, bool exclusive, bool index) -: TLocalisamfile(name, descname) -{ - init(name, exclusive, index); -} - -TExternisamfile::~TExternisamfile() -{ - close(); -} - -void TExternisamfile::init(const char* name, bool exclusive, bool index) -{ - _name = name; - _name.ext("dbf"); - -// Espande il nome! - const char c = _name[0]; - if (c == '%' || c == '$') - _name = CAddPref(_name.get_buffer()); - else - if (c == '#') - { - _name.ltrim(1); - _name.format("%s/%s",__ptprf,(const char*)_name); - } - open(exclusive, index); -} - -int TExternisamfile::open(bool exclusive, bool index) -{ - _isam_handle = prefix().open_isamfile(_logicnum, _name, exclusive, index); - if (_isam_handle > 0) - { - if (prefix().get_recdes(_logicnum).NKeys <= 0) - fatal_box("Il file %d (%s) e' senza indici", num(), (const char*)filename()); - _recno = RECORD_NON_FISICO; - setkey(1); - _lasterr = NOERR; - } - else - { - TString e_msg; - _lasterr = get_error(_isam_handle); - if (_lasterr == -60) - { - if (!_name.exist()) - e_msg.format("Il file %d(%s) non esiste, errore %d",num(),(const char*)_name,_lasterr); - else - e_msg.format("Il file %d(%s) e' aperto in modo esclusivo da un'altra applicazione", - num(), (const char*)_name); - } - if (e_msg.empty()) - e_msg.format("Il file %d(%s) non puo' essere aperto, errore %d",num(),(const char*)_name,_lasterr); - fatal_box((const char*) e_msg); - } - return _lasterr; -} - -int TExternisamfile::close() -{ - return _close(); -} - -int TExternisamfile::zap() -{ - RecDes rd = curr().rec_des(); - - int err = prefix().close_isamfile(_isam_handle); - if (err == NOERR) - { - err = DB_packfile(TRUE, _name, 0); - if (err == NOERR) - { - TRecnotype peod; - err = DB_packindex(TRUE, _name, &rd, &peod, FALSE); - } - _isam_handle = prefix().open_isamfile(_logicnum, _name); - } - - return err; -} - -const char* TExternisamfile::name() const -{ - return filename(); -} - -/////////////////////////////////////////////////////////// -// TSystemisamfile -/////////////////////////////////////////////////////////// - -int TSystemisamfile::build(const TTrec& r) -{ - int err = NOERR; - const TDir d(num()); - if (r.len() > 0) - { - TFilename f(filename()); - TFilename fname(f); fname.ext(""); // sostituto per _filename - - f = f.path(); if (!is_not_slash(f.right(1)[0])) f.rtrim(1); - if (!dexist(f)) - make_dir(f); - - err=DB_build(fname, &r.rec()); - if (err != NOERR) - err = get_error(err); - setstatus(err); - - if (err == NOERR && __autoload) - { - TFilename lf; - lf.format("%sstd/lf%04d.txt", __ptprf, num()); - if (fexist(lf)) - load(lf, '|', '\0', '\n', TRUE, TRUE); - } - } - else - { - NFCHECK("Can't create a file with empty field info"); - setstatus(_isbadtrc); - } - return err; -} - -int TSystemisamfile::build() -{ - TTrec r; - r.get(num()); - return build(r); -} - -long TSystemisamfile::size(TRecnotype eox) -{ - return 51200L; -} - -#ifndef FOXPRO - -// @doc INTERNAL - -// @mfunc Esegue la conversione del file -// -// @rdesc Ritorna il rusultato dell'operazione -// -// @flag TRUE | Se la conversione e' stata effettuata correttamente -// @flag FALSE | Se h stato rilevato un errore durante la conversione (viene emesso un ) -int TSystemisamfile::exec_convapp( - long flev, // @parm Livello a cui aggiornare l'archivio - const bool before) // @parm Indica se viene chiamata prima o dopo la conversione - -{ - const char * const v = before ? "BCNV" : "ACNV"; - int err = 0; - - if (flev == 0) flev = 199401; - else flev++; - - TConfig conv(CONFIG_FCONV); - TString16 paragraph; - - TString_array paralist; - conv.list_paragraphs(paralist); - - for (unsigned int l = flev; err == 0 && l <= prefix().get_stdlevel(); l++) - { - paragraph.format("%06ld", l); - if (paralist.find(paragraph) < 0) - continue; - if (conv.set_paragraph(paragraph) && conv.exist(v, num())) - { - TToken_string s(conv.get(v, NULL, num()), ' '); - TFilename f(s.get(0)); - f.ext(".exe"); - s << ' ' << prefix().get_codditta(); - TExternal_app app(s); - if (f.exist()) - { - err = app.run(FALSE, 0x3); // Synchronous Spawn with User - TMailbox mail; - TMessage* msg = mail.next(TRUE); - if (err == 0 && msg != NULL) - err = atoi(msg->body()); - } - if (err && err != 8) - return error_box("Impossibile eseguire il programma di %sconversione\ndel livello %ld/%ld\nErrore n.ro %d", before ? "pre" : "post", l / 100, l % 100, err); - } - } - return err; -} - -// @doc INTERNAL - -// @mfunc Recupera le conversioni logiche da effettuare sul file -// -// @rdesc Ritorna TRUE se occorre effettuare la conversione sul file -bool TSystemisamfile::getlcf( - long flev) // @parm livello archivi di partenza della convesione - -// @comm Recupera le conversioni logiche da effettuare sul file per per passare dal -// livello archivi

a quello attuale degli archivi standard. - -{ - _flds.destroy(); - _exps.destroy(); - if (flev == 0) flev = 199401; - else flev++; - - TConfig conv(CONFIG_FCONV); - TString16 paragraph; - - TString_array paralist; - conv.list_paragraphs(paralist); - - for (unsigned int l = flev; l <= prefix().get_stdlevel(); l++) - { - paragraph.format("%06ld", l); - if (paralist.find(paragraph) < 0) - continue; - - if (conv.set_paragraph(paragraph) && conv.exist("F", num())) - { - TToken_string exprline(conv.get("F", NULL, num())); - - if (exprline.empty()) return FALSE; - - TToken_string w("", '='); - const char * wexprs = exprline.get(); - - while (wexprs != NULL) - { - w = wexprs; - TFixed_string fld(w.get()); - _flds.add(new TFieldref(fld, 0)); - _exps.add(new TExpression(w.get(), _strexpr)); - wexprs = exprline.get(); - } - } - } - return _flds.items() > 0; -} - -void TSystemisamfile::makelc(TRectype& rec) -{ - for (int i = 0 ; i < _flds.items(); i++) - { - TFieldref& f = (TFieldref&) _flds[i]; - TExpression& e = (TExpression & )_exps[i]; - - for (int k = 0; k < e.numvar(); k++) - e.setvar(k, get(e.varname(k))); - f.write(e.as_string(), rec); - } -} - -// @doc EXTERNAL - -// @mfunc Esegue la conversione del tracciato record del file -// -// @rdesc Ritorna il risulato della conversione, altrimenti il codice di errore generato -// (vedi ) - -int TSystemisamfile::update( - const TTrec& newrec, // @parm Nuovo tracciato record con cui aggiornare il file - bool interactive) // @parm Indica se riportare i campi personalizzati - -{ - if (newrec.len() == 0) - { - // if (interactive) error_box(FR("Il nuovo tracciato per il file %d e' vuoto"), num()); // Fastidioso per Ilaria - setstatus(_istrcerr); - return status(); - } - - int err = NOERR; - - TTrec wrec(newrec); - TDir dir; - - dir.get(num(), _unlock, _nordir, _sysdirop); - const bool is_com = prefix().is_com(); - const bool toconvert = is_com ? dir.is_com() : dir.is_firm(); - - TTrec oldrec(num(), is_com ? _comdir : _nordir); - if (oldrec.fields() < 0 || oldrec.fields() > MaxFields) - { - if (yesno_box(FR("Il file %d (%s)\n" - "ha %d campi ed una lunghezza record di %d" - "\nSi desidera azzerare il vecchio tracciato?"), - num(), (const char*)filename(), oldrec.fields(), oldrec.len())) - { - oldrec.zero(); - } - else - { - setstatus(_istrcerr); - return status(); - } - } - - int lenr = wrec.len(); - if (lenr != 0) - { - const long lev = prefix().filelevel(); - const bool lcf = getlcf(lev); - - if (toconvert) - { - err = exec_convapp(lev, TRUE); // Pre-conversion - if (err != NOERR) - { - setstatus(err); - return err; - } - - if (!lcf && wrec == oldrec) - { - err = exec_convapp(lev, FALSE); // Post-conversion (SOLO se il record e' rimasto uguale) - setstatus(err); - return err; - } - } - else - { - if (dir.eox() > 0L) - dir.reset_eox(); - } - - const int oldfields = oldrec.fields(); //numero campi del vecchio file - const int wfields = wrec.fields(); //numero campi del nuovo file - int newfields = wfields; //numero campi del nuovo file compresi quelli personalizzati (_) - TToken_string def; //riga del file .trr nome|tipo|lungh|dec - - for (int j = 0; j < oldfields; j++) - { - def = oldrec.fielddef(j); - const TString16 fname = def.get(0); //nome e basta del campo - if (!interactive && fname[0] == '_') - { - if (wrec.field(fname) == FIELDERR) - { - if (newfields < MaxFields) - { - wrec.update_fielddef(newfields++, def); - wrec.set_fields(newfields); - wrec.rehash(); - } - else - { - if(!yesno_box("Il campo %s non verra' preservato, devo continuare?", - (const char*)fname)) - return NOERR; - } - } - } - } - if (wfields < newfields) - { - wrec.set_fields(newfields); - wrec.rehash(); - lenr = wrec.len(); - } - TFilename fname; - if (toconvert) - fname = filename(); - - if (toconvert && (dir.eox() > 0L || fname.exist())) - { - TRecnotype ni = 0L; - TFilename tmpfname; tmpfname.temp("tf"); - - err=DB_build(tmpfname, &wrec.rec()); - - if (err != NOERR) - { - err=get_error(err); - return (err); - } - - if (dir.eod() > 0 && oldrec.len() > 0) - { - // Apro il file destinazione in modo esclusivo e senza indici - //int tmpnum = num(); - //TIsam_handle ishandle = prefix().open_isamfile(tmpnum, tmpfname, true, false); - // TCodeb_handle fhnd = ishandle > 0 ? prefix().get_handle(ishandle) : ishandle; - TCodeb_handle fhnd = DB_open(tmpfname, 1, 0); - if (fhnd < 0) - { - err = get_error(fhnd); - return err; - } - - err = _open_ex(_excllock, false); - if (err != NOERR) - return err; - - TString s; s << TR("Aggiornamento") << ' ' << fname; - - const TRecnotype nitems = items(); - TProgress_monitor p(nitems > 0 ? nitems : 1, s, is_power_station()); - - TExtrectype nrec(wrec); - - const int nflds = curr().items(); - TArray infld, outfld; - int j; - for (j = 0; j < nflds; j++) - { - const char* fld_name = curr().fieldname(j); - infld.add(new TRecfield(curr(), fld_name), j); - if (nrec.exist(fld_name)) - outfld.add(new TRecfield(nrec, fld_name), j); - } - const bool memo_inside = rec_has_memo(nrec.rec_des()); - for (int errore = first(); errore == NOERR; errore = next()) - { - if (!p.add_status()) - { - err = _iseof; // Simula errore in caso di interruzione - break; - } - ni++; - - if (curr().isdeleted()) - continue; - - nrec.zero(); - for (j = outfld.last(); j >= 0; j = outfld.pred(j)) - { - TRecfield* in_fld = (TRecfield*)infld.objptr(j); - TRecfield* out_fld = (TRecfield*)outfld.objptr(j); - if (in_fld != NULL && out_fld != NULL) - { - char* fld_val = (char*)(const char*)*in_fld; - if (out_fld->type() != _datefld && out_fld->type() != _memofld) - { - const int l1 = out_fld->len(); - const int l2 = strlen(fld_val); - if (l1 < l2) - { - if (out_fld->type() != _alfafld) - *fld_val = '\0'; - else - fld_val[l1] = '\0'; - } - } - *out_fld = fld_val; - } - } - if (lcf) - makelc((TRectype &)nrec); - browse_null(nrec.string(),lenr); - memcpy(DB_getrecord(fhnd),nrec.string(),lenr); - err=DB_add(fhnd); - if ( err == NOERR && memo_inside) - { - // nrec.write_memo(ishandle, DB_recno(fhnd)); - for (j = outfld.last(); j >= 0; j = outfld.pred(j)) - { - const TRecfield* in_fld = (const TRecfield*)infld.objptr(j); - const TRecfield* out_fld = (const TRecfield*)outfld.objptr(j); - if (in_fld != NULL && out_fld != NULL && out_fld->type() == _memofld) - { - const TFixed_string val(*in_fld); - if (val.full()) - DB_memowrite(fhnd, out_fld->name(), val); - } - } - DB_flush(fhnd); - } - if (err != NOERR) - err=get_error(err); - setstatus(err); - - } - close(); - //prefix().close_isamfile(ishandle); - DB_close(fhnd); - - if (err != NOERR) - err = get_error(err); - - if (!p.setstatus(nitems)) - err = _iseof; - } - - if (err == NOERR) - { - long c = DB_getconf(); - fname.ext("dbf"); - tmpfname.ext("dbf"); - fcopy(tmpfname, fname); - ::remove(tmpfname); - if (c & 1) - tmpfname.ext("fpt"); - else - tmpfname.ext("dbt"); - if (tmpfname.exist()) - { - if (c & 1) - fname.ext("fpt"); - else - fname.ext("dbt"); - fcopy(tmpfname, fname); - ::remove(tmpfname); - } - if (c & 1) // FOXPRO format - tmpfname.ext("cdx"); - if (c & 4) // DBIV format - tmpfname.ext("mdx"); - if (c & 8 || c & 2) - { - tmpfname.ext("cgp"); - TFilename a; - FILE *fp=NULL; fopen_s(&fp, tmpfname,"rb"); - while (fgets(a.get_buffer(),16,fp) != NULL) - { - a.rtrim(1); // Cut \n - if (c & 8) // DBIII format - a.ext("ndx"); - else - a.ext("ntx"); // CLIPPER format - ::remove(a); - } - fclose(fp); - } - ::remove(tmpfname); - dir.set_eod(ni); - } - } - if (err==NOERR) - { - dir.set_len(lenr); - dir.put(num(), _nordir, _sysdirop); - wrec.put(num()); - prefix().update_recdes(num()); - - if (toconvert) - packindex(true); - if (err == NOERR) - err = exec_convapp(lev, FALSE); // Post - conversion - } - } - - setstatus(err); - return err; -} - -// @doc EXTERNAL - -// @mfunc Rimuove fisicamente i record cancellati -// -// @rdesc Ritorna NOERR se l'operazione di compattamento e' riuscita, altrimenti il codice di -// di errore generato (vedi ). -int TSystemisamfile::packfile( - bool vis, // @parm Indica se visualizzare lo stato dell'operazione - bool zap) // @parm Indica se distruggere tutti i records - -// @xref - -{ - TFilename fname = filename(); fname.ext(""); - - TRecnotype new_eod = 0L; - if (!zap) - { - const int lf = num(); - TDir d(lf); // Chi commenta muore! - d.get(lf,_nolock, d.is_com() ? _comdir : _nordir, _sysdirop); - new_eod = d.eod(); - if (d.len() <= 1) // Dati rovinati? - { - d.set_len(curr().len()); - d.put(lf, d.is_com() ? _comdir : _nordir, _sysdirop); - } - } - - int err = DB_packfile(vis, fname, new_eod); - - if (zap && err == NOERR) - err = packindex(vis, false); - if (err == NOERR && curr().has_memo()) - err = DB_packmemo(vis,fname); - - if (err != NOERR) - { - err = get_error(err); - if (err != NOERR) - error_box("Errore in compattamento dati.\nFile %d : %d", num(), err); - } - setstatus(err); - return err; -} - -int TSystemisamfile::zap() -{ - safely_close_closeable_isamfiles(); - return packfile(true, true); -} - -// @doc EXTERNAL - -// @mfunc Rimuove fisicamente gli indici cancellati -// -// @rdesc Ritorna NOERR se l'operazione di compattamento e' riuscita, altrimenti il codice di -// di errore generato (vedi ). -int TSystemisamfile::packindex( - bool vis, // @parm Indica se visualizzare lo stato dell'operazione - bool ask) // @parm Indica se chiedere il recupero dei record duplicati - -// @xref - -{ - const TTrec r(num()); - TDir d(num()); - const bool is_com = d.is_com(); - d.get(num(),_nolock, is_com ? _comdir : _nordir, _sysdirop); - - TFilename name = d.filename(); name.ext(""); - TRecnotype peod; - int err=DB_packindex(vis,name,&r.rec(),&peod,ask); - if (err != NOERR) - err = get_error(err); - if (err != NOERR) - { - if (vis || ask) - error_box("Errore in compattamento indici.\nFile %d : %d", num(),err); - } - else - { - if (peod >= 0 && peod != d.eod()) - { - d.set_eod(peod); - d.put(num(), is_com ? _comdir : _nordir); - } - } - setstatus(err); - return err; -} - -void TSystemisamfile::update_file() -{ - TFilename fname; - int logicnum = _logicnum; - int isam_handle = prefix().open_isamfile(logicnum, fname, FALSE, 1); - if (isam_handle > 0) - { - TCodeb_handle cb_handle = prefix().get_handle(isam_handle, 1); - const TRecnotype n = DB_reccount(cb_handle); //numero di elementi del file - - TDir dir; - dir.get(_logicnum, _lock, _nordir, _sysdirop); - dir.set_eox(n); - dir.set_eod(n); - dir.put(_logicnum, _nordir, _sysdirop); - prefix().close_isamfile(isam_handle); - } -} - -int TSystemisamfile::pack(bool vis, bool ask) -{ - int err = packfile(vis); - if (err == NOERR) - err = packindex(vis, ask); - setstatus(err); - return err; -} - -// @doc EXTERNAL - -// @mfunc Importa un file ascii -// -// @rdesc Ritorna NOERR se l'operazione di lettura e' riuscita, altrimenti il codice di -// di errore generato (vedi ). -int TSystemisamfile::load( - const char* from, // @parm Nome del file da importare - char fs, // @parm Carattere separatore di campo (default ) - char fd, // @parm Carattere delimitatore di campi (default '\\0') - char rs, // @parm Carattere separatore di record (default '\\n') - bool vis, // @parm Indica se visualizzare lo stato dell'operazione (default TRUE) - bool extended, // @parm Indica se interpretare alcune stringhe come macro (default FALSE) - bool indexed) // @parm Indica se indicizzare subito o alla fine - -// @comm Se

e' TRUE e trova alcune stringhe col formato %stringa% (es. %frm%) -// ne sostituisce i valori (es. ditta corrente). - -// @xref - -{ - int err=NOERR; - FILE* fl = NULL; fopen_s(&fl, from, "r"); - if (fl == NULL) - { - cantread_box(from); - setstatus(2); - return 2; - } - TRecnotype r = 0, e = 0, nitems = 0; - TString8 firm, year, attprev("00000"); - - if (extended) - { - const TDate d(TODAY); - year.format("%04d", d.year()); - firm.format("%05ld", prefix().get_codditta()); - attprev = cache().get(LF_NDITTE, firm, NDT_CODATTPREV); - } - - fseek(fl, 0L, SEEK_END); - nitems = ftell(fl); - fclose(fl); - - err = _open_ex(_excllock, indexed); - if (err != NOERR) - { - TString msg; msg << _logicnum << " (" << name() << ')'; - cantread_box(msg); - return err; - } - - TScanner f(from); - const bool fixedlen = (fs == '\0'); - TToken_string s(1024, fixedlen ? char(255) : fs); - int nflds = curr().items(); - TString_array fld(nflds); - TPointer_array fldlen(nflds); - int reclen = 0; - TString sfd(3); - TString s1(256); - bool lcf = FALSE; - - if (f.paragraph("Header")) - { - int equal; - TString key; - nflds = 0; - while ((equal = f.line().find('=')) > 0) - { - key = f.token().left(equal); - key.trim(); - if (key == "File") - { - const int logic = atoi(f.token().mid(equal+1)); - if (logic != num()) - { - error_box("L'archivio %s e' stato generato dal file %d", from, logic); - return _isbadtrc; - } - } else - if (key == "Fields") - { - TToken_string riga(f.token().mid(equal+1)); - TToken_string wfd(32, ','); - FOR_EACH_TOKEN(riga, fd) - { - wfd = fd; wfd.strip_spaces(); - fld.add(wfd.get(0)); - const int l = wfd.get_int(); - fldlen.add_long(l, nflds++); - reclen += l; - } - } - } - } - - if (nflds == 0 || fld.items() == 0) - { - nflds = curr().items(); - for (int j = 0; j < nflds; j++) - { - fld.add(curr().fieldname(j), j); - const TString& wfld = fld.row(j); - const int l = (curr().type(wfld) == _datefld) ? 10 : curr().length(wfld); - fldlen.add_long(l, j); - } - } - - if (!f.paragraph("Data")) - { - error_box("Formato file non valido: manca il paragrafo [Data]"); - close(); - err = 1; - setstatus(err); - return err; - } - - if (fd) sfd << fd; - int last = NOERR; - - const char* const fmt = FR("Importazione archivio %d da %s\n%6ld records %6ld errori - %3d"); - - s1.format(fmt, _logicnum, from, r, e, last); - TProgind p(nitems, s1); - - while(!f.eof()) - { - if (fixedlen) - f.getline(s.get_buffer(reclen+2), reclen+2); - else - s = f.line(); - if (s.empty()) - break; - - if (extended) - { - int p, i; - - while ((p = s.find("%yr%")) >= 0) - for (i = 0; i < 4; i++) s[p + i] = year[i]; - while ((p = s.find("%frm%")) >= 0) - for (i = 0; i < 5; i++) s[p + i] = firm[i]; - while ((p = s.find("%att%")) >= 0) - for (i = 0; i < 5; i++) s[p + i] = attprev[i]; - } - if ((r + e) % 100 == 0) - { - s1.format(fmt, _logicnum, from, r, e, last); - p.set_text(s1); - } - - if (!p.setstatus((long)f.tellg())) - break; - - zero(); - if (fixedlen) - { - if (s.len() < reclen) - { - error_box(FR("Record di lunghezza errata: %d invece di %d"), s.len(), reclen); - break; - } - int pos = 0; - for (int j = 0; j < nflds; j++) - { - const int l = fldlen.get_int(j); - s1 = s.mid(pos, l); - s1.rtrim(); - put(fld.row(j), s1); - pos += l; - } - } - else - { - s.restart(); - for (int j = 0; j < nflds; j++) - { - s1 = s.get(); - if (fd) - { - s1.rtrim(1); - s1.ltrim(1); - } - if (curr().type((const TString&) fld[j]) == _memofld) - { - TString s2 = s1; - - s1 = esc(s2); - } - - put((const TString&) fld[j], s1); - } - } - - int err = write(); - - if (err == NOERR) - r++; - else - { - e++; - last = status(); - } - } - s1.format(fmt, _logicnum, from, r, e, last); - p.set_text(s1); - - close(); - - setstatus(err); - - // Devo reindicizzare alla fine - if (err == NOERR && !indexed) - packindex(vis, false); - -//aggiorna lo sheet con i nuovi valori di EOX EOD caricati - if (err == NOERR) - update_file(); - - return err; -} - -// @doc EXTERNAL - -// @mfunc Importa un file ascii -// -// @rdesc Ritorna NOERR se l'operazione di lettura e' riuscita, altrimenti il codice di -// di errore generato (vedi ). -int TSystemisamfile::overwrite( - const char* from, // @parm Nome del file da importare - char fs, // @parm Carattere separatore di campo (default ) - char fd, // @parm Carattere delimitatore di campi (default '\\0') - char rs, // @parm Carattere separatore di record (default '\\n') - bool vis) // @parm Indica se visualizzare lo stato dell'operazione (default TRUE) - -// @comm Se

e' TRUE e trova alcune stringhe col formato %stringa% (es. %frm%) -// ne sostituisce i valori (es. ditta corrente). - -// @xref - -{ - int err=NOERR; - FILE* fl = NULL; fopen_s(&fl, from, "r"); - if (fl == NULL) - { - error_box("Impossibile aprire il file %s",from); - clearerr(fl); - setstatus(2); - return 2; - } - TRecnotype r = 0, e = 0, nitems = 0; - TString16 firm, year, attprev("00000"); - - fseek(fl, 0L, SEEK_END); - nitems = ftell(fl); - fclose(fl); - - err = _open_ex(_excllock); - if (err != NOERR) - { - error_box("Impossibile aprire il file %d in modo esclusivo", _logicnum); - return err; - } - - TScanner f(from); - bool fixedlen = (fs == '\0'); - TToken_string s(1024, fixedlen ? char(255) : fs); - int nflds = curr().items(); - TString_array fld(nflds); - TString_array keyfld(nflds); - TAssoc_array vals; - int len[MaxFields]; - TString sfd(3); - TString s1(256); - bool lcf = FALSE; - - if (f.paragraph("Header")) - { - int equal; - TString key; - nflds = 0; - while ((equal = f.line().find('=')) > 0) - { - key = f.token().left(equal); - key.trim(); - if (key == "Version") - { - const unsigned int level = atoi(f.token().mid(equal+1)); - if (level > prefix().filelevel()) - { - const unsigned int stdlevel = prefix().get_stdlevel(); - error_box(FR("L'archivio %s e' stato generato con gli archivi di livello %ld%/%ld.\n Il livello attuale e' %ld/%ld.\n Convertire gli archivi e ripetere l' operazione."), - from, level/100, level%100, stdlevel/100, stdlevel%100); - } - lcf = getlcf(level); - } else - if (key == "File") - { - const int logic = atoi(f.token().mid(equal+1)); - if (logic != num()) - error_box("L'archivio %s e' stato generato dal file %d", - from, logic); - } else - if (key == "Fields") - { - TToken_string riga(f.token().mid(equal+1)); - TToken_string wfd(32, ','); - FOR_EACH_TOKEN(riga, fd) - { - wfd = fd; wfd.strip_spaces(); - fld.add(wfd.get(0)); - len[nflds++] = wfd.get_int(); - } - const RecDes& rd = curr().rec_des(); - const KeyDes& kd = rd.Ky[0]; - - for (int i = 0 ; i < kd.NkFields; i++) - { - const int nf = kd.FieldSeq[i] % MaxFields; - const RecFieldDes& rf = rd.Fd[nf]; - keyfld.add(rf.Name); - } - } - } - } - - if (nflds == 0 || fld.items() == 0) - { - nflds = curr().items(); - for (int j = 0; j < nflds; j++) - { - fld.add(curr().fieldname(j), j); - const TString & wfld = fld.row(j); - int l = 0; - switch (curr().type(wfld)) - { - case _datefld: l = 10; break; - default : l = curr().length(wfld); break; - } - len[j] = l; - } - } - - if (!f.paragraph("Data")) - { - error_box("Formato file non valido: manca il paragrafo [Data]"); - close(); - err = 1; - setstatus(err); - return err; - } - - if (fd) sfd << fd; - int last = NOERR; - - s1.format("Importazione archivio %d da %s\n%6ld records %6ld errori - %3d", - _logicnum, from, r, e, last); - TProgind p(nitems, s1, true, true, 78); - long pos = 16*nflds; - for (s = f.line(); s.not_empty() && !p.iscancelled(); s = f.line()) - { - if ((r + e) % 50 == 0) - { - s1.format("Importazione archivio %d da %s\n%6ld records %6ld errori - %3d", - _logicnum, from, r, e, last); - p.set_text(s1); - } - - pos += s.len()+2; - p.setstatus(pos); - zero(); - vals.destroy(); - if (fixedlen) - { - int pos = 0; - for (int j = 0; j < nflds; j++) - { - const TString & fldname = fld.row(j); - - s1 = s.mid(pos,len[j]); - s1.rtrim(); - vals.add(fldname, s1); - pos += len[j]; - } - } - else - { - s.restart(); - for (int j = 0; j < nflds; j++) - { - const TString & fldname = fld.row(j); - - s1 = s.get(); - if (fd) - { - s1.rtrim(1); - s1.ltrim(1); - } - if (curr().type(fldname) == _memofld) - { - TString s2 = s1; - s1 = esc(s2); - } - vals.add(fldname, s1); - } - } - - FOR_EACH_ARRAY_ROW(keyfld, r0, kfldname) - { - const TString * value = (const TString *) vals.objptr(*kfldname); - - if (value != NULL) - put(*kfldname, *value); - } - - const bool nuovo = read() != NOERR; - - if (nuovo) - zero(); - - - FOR_EACH_ASSOC_STRING(vals, obj, fldname, value) - put(fldname, value); - - const int err = nuovo ? write() : rewrite(); - - if (err == NOERR) - r++; - else - { - e++; - last = status(); - } - } - s1.format("Importazione archivio %d da %s\n%6ld records %6ld errori - %3d", - _logicnum, from, r, e, last); - - p.set_text(s1); - close(); - setstatus(err); - //aggiorna lo sheet con i nuovi valori di EOX EOD caricati - if (err == NOERR) - update_file(); - - return err; -} - -// @doc EXTERNAL - -// @mfunc Esporta VERSO un file ascii. -// -// @rdesc Ritorna NOERR se l'operazione di esportazione e' riuscita, altrimenti il codice di -// di errore generato (vedi ). -int TSystemisamfile::dump( - const char* to, // @parm Nome del file verso quale esportare - int nkey, // @parm Numero della chiave di ordinamento con cui scaricare i dati (defualt 1) - char fs, // @parm Carattere seperatore di campo (defualt ) - char fd, // @parm Carattere delimitatore di campo (default '\\0') - char rs, // @parm Carattere separatore di record (default '\\n') - bool vis, // @parm Indica se visualizzare lo stato dell'operazione (defualt TRUE) - bool withdeleted,// @parm Indica se scaricare anche i record cancellati (dafault FALSE) - const char * filter, // @parm Indica l'espressione filtro - SELECTIONFUNCTION select_func, // @parm funzione filtro - TObject * filter_obj) // @parm oggetto di filtro - -// @xref - -{ - FILE* f = NULL; fopen_s(&f, to, "w"); - if (f == NULL) - { - setstatus(2); - return 2; - } - - if (withdeleted) nkey = 0; - int err = ferror(f); - - open(FALSE, nkey ? TRUE : FALSE); - TString s(512); - bool fixedlen = (fs == '\0'); - int nflds = curr().items(); - TString_array fld(nflds); - TBit_array rjust(nflds); - int len[MaxFields]; - int j; - - for (j = 0; j < nflds; j++) - { - fld.add(curr().fieldname(j), j); - const TString & wfld = fld.row(j); - const TFieldtypes t = curr().type(wfld); - rjust.set(j, t == _intfld || t == _longfld || t == _realfld || - t == _wordfld || t == _intzerofld || t == _longzerofld); - len[j] = (t == _datefld) ? 10 : curr().length(wfld); - if (fixedlen && t == _memofld) - { - error_box(TR("Non e' possibile scaricare a lunghezza fissa un file con campi memo")); - return _isbadtrc; - } - } - TRecnotype i = 0; - const TRecnotype nitems = items(); - - s.format(FR("Esportazione %s"), filename()); - TProgind p(nitems, s, TRUE, TRUE, 70); - TString s1, sfld; - - fprintf(f, "[Header]\nVersion=%ld\nFile=%d", - (long) prefix().filelevel(), num()); - for (int k = 0; k < nflds; k++) - { - if ((k % 10) == 0) fprintf(f, "\nFields="); - else fprintf(f, "|"); - fprintf(f, "%s,%d", (const char *) (const TString&) fld[k], len[k]); - } - fprintf(f, "\n\n[Data]\n"); - if (nkey) - { - setkey(nkey); - for ( first(); status() == NOERR && !p.iscancelled(); next(), i++) - { - p.setstatus(i + 1); - if (filter && *filter) - { - TToken_string filter_str(filter); - TString16 fname; - bool skip = false; - while (!skip && !(fname=filter_str.get()).empty()) - { - const char* fval = filter_str.get(); - const TString& cmp = get(fname); - skip = cmp != fval; - } - skip |= (select_func != NULL) && (select_func(curr(), filter_obj) == false); - if (skip) - continue; - } - s.cut(0); - for (j = 0; j < nflds; j++) - { - const TString& fname = fld.row(j); - if (fixedlen) - { - s1 = get(fname); - if (rjust[j]) s1.right_just(len[j]); - else s1.left_just(len[j]); - } - else - { - s1.cut(0); - if (j && fs) s1 << fs; - if (fd) s1 << fd; - sfld = get(fname); - switch (curr().type(fname)) - { - case _intfld: - case _longfld: - case _intzerofld: - case _longzerofld: - case _realfld: - if (real::is_null(sfld)) - sfld.cut(0); - break; - case _memofld: - if (sfld.full()) - { - int p = 0; - while ((p = sfld.find('\n', 0)) >= 0) - { - sfld.overwrite("\\", p); - sfld.insert("n", p+1); - } - } - else - sfld.cut(0); - break; - default: // strfld, charfld, boolfld - if (sfld.blank()) - sfld.cut(0); - break; - } - s1 << sfld; - if (fd) s1 << fd; - } - s << s1; - } - if (fs) // Elimina tutti i campi vuoti a fine record - { - int i; - for (i = s.len()-1; i >= 0 && s[i] == fs; i--); - s.cut(i+1); - } - fprintf(f, "%s%c", (const char*) s, rs); - } - } - else - { - for (i = 0; i < nitems && !p.iscancelled(); i++) - { - zero(); - p.setstatus(i + 1); - readat(i + 1); - - if (filter && *filter) - { - TToken_string filter_str(filter); - TString16 fname; - bool skip = FALSE; - while (!skip && !(fname=filter_str.get()).empty()) - { - const char* fval = filter_str.get(); - const TString& cmp = get(fname); - skip = cmp != fval; - } - if (skip) - continue; - } - - s=""; - if (withdeleted || curr().valid()) - { - for (j = 0; j < nflds; j++) - { - if (fixedlen) - { - s1 = get((const TString&)fld[j]); - if (rjust[j]) s1.right_just(len[j]); - else s1.left_just(len[j]); - } - else - { - s1 = ""; - if (j && fs) s1 << fs; - if (fd) s1 << fd; - sfld = get((const TString&)fld[j]); - if (curr().type((const TString&) fld[j]) == _memofld) - { - int p = 0; - while ((p = sfld.find('\n', 0)) >= 0) - { - sfld.overwrite("\\", p); - sfld.insert("n", p+1); - } - } - s1 << sfld; - if (fd) s1 << fd; - } - s << s1; - } - fprintf(f, "%s%c", (const char*) s, rs); - } - } - } - p.setstatus(nitems); - close(); - fclose(f); - setstatus(err); - return err; -} - -int TSystemisamfile::dump( - const char* to, // @parm Nome del file verso quale esportare - TToken_string & field_list, // @parm Lista dei campi - int nkey, // @parm Numero della chiave di ordinamento con cui scaricare i dati (defualt 1) - char fs, // @parm Carattere seperatore di campo (defualt ) - char fd, // @parm Carattere delimitatore di campo (default '\\0') - char rs, // @parm Carattere separatore di record (default '\\n') - bool vis, // @parm Indica se visualizzare lo stato dell'operazione (defualt TRUE) - bool withdeleted,// @parm Indica se scaricare anche i record cancellati (dafault FALSE) - const char * filter, // @parm Indica l'espressione filtro - SELECTIONFUNCTION select_func, // @parm funzione filtro - TObject * filter_obj) // @parm oggetto di filtro - -// @xref - -{ - FILE* f = NULL; fopen_s(&f, to, "w"); - if (f == NULL) - { - setstatus(2); - return 2; - } - - if (withdeleted) nkey = 0; - int err = ferror(f); - - open(FALSE, nkey ? TRUE : FALSE); - TString s(512); - bool fixedlen = (fs == '\0'); - int nflds = curr().items(); - TString_array fld(nflds); - TBit_array rjust(nflds); - int len[MaxFields]; - int j = 0; - - FOR_EACH_TOKEN(field_list, str) - { - const TString16 fldname(str); - - fld.add(fldname); - const TFieldtypes t = curr().type(fldname); - rjust.set(j, t == _intfld || t == _longfld || t == _realfld || - t == _wordfld || t == _intzerofld || t == _longzerofld); - len[j++] = (t == _datefld) ? 10 : curr().length(fldname); - if (fixedlen && t == _memofld) - return error_box(TR("Non è possibile scaricare a lunghezza fissa un file con campi memo")); - } - TRecnotype i = 0; - const TRecnotype nitems = items(); - - s.format(FR("Esportazione %s"), filename()); - TProgind p(nitems, s, TRUE, TRUE, 70); - TString s1, sfld; - - fprintf(f, "[Header]\nVersion=%ld\nFile=%d", - (long) prefix().filelevel(), num()); - FOR_EACH_ARRAY_ROW(fld, k, el) - { - if ((k % 10) == 0) fprintf(f, "\nFields="); - else fprintf(f, "|"); - - const TString & fldname =fld.row(k); - - fprintf(f, "%s,%d", (const char *) fldname, len[k]); - } - fprintf(f, "\n\n[Data]\n"); - if (nkey) - { - setkey(nkey); - for ( first(); status() == NOERR && !p.iscancelled(); next(), i++) - { - bool skip = false; - - p.setstatus(i + 1); - if (filter && *filter) - { - TToken_string filter_str(filter); - TString16 fname; - - while (!skip && !(fname=filter_str.get()).empty()) - { - const char* fval = filter_str.get(); - const TString& cmp = get(fname); - skip = cmp != fval; - } - } - skip |= (select_func != NULL) && (select_func(curr(), filter_obj) == false); - if (skip) - continue; - s = ""; - FOR_EACH_ARRAY_ROW(fld, j, el) - { - const TString & fldname =fld.row(j); - - if (fixedlen) - { - s1 = get(fldname); - if (rjust[j]) s1.right_just(len[j]); - else s1.left_just(len[j]); - } - else - { - s1 = ""; - if (j && fs) s1 << fs; - if (fd) s1 << fd; - sfld = get(fldname); - if (curr().type(fldname) == _memofld) - { - int p = 0; - while ((p = sfld.find('\n', 0)) >= 0) - { - sfld.overwrite("\\", p); - sfld.insert("n", p+1); - } - } - s1 << sfld; - if (fd) s1 << fd; - } - s << s1; - } - fprintf(f, "%s%c", (const char*) s, rs); - } - } - else - { - for (i = 0; i < nitems && !p.iscancelled(); i++) - { - zero(); - p.setstatus(i + 1); - readat(i + 1); - - if (filter && *filter) - { - TToken_string filter_str(filter); - TString16 fname; - bool skip = FALSE; - while (!skip && !(fname=filter_str.get()).empty()) - { - const char* fval = filter_str.get(); - const TString& cmp = get(fname); - skip = cmp != fval; - } - if (skip) - continue; - } - - s=""; - if (withdeleted || curr().valid()) - { - FOR_EACH_ARRAY_ROW(fld, j, el) - { - const TString & fldname = fld.row(j); - - if (fixedlen) - { - s1 = get(fldname); - if (rjust[j]) s1.right_just(len[j]); - else s1.left_just(len[j]); - } - else - { - s1 = ""; - if (j && fs) s1 << fs; - if (fd) s1 << fd; - sfld = get(fldname); - if (curr().type(fldname) == _memofld) - { - int p = 0; - while ((p = sfld.find('\n', 0)) >= 0) - { - sfld.overwrite("\\", p); - sfld.insert("n", p+1); - } - } - s1 << sfld; - if (fd) s1 << fd; - } - s << s1; - } - fprintf(f, "%s%c", (const char*) s, rs); - } - } - } - p.setstatus(nitems); - close(); - fclose(f); - setstatus(err); - return err; -} - -#endif // FOXPRO - - -void TBaseisamfile::recover() -{ -} - -//////////////////////////////////////////////////////////// -// Memo data -//////////////////////////////////////////////////////////// - -void TMemo_data::init(TRecnotype recno, TIsam_handle file) -{ - CHECK(file > 0 || recno < 0, "Valid memo recno with NULL memo file"); // verificare - _recno = recno; - _isamfile = file; -} - -void TMemo_data::destroy() -{ - TString_array::destroy(); - _dirty.reset(); - _recno = RECORD_NON_FISICO; - _isamfile = 0; -} - -void TMemo_data::copy(const TMemo_data& m) -{ - TString_array::operator=(m); - _dirty = m._dirty; - _recno = m._recno; - _isamfile = m._isamfile; -} - -//////////////////////////////////////////////////////////// -// TRectype -//////////////////////////////////////////////////////////// - -void TRectype::init(int logicnum) -{ - _logicnum = logicnum; - CHECK(_logicnum > 0,"Impossibile costruire un record di un file esterno"); - - _length = prefix().get_reclen(logicnum); - - _rec = new char [_length]; - *_tab = '\0'; - if (_length > 0) - zero(); - else - setempty(TRUE); - - if (_length > 0 && lf_has_memo(logicnum)) - init_memo(RECORD_NON_FISICO); -} - -TRectype::TRectype(int logicnum) - : _memo_data(NULL) -{ - init(logicnum); -} - -TRectype::TRectype(const TBaseisamfile* i) - : _memo_data(NULL) -{ - init(i->num()); -} - -TRectype::TRectype(const TRectype& r) - : _memo_data(NULL) - -{ - init(r._logicnum); - if (r._memo_data) - { - init_memo(r._memo_data->recno(), r._memo_data->file()); - *_memo_data = *r._memo_data; - } - memcpy(_rec, r._rec, _length); - strcpy_s(_tab, sizeof(_tab), r._tab); - setempty(r.empty()); -} - -TRectype::~TRectype() -{ - if (_rec != NULL) - delete _rec; - if (_memo_data != NULL ) - delete _memo_data; -} - -void TRectype::unknown_field(const char* name) const -{ - static int last_file = 0; - if (_logicnum != last_file) - { - NFCHECK("Il campo '%s' non appartiene al file %d", name, _logicnum); - last_file = _logicnum; - } -} - -void TRectype::write_memo(TIsam_handle file, const TRecnotype recno) -{ - const RecDes& r = rec_des( ); - TIsam_handle orig = _memo_data->file(); - if (orig && (file != orig || recno != _memo_data->recno())) - { - TCodeb_handle cb_orig = prefix().get_handle(orig); - DB_go(cb_orig, _memo_data->recno()); - for(int i = r.NFields - 1; i >= 0; i--) - { - if (r.Fd[i].TypeF == _memofld) - { - if (_memo_data->objptr(i) == NULL) - { - const char* memo = DB_memoptr(cb_orig, r.Fd[i].Name); - if (memo && *memo) - _memo_data->add(memo, i); - } - _memo_data->set_dirty(i); - } - } - } - CHECKD(recno >= 0, "Maiale! Non fare le GO con _recno < 0: ", recno); - const TCodeb_handle cb_handle = prefix().get_handle(file); - DB_go( cb_handle, recno); - FOR_EACH_ARRAY_ROW_BACK((*_memo_data), i, memo) - { - if (_memo_data->is_dirty(i)) - DB_memowrite(cb_handle, r.Fd[i].Name, *memo); - } - DB_flush(cb_handle); - *this = (const char*)DB_getrecord(cb_handle); - init_memo(recno, file); -} - -void TRectype::init_memo(TRecnotype recno, TIsam_handle file) -{ - if (_memo_data == NULL) - _memo_data = new TMemo_data; - else - _memo_data->destroy(); - _memo_data->init(recno, file); -} - -void TRectype::settab(const char *tab) -{ - strcpy_s(_tab, sizeof(_tab), tab); - zero(); -} - -TObject* TRectype::dup() const -{ - TRectype* o = new TRectype(*this); - return o; -} - -const char* TRectype::build_key(int num) const -{ - TString& tmp = get_tmp_string(256); - __build_key(rec_des(), num, string(), tmp.get_buffer(), TRUE); - return tmp; -} - -const char* TRectype::last_key_field(int key) const -{ - const KeyDes& kd = rec_des().Ky[key]; - const int last = kd.NkFields-1; - const bool upp = kd.FieldSeq[last] > MaxFields; - const int nf = upp ? kd.FieldSeq[last] - MaxFields : kd.FieldSeq[last]; - const RecFieldDes& rf = rec_des().Fd[nf]; - return rf.Name; -} - -// @doc EXTERNAL - -// @mfunc Confronta le chiavi di due record -// -// @rdesc Ritorna il risultato di una : -// -// @flag 0 | Se le due chiavi sono uguali -// @flag 0 | Se le due chiavi sono diverse -int TRectype::compare_key( - const TRectype& rec, // @parm Record di cui confrontare le chiavi - int key, // @parm Numero della chiave del presente record (defautl 1) - int skip_last) const // @parm Numero di campi da ignorare nella comparazione a partire dall'ultimo - -// @xref -{ -/* Vecchio modo con molte operazioni su stringhe e molte chiamate a rec_des()! - TString256 key1 = build_key(key); - TString256 key2 = rec.build_key(key); - if (skip_last > 0) - { - const KeyDes& kd = rec_des()->Ky[key-1]; - const int last = kd.NkFields-1; - CHECKD(last >= skip_last, "Can't ignore so many fields in key: ", skip_last); - for (int l = 0; l < skip_last; l++) - { - int nf = kd.FieldSeq[last-l]; - if (nf > MaxFields) nf -= MaxFields; - const RecFieldDes& rf = rec_des()->Fd[nf]; - key1.rtrim(rf.Len); - key2.rtrim(rf.Len); - } - } - const int res = strcmp(key1, key2); -*/ - const char* key1 = build_key(key); - const char* key2 = rec.build_key(key); - int res = 0; - if (skip_last > 0) - { - int maxlen = 0; - const RecDes& rd = rec_des(); - const KeyDes& kd = rd.Ky[key-1]; - const int last = kd.NkFields-skip_last; - for (int l = 0; l < last; l++) - { - const int nf = kd.FieldSeq[l] % MaxFields; - const RecFieldDes& rf = rd.Fd[nf]; - maxlen += rf.Len; - } - res = strncmp(key1, key2, maxlen); - } - else - res = strcmp(key1, key2); - - return res; -} - -HIDDEN bool fld_empty(const char* s, int len, bool /* number */) -{ - if (s && *s && len > 0) - { - for (; len; s++, len--) if (*s != ' ') - return false; - } - return true; -} - -HIDDEN int fld_cmp(const char* a, const char* b, int len, bool number) -{ - int res = memcmp(a, b, len); - if (res == 0) - return res; - - int i = 0; - if (number) // Aggiunta del 11-02-2014: ignoro spazi e zeri iniziali dei numeri - for (; i < len && (*a==' ' || *a=='0') && (*b==' ' || *b=='0'); b++, a++, i++); - - for (; i < len && *a == *b; b++, a++, i++); - if (i == len) - return 0; - - res = *a - *b; - if (number) - { - b -= i; - i = 0; - } - - return fld_empty(b, len - i, number) ? 0 : res; -} - - -/////////////////////////////////////////////////////////// -// TRectype (record di un file) -/////////////////////////////////////////////////////////// - -const RecDes& TRectype::rec_des() const -{ - return prefix().get_recdes(_logicnum); -} - -int TRectype::items() const -{ - return rec_des().NFields; -} - -const char* TRectype::start(int nf) const -{ - return string() + rec_des().Fd[nf].RecOff; -} - -// Confronto tra record: Attenzione i campi vuoti di s non vengono confrontati! -int TRectype::compare(const TSortable& s) const -{ - const TRectype& br = (const TRectype&) s; - int res = 0; - - if (br.empty()) return UNDEFINED; - - const RecDes& rd = rec_des(); - for (int i = 0; i < rd.NFields; i++) - { - const char* b = br.start(i); - const char* a = start(i); - const byte typ = rd.Fd[i].TypeF; - const int sz = rd.Fd[i].Len; - const bool number = (typ == _intfld) || (typ == _realfld) || - (typ == _longfld) || (typ == _wordfld) || - (typ == _intzerofld) || (typ == _longzerofld) || (typ == _datefld) ; - - if (fld_empty(b, sz, number)) continue; - res = ::fld_cmp(a, b, sz, number); - if (res) return res; - } - return 0; -} - -// Confronto stretto -bool TRectype::is_equal(const TRectype& r) const -{ - char* r1 = new char[_length]; - char* r2 = new char[_length]; - memcpy(r1, _rec, _length); - memcpy(r2, r._rec, _length); - browse_null(r1, _length); - browse_null(r2, _length); - - if (has_memo()) - { - const RecDes& rd = rec_des(); - for(int i = rd.NFields - 1; i >= 0; i--) - { - if (rd.Fd[i].TypeF == _memofld) - { - memset(r1+rd.Fd[i].RecOff, ' ', rd.Fd[i].Len); - memset(r2+rd.Fd[i].RecOff, ' ', rd.Fd[i].Len); - } - } - } - bool yes = memcmp(r1, r2, _length) == 0; - delete r1; - delete r2; - - if (yes && has_memo()) - { - const RecDes& rd = rec_des(); - for(int i = rd.NFields - 1; yes && i >= 0; i--) - { - if (rd.Fd[i].TypeF == _memofld) - yes = get(rd.Fd[i].Name) == r.get(rd.Fd[i].Name); - } - } - return yes; -} - -TFieldtypes TRectype::type(const char* fieldname) const -{ - const RecDes& recd = rec_des(); - const int p = findfld(&recd, fieldname); - return p != FIELDERR ? (TFieldtypes)recd.Fd[p].TypeF : _nullfld; -} - -int TRectype::length(const char* fieldname) const -{ - const RecDes& recd = rec_des(); - const int p = findfld(&recd, fieldname); - return p != FIELDERR ? recd.Fd[p].Len : 0; -} - -int TRectype::ndec(const char* fieldname) const -{ - const RecDes& recd = rec_des(); - const int p = findfld(&recd, fieldname); - return p != FIELDERR ? recd.Fd[p].Dec : 0; -} - -bool TRectype::exist(const char* fieldname) const -{ - return findfld(&rec_des(), fieldname) != FIELDERR; -} - -const char* TRectype::fieldname(int i) const -{ - const RecDes& recd = rec_des(); - return i >= 0 && i < recd.NFields ? recd.Fd[i].Name : NULL; -} - -const TString& TRectype::get_str(const char* fieldname) const -{ - const RecDes& recd = rec_des(); - const int nf = findfld(&recd, fieldname); - if (nf != FIELDERR) - { - const RecFieldDes& fd = recd.Fd[nf]; - TString& tmp = get_tmp_string(fd.Len + (fd.TypeF == _datefld ? 2 : 0)); - __getfieldbuff(fd.Len, fd.TypeF, _rec + fd.RecOff, tmp); - return tmp; - } - else - unknown_field(fieldname); - return EMPTY_STRING; -} - -const TString& TRectype::get(const char* fieldname) const -{ - if (_memo_data && type(fieldname) == _memofld) - { - const RecDes& recd = rec_des(); - const int index = findfld(&recd, fieldname); - if ( _memo_data->objptr( index )) - return _memo_data->row( index ); - if (_memo_data->recno() >= 0L) - { - const TIsam_handle orig = _memo_data->file(); - if (orig) - { - CHECKD(orig >= LF_EXTERNAL || orig == num(), "Invalid isam handle ", orig); - TCodeb_handle cb_handle = prefix().get_handle(orig, -1); - CHECKD(cb_handle >= 0, "Can't read memo from file ", orig); - if (DB_recno(cb_handle) != _memo_data->recno()) - DB_go(cb_handle, _memo_data->recno()); - _memo_data->add(DB_memoptr(cb_handle, fieldname), index); - } - else - NFCHECK("Valid memo recno with null memo file"); - } - else - _memo_data->add("", index); - return _memo_data->row(index); - } - return get_str(fieldname); -} - -int TRectype::get_int(const char* fieldname) const -{ - return atoi(get_str(fieldname)); -} - -long TRectype::get_long(const char* fieldname) const -{ - return atol(get_str(fieldname)); -} - - -word TRectype::get_word(const char* fieldname) const -{ - return (word)atoi(get_str(fieldname)); -} - -real TRectype::get_real(const char* fieldname) const -{ - const real r(get_str(fieldname)); - return r; -} - -char TRectype::get_char(const char* fieldname) const -{ - return get_str(fieldname)[0]; -} - -bool TRectype::get_bool(const char* fieldname) const -{ - const char c = get_char(fieldname); - return (c == 'X') || (c == '1'); -} - -TDate TRectype::get_date(const char* fieldname) const -{ - const TDate d(get_str(fieldname)); - return d; -} - -void TRectype::put(const char* fieldname, int val) -{ - char tmp[16]; - _itoa_s(val, tmp, 10); - put_str(fieldname, tmp); -} - - -void TRectype::put(const char* fieldname, long val) -{ - char tmp[16]; - _ltoa_s(val, tmp, 10); - put_str(fieldname, tmp); -} - - -void TRectype::put(const char* fieldname, word val) -{ - put(fieldname, (int)val); -} - -void TRectype::put(const char* fieldname, const real& val) -{ - put_str( fieldname, val.string()); -} - -void TRectype::put(const char* fieldname, const TCurrency& val) -{ - put_str( fieldname, val.get_num().string()); -} - -void TRectype::put(const char* fieldname, const TDate& val) -{ - put( fieldname, val.date2ansi()); -} - -void TRectype::put(const char* fieldname, char val) -{ - const char w[2] = { val, '\0' }; - put_str( fieldname, w); -} - - -void TRectype::put(const char* fieldname, bool val) -{ - put(fieldname, val ? 'X' : ' '); -} - - -void TRectype::put_str(const char* fieldname, const char* val) -{ - const RecDes& recd = rec_des(); - const int nf = findfld(&recd, fieldname); - if (nf == FIELDERR) - { - unknown_field(fieldname); - return; - } - - const RecFieldDes& fd = recd.Fd[nf]; - const TFieldtypes ft = TFieldtypes(fd.TypeF); - - if (val == NULL) - val = ""; - if (ft == _boolfld) - val = (*val && strchr("1STXY", toupper(*val)) != NULL) ? "T" : "F"; - - if (*val == '\0') // VERIFICARE COL REPOSITORY - { - TRecfield f(*this, fieldname); - if (*f.pos() == '\0') return; - } - if(ft == _memofld) - { - _memo_data->add(val, nf); - _memo_data->set_dirty(nf); - } - else - { - __putfieldbuff(fd.Len, fd.Dec, ft, val, _rec + fd.RecOff); - } - - setempty(FALSE); -} - -void TRectype::add(const char* fieldname, const real& val) -{ - if (!val.is_zero()) - { - real k = get_real(fieldname); - k += val; - put(fieldname, k); - } -} - -void TRectype::zero(const char* fieldname) -{ - if (*_tab && strcmp(fieldname , "COD") == 0) - put("COD", _tab); - else - { - const RecDes& recd = rec_des(); - const int nf = findfld(&recd, fieldname); - if (nf == FIELDERR) - unknown_field(fieldname); - else - { - const int recoff = recd.Fd[nf].RecOff; - char * p = _rec + recoff; - const byte len = recd.Fd[nf].Len; - const byte dec = recd.Fd[nf].Dec; - const TFieldtypes type = (TFieldtypes) recd.Fd[nf].TypeF; - switch (type) - { - case _datefld: - __putfieldbuff(len, dec, _datefld, "", p); - break; - case _memofld: - __putfieldbuff(len, dec, _memofld, "", p); - _memo_data->add("", nf); - _memo_data->set_dirty(nf); - break; - default: - memset(p, ' ', len); - if ((type == _intfld) || (type == _longfld) || (type == _wordfld)) - *(p + len - 1) = '0'; - else - if (type == _realfld) - { - if (dec) - { - memset(p + len - dec - 2, '0', dec + 2); - *(p + len - dec - 1) = '.'; - } - else - *(p + len - 1) = '0'; - } - break; - } - } - } -} - -void TRectype::zero(char c) -{ - memset(_rec, c, len()); - recall(); - - if (*_tab) - put("COD", _tab); - - if(has_memo()) - init_memo( RECORD_NON_FISICO ); - setempty(TRUE); -} - - -// Certified 99% -TRectype& TRectype::operator =(const TRectype& rec) - -{ - CHECK(num() == rec.num(), "Can't assign records of different file"); - - memcpy(_rec, rec._rec, _length); // Copy contents - if (rec._memo_data) - { - init_memo(rec._memo_data->recno(), rec._memo_data->file()); - *_memo_data = *rec._memo_data; - } - strcpy_s(_tab, sizeof(_tab), rec._tab); - setempty(rec.empty()); // Copy emptiness status - return *this; -} - -// Certified 100% -TRectype& TRectype::operator =(const TBaseisamfile& f) -{ - return *this = f.curr(); -} - -// Certified 50% -int TRectype::read(TBaseisamfile& f, word op, word lockop) -{ - int err = f._read(*this,op,lockop); - return err; -} - -int TRectype::readat(TBaseisamfile& f, TRecnotype nrec, word lockop) -{ - return f._readat(*this,nrec,lockop); -} - - -// Certified 100% -int TRectype::next(TBaseisamfile& f,word lockop) -{ - return read(f, _isnext, lockop); -} - -// Certified 100% -int TRectype::prev(TBaseisamfile& f,word lockop) -{ - return read(f, _isprev, lockop); -} - -int TRectype::first(TBaseisamfile& f,word lockop) -{ - return read(f, _isfirst, lockop); -} - -int TRectype::last(TBaseisamfile& f,word lockop) -{ - return read(f, _islast, lockop); -} - -// Certified ??% -int TRectype::write(TBaseisamfile& f) const -{ return f._write(*this); } - -// Certified ??% -int TRectype::rewrite(TBaseisamfile& f) const -{ - return f._rewrite(*this); -} - -int TRectype::write_rewrite(TBaseisamfile& f) const -{ - int err = write(f); - if (err == NOERR) - f._read((TRectype&)*this, _iscurr, _unlock); // Sblocca record 19-09-2012 (andrebbe nella _write) - else - err = rewrite(f); - return err; -} - -int TRectype::rewrite_write(TBaseisamfile& f) const -{ - int err = rewrite(f); - if (err != NOERR) - { - err = write(f); - if (err == NOERR) - f._read((TRectype&)*this, _iscurr, _unlock); // Sblocca record 19-09-2012 (andrebbe nella _write) - } - return err; -} - -// Certified ??% -int TRectype::remove(TBaseisamfile& f) const -{ - return f._remove(*this); -} - -void TRectype::renum_key(const char* field, const char* val) -{ - if (strchr(field, '[') != NULL) // Accept CODTAB[6,10] - { - const TFieldref fref(field, 0); - TString80 str = val; - if (real::is_natural(val)) - str.right_just(fref.len(*this), '0'); - fref.write(str, *this); - } - else - put(field, val); -} - -// Certified 99% -TRectype& TRectype::operator =(const char* rec) -{ - if (rec && *rec) - { - memcpy(_rec, rec, _length); - setempty(false); - } - else - zero(); - return *this; -} - -const char* TRectype::key(int numkey) const -{ - TString& tmp = get_tmp_string(256); - __build_key(rec_des(), numkey, _rec, tmp.get_buffer(), false); - return tmp; -} - -void TRectype::fill_transaction(TConfig& cfg, int row) const -{ - TString16 p; p << num(); - if (row > 0) p << ',' << row; - cfg.set_paragraph(p); - - for (int f = items()-1; f >= 0; f--) - { - const char* name = fieldname(f); - const char* value = get(name); - cfg.set(name, value); - } -} - -bool TRectype::send_mail(const char* action) const -{ - TWait_cursor hourglass; - bool ok = ::can_dispatch_transaction(*this); - if (ok) - { - TFilename ininame; ininame.temp("msg", "ini"); - if (ok) // Dummy test per {} - { - TConfig ini(ininame, "Transaction"); - ini.set("Action", action); - ini.set("Mode", "A"); - fill_transaction(ini); - } - ok = ::dispatch_transaction(*this, ininame); - ininame.fremove(); - } - return ok; -} - -bool TRectype::get_relapp(TString& app) const -{ - if (*_tab) - { - TString4 cod(_tab); - switch (num()) - { - case LF_TABCOM: cod.insert("%"); break; - case LF_TABGEN: cod.insert("^"); break; - case LF_TABMOD: - { - TModule_table mod(_tab); - return mod.get_relapp(app); - } - break; - default : break; - } - return ::get_tabapp(cod, app); - } - return ::get_relapp(num(), app); -} - -bool TRectype::edit(int logicnum, const char* alternate_key_fields, const char* hint) const -{ - bool ok = false; - if (logicnum <= 0) - logicnum = num(); - - TRectype r(logicnum); - if (*_tab) - r.settab(_tab); - - TString app = hint; - if (app.blank()) - r.get_relapp(app); - if (app.full()) - { - const RecDes& recd = r.rec_des(); // Descrizione del record della testata - const KeyDes& kd = recd.Ky[0]; // Elenco dei campi della chiave 1 - TToken_string key_labels; - for (int i = 0; i < kd.NkFields; i++) - { - const int nf = kd.FieldSeq[i] % MaxFields; - const RecFieldDes& rf = recd.Fd[nf]; - key_labels.add(rf.Name); - } - - TToken_string key_fields(alternate_key_fields); - if (key_fields.empty_items()) - key_fields = key_labels; - - TFilename ininame; ininame.temp("lnk", "ini"); - { - TConfig ini(ininame, "Transaction"); - ini.set("Action", "LINK"); - TString8 p; p << logicnum; - ini.set_paragraph(p); - - FOR_EACH_TOKEN(key_labels, tok) - { - const TString16 name(tok); - const TString& value = get(key_fields.get()); - ini.set(name, value); - } - } - - app << " -i" << ininame; - TExternal_app a(app); - ok = a.run() == 0; - - if (ok) - { - xvt_sys_sleep(500); - const TString& result = ini_get_string(ininame, "Transaction", "Result"); - ok = result == "OK"; - } - - xvt_fsys_remove_file(ininame); - - if (ok) - rec_cache(logicnum).notify_change(); - } - return ok; -} - -bool TRectype::set_edit_info(const char* ut, const char* dt, const char* or) -{ - bool ok = false; - if (num() > LF_TAB) // Inutile tentare di gestire le tabelle - { - // Se esiste un campo alfanumerioco UT* - if (ut && *ut && type(ut) == _alfafld) - { - put(ut, user()); // Scrivi utente corrente - ok = true; - - // Se esiste un campo data DT* - if (dt && *dt && type(dt) == _datefld) - { - const TDate oggi(TODAY); - put(dt, oggi); // Scrivi data odierna - - // Se esisnte un campo long OR* - if (or && *or && (type(or) == _longfld || type(or) == _longzerofld)) - put(or, daytime()); // Scrivi ora attuale HHMMSS - } - } - } - return ok; -} - -bool TRectype::set_modify_info() -{ - return set_edit_info("UTCREAZ", "DTCREAZ", "ORCREAZ"); -} - -bool TRectype::set_creation_info() -{ - return set_edit_info("UTULAGG", "DTULAGG", "ORULAGG"); -} - -/////////////////////////////////////////////////////////// -// TRecfield (campo/sottocampo di un record) -/////////////////////////////////////////////////////////// - -TRecfield::TRecfield(TRectype& rec, const char* name, int from, int to) -{ - _rec = &rec; - - const TFixed_string fname(name); - const int colon = fname.find(':'); - if (colon > 0) - { - _name.strncpy(name, colon); - _sub_field = name+colon+1; - _sub_field << '='; // ??????????????? - } - else - _name = name; - - const RecDes& rd = _rec->rec_des(); - - const int nf = findfld(&rd, _name); - - if (nf == FIELDERR) - { - _sub_field = _name; - _p = _rec->string(); - _len = 0; - _dec = 0; - _type = _alfafld; - } - else - { - if (from < 0) - { - NFCHECK("Invalid Start %d", from); - from = 0; - } - _p = _rec->string() + rd.Fd[nf].RecOff; - _dec = rd.Fd[nf].Dec; - _type = (TFieldtypes)rd.Fd[nf].TypeF; - if (_sub_field.empty()) - { - _p += from; - if (to >= 0) - { - CHECKS(_type == _memofld || (from <= to && to <= rd.Fd[nf].Len), "Invalid Range on field ", (const char *)_name); - _len = to - from + 1; - } - else - _len = rd.Fd[nf].Len - from; - } - else - { - CHECK(_type == _memofld, "You can use Subfields only with Memo"); - _from = from; - _to = to; - if (_type == _memofld) - _len = 0; - else - _len = rd.Fd[nf].Len; - } - } - - CHECKS(colon < 0 || _type == _memofld, "SubField on non memo field: ", name); -} - -void TRecfield::put_subfield(const char* s) -{ - if (_name == _sub_field) - return; - const TString& str = _rec->get(_name); - int p = str.find(_sub_field); - - if (p == 0 || (p > 0 && str[p - 1] < ' ')) - { - p += _sub_field.len(); - - int e = str.find('\n', p); - - if (_to > 0 && p + _to < e) - e = p + _to; - p += _from; - if (p < e) - { - TString val(s); - - if (_to > 0) - { - val.left(e - p + 1); - val.rpad(e - p + 1); - } - TString out = str.left(p); - out << val << str.mid(e); // ? e + 1 - _rec->put(_name, out); - } - } -} - -int TRecfield::operator =(int i) -{ - TString16 buff; buff << i; - if (_sub_field.empty()) - __putfieldbuff( _len, _dec, _type, buff, _p); - else - put_subfield(buff); - _rec->setempty(FALSE); - return i; -} - - -long TRecfield::operator =(long l) -{ - TString16 buff; buff << l; - if (_sub_field.empty()) - __putfieldbuff( _len, _dec, _type, buff, _p); - else - put_subfield(buff); - _rec->setempty(false); - return l; -} - -const real& TRecfield::operator =(const real& r) -{ - const char* buff = r.string(); - if (_sub_field.empty()) - __putfieldbuff( _len, _dec, _type, buff, _p); - else - put_subfield(buff); - _rec->setempty(FALSE); - return r; -} - -const TDate& TRecfield::operator =(const TDate& d) -{ - const TString16 buff = d.stringa(); - if (_sub_field.empty()) - __putfieldbuff( _len, _dec, _type, buff, _p); - else - put_subfield(buff); - _rec->setempty(FALSE); - return d; -} - -const char* TRecfield::operator =(const char* s) -{ - if (_sub_field.empty()) - { - if (_type == _memofld) - _rec->put(_name, s); - else - __putfieldbuff( _len, _dec, _type, s, _p); - } - else - put_subfield(s); - _rec->setempty(FALSE); - return s; -} - -void TRecfield::setptr(TRecnotype r) -{ - if (_p == NULL) return; - - bool n = r < 0; - unsigned char* wp = (unsigned char*) _p; - - if (n) r = -r; - while(wp - (unsigned char*) _p <= 3) - { - *wp = r && 0x000000FF; - r >>= 8; - wp++; - } - if (n) *wp += 128; -} - -void TRecfield::get_subfield(TString& s) const -{ - const TString& str = _rec->get(_name); - - if (_name == _sub_field) - s = str; - else - { - int p = str.find(_sub_field); - - if (p == 0 || (p > 0 && str[p - 1] < ' ')) - { - p += _sub_field.len(); - - int e = str.find('\n', p); - if (e < 0) e = str.len(); // L'ultima variabile non termina con \n - if (_to > 0 && p + _to < e) - e = p + _to; - p += _from; - if (p < e) - s = str.sub(p, e); - else - s.cut(0); - } - else - s.cut(0); - } -} - -TRecfield::operator int() const -{ - TString16 tmp; - if (_sub_field.empty()) - { - if (_type == _intfld || _type == _intzerofld || _type == _longfld || _type == _longzerofld) - tmp.strncpy(_p, _len); - else - __getfieldbuff( _len, _type, _p, tmp); - } - else - get_subfield(tmp); - return atoi(tmp); -} - - -TRecfield::operator long() const -{ - TString16 tmp; - - if (_sub_field.empty()) - { - if (_type == _longfld || _type == _longzerofld || _type == _intfld || _type == _intzerofld) - tmp.strncpy(_p, _len); - else - __getfieldbuff( _len, _type, _p, tmp); - } - else - get_subfield(tmp); - - return atol(tmp); -} - - -TRecfield::operator const real() const -{ - TString80 tmp; - - if (_sub_field.empty()) - { - if (_type == _realfld) - tmp.strncpy(_p, _len); - else - __getfieldbuff( _len, _type, _p, tmp); - } - else - get_subfield(tmp); - - return real(tmp); -} - - -TRecfield::operator TDate() const -{ - TString16 tmp; - - if (_sub_field.empty()) - { - if (_type == _datefld) - { - tmp.strncpy(_p, 8); - return TDate(atol(tmp)); - } - __getfieldbuff(_len, _type, _p, tmp); - } - else - get_subfield(tmp); - - return TDate(tmp); -} - - -TRecfield::operator const char*() const -{ - TString& tmp = get_tmp_string(max(_len, 50)); - - if (_sub_field.empty()) - { - if (_type == _memofld) - return _rec->get(_name); - __getfieldbuff(_len, _type, _p, tmp); - } - else - get_subfield(tmp); - - return tmp; -} - - -TRecnotype TRecfield::ptr() const -{ - if (_p == NULL) return(RECORD_NON_FISICO); - unsigned char* wp = (unsigned char*) _p + 3; - TRecnotype r = *wp; - bool n = r > 127; - - if (n) r -= 128; - while(wp-- > (unsigned char*) _p) - r = (r << 8) + *wp; - return n ? -r : r; -} +#define __ISAM_CPP +#define _CRT_SECURE_NO_WARNINGS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include +#include +#include +#endif + +#include +#include +#include + +#include +#include + +#define RECLOCKTYPES 0xFF00 +#define READTYPES 0x00FF +#define INVFLD 255 + +bool __field_changed = FALSE; + +#define NOALLOC (char **) -1 + +HIDDEN bool __autoload = TRUE; + +// @doc INTERNAL + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Funzioni C +//////////////////////////////////////////////////////////////////////////////////////////////////// + +int hashfun(const char *s) +{ + int l = strlen(s); + unsigned short temp = 0, *pw = (unsigned short *) s; + + const unsigned short * end = (unsigned short *) (s + (l - 1)); + while ((char *) pw < (char *) end) + { + temp ^= *pw; + pw++; + } + if (l & 1) + temp ^= (unsigned short ) (8192 + s[l - 1]); + l = (short) (temp % (MaxFields - 3)); + CHECKS(l >= 0, "Negative remainder on ", s); + return(l); +} + +int findfld(const RecDes *recd, const char *s) +{ + short stp = hashfun(s); + + for (byte i = 0 ; i < MaxFields; i++) + { + if (stp + i >= MaxFields) + stp -= MaxFields; + byte p = stp + i; + const int fp = recd->SortFd[p]; + if (fp == INVFLD) + return(FIELDERR); + + const int cmp = strcmp(recd->Fd[fp].Name, s); + if (cmp == 0) + return (int) fp; + else + if (cmp > 0) + return(FIELDERR); + } + return(FIELDERR); +} + +void __getfieldbuff(byte l, byte t, const char * recin, TString& s) +{ + CHECK(recin, "Can't read from a Null record"); + + if (t != _alfafld && t != _datefld) + { + if (t == _intzerofld || t == _longzerofld) + { + byte i = 0; + for (char* c = (char*)recin; *c == ' ' && i < l; c++, i++) + *c = '0'; + if (i == l) + l = 0; + } + else + { + while ((*recin == ' ') && (l)) + { + recin++; + l--; + } + if ((t != _realfld) && (t != _charfld)) + { + while ((*recin == '0') && (l)) + { + recin++; + l--; + } + } + } + } + + if (l) + { + while(l > 0 && recin[l - 1] == ' ') l--; + if (l) + s.strncpy(recin, l); + } + s.cut(l); + if (l) + { + if (t == _datefld) + { + const TDate dt(s); + s = dt.string(full); + } + else + { + if (t == _boolfld) + { + const char ok = toupper(*s); + if (ok == 'T' || ok == 'Y' || ok == 'S' || ok == 'X') + s = "X"; + else + s.spaces(1); + } + } + } +} + +void __putfieldbuff(byte l, byte d, byte t, const char* s, char* recout) +{ + CHECK(recout, "Can't write null record" ); + + TString80 s2; + if (t == _datefld) + { + if (s && *s && strlen(s) != 8) + { + const TDate dt(s); + s2 << dt.date2ansi(); + s = s2.get_buffer(); + } + } + else + if (t == _boolfld) + { + s2 = (*s && strchr("1STXY", toupper(*s)) != NULL) ? "T" : "F"; + s = s2.get_buffer(); + } + else + if (t == _realfld) + { + real r(s); + s2 = r.string(l, d); + s = s2.get_buffer(); + } + + int len = strlen(s); + const bool exceeded = len > l; + + if ((t == _intfld) || + (t == _longfld) || + (t == _wordfld) || + (t == _realfld) || + (t == _intzerofld) || + (t == _longzerofld) + ) + { + if (len == 0 || exceeded) + { + s2 = "0"; + s = s2.get_buffer(); + len = 1; + } + + __field_changed = FALSE; + const char c = (t == _intzerofld || t == _longzerofld) ? '0' : ' '; + for (int i = l - len - 1; i >= 0; i--) + { + __field_changed |= (recout[i] != c); + recout[i] = c; + } + if (!__field_changed) + { + __field_changed = memcmp(s, recout, l) != 0; + if (!__field_changed) + return; + } + strncpy(&recout[l-len], s, len) ; + } + else + { + if (exceeded) + len = l; + +/* + // Il codice seguente e' completamente errato in quanto tutti i prefissi ingannano il test! + // La stringa vuota e' prefisso di qualsiasi stringa + // per cui l'azzeramento di un campo risulta sempre impossibile! + + __field_changed = memcmp(s, recout, len) != 0; + if (!__field_changed) + return; +*/ + __field_changed = TRUE; // Per ora e' meglio cosi' + + strncpy(recout, s, len) ; + for (int i = l - 1; i >= len; i--) + recout[i] = ' '; + } +} + +struct TCallbackFileinfo +{ + TString16 _var; + TFilename _app; +}; + +HIDDEN int find_relapp(TConfig& cfg, void* jolly) +{ + TCallbackFileinfo& info = *((TCallbackFileinfo*)jolly); + if (cfg.exist(info._var)) + { + info._app = cfg.get(info._var); + return info._app.not_empty(); + } + return FALSE; +} + +bool get_relapp(int logicnum, TString& app) +{ + TConfig ini(CONFIG_GENERAL); + TCallbackFileinfo fi; + fi._var.format("Edit_%d", logicnum); + ini.for_each_paragraph(find_relapp, &fi); + if (fi._app.not_empty()) + app = fi._app; + return app.not_empty(); +} + +struct TCallbackTableinfo +{ + TString16 _var1, _var2, _var3; + TString4 _module; + TFilename _tabapp, _relapp; +}; + +HIDDEN int find_tabapp(TConfig& cfg, void* jolly) +{ + TCallbackTableinfo& info = *((TCallbackTableinfo*)jolly); + + if (cfg.exist(info._var1)) + { + info._tabapp = cfg.get(info._var1); + if (info._tabapp.not_empty()) + return 1; + } + if (cfg.get_paragraph().compare(info._module, 2, TRUE) == 0) + { + if (cfg.exist(info._var2)) + { + info._relapp = cfg.get(info._var2); + if (info._relapp.not_empty()) + return 2; + } + if (info._var3.full() && cfg.exist(info._var3)) + { + info._relapp = cfg.get(info._var3); + if (info._relapp.not_empty()) + return 3; + } + } + return 0; +} + +bool get_tabapp(const char* tabname, TString& app) +{ + TConfig ini(CONFIG_GENERAL, "Main"); + TCallbackTableinfo fi; + TTable t(tabname); + fi._var1.format("Edit_%s", t.name()); + fi._var2.format("Edit_%d", t.num()); + fi._var3.format("Edit_%d", t.num() == LF_TABCOM ? LF_TAB : LF_TABCOM); + fi._module = t.module(); + ini.for_each_paragraph(find_tabapp, &fi); + + app = fi._tabapp; + if (app.empty()) + app = fi._relapp; + + if (app.empty()) + { + app = "ba3 -0"; + if (!fi._module.starts_with("ba")) // Compatibility mode :-( + { + const TString& tp = ini_get_string(CONFIG_STUDIO, fi._module, "TabPrg"); + if (tp.full()) + app = tp; + } + } + app << ' ' << tabname; + return tabname && *tabname > ' '; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Funzioni implementate per la gestione file dati tramite Codebase +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Inizio(@) + +// @doc INTERNAL + +// @func Ritorna una Token_string con in nome dell'indice +int get_table_names( + int logicnum, // @parm Numero logico del file di cui riconoscere l'indice + TToken_string& i_names, // @parm Token_string in cui inserire il nome dell'indice + int mode) + +// @comm Ritorna il nome con il prefisso corrente +{ + TFilename f = prefix().get_filename(logicnum); + i_names.cut(0); + + if (mode & 1) + i_names = f; + + if (mode & 2) + { + f.ext("cdx"); + i_names.add(f); + } + + if (mode & 4) + { + f.ext("fpt"); + if (f.exist()) + i_names.add(f); + } + + return i_names.items(); +} + +// Converte un errore di codebase in un errore isam +#ifdef DBG +HIDDEN int cb_error = NOERR; +#endif + +int get_error(int err) +{ +// Codici negativi +HIDDEN int error_codes_g[] = {-1,_isnotopen,-1,-1,-1,_islocked,-1,-1,-1,-1,-1,-1,_isfilefull, + -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,_iskeynotfound,_ispatherr,-1,-1,_isdupkey}; +// Codici da 0 a 9 +HIDDEN int error_codes_ra[] = {NOERR,NOERR,_iskeynotfound,_iseof,_isbof,_isnrecerr} ; +// Codici da 10 a ... +HIDDEN int error_codes_rb[] = {-1,-1,_isreinsert,-1,-1,_islocked,-1,_isalropen,_iskeyerr } ; + + int isamerr = NOERR; + +#ifdef DBG + if (err <= 200 || err >= 230) + cb_error = err; +#endif + + if (err > 0) + { + if (err >= 10) + { + if (err > 80 || error_codes_rb[err/10]==-1) + isamerr = err; + else + isamerr = error_codes_rb[err/10]; + } + else + isamerr = error_codes_ra[err]; + } + else + if (err < 0) + { + if (err == -1) + { +#ifdef DBG + int ierr = DB_get_error(); +#endif + isamerr = _isnotopen; + } + else + { + int ierr = DB_get_error(); + if (ierr == 0) ierr = -err; // DB_get_error already called + if (ierr < 0) ierr = -ierr; + if (ierr > 340 || error_codes_g[ierr/10]==-1) + isamerr = -ierr; + else + isamerr = error_codes_g[ierr/10]; + } + } + DB_zero_error(); + return isamerr; +} + +// Used also by varrec +bool rec_has_memo(const RecDes& rd) +{ + for( int i = rd.NFields - 1; i >= 0; i--) + if (rd.Fd[i].TypeF == _memofld) + return true; + return false; +} + +HIDDEN bool lf_has_memo(int lffile) +{ + return rec_has_memo(prefix().get_recdes(lffile)); +} + +HIDDEN void browse_null(char *start, int nc) +{ + for (int i = nc - 1; i >= 0 ; i--) // Anche il primo byte(deletion flag) deve essere cambiato. nc comprende il primo byte + if (start[i] == '\0') start[i] = ' '; +} + +// Traduce l'espressione chiave di CodeBase + +HIDDEN int __build_key(const RecDes& recd, int numkey, const RecType recin, char *key, bool build_x_cb) + /* *recd; descrittore record */ + /* numkey; numero chiave */ + /* recin; buffer contenente il record */ + /* *key; valore della chiave */ + /* build_x_cb flag di costruzione per codebase */ +{ + CHECKD(numkey > 0, "Can't build key ", numkey); + + const char null_char = -1; + key[0] = '\0'; + if (numkey-- <= recd.NKeys) + { + int l = 0; + for (int i = 0; i < recd.Ky[numkey].NkFields; i++) + { + const KeyDes& kd = recd.Ky[numkey]; + const bool upp = kd.FieldSeq[i] > MaxFields; + const int nf = upp ? kd.FieldSeq[i] - MaxFields : kd.FieldSeq[i]; + const RecFieldDes& rf = recd.Fd[nf]; + const TFieldtypes f = (TFieldtypes) rf.TypeF; + + int off, len; + if (kd.FromCh[i] == 255) + { + off = rf.RecOff; + len = rf.Len; + } + else + { + off = rf.RecOff + kd.FromCh[i]; + len = kd.ToCh[i] - kd.FromCh[i] + 1; + } + if ((l + len) > 255) + { + key[0] = '\0'; + return(_iskeylenerr); + } + if (f == _boolfld) + { + const bool on = *(recin + off) > ' ' && strchr("STXY", *(recin + off)) != NULL; + key[l] = on ? 'T' : 'F'; + } + else + strncpy((key + l), (recin + off), len); + + if (recin[off] == '\0') + { + memset(key + l, ' ', len); + if ((f == _intfld) || (f == _longfld) || (f == _wordfld) || + (f == _intzerofld) || (f == _longzerofld)) + key[l + len - 1] = build_x_cb ? '0' : null_char; + } + else + if ((f == _intfld) || (f == _longfld) || (f == _wordfld) || (f == _intzerofld) || (f == _longzerofld)) + { + int w = l, j = l + len; + while (w < j && key[w] == ' ') w++; + while (w < j && key[w] == '0') key[w++] = ' '; + if (w == j) key[w-1] = build_x_cb ? '0' : null_char; + } + if (upp) + for (int i = l+len-1; i >= l; i--) + key[i] = toupper(key[i]); + + l += len; + } + + // rtrim + if (build_x_cb) + { + for (l--; l>=0 && key[l] == ' '; l--); + key[l + 1] = '\0'; + } + else + { + for (l--; l>=0 && (key[l] == ' ' || key[l] == null_char); l--); + key[l + 1] = '\0'; + for (;l >= 0; l--) + if (key[l] == null_char) + key[l] = '0'; + } + + return(NOERR); + } + return(_ispatherr); +} + + +HIDDEN int cisread(int fhnd, int knum, TRectype& record, int mode, TRecnotype& curr_recno) +{ + CHECKD(fhnd >= 0, "Can't use codebase handle ", fhnd); + + const int rmode = (mode & READTYPES); + const int lmode = (mode & RECLOCKTYPES); + + // Non usare mai _isnextn o _isprevn, usare il metodo skip! + CHECK (rmode !=_isnextn && rmode !=_isprevn, "_isnextn and _isprevn not supported in cisread"); + + TString256 keystr; + char* key = keystr.get_buffer(); + + int err = NOERR; + do + { + if (rmode>=_isequal && rmode<=_isgteq) + { + const RecDes& r = record.rec_des(); + err=__build_key(r, knum, record.string(),key,TRUE); + if (err == NOERR) + { + err = DB_seek(fhnd,key); + if (err == NOERR && rmode == _isgreat) + err = DB_next(fhnd); + if (err != NOERR) + err = get_error(err); + } + if (rmode != _isequal && err == _iskeynotfound) + err = NOERR; + } + else + { + if (rmode==_isfirst) + err=DB_first(fhnd); + else + if (rmode==_islast) + err=DB_last(fhnd); + else + if (rmode==_isnext) + { + if (curr_recno != DB_recno(fhnd)) + { + const RecDes& r = record.rec_des(); + err = __build_key(r, knum, record.string(),key,TRUE); + if (err == NOERR) + { + err = DB_seek(fhnd,key); + err = get_error(err); + if (err != NOERR && err != _iskeynotfound && err != _iseof) + fatal_box("Errore nella next %d : non posso riposizionarmi", err); + else + if (err == NOERR) + err=DB_next(fhnd); + } + } + else + err=DB_next(fhnd); + } + else + if (rmode==_isprev) + { + if (curr_recno != DB_recno(fhnd)) + { + const RecDes& r = record.rec_des(); + err = __build_key(r, knum, record.string(),key,TRUE); + if (err == NOERR) + { + err = DB_seek(fhnd,key); + err = get_error(err); + if (err != NOERR && err != _iskeynotfound && err != _iseof) + fatal_box("Errore nella prev %d : non posso riposizionarmi", err); + else + if (err == NOERR) + err=DB_prev(fhnd); + } + } + else + err=DB_prev(fhnd); + } + else + if (rmode==_iscurr) + err=DB_go(fhnd,DB_recno(fhnd)); + if (err != NOERR) + err=get_error(err); + } + + if (err == _iseof) + DB_last(fhnd); + if (err == NOERR && (lmode == _lock || lmode == _testandlock)) // _lock e _testandlock + { + err=DB_lock(fhnd); + if (err != NOERR) + err = get_error(err); + if (err == _islocked && lmode == _testandlock) + break; + } + if (err == _islocked) + { + const RecDes& r = record.rec_des(); + record = (const char*)DB_getrecord(fhnd); + __build_key(r, knum, record.string(), key, TRUE); + message_box("Codice %s in uso da parte\ndi un altro utente.", key); + if (lmode != _lock) + break; + } + } while (err ==_islocked); + + if (err == NOERR && lmode == _unlock) + { + err=DB_unlock(fhnd); + if (err != NOERR) + err = get_error(err); + } + + curr_recno = DB_recno(fhnd); + record = (const char *)DB_getrecord(fhnd); + + return err; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Funzioni implementate per la gestione file dati tramite Codebase +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Fine(@) + +// @doc EXTERNAL + +// @func Setta il valore della variabile

+void set_autoload_new_files( + bool on) // @parm Valore da assegnare + +// @comm Il valore di

indica il caricamento dei valori standard dei file + +{ + __autoload = on; +} + +/////////////////////////////////////////////////////////// +// TBaseisamfile +/////////////////////////////////////////////////////////// + +TBaseisamfile::TBaseisamfile(int logicnum) +{ + _logicnum = logicnum; + _isam_handle = 0; + _curr_key = 0; + _lasterr = NOERR; + _current = new TRectype(logicnum); +} + +// @doc EXTERNAL + +// @mfunc Reperisce il tracciato dal file stesso. +// +TBaseisamfile::TBaseisamfile( + const char* name, // @parm Indica il nome del file + const char* descname) // @parm Indica la descrizione del file +// @comm Esiste la possibilita' di codificare i valori di pathpref e prefix in

+// % si riferisce ai dati comuni +// $ si riferisce ai dati di ditta corrente +// # si riferisce al direttorio indicato da PATHPREF.INI +{ + if (descname && *descname) + { + TTrec r; + ifstream f(descname); + f >> r; + const int err=DB_build(name, &r.rec()) ; + if (err != NOERR) + fatal_box("Non posso creare il file %s : errore n.ro %d", name, err); + } + _lasterr = NOERR; + TFilename filename(name); + CHECK(filename.full(),"Must define the file to open!"); + _logicnum = prefix().get_handle(filename); + _current = new TRectype(this); + +} + +TBaseisamfile::~TBaseisamfile() +{ + if (_current) + delete _current; +} + +TCodeb_handle TBaseisamfile::handle(int key) const +{ + return prefix().get_handle(_isam_handle, key > 0 ? key : _curr_key); +} + +TRecnotype TBaseisamfile::items() const +{ + return DB_reccount(handle()); +} + +const char* TBaseisamfile::name() const +{ + TString& tmp = get_tmp_string(); + tmp.format("%d", num()); + return tmp; +} + +const char* TBaseisamfile::module() const +{ + TFilename app; + curr().get_relapp(app); + if (app.full()) + return app.left(2); + return "ba"; +} + +const char* TBaseisamfile::filename() const +{ + const int n = _isam_handle > 0 ? _isam_handle : num(); + TString& tmp = get_tmp_string(); + tmp = prefix().get_filename(n); + tmp << ".dbf"; + return tmp; +} + +const char* TBaseisamfile::description() +{ + const int n = _isam_handle > 0 ? _isam_handle : num(); + const FileDes& d = prefix().get_filedes(n); + return d.Des; +} + +TRecnotype TBaseisamfile::eod() const +{ + return items(); +} + +void TBaseisamfile::set_curr(TRectype * curr) +{ + CHECK(curr != NULL, "You must set a valid current record"); + CHECK(num() == curr->num(), "You must set a coherent current record"); + if (_current != NULL) + delete _current; + _current = curr; +} + +void TBaseisamfile::setkey(int nkey) +{ + _curr_key = nkey; +} + +int TBaseisamfile::getkey() const +{ + return _curr_key; +} + +int TBaseisamfile::first(word lockop) +{ + return TBaseisamfile::read(curr(), _isfirst, lockop); +} + +int TBaseisamfile::last(word lockop) +{ + return TBaseisamfile::read(curr(), _islast, lockop); +} + +int TBaseisamfile::next(word lockop) +{ + return TBaseisamfile::read(curr(), _isnext, lockop); +} + +int TBaseisamfile::prev(word lockop) +{ + return TBaseisamfile::read(curr(), _isprev, lockop); +} + +int TBaseisamfile::reread(word lockop) +{ + return TBaseisamfile::reread(curr(), lockop); +} + +int TBaseisamfile::reread(TRectype& rec, word lockop) +{ + return rec.read(*this, _iscurr, lockop); +} + +int TBaseisamfile::skip(TRecnotype nrec, word lockop) +{ + if (nrec == 0) + return NOERR; + + curr().setdirty(); + const int fhnd = handle(); + + // controllo se mi sono spostato dall'ultima lettura + if (_recno != DB_recno(fhnd)) + { + _lasterr = DB_go(fhnd, _recno); + if (_lasterr != NOERR) + { + _lasterr = get_error(_lasterr); + if (_lasterr != _islocked) + fatal_box("Errore nella skip %d : non posso riposizionarmi", _lasterr); + } + } + _lasterr=DB_skip(fhnd, nrec); + if (_lasterr != NOERR) + _lasterr = get_error(_lasterr); + while (_lasterr ==_islocked) + { + const RecDes& r = prefix().get_recdes(num()); + TString256 key; + __build_key(r, _curr_key, curr().string(), key.get_buffer(), TRUE); + message_box("Codice %s in uso da parte\ndi un altro utente.\nSkipping", (const char*)key); + _lasterr = cisread(fhnd, getkey(), curr(),_iscurr + lockop, _recno); + } + _recno = DB_recno(fhnd); + if (curr().has_memo()) + curr().init_memo(_recno, _isam_handle); + + return _lasterr; +} + +// funzione di lettura dei file +int TBaseisamfile::_read(TRectype& rec, word op, word lockop) +{ + const TCodeb_handle fhnd = handle(); + rec.setdirty(); + + _lasterr = cisread(fhnd, getkey(), rec, op + lockop, _recno); + + // _recno = DB_recno(fhnd); // Gia' fatto nella cisread + + if(rec.has_memo()) + rec.init_memo(_recno, _isam_handle); + + if (_lasterr == NOERR) + { + if (lockop == _lock || lockop == _testandlock) + prefix().lock_record(_isam_handle, _recno); else + if (lockop == _unlock) + prefix().unlock_record(_isam_handle, _recno); + } + + return _lasterr; +} + +int TBaseisamfile::read(TRectype& rec, word op, word lockop) +{ + _lasterr=rec.read(*this, op, lockop); + return _lasterr; +} + +int TBaseisamfile::read(word op, word lockop) +{ + return TBaseisamfile::read(curr(), op, lockop); +} + +int TBaseisamfile::readat(TRectype& rec, TRecnotype nrec, word lockop) +{ + return rec.readat(*this, nrec, lockop); +} + +int TBaseisamfile::readat(TRecnotype nrec, word lockop) +{ + return TBaseisamfile::readat(curr(), nrec, lockop); +} + +int TBaseisamfile::_readat(TRectype& rec, TRecnotype nrec, word lockop) +{ + const int fhnd = handle(); + rec.setdirty(); + _lasterr = DB_go(fhnd, nrec); + if (_lasterr != NOERR) + _lasterr = get_error(_lasterr); + else + rec = (const char*)DB_getrecord(fhnd); + _recno = DB_recno(fhnd); + if (rec.has_memo()) + rec.init_memo(_recno, _isam_handle); + return _lasterr; +} + +int TBaseisamfile::_write(const TRectype& rec) +{ + CHECK(!rec.empty(), "Can't write an empty record"); + + // Controlla che la chiave sia piena + TString256 key; + + __build_key(rec.rec_des(), 1, rec.string(), key.get_buffer(), true); + if (key.blank()) + return _iskeyerr; + + if (dongle().demo() && items() > 979L) + return _isfilefull; + + // Forza l'uso della chiave principale (per chiavi duplicate?) + const int fhnd = handle(_curr_key > 0 ? 1 : 0); + + const int dst_len = DB_reclen(fhnd); + if (dst_len != rec.len()) + NFCHECK("Record size mismatch on file %d: RecDes=%d, DB_reclen=%d", + _logicnum, rec.len(), dst_len); + + browse_null(rec.string(), dst_len); + memcpy(DB_getrecord(fhnd), rec.string(), dst_len); + _lasterr = DB_add(fhnd); + _recno = DB_recno(fhnd); + + if (_lasterr == NOERR) + { + if (rec.has_memo()) + ((TRectype&)rec).write_memo(_isam_handle, _recno ); + } + else + _lasterr = get_error(_lasterr); + + return _lasterr; +} + +int TBaseisamfile::write(const TRectype& rec) +{ + return rec.write(*this); +} + +int TBaseisamfile::write() +{ + return TBaseisamfile::write(curr()); +} + +int TBaseisamfile::write_rewrite(const TRectype& rec) +{ + return rec.write_rewrite(*this); +} + +int TBaseisamfile::write_rewrite() +{ + return TBaseisamfile::write_rewrite(curr()); +} + +int TBaseisamfile::rewrite_write(const TRectype& rec) +{ + return rec.rewrite_write(*this); +} + +int TBaseisamfile::rewrite_write() +{ + return TBaseisamfile::rewrite_write(curr()); +} + +int TBaseisamfile::_rewrite(const TRectype& rec) +{ + CHECK(!rec.empty(), "Can't write an empty record"); + + TRectype save_rec(rec); + + // Forza l'uso della chiave principale (per chiavi duplicate?) + const int fhnd = handle(1); + _lasterr = cisread(fhnd, 1, save_rec, _isequal + _nolock, _recno); // Si Posiziona per sicurezza... + + if (_lasterr == NOERR) + { + const int len = DB_reclen(fhnd); + if (len != save_rec.len()) + NFCHECK("Record size mismatch on file %d: RecDes=%d, DB_reclen=%d", + _logicnum, save_rec.len(), len); + + browse_null(rec.string(), len); + if (memcmp(rec.string(), save_rec.string(), len) != 0) + { + memcpy(DB_getrecord(fhnd), rec.string(), len); + _lasterr = DB_rewrite(fhnd); + if (_lasterr == NOERR) + rec_cache(_logicnum).notify_change(); + else + _lasterr = get_error(_lasterr); + } + else + DB_unlock(fhnd); // non vale la pena farlo sempre ? + _recno = DB_recno(fhnd); + prefix().unlock_record(_isam_handle, _recno); + + if (_lasterr == NOERR) + { + if (curr().has_memo()) + ((TRectype&)rec).write_memo(_isam_handle, _recno); + } + } + + return _lasterr; +} + +int TBaseisamfile::rewrite(const TRectype& rec) +{ + return rec.rewrite(*this); +} + +int TBaseisamfile::rewrite() +{ + return TBaseisamfile::rewrite(curr()); +} + +int TBaseisamfile::rewriteat(const TRectype& rec, TRecnotype nrec) +{ + const int fhnd = handle(); + + if ((_lasterr=DB_go(fhnd,nrec))== NOERR) + { + browse_null(rec.string(),DB_reclen(fhnd)); + memcpy(DB_getrecord(fhnd),rec.string(),DB_reclen(fhnd)); + _lasterr=DB_rewrite(fhnd); + if (_lasterr != NOERR) _lasterr = get_error(_lasterr); + } + else + _lasterr = get_error(_lasterr); + _recno = DB_recno(fhnd); + + if(_lasterr == NOERR) + { + if (curr().has_memo()) + ((TRectype &)rec).write_memo(_isam_handle, _recno); + rec_cache(_logicnum).notify_change(); + } + + return _lasterr; +} + +int TBaseisamfile::rewriteat(TRecnotype nrec) +{ + return TBaseisamfile::rewriteat(curr(),nrec); +} + +int TBaseisamfile::_remove(const TRectype& rec) +{ + CHECK(!rec.empty(), "Can't remove an empty record"); + + const int fhnd = handle(1); // Forza l'uso della chiave principale (per chiavi duplicate?) + + TRectype save_rec(rec); + _lasterr = cisread(fhnd, 1, save_rec, _isequal + _nolock, _recno); // Si Posiziona per sicurezza... + + if (_lasterr == NOERR) + { + _lasterr = DB_delete(fhnd); // Put only deletion flag on record, must remove keys too! + if (_lasterr == NOERR) + { + if (curr().has_memo( )) + curr().init_memo(); + rec_cache(_logicnum).notify_change(); + DB_flush(fhnd); + } + else + _lasterr = get_error(_lasterr); + } + + if (_lasterr != NOERR) + DB_recall(fhnd); + + return _lasterr; +} + +int TBaseisamfile::remove(const TRectype& rec) +{ + return rec.remove(*this); +} + +int TBaseisamfile::remove() +{ + return TBaseisamfile::remove(curr()); +} + +int TBaseisamfile::lock() +{ + const int fhnd = handle(); + _lasterr = DB_lockfile(fhnd); + if (_lasterr != NOERR) + _lasterr = get_error(_lasterr); + return _lasterr; +} + +int TBaseisamfile::unlock() +{ + const int fhnd = handle(); + _lasterr = DB_unlock(fhnd); + if (_lasterr != NOERR) + _lasterr = get_error(_lasterr); + return (_lasterr); +} + +void TBaseisamfile::indexon() +{ +} + +void TBaseisamfile::indexoff() +{ +} + +bool TBaseisamfile::empty() +{ + return items() <= 0; +} + +// @doc EXTERNAL + +// @mfunc Apre il file isam di base con lock +// +// @rdesc Ritorna NOERR se e' riuscita ad aprire il file, altrimenti ritorna il numero di errore +// generato (vedi ). +int TBaseisamfile::_open( + unsigned int mode, // @parm Indica il modo di apertura del file (default _manulock) + bool index) // @parm Indica se aprire con indici o meno (default TRUE) + +// @comm Il parametro

puo' assumere i valori: +// +// @flag _manulock | Il lock dei record viene fatto manualmente +// @flag _exclock | Il file viene aperte in modo esclusivo +// @flag _autolock | Il lock dei record viene fatto in modo automatico +// @comm Il parametro

puo' assumere i valori: +// +// @flag TRUE | Il file viene aperto con indici +// @flag FALSE | Il file viene aperto senza indici + +{ + CHECKD(_isam_handle == 0, "Can't reopen file ", _logicnum); + _curr_key = index ? 1 : 0; + + TFilename filename; + _isam_handle = prefix().open_isamfile(_logicnum, filename, mode==_excllock, index); + if (_isam_handle > 0) + { + TCodeb_handle cb_handle = prefix().get_handle(_isam_handle, _curr_key); + const int dbfreclen = DB_reclen(cb_handle); + const int trcreclen = prefix().get_reclen(_logicnum); + const TRecnotype n = DB_reccount(cb_handle); + + if (dbfreclen != trcreclen) + { + TString msg; + msg.format("Lunghezza record incoerente sul file %d (%s): file=%d trc=%d", + num(), (const char*)filename, dbfreclen, trcreclen); + if (n <= 0) + { + msg << "\nSi consiglia di eliminare il file ed i suoi indici."; + error_box(msg); + } + else + fatal_box(msg); + } + if (prefix().get_recdes(_logicnum).NKeys <= 0) + fatal_box("Il file %d (%s) e' senza indici", num(), (const char*)filename); + _recno = RECORD_NON_FISICO; + setkey(_curr_key); + _lasterr = NOERR; + } + else + { + TString e_msg; + _lasterr = get_error(_isam_handle); + if (_lasterr == -60) + { + if (!filename.exist()) + e_msg.format("Il file %d(%s) non esiste, errore %d",num(),(const char*)filename,_lasterr); + else + e_msg.format("Il file %d(%s) e' aperto in modo esclusivo da un'altra applicazione", + num(), (const char*)filename); + } + if (e_msg.empty()) + e_msg.format("Il file %d(%s) non puo' essere aperto, errore %d",num(),(const char*)filename,_lasterr); + fatal_box((const char*) e_msg); + } + return _lasterr; +} + +int TBaseisamfile::_open_ex( + unsigned int mode, // @parm Indica il modo di apertura del file (default _manulock) + bool index) // @parm Indica se aprire con indici o meno (default TRUE) + +// @comm Il parametro

puo' assumere i valori: +// +// @flag _manulock | Il lock dei record viene fatto manualmente +// @flag _exclock | Il file viene aperte in modo esclusivo +// @flag _autolock | Il lock dei record viene fatto in modo automatico +// @comm Il parametro

puo' assumere i valori: +// +// @flag TRUE | Il file viene aperto con indici +// @flag FALSE | Il file viene aperto senza indici + +{ + CHECKD(_isam_handle == 0, "Can't reopen file ", _logicnum); + _curr_key = index ? 1 : 0; + + TFilename filename; + _isam_handle = prefix().open_isamfile(_logicnum, filename, mode==_excllock, index); + if (_isam_handle > 0) + { + if (prefix().get_reclen(_logicnum) > 0) + { + const int fhnd = handle(); + if (fhnd >= 0) + { + _recno = RECORD_NON_FISICO; + _lasterr = NOERR; + } + else + _lasterr = get_error(fhnd); + } + else + _lasterr = _isbadtrc; + } + else + { + _lasterr = get_error(_isam_handle); + _isam_handle = 0; + } + return _lasterr; +} + +int TBaseisamfile::_close() +{ + int err = NOERR; + if (prefix_valid()) + { + err = prefix().close_isamfile(_isam_handle); + setstatus(err); + } + return err; +} + +int TBaseisamfile::is_valid(bool exclusive) +{ // Ritorna NOERR se il file puo' essere aperto senza errori + CHECKD(_isam_handle == 0, "Can't reopen file ", _logicnum); + TFilename filename; + TIsam_handle isam_handle = prefix().open_isamfile(_logicnum, filename, exclusive, true); + TCodeb_handle fhnd = isam_handle > 0 ? prefix().get_handle(isam_handle,1) : isam_handle; + + int err = NOERR; + if (fhnd < 0) + err = get_error(fhnd); + else + { + const int trcreclen = prefix().get_reclen(_logicnum); + if (trcreclen > 0) + { + if (DB_tagget(fhnd) == -1) + err = _ispatherr; + else + { + const int dbfreclen = DB_reclen(fhnd); + if (dbfreclen != trcreclen) + { + err = _istrcerr; + if (_logicnum == LF_CLIFO) + error_box("Clifo trc=%d dbf=%d", trcreclen, dbfreclen); + } + } + } + else + err = _isbadtrc; + } + if (isam_handle > 0) + prefix().close_isamfile(isam_handle); + return err; +} + +bool TBaseisamfile::get_relapp(TString& app) const +{ + return curr().get_relapp(app); +} + +bool TBaseisamfile::is_changed_since(long& last) const +{ + bool yes = false; + +#ifdef WIN32 + int fh = 0; + ::_sopen_s(&fh, filename(), _O_RDONLY, _SH_DENYNO, _S_IREAD); + if (fh > 0) + { + struct stat stat; + if (::fstat(fh, &stat) == 0) + { + const long tim = long(stat.st_mtime) ^ long(stat.st_size); + yes = tim != last; + last = tim; + } + ::_close(fh); + } +#else + struct stat stat; + if (lstat(filename(), &stat) == 0) + { + const long tim = long(stat.st_mtime) ^ long(stat.st_size); + yes = tim != last; + last = tim; + } +#endif + + return yes; +} + +/////////////////////////////////////////////////////////// +// TLocalisamfile +/////////////////////////////////////////////////////////// + +// @doc EXTERNAL + +// @mfunc Costruttore +// +// @rdesc Ritorna l'oggetto +TLocalisamfile::TLocalisamfile( + int logicnum) // @parm Numero del logico del file + : TBaseisamfile(logicnum) +{ + if (open() != NOERR) + fatal_box("Impossibile aprire il file %d", logicnum); +} + +// @mfunc Costruttore +// +// @rdesc Ritorna l'oggetto +TLocalisamfile::TLocalisamfile( + const char* name, // @parm Nome del file esterno da aprire + const char* descname) // @parm Indica la descrizione del file +: TBaseisamfile(name, descname) +{ +} + +TLocalisamfile::TLocalisamfile(int logicnum, bool tmpfile) + : TBaseisamfile(logicnum) +{ + CHECK(tmpfile == TRUE, "Protected constructor badly used"); +} + + +TLocalisamfile::~TLocalisamfile() +{ + close(); +} + +int TLocalisamfile::close() +{ + return TBaseisamfile::_close(); +} + +int TLocalisamfile::open(unsigned int mode) +{ + return TBaseisamfile::_open(mode); +} + +int TLocalisamfile::operator +=(const TRecnotype npos) +{ + skip(npos); + return status(); +} + + +int TLocalisamfile::operator -=(const TRecnotype npos) +{ + skip(-npos); + return status(); +} + + +int TLocalisamfile::operator ++() +{ + next(); + return status(); +} + + +int TLocalisamfile::operator --() +{ + prev(); + return status(); +} + + + +TIsamfile::TIsamfile(int logicnum) + : TBaseisamfile(logicnum) +{ } + + +TIsamfile::~TIsamfile() +{ + close(); +} + +/////////////////////////////////////////////////////////// +// TIsamtempfile +/////////////////////////////////////////////////////////// + +TIsamtempfile::TIsamtempfile(int logicnum, const char* radix, bool create, bool autodel) + : TLocalisamfile(logicnum, TRUE) +{ + TRecnotype eod = 0; + TRecnotype eox = 100; + + TFilename n; + + if (radix && *radix) + { + if (*radix == '%') + n = radix + 1; + else + { + n.tempdir(); + n.add(radix); + } + n.ext("dbf"); + } + else + n.temp(NULL, "dbf"); + + if (!create) + { + const long sz = fsize(n); + if (sz <= 64) + fatal_box("Impossibile aprire il file %s", (const char*)n); + + const long len = curr().len(); + eod = eox = sz / len; + } + + CHECK(create == FALSE || create == TRUE, "Il flag di autodel ora si setta con il terzo parametro del costruttore"); + _autodel = autodel || (create != FALSE && create != TRUE); + + n.insert("%", 0); + + open(n, create, eod, eox); +} + + +TIsamtempfile::~TIsamtempfile() +{ + close(); +} + +// @doc EXTERNAL + +// @mfunc Apre il file +// +// @rdesc Ritorna NOERR se e' riuscita ad aprire il file, altrimenti ritorna il numero di errore +// generato (vedi ). +int TIsamtempfile::open( + const char* radix, // @parm Radice del path del file + bool create, // @parm Indica se va creato un nuovo file (se FALSE il file esiste gia') + TRecnotype eod, // @parm Numero di record presenti nel file + TRecnotype eox) // @parm Numero di record da aggiungere al file + +// @comm Nel case

sia TRUE allora viene settato automaticamente il valore di

+// a TRUE, cioe' viene abilitata l'eliminazione del file in chiusura. + +{ + int err = NOERR; + + TFilename filename; + if (radix[0] == '%') + filename = radix+1; + else + filename.temp(radix); + filename.ext(""); + + CHECKS(_isam_handle == 0, "File already open ", (const char*)filename); + + if (create) + { + RecDes* r = (RecDes*)&prefix().get_recdes(num()); + err = DB_build(filename, r) ; + if (err != NOERR) + { + err = get_error(err); + fatal_box("Can't create temp file '%s' num. %d: Error n. %d", (const char*)filename, num(), err); + } + } + else + { + TFilename test = filename; test.ext("dbf"); + for (int t = 0; t < 2; t++) + { + test.ext(t == 0 ? "dbf" : "cdx"); + if (!test.exist()) + { + err = -60; + break; + } + } + } + + if (err == NOERR) + { + _isam_handle = prefix().open_isamfile(_logicnum, filename, true); + TCodeb_handle fhnd = handle(_curr_key = 1); + if (fhnd < 0) + err = get_error(fhnd); + } + + if (err != NOERR) + { + filename.ext("dbf"); + if (err == -60) + { + if (!filename.exist()) + fatal_box("Apertura file %s : errore n. %d. File non esistente.",(const char*)filename,err); + else + fatal_box("Apertura file %s : errore n. %d. File aperto in uso esclusivo da un'altra applicazione.",(const char*)filename,err); + } + else + fatal_box("Apertura file %s : errore n. %d ",(const char*)filename,err); + } + + _recno = RECORD_NON_FISICO; + setstatus(err); + return err; +} + + +int TIsamtempfile::close() +{ + TFilename f = filename(); + int err = prefix().close_isamfile(_isam_handle); + if (err == NOERR && _autodel) + { + const long c = DB_getconf(); + + f.ext("dbf"); + ::remove(f); + + if (c & 1) + f.ext("fpt"); + else + f.ext("dbt"); + ::remove(f); + + if (c & 1) // FOXPRO format + f.ext("cdx"); + if (c & 4) // DBIV format + f.ext("mdx"); + if (c & 8 || c & 2) // CLIPPER and DBIII format + { + f.ext("cgp"); + FILE* fp=NULL; fopen_s(&fp, f, "r"); + char in[16]; + while (fgets(in,16,fp)!=NULL) + { + TFilename a(in); + if (c & 8) // DBIII format + a.ext("ndx"); + else + a.ext("ntx"); // CLIPPER format + ::remove((const char *)a); + } + fclose(fp); + } + ::remove(f); + + if (curr().has_memo()) // Cancella eventuale file dei memo + { + f.ext("fpt"); + ::remove(f); + } + } + + setstatus(err); + return err; +} + +/////////////////////////////////////////////////////////// +// TExternisamfile +/////////////////////////////////////////////////////////// +TExternisamfile::TExternisamfile(const char* name, bool exclusive, bool index) +: TLocalisamfile(name) +{ + init(name, exclusive, index); +} + +TExternisamfile::TExternisamfile(const char* name, const char* descname, bool exclusive, bool index) +: TLocalisamfile(name, descname) +{ + init(name, exclusive, index); +} + +TExternisamfile::~TExternisamfile() +{ + close(); +} + +void TExternisamfile::init(const char* name, bool exclusive, bool index) +{ + _name = name; + _name.ext("dbf"); + +// Espande il nome! + const char c = _name[0]; + if (c == '%' || c == '$') + _name = CAddPref(_name.get_buffer()); + else + if (c == '#') + { + _name.ltrim(1); + _name.format("%s/%s",__ptprf,(const char*)_name); + } + open(exclusive, index); +} + +int TExternisamfile::open(bool exclusive, bool index) +{ + _isam_handle = prefix().open_isamfile(_logicnum, _name, exclusive, index); + if (_isam_handle > 0) + { + if (prefix().get_recdes(_logicnum).NKeys <= 0) + fatal_box("Il file %d (%s) e' senza indici", num(), (const char*)filename()); + _recno = RECORD_NON_FISICO; + setkey(1); + _lasterr = NOERR; + } + else + { + TString e_msg; + _lasterr = get_error(_isam_handle); + if (_lasterr == -60) + { + if (!_name.exist()) + e_msg.format("Il file %d(%s) non esiste, errore %d",num(),(const char*)_name,_lasterr); + else + e_msg.format("Il file %d(%s) e' aperto in modo esclusivo da un'altra applicazione", + num(), (const char*)_name); + } + if (e_msg.empty()) + e_msg.format("Il file %d(%s) non puo' essere aperto, errore %d",num(),(const char*)_name,_lasterr); + fatal_box((const char*) e_msg); + } + return _lasterr; +} + +int TExternisamfile::close() +{ + return _close(); +} + +int TExternisamfile::zap() +{ + RecDes rd = curr().rec_des(); + + int err = prefix().close_isamfile(_isam_handle); + if (err == NOERR) + { + err = DB_packfile(TRUE, _name, 0); + if (err == NOERR) + { + TRecnotype peod; + err = DB_packindex(TRUE, _name, &rd, &peod, FALSE); + } + _isam_handle = prefix().open_isamfile(_logicnum, _name); + } + + return err; +} + +const char* TExternisamfile::name() const +{ + return filename(); +} + +/////////////////////////////////////////////////////////// +// TSystemisamfile +/////////////////////////////////////////////////////////// + +int TSystemisamfile::build(const TTrec& r) +{ + int err = NOERR; + const TDir d(num()); + if (r.len() > 0) + { + TFilename f(filename()); + TFilename fname(f); fname.ext(""); // sostituto per _filename + + f = f.path(); if (!is_not_slash(f.right(1)[0])) f.rtrim(1); + if (!dexist(f)) + make_dir(f); + + err=DB_build(fname, &r.rec()); + if (err != NOERR) + err = get_error(err); + setstatus(err); + + if (err == NOERR && __autoload) + { + TFilename lf; + lf.format("%sstd/lf%04d.txt", __ptprf, num()); + if (fexist(lf)) + load(lf, '|', '\0', '\n', TRUE, TRUE); + } + } + else + { + NFCHECK("Can't create a file with empty field info"); + setstatus(_isbadtrc); + } + return err; +} + +int TSystemisamfile::build() +{ + TTrec r; + r.get(num()); + return build(r); +} + +long TSystemisamfile::size(TRecnotype eox) +{ + return 51200L; +} + +#ifndef FOXPRO + +// @doc INTERNAL + +// @mfunc Esegue la conversione del file +// +// @rdesc Ritorna il rusultato dell'operazione +// +// @flag TRUE | Se la conversione e' stata effettuata correttamente +// @flag FALSE | Se h stato rilevato un errore durante la conversione (viene emesso un ) +int TSystemisamfile::exec_convapp( + long flev, // @parm Livello a cui aggiornare l'archivio + const bool before) // @parm Indica se viene chiamata prima o dopo la conversione + +{ + const char * const v = before ? "BCNV" : "ACNV"; + int err = 0; + + if (flev == 0) flev = 199401; + else flev++; + + TConfig conv(CONFIG_FCONV); + TString16 paragraph; + + TString_array paralist; + conv.list_paragraphs(paralist); + + for (unsigned int l = flev; err == 0 && l <= prefix().get_stdlevel(); l++) + { + paragraph.format("%06ld", l); + if (paralist.find(paragraph) < 0) + continue; + if (conv.set_paragraph(paragraph) && conv.exist(v, num())) + { + TToken_string s(conv.get(v, NULL, num()), ' '); + TFilename f(s.get(0)); + f.ext(".exe"); + s << ' ' << prefix().get_codditta(); + TExternal_app app(s); + if (f.exist()) + { + err = app.run(FALSE, 0x3); // Synchronous Spawn with User + TMailbox mail; + TMessage* msg = mail.next(TRUE); + if (err == 0 && msg != NULL) + err = atoi(msg->body()); + } + if (err && err != 8) + return error_box("Impossibile eseguire il programma di %sconversione\ndel livello %ld/%ld\nErrore n.ro %d", before ? "pre" : "post", l / 100, l % 100, err); + } + } + return err; +} + +// @doc INTERNAL + +// @mfunc Recupera le conversioni logiche da effettuare sul file +// +// @rdesc Ritorna TRUE se occorre effettuare la conversione sul file +bool TSystemisamfile::getlcf( + long flev) // @parm livello archivi di partenza della convesione + +// @comm Recupera le conversioni logiche da effettuare sul file per per passare dal +// livello archivi

a quello attuale degli archivi standard. + +{ + _flds.destroy(); + _exps.destroy(); + if (flev == 0) flev = 199401; + else flev++; + + TConfig conv(CONFIG_FCONV); + TString16 paragraph; + + TString_array paralist; + conv.list_paragraphs(paralist); + + for (unsigned int l = flev; l <= prefix().get_stdlevel(); l++) + { + paragraph.format("%06ld", l); + if (paralist.find(paragraph) < 0) + continue; + + if (conv.set_paragraph(paragraph) && conv.exist("F", num())) + { + TToken_string exprline(conv.get("F", NULL, num())); + + if (exprline.empty()) return FALSE; + + TToken_string w("", '='); + const char * wexprs = exprline.get(); + + while (wexprs != NULL) + { + w = wexprs; + TFixed_string fld(w.get()); + _flds.add(new TFieldref(fld, 0)); + _exps.add(new TExpression(w.get(), _strexpr)); + wexprs = exprline.get(); + } + } + } + return _flds.items() > 0; +} + +void TSystemisamfile::makelc(TRectype& rec) +{ + for (int i = 0 ; i < _flds.items(); i++) + { + TFieldref& f = (TFieldref&) _flds[i]; + TExpression& e = (TExpression & )_exps[i]; + + for (int k = 0; k < e.numvar(); k++) + e.setvar(k, get(e.varname(k))); + f.write(e.as_string(), rec); + } +} + +// @doc EXTERNAL + +// @mfunc Esegue la conversione del tracciato record del file +// +// @rdesc Ritorna il risulato della conversione, altrimenti il codice di errore generato +// (vedi ) + +int TSystemisamfile::update( + const TTrec& newrec, // @parm Nuovo tracciato record con cui aggiornare il file + bool interactive) // @parm Indica se riportare i campi personalizzati + +{ + //if (newrec.len() == 0) + if (newrec.len() <= 8) + { + // if (interactive) error_box(FR("Il nuovo tracciato per il file %d e' vuoto"), num()); // Fastidioso per Ilaria + setstatus(_istrcerr); + return status(); + } + + int err = NOERR; + + TTrec wrec(newrec); + TDir dir; dir.get(num(), _unlock, _nordir, _sysdirop); + + const bool is_com = prefix().is_com(); + const bool toconvert = is_com ? dir.is_com() : dir.is_firm(); + + TTrec oldrec(num(), is_com ? _comdir : _nordir); + if (oldrec.fields() < 0 || oldrec.fields() > MaxFields) + { + if (yesno_box(FR("Il file %d (%s)\n" + "ha %d campi ed una lunghezza record di %d" + "\nSi desidera azzerare il vecchio tracciato?"), + num(), (const char*)filename(), oldrec.fields(), oldrec.len())) + { + oldrec.zero(); + } + else + { + setstatus(_istrcerr); + return status(); + } + } + + int lenr = wrec.len(); + if (lenr != 0) + { + const long lev = prefix().filelevel(); + const bool lcf = getlcf(lev); + + if (toconvert) + { + err = exec_convapp(lev, true); // Pre-conversion + if (err != NOERR) + { + setstatus(err); + return err; + } + + if (!lcf && wrec == oldrec) + { + err = exec_convapp(lev, false); // Post-conversion (SOLO se il record e' rimasto uguale) + setstatus(err); + return err; + } + } + else + { + if (dir.eox() > 0L) + dir.reset_eox(); + } + + const int oldfields = oldrec.fields(); //numero campi del vecchio file + const int wfields = wrec.fields(); //numero campi del nuovo file + int newfields = wfields; //numero campi del nuovo file compresi quelli personalizzati (_) + TToken_string def; //riga del file .trr nome|tipo|lungh|dec + + for (int j = 0; j < oldfields; j++) + { + def = oldrec.fielddef(j); + const TString16 fname = def.get(0); //nome e basta del campo + if (!interactive && fname[0] == '_') + { + if (wrec.field(fname) == FIELDERR) + { + if (newfields < MaxFields) + { + wrec.update_fielddef(newfields++, def); + wrec.set_fields(newfields); + wrec.rehash(); + } + else + { + if(!yesno_box("Il campo %s non verrà preservato: continuare?", + (const char*)fname)) + return NOERR; + } + } + } + } + if (wfields < newfields) + { + wrec.set_fields(newfields); + wrec.rehash(); + lenr = wrec.len(); + } + TFilename fname; + if (toconvert) + fname = filename(); + + if (toconvert && (dir.eox() > 0L || fname.exist())) + { + TRecnotype ni = 0L; + TFilename tmpfname; tmpfname.temp("tf"); + + err=DB_build(tmpfname, &wrec.rec()); + + if (err != NOERR) + { + err=get_error(err); + return (err); + } + + if (dir.eod() > 0 && oldrec.len() > 0) + { + // Apro il file destinazione in modo esclusivo e senza indici + //int tmpnum = num(); + //TIsam_handle ishandle = prefix().open_isamfile(tmpnum, tmpfname, true, false); + // TCodeb_handle fhnd = ishandle > 0 ? prefix().get_handle(ishandle) : ishandle; + TCodeb_handle fhnd = DB_open(tmpfname, 1, 0); + if (fhnd < 0) + { + err = get_error(fhnd); + return err; + } + + err = _open_ex(_excllock, false); + if (err != NOERR) + return err; + + TString s; s << TR("Aggiornamento") << ' ' << fname; + + const TRecnotype nitems = items(); + TProgress_monitor p(nitems, s, is_power_station()); + + TExtrectype nrec(wrec); + + const int nflds = curr().items(); + TArray infld, outfld; + int j; + for (j = 0; j < nflds; j++) + { + const char* fld_name = curr().fieldname(j); + infld.add(new TRecfield(curr(), fld_name), j); + if (nrec.exist(fld_name)) + outfld.add(new TRecfield(nrec, fld_name), j); + } + const bool memo_inside = rec_has_memo(nrec.rec_des()); + for (int errore = first(); errore == NOERR; errore = next()) + { + if (!p.add_status()) + { + err = _iseof; // Simula errore in caso di interruzione + break; + } + ni++; + + if (curr().isdeleted()) + continue; // Shold never happen + + nrec.zero(); + for (j = outfld.last(); j >= 0; j = outfld.pred(j)) + { + TRecfield* in_fld = (TRecfield*)infld.objptr(j); + TRecfield* out_fld = (TRecfield*)outfld.objptr(j); + if (in_fld != NULL && out_fld != NULL) + { + char* fld_val = (char*)(const char*)*in_fld; + if (out_fld->type() != _datefld && out_fld->type() != _memofld) + { + const int l1 = out_fld->len(); + const int l2 = strlen(fld_val); + if (l1 < l2) + { + if (out_fld->type() != _alfafld) + *fld_val = '\0'; + else + fld_val[l1] = '\0'; + } + } + *out_fld = fld_val; + } + } + if (lcf) + makelc((TRectype &)nrec); + browse_null(nrec.string(),lenr); + memcpy(DB_getrecord(fhnd),nrec.string(),lenr); + err=DB_add(fhnd); + if ( err == NOERR && memo_inside) + { + // nrec.write_memo(ishandle, DB_recno(fhnd)); + for (j = outfld.last(); j >= 0; j = outfld.pred(j)) + { + const TRecfield* in_fld = (const TRecfield*)infld.objptr(j); + const TRecfield* out_fld = (const TRecfield*)outfld.objptr(j); + if (in_fld != NULL && out_fld != NULL && out_fld->type() == _memofld) + { + const TFixed_string val(*in_fld); + if (val.full()) + DB_memowrite(fhnd, out_fld->name(), val); + } + } + DB_flush(fhnd); + } + if (err != NOERR) + err=get_error(err); + setstatus(err); + + } + close(); + //prefix().close_isamfile(ishandle); + DB_close(fhnd); + + if (err != NOERR) + err = get_error(err); + + if (!p.setstatus(nitems)) + err = _iseof; + } + + if (err == NOERR) + { + long c = DB_getconf(); + fname.ext("dbf"); + tmpfname.ext("dbf"); + fcopy(tmpfname, fname); + ::remove(tmpfname); + if (c & 1) + tmpfname.ext("fpt"); + else + tmpfname.ext("dbt"); + if (tmpfname.exist()) + { + if (c & 1) + fname.ext("fpt"); + else + fname.ext("dbt"); + fcopy(tmpfname, fname); + ::remove(tmpfname); + } + if (c & 1) // FOXPRO format + tmpfname.ext("cdx"); + if (c & 4) // DBIV format + tmpfname.ext("mdx"); + if (c & 8 || c & 2) + { + tmpfname.ext("cgp"); + TFilename a; + FILE *fp=NULL; fopen_s(&fp, tmpfname,"rb"); + while (fgets(a.get_buffer(),16,fp) != NULL) + { + a.rtrim(1); // Cut \n + if (c & 8) // DBIII format + a.ext("ndx"); + else + a.ext("ntx"); // CLIPPER format + ::remove(a); + } + fclose(fp); + } + ::remove(tmpfname); + dir.set_eod(ni); + } + } + if (err==NOERR) + { + dir.set_len(lenr); + dir.put(num(), _nordir, _sysdirop); + wrec.put(num()); + prefix().update_recdes(num()); + + if (toconvert) + packindex(true); + if (err == NOERR) + err = exec_convapp(lev, FALSE); // Post - conversion + } + } + + setstatus(err); + return err; +} + +// @doc EXTERNAL + +// @mfunc Rimuove fisicamente i record cancellati +// +// @rdesc Ritorna NOERR se l'operazione di compattamento e' riuscita, altrimenti il codice di +// di errore generato (vedi ). +int TSystemisamfile::packfile( + bool vis, // @parm Indica se visualizzare lo stato dell'operazione + bool zap) // @parm Indica se distruggere tutti i records + +// @xref + +{ + TFilename fname = filename(); fname.ext(""); + + TRecnotype new_eod = 0L; + if (!zap) + { + const int lf = num(); + TDir d(lf); // Chi commenta muore! + d.get(lf,_nolock, d.is_com() ? _comdir : _nordir, _sysdirop); + new_eod = d.eod(); + if (d.len() <= 1) // Dati rovinati? + { + d.set_len(curr().len()); + d.put(lf, d.is_com() ? _comdir : _nordir, _sysdirop); + } + } + + int err = DB_packfile(vis, fname, new_eod); + + if (zap && err == NOERR) + err = packindex(vis, false); + if (err == NOERR && curr().has_memo()) + err = DB_packmemo(vis,fname); + + if (err != NOERR) + { + err = get_error(err); + if (err != NOERR) + error_box("Errore in compattamento dati.\nFile %d : %d", num(), err); + } + setstatus(err); + return err; +} + +int TSystemisamfile::zap() +{ + safely_close_closeable_isamfiles(); + return packfile(true, true); +} + +// @doc EXTERNAL + +// @mfunc Rimuove fisicamente gli indici cancellati +// +// @rdesc Ritorna NOERR se l'operazione di compattamento e' riuscita, altrimenti il codice di +// di errore generato (vedi ). +int TSystemisamfile::packindex( + bool vis, // @parm Indica se visualizzare lo stato dell'operazione + bool ask) // @parm Indica se chiedere il recupero dei record duplicati + +// @xref + +{ + const TTrec r(num()); + TDir d(num()); + const bool is_com = d.is_com(); + d.get(num(),_nolock, is_com ? _comdir : _nordir, _sysdirop); + + TFilename name = d.filename(); name.ext(""); + TRecnotype peod; + int err=DB_packindex(vis,name,&r.rec(),&peod,ask); + if (err != NOERR) + err = get_error(err); + if (err != NOERR) + { + if (vis || ask) + error_box("Errore in compattamento indici.\nFile %d : %d", num(),err); + } + else + { + if (peod >= 0 && peod != d.eod()) + { + d.set_eod(peod); + d.put(num(), is_com ? _comdir : _nordir); + } + } + setstatus(err); + return err; +} + +void TSystemisamfile::update_file() +{ + TFilename fname; + int logicnum = _logicnum; + int isam_handle = prefix().open_isamfile(logicnum, fname, FALSE, 1); + if (isam_handle > 0) + { + TCodeb_handle cb_handle = prefix().get_handle(isam_handle, 1); + const TRecnotype n = DB_reccount(cb_handle); //numero di elementi del file + + TDir dir; + dir.get(_logicnum, _lock, _nordir, _sysdirop); + dir.set_eox(n); + dir.set_eod(n); + dir.put(_logicnum, _nordir, _sysdirop); + prefix().close_isamfile(isam_handle); + } +} + +int TSystemisamfile::pack(bool vis, bool ask) +{ + int err = packfile(vis); + if (err == NOERR) + err = packindex(vis, ask); + setstatus(err); + return err; +} + +// @doc EXTERNAL + +// @mfunc Importa un file ascii +// +// @rdesc Ritorna NOERR se l'operazione di lettura e' riuscita, altrimenti il codice di +// di errore generato (vedi ). +int TSystemisamfile::load( + const char* from, // @parm Nome del file da importare + char fs, // @parm Carattere separatore di campo (default ) + char fd, // @parm Carattere delimitatore di campi (default '\\0') + char rs, // @parm Carattere separatore di record (default '\\n') + bool vis, // @parm Indica se visualizzare lo stato dell'operazione (default TRUE) + bool extended, // @parm Indica se interpretare alcune stringhe come macro (default FALSE) + bool indexed) // @parm Indica se indicizzare subito o alla fine + +// @comm Se

e' TRUE e trova alcune stringhe col formato %stringa% (es. %frm%) +// ne sostituisce i valori (es. ditta corrente). + +// @xref + +{ + int err=NOERR; + FILE* fl = NULL; fopen_s(&fl, from, "r"); + if (fl == NULL) + { + cantread_box(from); + setstatus(2); + return 2; + } + TRecnotype r = 0, e = 0, nitems = 0; + TString8 firm, year, attprev("00000"); + + if (extended) + { + const TDate d(TODAY); + year.format("%04d", d.year()); + firm.format("%05ld", prefix().get_codditta()); + attprev = cache().get(LF_NDITTE, firm, NDT_CODATTPREV); + } + + fseek(fl, 0L, SEEK_END); + nitems = ftell(fl); + fclose(fl); + + err = _open_ex(_excllock, indexed); + if (err != NOERR) + { + TString msg; msg << _logicnum << " (" << name() << ')'; + cantread_box(msg); + return err; + } + + TScanner f(from); + const bool fixedlen = (fs == '\0'); + TToken_string s(1024, fixedlen ? char(255) : fs); + int nflds = curr().items(); + TString_array fld(nflds); + TPointer_array fldlen(nflds); + int reclen = 0; + TString sfd(3); + TString s1(256); + bool lcf = FALSE; + + if (f.paragraph("Header")) + { + int equal; + TString key; + nflds = 0; + while ((equal = f.line().find('=')) > 0) + { + key = f.token().left(equal); + key.trim(); + if (key == "File") + { + const int logic = atoi(f.token().mid(equal+1)); + if (logic != num()) + { + error_box("L'archivio %s e' stato generato dal file %d", from, logic); + return _isbadtrc; + } + } else + if (key == "Fields") + { + TToken_string riga(f.token().mid(equal+1)); + TToken_string wfd(32, ','); + FOR_EACH_TOKEN(riga, fd) + { + wfd = fd; wfd.strip_spaces(); + fld.add(wfd.get(0)); + const int l = wfd.get_int(); + fldlen.add_long(l, nflds++); + reclen += l; + } + } + } + } + + if (nflds == 0 || fld.items() == 0) + { + nflds = curr().items(); + for (int j = 0; j < nflds; j++) + { + fld.add(curr().fieldname(j), j); + const TString& wfld = fld.row(j); + const int l = (curr().type(wfld) == _datefld) ? 10 : curr().length(wfld); + fldlen.add_long(l, j); + } + } + + if (!f.paragraph("Data")) + { + error_box("Formato file non valido: manca il paragrafo [Data]"); + close(); + err = 1; + setstatus(err); + return err; + } + + if (fd) sfd << fd; + int last = NOERR; + + const char* const fmt = FR("Importazione archivio %d da %s\n%6ld records %6ld errori - %3d"); + + s1.format(fmt, _logicnum, from, r, e, last); + TProgind p(nitems, s1); + + while(!f.eof()) + { + if (fixedlen) + f.getline(s.get_buffer(reclen+2), reclen+2); + else + s = f.line(); + if (s.empty()) + break; + + if (extended) + { + int p, i; + + while ((p = s.find("%yr%")) >= 0) + for (i = 0; i < 4; i++) s[p + i] = year[i]; + while ((p = s.find("%frm%")) >= 0) + for (i = 0; i < 5; i++) s[p + i] = firm[i]; + while ((p = s.find("%att%")) >= 0) + for (i = 0; i < 5; i++) s[p + i] = attprev[i]; + } + if ((r + e) % 100 == 0) + { + s1.format(fmt, _logicnum, from, r, e, last); + p.set_text(s1); + } + + if (!p.setstatus((long)f.tellg())) + break; + + zero(); + if (fixedlen) + { + if (s.len() < reclen) + { + error_box(FR("Record di lunghezza errata: %d invece di %d"), s.len(), reclen); + break; + } + int pos = 0; + for (int j = 0; j < nflds; j++) + { + const int l = fldlen.get_int(j); + s1 = s.mid(pos, l); + s1.rtrim(); + put(fld.row(j), s1); + pos += l; + } + } + else + { + s.restart(); + for (int j = 0; j < nflds; j++) + { + s1 = s.get(); + if (fd) + { + s1.rtrim(1); + s1.ltrim(1); + } + if (curr().type((const TString&) fld[j]) == _memofld) + { + TString s2 = s1; + + s1 = esc(s2); + } + + put((const TString&) fld[j], s1); + } + } + + int err = write(); + + if (err == NOERR) + r++; + else + { + e++; + last = status(); + } + } + s1.format(fmt, _logicnum, from, r, e, last); + p.set_text(s1); + + close(); + + setstatus(err); + + // Devo reindicizzare alla fine + if (err == NOERR && !indexed) + packindex(vis, false); + +//aggiorna lo sheet con i nuovi valori di EOX EOD caricati + if (err == NOERR) + update_file(); + + return err; +} + +// @doc EXTERNAL + +// @mfunc Importa un file ascii +// +// @rdesc Ritorna NOERR se l'operazione di lettura e' riuscita, altrimenti il codice di +// di errore generato (vedi ). +int TSystemisamfile::overwrite( + const char* from, // @parm Nome del file da importare + char fs, // @parm Carattere separatore di campo (default ) + char fd, // @parm Carattere delimitatore di campi (default '\\0') + char rs, // @parm Carattere separatore di record (default '\\n') + bool vis) // @parm Indica se visualizzare lo stato dell'operazione (default TRUE) + +// @comm Se

e' TRUE e trova alcune stringhe col formato %stringa% (es. %frm%) +// ne sostituisce i valori (es. ditta corrente). + +// @xref + +{ + int err=NOERR; + FILE* fl = NULL; fopen_s(&fl, from, "r"); + if (fl == NULL) + { + error_box("Impossibile aprire il file %s",from); + clearerr(fl); + setstatus(2); + return 2; + } + TRecnotype r = 0, e = 0, nitems = 0; + TString16 firm, year, attprev("00000"); + + fseek(fl, 0L, SEEK_END); + nitems = ftell(fl); + fclose(fl); + + err = _open_ex(_excllock); + if (err != NOERR) + { + error_box("Impossibile aprire il file %d in modo esclusivo", _logicnum); + return err; + } + + TScanner f(from); + bool fixedlen = (fs == '\0'); + TToken_string s(1024, fixedlen ? char(255) : fs); + int nflds = curr().items(); + TString_array fld(nflds); + TString_array keyfld(nflds); + TAssoc_array vals; + int len[MaxFields]; + TString sfd(3); + TString s1(256); + bool lcf = FALSE; + + if (f.paragraph("Header")) + { + int equal; + TString key; + nflds = 0; + while ((equal = f.line().find('=')) > 0) + { + key = f.token().left(equal); + key.trim(); + if (key == "Version") + { + const unsigned int level = atoi(f.token().mid(equal+1)); + if (level > prefix().filelevel()) + { + const unsigned int stdlevel = prefix().get_stdlevel(); + error_box(FR("L'archivio %s e' stato generato con gli archivi di livello %ld%/%ld.\n Il livello attuale e' %ld/%ld.\n Convertire gli archivi e ripetere l' operazione."), + from, level/100, level%100, stdlevel/100, stdlevel%100); + } + lcf = getlcf(level); + } else + if (key == "File") + { + const int logic = atoi(f.token().mid(equal+1)); + if (logic != num()) + error_box("L'archivio %s e' stato generato dal file %d", + from, logic); + } else + if (key == "Fields") + { + TToken_string riga(f.token().mid(equal+1)); + TToken_string wfd(32, ','); + FOR_EACH_TOKEN(riga, fd) + { + wfd = fd; wfd.strip_spaces(); + fld.add(wfd.get(0)); + len[nflds++] = wfd.get_int(); + } + const RecDes& rd = curr().rec_des(); + const KeyDes& kd = rd.Ky[0]; + + for (int i = 0 ; i < kd.NkFields; i++) + { + const int nf = kd.FieldSeq[i] % MaxFields; + const RecFieldDes& rf = rd.Fd[nf]; + keyfld.add(rf.Name); + } + } + } + } + + if (nflds == 0 || fld.items() == 0) + { + nflds = curr().items(); + for (int j = 0; j < nflds; j++) + { + fld.add(curr().fieldname(j), j); + const TString & wfld = fld.row(j); + int l = 0; + switch (curr().type(wfld)) + { + case _datefld: l = 10; break; + default : l = curr().length(wfld); break; + } + len[j] = l; + } + } + + if (!f.paragraph("Data")) + { + error_box("Formato file non valido: manca il paragrafo [Data]"); + close(); + err = 1; + setstatus(err); + return err; + } + + if (fd) sfd << fd; + int last = NOERR; + + s1.format("Importazione archivio %d da %s\n%6ld records %6ld errori - %3d", + _logicnum, from, r, e, last); + TProgind p(nitems, s1, true, true, 78); + long pos = 16*nflds; + for (s = f.line(); s.not_empty() && !p.iscancelled(); s = f.line()) + { + if ((r + e) % 50 == 0) + { + s1.format("Importazione archivio %d da %s\n%6ld records %6ld errori - %3d", + _logicnum, from, r, e, last); + p.set_text(s1); + } + + pos += s.len()+2; + p.setstatus(pos); + zero(); + vals.destroy(); + if (fixedlen) + { + int pos = 0; + for (int j = 0; j < nflds; j++) + { + const TString & fldname = fld.row(j); + + s1 = s.mid(pos,len[j]); + s1.rtrim(); + vals.add(fldname, s1); + pos += len[j]; + } + } + else + { + s.restart(); + for (int j = 0; j < nflds; j++) + { + const TString & fldname = fld.row(j); + + s1 = s.get(); + if (fd) + { + s1.rtrim(1); + s1.ltrim(1); + } + if (curr().type(fldname) == _memofld) + { + TString s2 = s1; + s1 = esc(s2); + } + vals.add(fldname, s1); + } + } + + FOR_EACH_ARRAY_ROW(keyfld, r0, kfldname) + { + const TString * value = (const TString *) vals.objptr(*kfldname); + + if (value != NULL) + put(*kfldname, *value); + } + + const bool nuovo = read() != NOERR; + + if (nuovo) + zero(); + + + FOR_EACH_ASSOC_STRING(vals, obj, fldname, value) + put(fldname, value); + + const int err = nuovo ? write() : rewrite(); + + if (err == NOERR) + r++; + else + { + e++; + last = status(); + } + } + s1.format("Importazione archivio %d da %s\n%6ld records %6ld errori - %3d", + _logicnum, from, r, e, last); + + p.set_text(s1); + close(); + setstatus(err); + //aggiorna lo sheet con i nuovi valori di EOX EOD caricati + if (err == NOERR) + update_file(); + + return err; +} + +// @doc EXTERNAL + +// @mfunc Esporta VERSO un file ascii. +// +// @rdesc Ritorna NOERR se l'operazione di esportazione e' riuscita, altrimenti il codice di +// di errore generato (vedi ). +int TSystemisamfile::dump( + const char* to, // @parm Nome del file verso quale esportare + int nkey, // @parm Numero della chiave di ordinamento con cui scaricare i dati (defualt 1) + char fs, // @parm Carattere seperatore di campo (defualt ) + char fd, // @parm Carattere delimitatore di campo (default '\\0') + char rs, // @parm Carattere separatore di record (default '\\n') + bool vis, // @parm Indica se visualizzare lo stato dell'operazione (defualt TRUE) + bool withdeleted,// @parm Indica se scaricare anche i record cancellati (dafault FALSE) + const char * filter, // @parm Indica l'espressione filtro + SELECTIONFUNCTION select_func, // @parm funzione filtro + TObject * filter_obj) // @parm oggetto di filtro + +// @xref + +{ + FILE* f = NULL; fopen_s(&f, to, "w"); + if (f == NULL) + { + setstatus(2); + return 2; + } + + if (withdeleted) nkey = 0; + int err = ferror(f); + + open(FALSE, nkey ? TRUE : FALSE); + TString s(512); + bool fixedlen = (fs == '\0'); + int nflds = curr().items(); + TString_array fld(nflds); + TBit_array rjust(nflds); + int len[MaxFields]; + int j; + + for (j = 0; j < nflds; j++) + { + fld.add(curr().fieldname(j), j); + const TString & wfld = fld.row(j); + const TFieldtypes t = curr().type(wfld); + rjust.set(j, t == _intfld || t == _longfld || t == _realfld || + t == _wordfld || t == _intzerofld || t == _longzerofld); + len[j] = (t == _datefld) ? 10 : curr().length(wfld); + if (fixedlen && t == _memofld) + { + error_box(TR("Non e' possibile scaricare a lunghezza fissa un file con campi memo")); + return _isbadtrc; + } + } + TRecnotype i = 0; + const TRecnotype nitems = items(); + + s.format(FR("Esportazione %s"), filename()); + TProgind p(nitems, s, TRUE, TRUE, 70); + TString s1, sfld; + + fprintf(f, "[Header]\nVersion=%ld\nFile=%d", + (long) prefix().filelevel(), num()); + for (int k = 0; k < nflds; k++) + { + if ((k % 10) == 0) fprintf(f, "\nFields="); + else fprintf(f, "|"); + fprintf(f, "%s,%d", (const char *) (const TString&) fld[k], len[k]); + } + fprintf(f, "\n\n[Data]\n"); + if (nkey) + { + setkey(nkey); + for ( first(); status() == NOERR && !p.iscancelled(); next(), i++) + { + p.setstatus(i + 1); + if (filter && *filter) + { + TToken_string filter_str(filter); + TString16 fname; + bool skip = false; + while (!skip && !(fname=filter_str.get()).empty()) + { + const char* fval = filter_str.get(); + const TString& cmp = get(fname); + skip = cmp != fval; + } + skip |= (select_func != NULL) && (select_func(curr(), filter_obj) == false); + if (skip) + continue; + } + s.cut(0); + for (j = 0; j < nflds; j++) + { + const TString& fname = fld.row(j); + if (fixedlen) + { + s1 = get(fname); + if (rjust[j]) s1.right_just(len[j]); + else s1.left_just(len[j]); + } + else + { + s1.cut(0); + if (j && fs) s1 << fs; + if (fd) s1 << fd; + sfld = get(fname); + switch (curr().type(fname)) + { + case _intfld: + case _longfld: + case _intzerofld: + case _longzerofld: + case _realfld: + if (real::is_null(sfld)) + sfld.cut(0); + break; + case _memofld: + if (sfld.full()) + { + int p = 0; + while ((p = sfld.find('\n', 0)) >= 0) + { + sfld.overwrite("\\", p); + sfld.insert("n", p+1); + } + } + else + sfld.cut(0); + break; + default: // strfld, charfld, boolfld + if (sfld.blank()) + sfld.cut(0); + break; + } + s1 << sfld; + if (fd) s1 << fd; + } + s << s1; + } + if (fs) // Elimina tutti i campi vuoti a fine record + { + int i; + for (i = s.len()-1; i >= 0 && s[i] == fs; i--); + s.cut(i+1); + } + fprintf(f, "%s%c", (const char*) s, rs); + } + } + else + { + for (i = 0; i < nitems && !p.iscancelled(); i++) + { + zero(); + p.setstatus(i + 1); + readat(i + 1); + + if (filter && *filter) + { + TToken_string filter_str(filter); + TString16 fname; + bool skip = FALSE; + while (!skip && !(fname=filter_str.get()).empty()) + { + const char* fval = filter_str.get(); + const TString& cmp = get(fname); + skip = cmp != fval; + } + if (skip) + continue; + } + + s=""; + if (withdeleted || curr().valid()) + { + for (j = 0; j < nflds; j++) + { + if (fixedlen) + { + s1 = get((const TString&)fld[j]); + if (rjust[j]) s1.right_just(len[j]); + else s1.left_just(len[j]); + } + else + { + s1 = ""; + if (j && fs) s1 << fs; + if (fd) s1 << fd; + sfld = get((const TString&)fld[j]); + if (curr().type((const TString&) fld[j]) == _memofld) + { + int p = 0; + while ((p = sfld.find('\n', 0)) >= 0) + { + sfld.overwrite("\\", p); + sfld.insert("n", p+1); + } + } + s1 << sfld; + if (fd) s1 << fd; + } + s << s1; + } + fprintf(f, "%s%c", (const char*) s, rs); + } + } + } + p.setstatus(nitems); + close(); + fclose(f); + setstatus(err); + return err; +} + +int TSystemisamfile::dump( + const char* to, // @parm Nome del file verso quale esportare + TToken_string & field_list, // @parm Lista dei campi + int nkey, // @parm Numero della chiave di ordinamento con cui scaricare i dati (defualt 1) + char fs, // @parm Carattere seperatore di campo (defualt ) + char fd, // @parm Carattere delimitatore di campo (default '\\0') + char rs, // @parm Carattere separatore di record (default '\\n') + bool vis, // @parm Indica se visualizzare lo stato dell'operazione (defualt TRUE) + bool withdeleted,// @parm Indica se scaricare anche i record cancellati (dafault FALSE) + const char * filter, // @parm Indica l'espressione filtro + SELECTIONFUNCTION select_func, // @parm funzione filtro + TObject * filter_obj) // @parm oggetto di filtro + +// @xref + +{ + FILE* f = NULL; fopen_s(&f, to, "w"); + if (f == NULL) + { + setstatus(2); + return 2; + } + + if (withdeleted) nkey = 0; + int err = ferror(f); + + open(FALSE, nkey ? TRUE : FALSE); + TString s(512); + bool fixedlen = (fs == '\0'); + int nflds = curr().items(); + TString_array fld(nflds); + TBit_array rjust(nflds); + int len[MaxFields]; + int j = 0; + + FOR_EACH_TOKEN(field_list, str) + { + const TString16 fldname(str); + + fld.add(fldname); + const TFieldtypes t = curr().type(fldname); + rjust.set(j, t == _intfld || t == _longfld || t == _realfld || + t == _wordfld || t == _intzerofld || t == _longzerofld); + len[j++] = (t == _datefld) ? 10 : curr().length(fldname); + if (fixedlen && t == _memofld) + return error_box(TR("Non è possibile scaricare a lunghezza fissa un file con campi memo")); + } + TRecnotype i = 0; + const TRecnotype nitems = items(); + + s.format(FR("Esportazione %s"), filename()); + TProgind p(nitems, s, TRUE, TRUE, 70); + TString s1, sfld; + + fprintf(f, "[Header]\nVersion=%ld\nFile=%d", + (long) prefix().filelevel(), num()); + FOR_EACH_ARRAY_ROW(fld, k, el) + { + if ((k % 10) == 0) fprintf(f, "\nFields="); + else fprintf(f, "|"); + + const TString & fldname =fld.row(k); + + fprintf(f, "%s,%d", (const char *) fldname, len[k]); + } + fprintf(f, "\n\n[Data]\n"); + if (nkey) + { + setkey(nkey); + for ( first(); status() == NOERR && !p.iscancelled(); next(), i++) + { + bool skip = false; + + p.setstatus(i + 1); + if (filter && *filter) + { + TToken_string filter_str(filter); + TString16 fname; + + while (!skip && !(fname=filter_str.get()).empty()) + { + const char* fval = filter_str.get(); + const TString& cmp = get(fname); + skip = cmp != fval; + } + } + skip |= (select_func != NULL) && (select_func(curr(), filter_obj) == false); + if (skip) + continue; + s = ""; + FOR_EACH_ARRAY_ROW(fld, j, el) + { + const TString & fldname =fld.row(j); + + if (fixedlen) + { + s1 = get(fldname); + if (rjust[j]) s1.right_just(len[j]); + else s1.left_just(len[j]); + } + else + { + s1 = ""; + if (j && fs) s1 << fs; + if (fd) s1 << fd; + sfld = get(fldname); + if (curr().type(fldname) == _memofld) + { + int p = 0; + while ((p = sfld.find('\n', 0)) >= 0) + { + sfld.overwrite("\\", p); + sfld.insert("n", p+1); + } + } + s1 << sfld; + if (fd) s1 << fd; + } + s << s1; + } + fprintf(f, "%s%c", (const char*) s, rs); + } + } + else + { + for (i = 0; i < nitems && !p.iscancelled(); i++) + { + zero(); + p.setstatus(i + 1); + readat(i + 1); + + if (filter && *filter) + { + TToken_string filter_str(filter); + TString16 fname; + bool skip = FALSE; + while (!skip && !(fname=filter_str.get()).empty()) + { + const char* fval = filter_str.get(); + const TString& cmp = get(fname); + skip = cmp != fval; + } + if (skip) + continue; + } + + s=""; + if (withdeleted || curr().valid()) + { + FOR_EACH_ARRAY_ROW(fld, j, el) + { + const TString & fldname = fld.row(j); + + if (fixedlen) + { + s1 = get(fldname); + if (rjust[j]) s1.right_just(len[j]); + else s1.left_just(len[j]); + } + else + { + s1 = ""; + if (j && fs) s1 << fs; + if (fd) s1 << fd; + sfld = get(fldname); + if (curr().type(fldname) == _memofld) + { + int p = 0; + while ((p = sfld.find('\n', 0)) >= 0) + { + sfld.overwrite("\\", p); + sfld.insert("n", p+1); + } + } + s1 << sfld; + if (fd) s1 << fd; + } + s << s1; + } + fprintf(f, "%s%c", (const char*) s, rs); + } + } + } + p.setstatus(nitems); + close(); + fclose(f); + setstatus(err); + return err; +} + +#endif // FOXPRO + + +void TBaseisamfile::recover() +{ +} + +//////////////////////////////////////////////////////////// +// Memo data +//////////////////////////////////////////////////////////// + +void TMemo_data::init(TRecnotype recno, TIsam_handle file) +{ + CHECK(file > 0 || recno < 0, "Valid memo recno with NULL memo file"); // verificare + _recno = recno; + _isamfile = file; +} + +void TMemo_data::destroy() +{ + TString_array::destroy(); + _dirty.reset(); + _recno = RECORD_NON_FISICO; + _isamfile = 0; +} + +void TMemo_data::copy(const TMemo_data& m) +{ + TString_array::operator=(m); + _dirty = m._dirty; + _recno = m._recno; + _isamfile = m._isamfile; +} + +//////////////////////////////////////////////////////////// +// TRectype +//////////////////////////////////////////////////////////// + +void TRectype::init(int logicnum) +{ + _logicnum = logicnum; + CHECK(_logicnum > 0,"Impossibile costruire un record di un file esterno"); + + _length = prefix().get_reclen(logicnum); + + _rec = new char [_length]; + *_tab = '\0'; + if (_length > 0) + zero(); + else + setempty(TRUE); + + if (_length > 0 && lf_has_memo(logicnum)) + init_memo(RECORD_NON_FISICO); +} + +TRectype::TRectype(int logicnum) + : _memo_data(NULL) +{ + init(logicnum); +} + +TRectype::TRectype(const TBaseisamfile* i) + : _memo_data(NULL) +{ + init(i->num()); +} + +TRectype::TRectype(const TRectype& r) + : _memo_data(NULL) + +{ + init(r._logicnum); + if (r._memo_data) + { + init_memo(r._memo_data->recno(), r._memo_data->file()); + *_memo_data = *r._memo_data; + } + memcpy(_rec, r._rec, _length); + memcpy(_tab, r._tab, sizeof(_tab)); + setempty(r.empty()); +} + +TRectype::~TRectype() +{ + if (_rec != NULL) + delete _rec; + if (_memo_data != NULL ) + delete _memo_data; +} + +void TRectype::unknown_field(const char* name) const +{ + static int last_file = 0; + if (_logicnum != last_file) + { + NFCHECK("Il campo '%s' non appartiene al file %d", name, _logicnum); + last_file = _logicnum; + } +} + +void TRectype::write_memo(TIsam_handle file, const TRecnotype recno) +{ + const RecDes& r = rec_des( ); + TIsam_handle orig = _memo_data->file(); + if (orig && (file != orig || recno != _memo_data->recno())) + { + TCodeb_handle cb_orig = prefix().get_handle(orig); + DB_go(cb_orig, _memo_data->recno()); + for(int i = r.NFields - 1; i >= 0; i--) + { + if (r.Fd[i].TypeF == _memofld) + { + if (_memo_data->objptr(i) == NULL) + { + const char* memo = DB_memoptr(cb_orig, r.Fd[i].Name); + if (memo && *memo) + _memo_data->add(memo, i); + } + _memo_data->set_dirty(i); + } + } + } + CHECKD(recno >= 0, "Maiale! Non fare le GO con _recno < 0: ", recno); + const TCodeb_handle cb_handle = prefix().get_handle(file); + DB_go( cb_handle, recno); + FOR_EACH_ARRAY_ROW_BACK((*_memo_data), i, memo) + { + if (_memo_data->is_dirty(i)) + DB_memowrite(cb_handle, r.Fd[i].Name, *memo); + } + DB_flush(cb_handle); + *this = (const char*)DB_getrecord(cb_handle); + init_memo(recno, file); +} + +void TRectype::init_memo(TRecnotype recno, TIsam_handle file) +{ + if (_memo_data == NULL) + _memo_data = new TMemo_data; + else + _memo_data->destroy(); + _memo_data->init(recno, file); +} + +void TRectype::settab(const char *tab) +{ + strcpy(_tab, tab); + zero(); +} + +TObject* TRectype::dup() const +{ + TRectype* o = new TRectype(*this); + return o; +} + +const char* TRectype::build_key(int num) const +{ + TString& tmp = get_tmp_string(256); + __build_key(rec_des(), num, string(), tmp.get_buffer(), TRUE); + return tmp; +} + +const char* TRectype::last_key_field(int key) const +{ + const KeyDes& kd = rec_des().Ky[key]; + const int last = kd.NkFields-1; + const bool upp = kd.FieldSeq[last] > MaxFields; + const int nf = upp ? kd.FieldSeq[last] - MaxFields : kd.FieldSeq[last]; + const RecFieldDes& rf = rec_des().Fd[nf]; + return rf.Name; +} + +// @doc EXTERNAL + +// @mfunc Confronta le chiavi di due record +// +// @rdesc Ritorna il risultato di una : +// +// @flag 0 | Se le due chiavi sono uguali +// @flag 0 | Se le due chiavi sono diverse +int TRectype::compare_key( + const TRectype& rec, // @parm Record di cui confrontare le chiavi + int key, // @parm Numero della chiave del presente record (defautl 1) + int skip_last) const // @parm Numero di campi da ignorare nella comparazione a partire dall'ultimo + +// @xref +{ +/* Vecchio modo con molte operazioni su stringhe e molte chiamate a rec_des()! + TString256 key1 = build_key(key); + TString256 key2 = rec.build_key(key); + if (skip_last > 0) + { + const KeyDes& kd = rec_des()->Ky[key-1]; + const int last = kd.NkFields-1; + CHECKD(last >= skip_last, "Can't ignore so many fields in key: ", skip_last); + for (int l = 0; l < skip_last; l++) + { + int nf = kd.FieldSeq[last-l]; + if (nf > MaxFields) nf -= MaxFields; + const RecFieldDes& rf = rec_des()->Fd[nf]; + key1.rtrim(rf.Len); + key2.rtrim(rf.Len); + } + } + const int res = strcmp(key1, key2); +*/ + const char* key1 = build_key(key); + const char* key2 = rec.build_key(key); + int res = 0; + if (skip_last > 0) + { + int maxlen = 0; + const RecDes& rd = rec_des(); + const KeyDes& kd = rd.Ky[key-1]; + const int last = kd.NkFields-skip_last; + for (int l = 0; l < last; l++) + { + const int nf = kd.FieldSeq[l] % MaxFields; + const RecFieldDes& rf = rd.Fd[nf]; + maxlen += rf.Len; + } + res = strncmp(key1, key2, maxlen); + } + else + res = strcmp(key1, key2); + + return res; +} + +HIDDEN bool fld_empty(const char* s, int len, bool /* number */) +{ + if (s && *s && len > 0) + { + for (; len; s++, len--) if (*s != ' ') + return false; + } + return true; +} + +HIDDEN int fld_cmp(const char* a, const char* b, int len, bool number) +{ + int res = memcmp(a, b, len); + if (res == 0) + return res; + + int i = 0; + if (number) // Aggiunta del 11-02-2014: ignoro spazi e zeri iniziali dei numeri + for (; i < len && (*a==' ' || *a=='0') && (*b==' ' || *b=='0'); b++, a++, i++); + + for (; i < len && *a == *b; b++, a++, i++); + if (i == len) + return 0; + + res = *a - *b; + if (number) + { + b -= i; + i = 0; + } + + return fld_empty(b, len - i, number) ? 0 : res; +} + + +/////////////////////////////////////////////////////////// +// TRectype (record di un file) +/////////////////////////////////////////////////////////// + +const RecDes& TRectype::rec_des() const +{ + return prefix().get_recdes(_logicnum); +} + +int TRectype::items() const +{ + return rec_des().NFields; +} + +const char* TRectype::start(int nf) const +{ + return string() + rec_des().Fd[nf].RecOff; +} + +// Confronto tra record: Attenzione i campi vuoti di s non vengono confrontati! +int TRectype::compare(const TSortable& s) const +{ + const TRectype& br = (const TRectype&) s; + int res = 0; + + if (br.empty()) return UNDEFINED; + + const RecDes& rd = rec_des(); + for (int i = 0; i < rd.NFields; i++) + { + const char* b = br.start(i); + const char* a = start(i); + const byte typ = rd.Fd[i].TypeF; + const int sz = rd.Fd[i].Len; + const bool number = (typ == _intfld) || (typ == _realfld) || + (typ == _longfld) || (typ == _wordfld) || + (typ == _intzerofld) || (typ == _longzerofld) || (typ == _datefld) ; + + if (fld_empty(b, sz, number)) continue; + res = ::fld_cmp(a, b, sz, number); + if (res) return res; + } + return 0; +} + +// Confronto stretto +bool TRectype::is_equal(const TRectype& r) const +{ + char* r1 = new char[_length]; + char* r2 = new char[_length]; + memcpy(r1, _rec, _length); + memcpy(r2, r._rec, _length); + browse_null(r1, _length); + browse_null(r2, _length); + + if (has_memo()) + { + const RecDes& rd = rec_des(); + for(int i = rd.NFields - 1; i >= 0; i--) + { + if (rd.Fd[i].TypeF == _memofld) + { + memset(r1+rd.Fd[i].RecOff, ' ', rd.Fd[i].Len); + memset(r2+rd.Fd[i].RecOff, ' ', rd.Fd[i].Len); + } + } + } + bool yes = memcmp(r1, r2, _length) == 0; + delete r1; + delete r2; + + if (yes && has_memo()) + { + const RecDes& rd = rec_des(); + for(int i = rd.NFields - 1; yes && i >= 0; i--) + { + if (rd.Fd[i].TypeF == _memofld) + yes = get(rd.Fd[i].Name) == r.get(rd.Fd[i].Name); + } + } + return yes; +} + +TFieldtypes TRectype::type(const char* fieldname) const +{ + const RecDes& recd = rec_des(); + const int p = findfld(&recd, fieldname); + return p != FIELDERR ? (TFieldtypes)recd.Fd[p].TypeF : _nullfld; +} + +int TRectype::length(const char* fieldname) const +{ + const RecDes& recd = rec_des(); + const int p = findfld(&recd, fieldname); + return p != FIELDERR ? recd.Fd[p].Len : 0; +} + +int TRectype::ndec(const char* fieldname) const +{ + const RecDes& recd = rec_des(); + const int p = findfld(&recd, fieldname); + return p != FIELDERR ? recd.Fd[p].Dec : 0; +} + +bool TRectype::exist(const char* fieldname) const +{ + return findfld(&rec_des(), fieldname) != FIELDERR; +} + +const char* TRectype::fieldname(int i) const +{ + const RecDes& recd = rec_des(); + return i >= 0 && i < recd.NFields ? recd.Fd[i].Name : NULL; +} + +const TString& TRectype::get_str(const char* fieldname) const +{ + const RecDes& recd = rec_des(); + const int nf = findfld(&recd, fieldname); + if (nf != FIELDERR) + { + const RecFieldDes& fd = recd.Fd[nf]; + TString& tmp = get_tmp_string(fd.Len + (fd.TypeF == _datefld ? 2 : 0)); + __getfieldbuff(fd.Len, fd.TypeF, _rec + fd.RecOff, tmp); + return tmp; + } + else + unknown_field(fieldname); + return EMPTY_STRING; +} + +const TString& TRectype::get(const char* fieldname) const +{ + if (_memo_data && type(fieldname) == _memofld) + { + const RecDes& recd = rec_des(); + const int index = findfld(&recd, fieldname); + if ( _memo_data->objptr( index )) + return _memo_data->row( index ); + if (_memo_data->recno() >= 0L) + { + const TIsam_handle orig = _memo_data->file(); + if (orig) + { + CHECKD(orig >= LF_EXTERNAL || orig == num(), "Invalid isam handle ", orig); + TCodeb_handle cb_handle = prefix().get_handle(orig, -1); + CHECKD(cb_handle >= 0, "Can't read memo from file ", orig); + if (DB_recno(cb_handle) != _memo_data->recno()) + DB_go(cb_handle, _memo_data->recno()); + _memo_data->add(DB_memoptr(cb_handle, fieldname), index); + } + else + NFCHECK("Valid memo recno with null memo file"); + } + else + _memo_data->add("", index); + return _memo_data->row(index); + } + return get_str(fieldname); +} + +int TRectype::get_int(const char* fieldname) const +{ + return atoi(get_str(fieldname)); +} + +long TRectype::get_long(const char* fieldname) const +{ + return atol(get_str(fieldname)); +} + + +word TRectype::get_word(const char* fieldname) const +{ + return (word)atoi(get_str(fieldname)); +} + +real TRectype::get_real(const char* fieldname) const +{ + const real r(get_str(fieldname)); + return r; +} + +char TRectype::get_char(const char* fieldname) const +{ + return get_str(fieldname)[0]; +} + +bool TRectype::get_bool(const char* fieldname) const +{ + const char c = get_char(fieldname); + return (c == 'X') || (c == '1'); +} + +TDate TRectype::get_date(const char* fieldname) const +{ + const TDate d(get_str(fieldname)); + return d; +} + +void TRectype::put(const char* fieldname, int val) +{ + char tmp[16]; + _itoa_s(val, tmp, 10); + put_str(fieldname, tmp); +} + + +void TRectype::put(const char* fieldname, long val) +{ + char tmp[16]; + _ltoa_s(val, tmp, 10); + put_str(fieldname, tmp); +} + + +void TRectype::put(const char* fieldname, word val) +{ + put(fieldname, (int)val); +} + +void TRectype::put(const char* fieldname, const real& val) +{ + put_str( fieldname, val.string()); +} + +void TRectype::put(const char* fieldname, const TCurrency& val) +{ + put_str( fieldname, val.get_num().string()); +} + +void TRectype::put(const char* fieldname, const TDate& val) +{ + put( fieldname, val.date2ansi()); +} + +void TRectype::put(const char* fieldname, char val) +{ + const char w[2] = { val, '\0' }; + put_str( fieldname, w); +} + + +void TRectype::put(const char* fieldname, bool val) +{ + put(fieldname, val ? 'X' : ' '); +} + + +void TRectype::put_str(const char* fieldname, const char* val) +{ + const RecDes& recd = rec_des(); + const int nf = findfld(&recd, fieldname); + if (nf == FIELDERR) + { + unknown_field(fieldname); + return; + } + + const RecFieldDes& fd = recd.Fd[nf]; + const TFieldtypes ft = TFieldtypes(fd.TypeF); + + if (val == NULL) + val = ""; + if (ft == _boolfld) + val = (*val && strchr("1STXY", toupper(*val)) != NULL) ? "T" : "F"; + + if (*val == '\0') + { + TRecfield f(*this, fieldname); + if (*f.pos() == '\0') return; + } + if (ft == _memofld) + { + _memo_data->add(val, nf); + _memo_data->set_dirty(nf); + } + else + { + __putfieldbuff(fd.Len, fd.Dec, ft, val, _rec + fd.RecOff); + } + + setempty(FALSE); +} + +void TRectype::add(const char* fieldname, const real& val) +{ + if (!val.is_zero()) + { + real k = get_real(fieldname); + k += val; + put(fieldname, k); + } +} + +void TRectype::zero(const char* fieldname) +{ + if (*_tab && strcmp(fieldname , "COD") == 0) + put("COD", _tab); + else + { + const RecDes& recd = rec_des(); + const int nf = findfld(&recd, fieldname); + if (nf == FIELDERR) + unknown_field(fieldname); + else + { + const int recoff = recd.Fd[nf].RecOff; + char * p = _rec + recoff; + const byte len = recd.Fd[nf].Len; + const byte dec = recd.Fd[nf].Dec; + const TFieldtypes type = (TFieldtypes) recd.Fd[nf].TypeF; + switch (type) + { + case _datefld: + __putfieldbuff(len, dec, _datefld, "", p); + break; + case _memofld: + __putfieldbuff(len, dec, _memofld, "", p); + _memo_data->add("", nf); + _memo_data->set_dirty(nf); + break; + default: + memset(p, ' ', len); + if ((type == _intfld) || (type == _longfld) || (type == _wordfld)) + *(p + len - 1) = '0'; + else + if (type == _realfld) + { + if (dec) + { + memset(p + len - dec - 2, '0', dec + 2); + *(p + len - dec - 1) = '.'; + } + else + *(p + len - 1) = '0'; + } + break; + } + } + } +} + +void TRectype::zero(char c) +{ + memset(_rec, c, len()); + recall(); + + if (*_tab) + put("COD", _tab); + + if(has_memo()) + init_memo( RECORD_NON_FISICO ); + setempty(true); +} + +// Certified 99% +TRectype& TRectype::operator =(const TRectype& rec) +{ + CHECK(num() == rec.num(), "Can't assign records of different file"); + + memcpy(_rec, rec._rec, _length); // Copy contents + if (rec._memo_data) + { + init_memo(rec._memo_data->recno(), rec._memo_data->file()); + *_memo_data = *rec._memo_data; + } + memcpy(_tab, rec._tab, sizeof(_tab)); + setempty(rec.empty()); // Copy emptiness status + return *this; +} + +// Certified 100% +TRectype& TRectype::operator =(const TBaseisamfile& f) +{ + return *this = f.curr(); +} + +// Certified 50% +int TRectype::read(TBaseisamfile& f, word op, word lockop) +{ + int err = f._read(*this,op,lockop); + return err; +} + +int TRectype::readat(TBaseisamfile& f, TRecnotype nrec, word lockop) +{ + return f._readat(*this,nrec,lockop); +} + + +// Certified 100% +int TRectype::next(TBaseisamfile& f,word lockop) +{ + return read(f, _isnext, lockop); +} + +// Certified 100% +int TRectype::prev(TBaseisamfile& f,word lockop) +{ + return read(f, _isprev, lockop); +} + +int TRectype::first(TBaseisamfile& f,word lockop) +{ + return read(f, _isfirst, lockop); +} + +int TRectype::last(TBaseisamfile& f,word lockop) +{ + return read(f, _islast, lockop); +} + +// Certified ??% +int TRectype::write(TBaseisamfile& f) const +{ return f._write(*this); } + +// Certified ??% +int TRectype::rewrite(TBaseisamfile& f) const +{ + return f._rewrite(*this); +} + +int TRectype::write_rewrite(TBaseisamfile& f) const +{ + int err = write(f); + if (err == NOERR) + f._read((TRectype&)*this, _iscurr, _unlock); // Sblocca record 19-09-2012 (andrebbe nella _write) + else + err = rewrite(f); + return err; +} + +int TRectype::rewrite_write(TBaseisamfile& f) const +{ + int err = rewrite(f); + if (err != NOERR) + { + err = write(f); + if (err == NOERR) + f._read((TRectype&)*this, _iscurr, _unlock); // Sblocca record 19-09-2012 (andrebbe nella _write) + } + return err; +} + +// Certified ??% +int TRectype::remove(TBaseisamfile& f) const +{ + return f._remove(*this); +} + +void TRectype::renum_key(const char* field, const char* val) +{ + if (strchr(field, '[') != NULL) // Accept CODTAB[6,10] + { + const TFieldref fref(field, 0); + TString80 str = val; + if (real::is_natural(val)) + str.right_just(fref.len(*this), '0'); + fref.write(str, *this); + } + else + put(field, val); +} + +// Certified 99% +TRectype& TRectype::operator =(const char* rec) +{ + if (rec && *rec) + { + memcpy(_rec, rec, _length); + setempty(false); + } + else + zero(); + return *this; +} + +const char* TRectype::key(int numkey) const +{ + TString& tmp = get_tmp_string(256); + __build_key(rec_des(), numkey, _rec, tmp.get_buffer(), false); + return tmp; +} + +void TRectype::fill_transaction(TConfig& cfg, int row) const +{ + TString16 p; p << num(); + if (row > 0) p << ',' << row; + cfg.set_paragraph(p); + + for (int f = items()-1; f >= 0; f--) + { + const char* name = fieldname(f); + const char* value = get(name); + cfg.set(name, value); + } +} + +bool TRectype::send_mail(const char* action) const +{ + TWait_cursor hourglass; + bool ok = ::can_dispatch_transaction(*this); + if (ok) + { + TFilename ininame; ininame.temp("msg", "ini"); + if (ok) // Dummy test per {} + { + TConfig ini(ininame, "Transaction"); + ini.set("Action", action); + ini.set("Mode", "A"); + fill_transaction(ini); + } + ok = ::dispatch_transaction(*this, ininame); + ininame.fremove(); + } + return ok; +} + +bool TRectype::get_relapp(TString& app) const +{ + if (*_tab) + { + TString4 cod(_tab); + switch (num()) + { + case LF_TABCOM: cod.insert("%"); break; + case LF_TABGEN: cod.insert("^"); break; + case LF_TABMOD: + { + TModule_table mod(_tab); + return mod.get_relapp(app); + } + break; + default : break; + } + return ::get_tabapp(cod, app); + } + return ::get_relapp(num(), app); +} + +bool TRectype::edit(int logicnum, const char* alternate_key_fields, const char* hint) const +{ + bool ok = false; + if (logicnum <= 0) + logicnum = num(); + + TRectype r(logicnum); + if (*_tab) + r.settab(_tab); + + TString app = hint; + if (app.blank()) + r.get_relapp(app); + if (app.full()) + { + const RecDes& recd = r.rec_des(); // Descrizione del record della testata + const KeyDes& kd = recd.Ky[0]; // Elenco dei campi della chiave 1 + TToken_string key_labels; + for (int i = 0; i < kd.NkFields; i++) + { + const int nf = kd.FieldSeq[i] % MaxFields; + const RecFieldDes& rf = recd.Fd[nf]; + key_labels.add(rf.Name); + } + + TToken_string key_fields(alternate_key_fields); + if (key_fields.empty_items()) + key_fields = key_labels; + + TFilename ininame; ininame.temp("lnk", "ini"); + { + TConfig ini(ininame, "Transaction"); + ini.set("Action", "LINK"); + TString8 p; p << logicnum; + ini.set_paragraph(p); + + FOR_EACH_TOKEN(key_labels, tok) + { + const TString16 name(tok); + const TString& value = get(key_fields.get()); + ini.set(name, value); + } + } + + app << " -i" << ininame; + TExternal_app a(app); + ok = a.run() == 0; + + if (ok) + { + xvt_sys_sleep(500); + const TString& result = ini_get_string(ininame, "Transaction", "Result"); + ok = result == "OK"; + } + + xvt_fsys_remove_file(ininame); + + if (ok) + rec_cache(logicnum).notify_change(); + } + return ok; +} + +bool TRectype::set_edit_info(const char* ut, const char* dt, const char* or) +{ + bool ok = false; + if (num() >= LF_TABCOM) + { + // Se esiste un campo alfanumerioco UT* + if (ut && *ut && type(ut) == _alfafld) + { + const int len = length(ut); + TString80 usr = user(); + + TString80 s; + xvt_sys_get_user_name(s.get_buffer(), s.size()); + const int at = s.find('@'); if (at > 0 ) s.cut(at); // Windows 8.1 / 10.0 user profile + if (usr.len()+s.len()+1 <= len) + usr << ':' << s; + + xvt_sys_get_host_name(s.get_buffer(), s.size()); + if (usr.len()+s.len()+1 <= len) + usr << '@' << s; + put(ut, usr); // Scrivi utente corrente + ok = true; + + // Se esiste un campo data DT* + if (dt && *dt && type(dt) == _datefld) + { + const TDate oggi(TODAY); + put(dt, oggi); // Scrivi data odierna + + // Se esisnte un campo long OR* + if (or && *or && (type(or) == _longfld || type(or) == _longzerofld)) + put(or, daytime()); // Scrivi ora attuale HHMMSS + } + } + } + return ok; +} + +bool TRectype::set_modify_info() +{ + bool done = false; + if (num() >= LF_LVPASPLAN && exist("UTULAGG")) // Lavanderie + done = set_edit_info("UTULAGG", "DTULAGG", "ORULAGG"); else + if (exist("UTENTE")) + done = set_edit_info("UTENTE", "DATAAGG", NULL); + return done; +} + +bool TRectype::set_creation_info() +{ + bool done = set_modify_info(); + if (num() >= LF_LVPASPLAN && exist("UTCREAZ")) // Lavanderie + done |= set_edit_info("UTCREAZ", "DTCREAZ", "ORCREAZ"); + return done; +} + +/////////////////////////////////////////////////////////// +// TRecfield (campo/sottocampo di un record) +/////////////////////////////////////////////////////////// + +TRecfield::TRecfield(TRectype& rec, const char* name, int from, int to) +{ + _rec = &rec; + + const TFixed_string fname(name); + const int colon = fname.find(':'); + if (colon > 0) + { + _name.strncpy(name, colon); + _sub_field = name+colon+1; + _sub_field << '='; // ??????????????? + } + else + _name = name; + + const RecDes& rd = _rec->rec_des(); + + const int nf = findfld(&rd, _name); + + if (nf == FIELDERR) + { + _sub_field = _name; + _p = _rec->string(); + _len = 0; + _dec = 0; + _type = _alfafld; + } + else + { + if (from < 0) + { + NFCHECK("Invalid Start %d", from); + from = 0; + } + _p = _rec->string() + rd.Fd[nf].RecOff; + _dec = rd.Fd[nf].Dec; + _type = (TFieldtypes)rd.Fd[nf].TypeF; + if (_sub_field.empty()) + { + _p += from; + if (to >= 0) + { + CHECKS(_type == _memofld || (from <= to && to <= rd.Fd[nf].Len), "Invalid Range on field ", (const char *)_name); + _len = to - from + 1; + } + else + _len = rd.Fd[nf].Len - from; + } + else + { + CHECK(_type == _memofld, "You can use Subfields only with Memo"); + _from = from; + _to = to; + if (_type == _memofld) + _len = 0; + else + _len = rd.Fd[nf].Len; + } + } + + CHECKS(colon < 0 || _type == _memofld, "SubField on non memo field: ", name); +} + +void TRecfield::put_subfield(const char* s) +{ + if (_name == _sub_field) + return; + const TString& str = _rec->get(_name); + int p = str.find(_sub_field); + + if (p == 0 || (p > 0 && str[p - 1] < ' ')) + { + p += _sub_field.len(); + + int e = str.find('\n', p); + + if (_to > 0 && p + _to < e) + e = p + _to; + p += _from; + if (p < e) + { + TString val(s); + + if (_to > 0) + { + val.left(e - p + 1); + val.rpad(e - p + 1); + } + TString out = str.left(p); + out << val << str.mid(e); // ? e + 1 + _rec->put(_name, out); + } + } +} + +int TRecfield::operator =(int i) +{ + TString16 buff; buff << i; + if (_sub_field.empty()) + __putfieldbuff( _len, _dec, _type, buff, _p); + else + put_subfield(buff); + _rec->setempty(FALSE); + return i; +} + + +long TRecfield::operator =(long l) +{ + TString16 buff; buff << l; + if (_sub_field.empty()) + __putfieldbuff( _len, _dec, _type, buff, _p); + else + put_subfield(buff); + _rec->setempty(false); + return l; +} + +const real& TRecfield::operator =(const real& r) +{ + const char* buff = r.string(); + if (_sub_field.empty()) + __putfieldbuff( _len, _dec, _type, buff, _p); + else + put_subfield(buff); + _rec->setempty(FALSE); + return r; +} + +const TDate& TRecfield::operator =(const TDate& d) +{ + const TString16 buff = d.stringa(); + if (_sub_field.empty()) + __putfieldbuff( _len, _dec, _type, buff, _p); + else + put_subfield(buff); + _rec->setempty(FALSE); + return d; +} + +const char* TRecfield::operator =(const char* s) +{ + if (_sub_field.empty()) + { + if (_type == _memofld) + _rec->put(_name, s); + else + __putfieldbuff( _len, _dec, _type, s, _p); + } + else + put_subfield(s); + _rec->setempty(FALSE); + return s; +} + +void TRecfield::setptr(TRecnotype r) +{ + if (_p == NULL) return; + + bool n = r < 0; + unsigned char* wp = (unsigned char*) _p; + + if (n) r = -r; + while(wp - (unsigned char*) _p <= 3) + { + *wp = r && 0x000000FF; + r >>= 8; + wp++; + } + if (n) *wp += 128; +} + +void TRecfield::get_subfield(TString& s) const +{ + const TString& str = _rec->get(_name); + + if (_name == _sub_field) + s = str; + else + { + int p = str.find(_sub_field); + + if (p == 0 || (p > 0 && str[p - 1] < ' ')) + { + p += _sub_field.len(); + + int e = str.find('\n', p); + if (e < 0) e = str.len(); // L'ultima variabile non termina con \n + if (_to > 0 && p + _to < e) + e = p + _to; + p += _from; + if (p < e) + s = str.sub(p, e); + else + s.cut(0); + } + else + s.cut(0); + } +} + +TRecfield::operator int() const +{ + TString16 tmp; + if (_sub_field.empty()) + { + if (_type == _intfld || _type == _intzerofld || _type == _longfld || _type == _longzerofld) + tmp.strncpy(_p, _len); + else + __getfieldbuff( _len, _type, _p, tmp); + } + else + get_subfield(tmp); + return atoi(tmp); +} + + +TRecfield::operator long() const +{ + TString16 tmp; + + if (_sub_field.empty()) + { + if (_type == _longfld || _type == _longzerofld || _type == _intfld || _type == _intzerofld) + tmp.strncpy(_p, _len); + else + __getfieldbuff( _len, _type, _p, tmp); + } + else + get_subfield(tmp); + + return atol(tmp); +} + + +TRecfield::operator const real() const +{ + TString80 tmp; + + if (_sub_field.empty()) + { + if (_type == _realfld) + tmp.strncpy(_p, _len); + else + __getfieldbuff( _len, _type, _p, tmp); + } + else + get_subfield(tmp); + + return real(tmp); +} + + +TRecfield::operator TDate() const +{ + TString16 tmp; + + if (_sub_field.empty()) + { + if (_type == _datefld) + { + tmp.strncpy(_p, 8); + return TDate(atol(tmp)); + } + __getfieldbuff(_len, _type, _p, tmp); + } + else + get_subfield(tmp); + + return TDate(tmp); +} + + +TRecfield::operator const char*() const +{ + TString& tmp = get_tmp_string(max(_len, 50)); + + if (_sub_field.empty()) + { + if (_type == _memofld) + return _rec->get(_name); + __getfieldbuff(_len, _type, _p, tmp); + } + else + get_subfield(tmp); + + return tmp; +} + + +TRecnotype TRecfield::ptr() const +{ + if (_p == NULL) return(RECORD_NON_FISICO); + unsigned char* wp = (unsigned char*) _p + 3; + TRecnotype r = *wp; + bool n = r > 127; + + if (n) r -= 128; + while(wp-- > (unsigned char*) _p) + r = (r << 8) + *wp; + return n ? -r : r; +} diff --git a/include/prefix.cpp b/include/prefix.cpp index bfc60bbec..ba648f83f 100755 --- a/include/prefix.cpp +++ b/include/prefix.cpp @@ -494,7 +494,7 @@ const TFilename& TFile_info::load_filedes() { _dir = _filedes.SysName[0] != '$' ? _comdir : _nordir; _name = CAddPref(_filedes.SysName); - strncpy_s(_filedes.Des, sizeof(_filedes.Des), dictionary_translate(_filedes.Des), sizeof(_filedes.Des)-1); + strncpy(_filedes.Des, dictionary_translate(_filedes.Des), sizeof(_filedes.Des)-1); } else _name.cut(0); @@ -533,8 +533,8 @@ TFile_info::TFile_info(int logicnum, TFilename& name) int err = DB_recinfo(_name, &_filedes, (RecDes*)&rec.rec(), keys.get_buffer()); if (err == NOERR && prefix().add_recdes(logicnum, rec, keys)) { - strncpy_s(_filedes.SysName, sizeof(_filedes.SysName), _name, sizeof(_filedes.SysName)); - _filedes.SysName[sizeof(_filedes.SysName)-1] = '\0'; + strncpy(_filedes.SysName, _name, sizeof(_filedes.SysName)); + _filedes.SysName[41] = '\0'; } else _name.cut(0); @@ -800,15 +800,12 @@ long TFile_manager::last_change(TIsam_handle name) const return i.last_change(); } -int TFile_manager::close_closeable(bool firm_only) +int TFile_manager::close_closeable() { _open_files = 0; // Ricalcolo per sicurezza for (TIsam_handle n = _fileinfo.last(); n > 0; n = _fileinfo.pred(n)) { TFile_info& i = fileinfo(n); - if (firm_only && i.dir_type() != _nordir) - continue; - if (i.is_open()) { _open_files++; @@ -824,9 +821,9 @@ int TFile_manager::close_closeable(bool firm_only) return _open_files; } -void TFile_manager::close_all(bool firm_only) +void TFile_manager::close_all() { - const int zoccolo_duro = close_closeable(firm_only); + const int zoccolo_duro = close_closeable(); #ifdef DBG if (zoccolo_duro > 0) NFCHECK("%d files refuse to be closed!", zoccolo_duro); @@ -835,8 +832,6 @@ void TFile_manager::close_all(bool firm_only) for (int n = _recinfo.last(); n > 0; n = _recinfo.pred(n)) { const TRecord_info& r = recinfo(n); - if (firm_only && r.dir_type() != _nordir) - continue; if (r.mutable_dir()) _recinfo.destroy(n); } @@ -1021,15 +1016,14 @@ void TPrefix::set( return; if (_prefix != ".") { - const bool firm_only = !xvt_str_same(name, "COM") && !xvt_str_same(name, "DEF"); - _manager.close_all(firm_only); + _manager.close_all(); CCloseDir(NORDIR); CCloseDir(COMDIR); CCloseRecDir(NORDIR); CCloseRecDir(COMDIR); } - if (xvt_str_same(name, "DEF")) + if (strcmp(name, "DEF") == 0) { const char* prfx = CGetPref(); xvt_fsys_parse_pathname(prfx, NULL, NULL, _prefix.get_buffer(), NULL, NULL); @@ -1041,7 +1035,7 @@ void TPrefix::set( { const TString saved_prf = __ptprf; // Salvo __ptprf che viene cambiato da CGetPref char* prfx = (char*)CGetPref(); // Safe non const cast for StPath cprefix - strcpy_s(__ptprf, sizeof(__ptprf), saved_prf); + strcpy(__ptprf, saved_prf); xvt_fsys_build_pathname(prfx, NULL, __ptprf, _prefix, NULL, NULL); } else @@ -1086,11 +1080,12 @@ bool TPrefix::exist(long codditta) const bool TPrefix::test(const char* s) const { - if (s && *s && !xvt_str_same(s, "DEF")) + if (s && *s && strcmp(s, "DEF") != 0) { TFilename s1(__ptprf); s1.add(s); - s1.add("dir.gen"); + s1.add("dir.gen"); + if (s1.exist()) { if (xvt_fsys_access(s1, 0x2) != 0) @@ -1171,7 +1166,7 @@ bool TPrefix::set_studio(const char* study, long ditta) const TString old_study(__ptprf); const TString old_firm(_prefix); - strcpy_s(__ptprf, sizeof(__ptprf), study); + strcpy(__ptprf, study); const word len = strlen(__ptprf); if (len > 0 && __ptprf[len-1] != '\\' && __ptprf[len-1] != '/') { @@ -1184,7 +1179,7 @@ bool TPrefix::set_studio(const char* study, long ditta) bool ok = set_codditta(ditta, TRUE); if (!ok) { - strcpy_s(__ptprf, sizeof(__ptprf), old_study); + strcpy(__ptprf, old_study); set(old_firm, true); } return ok; diff --git a/include/prefix.h b/include/prefix.h index 313761199..54fa76c52 100755 --- a/include/prefix.h +++ b/include/prefix.h @@ -54,8 +54,8 @@ public: void notify_change(TIsam_handle name); long last_change(TIsam_handle name) const; - int close_closeable(bool firm_only = false); - void close_all(bool firm_only = false); + int close_closeable(); + void close_all(); void open_all(); TFile_manager(); @@ -138,16 +138,19 @@ public: // @cmember Setta lo studio corrente bool set_studio(const char* study, long firm = 0); // @cmember Ritorna il contenuto della variabile

- const char* name() const { return _prefix; } + const char* name() const + { return _prefix;} // @cmember Ritorna il livello degli archivi - unsigned int filelevel() const { return _filelevel; } + unsigned int filelevel() const + {return _filelevel;} // @cmember Ritorna il livello standard degli archivi unsigned int get_stdlevel() const { return _stdlevel; } void set_stdlevel(unsigned int sl) { _stdlevel = sl; } // @cmember Ritorna il numero di archivi - int items() const { return _items; } + int items() const + { return _items; } // @cmember Ritorna la descrizione del file passato const char* description(const char* cod) const; // @cmember Ritorna la descrizione del file passato @@ -163,7 +166,7 @@ public: // @cmember Riapre tutti gli archivi della ditta attiva void reopen() const ; - TIsam_handle open_isamfile(int& logicnum, TFilename& name, bool excl = false, bool idx = true) + TIsam_handle open_isamfile(int& logicnum, TFilename& name, bool excl = FALSE, bool idx = TRUE) { return _manager.open(logicnum, name, excl, idx); } int close_isamfile(TIsam_handle& name) diff --git a/include/relapp.cpp b/include/relapp.cpp index 681c527b7..7fe764e7a 100755 --- a/include/relapp.cpp +++ b/include/relapp.cpp @@ -552,7 +552,7 @@ bool TRelation_application::modify_mode() if (err != NOERR) { if (err == _islocked) - message_box(TR("I dati sono gia' usati da un altro programma")); + message_box(TR("I dati sono già usati da un altro utente")); else error_box(FR("Impossibile leggere i dati: errore %d"), err); if (!is_transaction()) diff --git a/include/validate.cpp b/include/validate.cpp index f92d2f1ca..42df18f4c 100755 --- a/include/validate.cpp +++ b/include/validate.cpp @@ -289,12 +289,12 @@ HIDDEN bool _cf_val(TMask_field& f, KEY key) bool ok = true; if (cf.empty()) return true; - if (cf.len() == 11 && isdigit(cf[0])) + if (isdigit(cf[0]) && cf.len() >= 11) { const TString& stato = get_fld_val_param(f, 0); if (stato.full() && stato != "IT") return true; - ok = pi_check (stato, cf); + ok = pi_check(stato, cf); } else ok = __cf_check(cf); @@ -302,7 +302,7 @@ HIDDEN bool _cf_val(TMask_field& f, KEY key) { if(f.dirty()) { - ok = f.noyes_box(TR("Codice fiscale errato: si desidera accettarlo ugualmente?")); + ok = f.yesno_box(TR("Codice fiscale errato: si desidera accettarlo ugualmente?")); if (ok) f.set_dirty(false); } else