Files correlati : ve7.exe Ricompilazione Demo : [ ] Commento : Nella ricezione da galileo si devono esportare nel file di testo solo i record modificati git-svn-id: svn://10.65.10.50/trunk@14711 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			4387 lines
		
	
	
		
			104 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			4387 lines
		
	
	
		
			104 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <fcntl.h>
 | |
| 
 | |
| #include <diction.h>
 | |
| #ifdef WIN32
 | |
| #include <io.h>
 | |
| #include <share.h>
 | |
| #include <stdio.h>
 | |
| #endif
 | |
| #include <stdlib.h>        
 | |
| #include <sys/stat.h>
 | |
| 
 | |
| #include <codeb.h>  
 | |
| 
 | |
| #define __ISAM_CPP
 | |
| 
 | |
| #include <config.h>
 | |
| #include <execp.h>
 | |
| #include <expr.h>
 | |
| #include <extcdecl.h>
 | |
| #include <mailbox.h>
 | |
| #include <postman.h>
 | |
| #include <prefix.h>
 | |
| #include <progind.h>
 | |
| #include <recarray.h>
 | |
| #include <relation.h>
 | |
| #include <scanner.h>
 | |
| #include <utility.h>  
 | |
| #include <tabutil.h>
 | |
| #include <varrec.h>
 | |
| 
 | |
| 
 | |
| #ifdef JOURNAL
 | |
| #include <journal.h>
 | |
| 
 | |
| static FILE* _journal = (FILE*)0xFFFF;
 | |
| 
 | |
| FILE* get_journal()
 | |
| {
 | |
|   if (_journal == (FILE*)0xFFFF)
 | |
|   {
 | |
|     TConfig ini(CONFIG_INSTALL, "Main");
 | |
|     const TString& name = ini.get("Journal");
 | |
|     if (name.not_empty())
 | |
|       _journal = fopen(name, "ab");
 | |
|     else
 | |
|       _journal = NULL;
 | |
|   }
 | |
|   return _journal;
 | |
| }
 | |
| 
 | |
| TJournalHeader& get_journal_header(int num, const char* op, const char* type)
 | |
| {
 | |
|   static TJournalHeader jh;
 | |
|   const int size = sizeof(TJournalHeader);
 | |
|   CHECKD(size == 64, "Invalid journal header: ", size);
 | |
| 
 | |
|   memset(&jh, 0, size);
 | |
|   strcpy(jh._signature, "J00");
 | |
|   jh._header_length = size;
 | |
|   time(&jh._time);
 | |
|   jh._firm = prefix().get_codditta();
 | |
|   jh._logic_num = num;
 | |
|   strcpy(jh._operation, op);
 | |
|   strcpy(jh._type, type);
 | |
|   jh._data_size = 0;
 | |
|   return jh;
 | |
| }
 | |
| 
 | |
| void write_journal(TJournalHeader& jh, void* data, int len)
 | |
| {
 | |
|   FILE* j = get_journal();
 | |
|   jh._data_size = len;
 | |
|   fwrite(&jh, sizeof(TJournalHeader), 1, j);
 | |
|   fwrite(data, len, 1, j);
 | |
|   fflush(j);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| #define RECLOCKTYPES    0xFF00
 | |
| #define READTYPES       0x00FF                                                                       
 | |
| #define INVFLD          255
 | |
| 
 | |
| Str80 cprefix;
 | |
| 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 (ODD(l))
 | |
|    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);
 | |
| }
 | |
| 
 | |
| bool __file_is_crypted(int logicnum)
 | |
| {
 | |
| 	return logicnum == LF_TURNI;
 | |
| }
 | |
| 
 | |
| void __getfieldbuff(byte l, byte t, const char * recin, char *s, bool is_crypted)
 | |
| {     
 | |
|   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)
 | |
|       strncpy(s, recin, l);
 | |
|   }
 | |
|   s[l] = '\0'; 
 | |
|   if (l)
 | |
|   {
 | |
|     if (t == _datefld)
 | |
|     {
 | |
|       TDate dt(s);
 | |
| #ifdef _DEMO_
 | |
|       int y = dt.year();
 | |
|       if (y & 0x0001) y--;  
 | |
|       y >>= 3;
 | |
|       y++;
 | |
|       y /= 10; 
 | |
|       if (y >= 25)
 | |
|       {
 | |
|         int m = dt.month();
 | |
|         if (m > 3)
 | |
|           dt.set_month(rand() % 3 + 1);
 | |
|       }
 | |
| #endif
 | |
|       strcpy(s, dt.string(full));
 | |
|     }
 | |
|     else
 | |
|       if (t == _boolfld)
 | |
|       {
 | |
|         const char ok = toupper(*s);
 | |
|         if (ok == 'T' || ok == 'Y' || ok == 'S' || ok == 'X')
 | |
|           strcpy(s,"X");
 | |
|         else
 | |
|           strcpy(s," ");
 | |
|       }    
 | |
|   }
 | |
| }
 | |
| 
 | |
| void  __putfieldbuff(byte l, byte d, byte t, const char* s, char* recout, bool is_crypted)
 | |
| {
 | |
|   CHECK(recout, "Can't write null record" );
 | |
| 
 | |
|   char s2[40];
 | |
|   if (t == _datefld)
 | |
|   {
 | |
|     if (s && *s && strlen(s) != 8)
 | |
|     {
 | |
|       const TDate dt(s);    
 | |
|       sprintf(s2, "%ld", dt.date2ansi());
 | |
|       s = s2;
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|     if (t == _boolfld)
 | |
|     {           
 | |
|       strcpy(s2, (*s && strchr("1STXY", toupper(*s)) != NULL) ? "T" : "F");
 | |
|       s = s2;
 | |
|     }
 | |
|     else
 | |
|       if (t == _realfld)
 | |
|       {
 | |
|         real r(s);
 | |
|         strcpy(s2, r.string(l, d)); 
 | |
|         s = s2;
 | |
|       }
 | |
| 
 | |
|   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)
 | |
|     {
 | |
|       strcpy(s2, "0");
 | |
|       s = s2;
 | |
|       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("install.ini");
 | |
|   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 (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("install.ini");
 | |
|   TCallbackTableinfo fi;
 | |
|   TTable t(tabname);
 | |
|   fi._var1.format("Edit_%s", t.name());
 | |
|   fi._var2.format("Edit_%d", t.num());
 | |
|   fi._var2.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.compare("ba", 2, TRUE) != 0)
 | |
|     {
 | |
|       TConfig c(CONFIG_STUDIO, fi._module);
 | |
|       if (c.exist("TabPrg"))
 | |
|         app = c.get("TabPrg");
 | |
|     }
 | |
|   }
 | |
|   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
 | |
| void get_idx_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
 | |
| 
 | |
| // @comm Ritorna il nome con il prefisso corrente
 | |
| {
 | |
|   long      c = DB_getconf();
 | |
|   TDir      d; 
 | |
|   TTrec     r;
 | |
|   d.get(logicnum);
 | |
|   r.get(logicnum);
 | |
|   TFilename f(d.name());
 | |
|   
 | |
|   if (c & 1) f.ext("cdx");
 | |
|   if (c & 4) f.ext("mdx");
 | |
|   i_names.cut(0);
 | |
|   i_names.add(f);
 | |
|   f.ext("");
 | |
|   f.rtrim(1);
 | |
|   if ((c & 2) || (c & 8))    // DBIII or CLIPPER format, returns f_name + .cgp, f_nameX + .n{d|t}x
 | |
|     for (int j=1; j<=r.keys();j++)
 | |
|     { 
 | |
|       TString xx=f.name();
 | |
|       if (xx.len()<8)
 | |
|         f << ('0' + j);
 | |
|       else
 | |
|         f[8] = ('0' + j); 
 | |
|       if (c & 2) // CLIPPER
 | |
|         f.ext("ndx");        
 | |
|       else       // DBIII
 | |
|         f.ext("ntx");
 | |
|       i_names.add(f);
 | |
|     }
 | |
|   i_names.restart();
 | |
| }
 | |
| 
 | |
| // 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)
 | |
| {
 | |
|   CHECKD(rd->NFields <= MaxFields, "Tracciato con troppi campi ", rd->NFields);
 | |
|   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 const char * translate_key(const char* key)
 | |
| {
 | |
|   // Trasforma l'espressione
 | |
|   TToken_string t = key;
 | |
|   TToken_string k(t.get(0),'+');
 | |
|   TToken_string range("",',');
 | |
|   TString ws;
 | |
|   const bool is_dup = t.get(1)[0] == 'X';
 | |
|   const int items = k.items();
 | |
|   t = "";
 | |
|   for (int i = 0; i<items; i++) // scorre i campi dell'espressione
 | |
|   {
 | |
|     ws = k.get(i); ws.upper(); // Primo campo
 | |
|     const bool is_upper = ws.find("UPPER")  >= 0;
 | |
|     const bool is_sub   = ws.find("SUBSTR") >= 0;
 | |
|     int   paren1        = ws.find('('); // Trova la prima parentesi aperta
 | |
|     int   paren2,last,from = 0,to = 0;
 | |
|     
 | |
|     if (paren1 >= 0 && is_sub && is_upper)
 | |
|       paren1 = ws.find('('); // Trova la seconda parentesi (in questo caso c'e' per forza)
 | |
| 
 | |
|     if (paren1 >= 0) // Trova la prima virgola o parentesi chiusa (per qualsiasi espressione)
 | |
|     {
 | |
|       paren2 = ws.find(',');
 | |
|       if (paren2 == -1) // se non ci sono virgole trova la parentesi chiusa
 | |
|         paren2 = ws.find(')');
 | |
|       CHECK(paren2 > paren1,"Something wrong happened translating CodeBase expressions.");
 | |
|       if (is_sub) // Se e' una sottostringa estrae i campi DA e A
 | |
|       {
 | |
|         range = ws;
 | |
|         last = ws.find(')');
 | |
|         range.sub(paren2,last); // dalla virgola alla parentesi
 | |
|         from = range.get_int(0);
 | |
|         to   = range.get_int(1);
 | |
|       }
 | |
|       ws = ws.sub(paren1+1,paren2); // Nome del campo pulito pulito
 | |
|       ws.upper();
 | |
|     }
 | |
|     
 | |
|     if (is_upper)
 | |
|       t << "UPPER(";
 | |
|     
 | |
|     t << ws; // aggiunge il nome del campo
 | |
| 
 | |
|     if (is_sub)
 | |
|     {
 | |
|       t << "[";
 | |
|       t << from << ",";
 | |
|       t << to << "]";
 | |
|     }
 | |
|     if (is_upper)
 | |
|       t << ")";
 | |
|     t << '+';
 | |
|   }
 | |
|   t.rtrim(1); // Toglie il + in piu'
 | |
|   t.add(is_dup ? "X" : " "); 
 | |
| 
 | |
|   TString& tmp = get_tmp_string();
 | |
|   tmp = t;
 | |
|   return tmp;
 | |
| } */
 | |
| 
 | |
| HIDDEN  int __build_key(const RecDes *recd, int numkey, 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) > 80)
 | |
|       {
 | |
|         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))
 | |
|             {
 | |
|               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))
 | |
|               {
 | |
|                 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)
 | |
|     {
 | |
|       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 <p __autoload>
 | |
| void set_autoload_new_files(
 | |
|      bool on) // @parm Valore da assegnare
 | |
| 
 | |
| // @comm Il valore di <p __autoload> 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 <p name>
 | |
| // %  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.not_empty(),"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);
 | |
| }
 | |
| 
 | |
| long 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::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) 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());
 | |
|     TString key(128);
 | |
|     __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)
 | |
|       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;
 | |
| 
 | |
| #ifdef _DEMO_
 | |
|   const int logicnum = num();
 | |
|   if ((logicnum > LF_COMUNI && logicnum < LF_ANALISI) || logicnum > LF_RELANA)
 | |
|   {
 | |
|     if (items() > 979L)
 | |
|       return _isfilefull;
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|   // 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);
 | |
|   
 | |
|   if (_lasterr == NOERR) 
 | |
|   {
 | |
| #ifdef JOURNAL
 | |
|     if (get_journal())
 | |
|     {
 | |
|       TJournalHeader& jh = get_journal_header(num(), "ADD", "REC");
 | |
|       write_journal(jh, rec.string(), dst_len);
 | |
|     }
 | |
| #endif
 | |
|   }
 | |
|   else
 | |
|     _lasterr = get_error(_lasterr);
 | |
|   
 | |
|   _recno = DB_recno(fhnd);
 | |
|   if (_lasterr == NOERR && rec.has_memo())
 | |
|     ((TRectype &)rec).write_memo(_isam_handle, _recno );
 | |
|   
 | |
|   return _lasterr;
 | |
| }
 | |
| 
 | |
| int TBaseisamfile::write(const TRectype& rec)
 | |
| {
 | |
|   return rec.write(*this);
 | |
| }
 | |
| 
 | |
| 
 | |
| int TBaseisamfile::write()
 | |
| {                 
 | |
|   return TBaseisamfile::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) 
 | |
|       {
 | |
| #ifdef JOURNAL
 | |
|         if (get_journal())
 | |
|         {
 | |
|           TJournalHeader& jh = get_journal_header(num(), "MOD", "REC");
 | |
|           write_journal(jh, rec.string(), len);
 | |
|         }
 | |
| #endif
 | |
|       }
 | |
|       else
 | |
|         _lasterr = get_error(_lasterr);
 | |
|     }
 | |
|     else
 | |
|       DB_unlock(fhnd);  
 | |
|     _recno = DB_recno(fhnd);
 | |
|     prefix().unlock_record(_isam_handle, _recno);
 | |
| 
 | |
|     if(_lasterr == NOERR)
 | |
|     {
 | |
|       if (curr().has_memo( ))
 | |
|         ((TRectype &)rec).write_memo(_isam_handle, _recno );
 | |
|       rec_cache(_logicnum).notify_change();
 | |
|     }
 | |
|   }    
 | |
| 
 | |
|   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");
 | |
| 
 | |
|   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)
 | |
|   {
 | |
|     _lasterr = DB_delete(fhnd);   // Put only deletion flag on record, must remove keys too!
 | |
|     if (_lasterr == NOERR)         
 | |
|     {
 | |
|       DB_flush(fhnd);
 | |
| #ifdef JOURNAL
 | |
|       if (get_journal())
 | |
|       {
 | |
|         const int len = DB_reclen(fhnd);
 | |
|         TJournalHeader& jh = get_journal_header(num(), "DEL", "REC");
 | |
|         write_journal(jh, rec.string(), len);
 | |
|       }
 | |
| #endif
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       _lasterr = get_error(_lasterr);
 | |
|       DB_recall(fhnd);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if(_lasterr == NOERR)
 | |
|   {
 | |
|     if (curr().has_memo( ))
 | |
|       curr().init_memo();
 | |
|     rec_cache(_logicnum).notify_change();
 | |
|   }
 | |
| 
 | |
|   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 <t TIsamerr>).
 | |
| 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 <p mode> 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 <p index> 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 <p mode> 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 <p index> 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            
 | |
|   {
 | |
|     _isam_handle = 0;
 | |
|     _lasterr = get_error(_isam_handle);
 | |
|   }
 | |
|   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
 | |
|   const int fh = ::_sopen(filename(), _O_RDONLY, _SH_DENYNO);
 | |
|   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 <c TLocalisamfile>
 | |
| 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 <c TLocalisamfile>
 | |
| 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();
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
| //A cosa cavolo serve?
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Aggiorna i flags associati al file
 | |
| //
 | |
| // @rdesc Ritorna NOERR se e' riuscita ad eseguire l'operazione, altrimenti ritorna il numero 
 | |
| //    di errore generato (vedi <t TIsamerr>).
 | |
| int TIsamfile::flags(
 | |
|     bool updateeod) // @parm Indica se aggiornare anche l'EOD del file
 | |
|   
 | |
| {
 | |
|   if (num() <= 0) 
 | |
|     return NOERR ;
 | |
| 
 | |
|   TDir d;
 | |
|   const TDirtype dirtype = prefix().get_dirtype(_filename);
 | |
|   d.get(num(), _lock, dirtype);
 | |
|   int err = d.status(dirtype);
 | |
|   if (err == NOERR)
 | |
|   {
 | |
|     const FileDes& fd = prefix().get_filedes(_filename);
 | |
|     d.flags() = fd.Flags;
 | |
|     if (updateeod) 
 | |
|       d.eod() = fd.EOD;
 | |
|     d.put(num(), dirtype);
 | |
|   }
 | |
|   setstatus(err);
 | |
|   return err;
 | |
| }
 | |
| 
 | |
| */
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // 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 << SLASH << radix; 
 | |
|     }
 | |
|     n.ext("dbf");
 | |
|   }  
 | |
|   else
 | |
|     n.temp(NULL, "dbf");
 | |
|   
 | |
|   if (!create)
 | |
|   {      
 | |
|     TDir dir; dir.get(logicnum);
 | |
|     const word& len = dir.len();  
 | |
| 
 | |
|     FILE* f = fopen(n, "rb");
 | |
|     if (f == NULL)
 | |
| #ifdef WIN32
 | |
|       fatal_box("Impossibile aprire il file temporaneo %s: %s",(const char*) n,(const char*)_strerror(NULL));
 | |
| #else
 | |
|       fatal_box("Impossibile aprire il file temporaneo %s: %s",(const char*) n,(const char*)strerror(errno));
 | |
| #endif
 | |
| 
 | |
|     fseek(f, 0, SEEK_END);
 | |
|     eod = eox = ftell(f) / len;
 | |
|     fclose(f);
 | |
|   }
 | |
|   
 | |
|   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 <t TIsamerr>).
 | |
| 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 <p create> sia TRUE allora viene settato automaticamente il valore di <p _autodel>
 | |
| //   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);     
 | |
| // dalla 1.5 serve ?      relisfd(_isamfile);
 | |
|       fatal_box("Can't create temp file '%s' num. %d: Error n. %d", (const char*)filename, num(), err);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   _isam_handle = prefix().open_isamfile(_logicnum, filename);
 | |
|   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=fopen(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 = new RecDes;
 | |
|   memcpy(rd, curr().rec_des(), sizeof(RecDes));
 | |
| 
 | |
|   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);
 | |
|   }
 | |
| 
 | |
|   delete rd;
 | |
|   return err;
 | |
| }
 | |
| 
 | |
| const char* TExternisamfile::name() const
 | |
| {     
 | |
|   return filename();
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TSystemisamfile
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| int TSystemisamfile::build(TRecnotype eox, const TTrec& r)
 | |
| {
 | |
|   int err=NOERR;
 | |
|   TDir d;
 | |
|   d.get(num());
 | |
|   CHECK(r.len() != 0, "Can't create a file with empty field info");
 | |
| 
 | |
|   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 (!fexist(f)) 
 | |
|     make_dir(f);
 | |
|   if (r.len() != 0)
 | |
|   {  
 | |
|     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);
 | |
|     }
 | |
| 
 | |
|   }
 | |
|   return err;
 | |
| }
 | |
| 
 | |
| int TSystemisamfile::build(TRecnotype eox)
 | |
| {
 | |
|   TTrec r;
 | |
|   r.get(num());
 | |
|   return build(eox,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 <f error_box>)
 | |
| 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 <p flev> 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 <t TIsamerr>)
 | |
| 
 | |
| int TSystemisamfile::update(
 | |
|     const TTrec& newrec, // @parm Nuovo tracciato record con cui aggiornare il file
 | |
|     bool interactive)    // @parm Indica se riportare i campi personalizzati (!interactive
 | |
|   
 | |
| {        
 | |
|   if (newrec.len() == 0)
 | |
|   {
 | |
|     error_box(FR("Il nuovo tracciato per il file %d e' vuoto"), num());
 | |
|     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;
 | |
|   oldrec.get(num());
 | |
| 
 | |
|   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
 | |
|         setstatus(err);
 | |
|         return err;
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|       if (dir.eox() > 0L)
 | |
|       {
 | |
|         dir.eod() = 0L; 
 | |
|         dir.eox() = 0L;
 | |
|       }
 | |
|     }
 | |
| 
 | |
| 		const int wfields = wrec.fields();
 | |
| 		int newfields = wfields;
 | |
| 		TToken_string def;
 | |
| 
 | |
|    	const int oldfields = oldrec.fields();
 | |
| 		for (int j = 0; j < oldfields; j++)
 | |
|     {
 | |
| 			def = oldrec.fielddef(j);
 | |
| 			if (!interactive && (def.get(0)[0] == '_'))
 | |
| 			{
 | |
|         if (newrec.field(def) == FIELDERR)
 | |
|         {
 | |
| 				  if (newfields < MaxFields)
 | |
| 					  wrec.update_fielddef(newfields++, def);
 | |
| 				  else
 | |
| 					  if(!yesno_box(FR("Il campo %s non verra' preservato, continuare"),
 | |
| 							     	  	  (const char *) def.get(0)))
 | |
| 						  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((const char*) tmpfname, wrec.rec());
 | |
|       
 | |
|       if (err != NOERR) 
 | |
|       {
 | |
|         err=get_error(err);
 | |
|         return (err);
 | |
|       }
 | |
| 
 | |
|       if (dir.eod() > 0 && oldrec.len() > 0)
 | |
|       {
 | |
|         err = _open_ex(_excllock, FALSE);
 | |
|         if (err != NOERR) 
 | |
|           return err;
 | |
| 
 | |
|         // 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;
 | |
|         if (fhnd < 0 ) 
 | |
|         {
 | |
|           err=get_error(fhnd);
 | |
|           return err;
 | |
|         }
 | |
|     
 | |
|         TString s; s << TR("Aggiornamento") << ' ' << fname;
 | |
| 
 | |
|         const TRecnotype nitems = items();
 | |
|         TProgind p(nitems > 0 ? nitems : 1, s, FALSE, TRUE, 70);
 | |
| 
 | |
|         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);    
 | |
|         }
 | |
| 
 | |
|         for (first(); good(); next())
 | |
|         {
 | |
|           p.addstatus(1);
 | |
|           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 && nrec.has_memo())
 | |
|             nrec.write_memo(ishandle, DB_recno(fhnd)); 
 | |
|           if (err != NOERR) 
 | |
|             err=get_error(err);
 | |
|           setstatus(err);
 | |
| 
 | |
|         }
 | |
|         close();
 | |
|         prefix().close_isamfile(ishandle);
 | |
| 
 | |
|         if (err!=NOERR) err=get_error(err);
 | |
| 
 | |
|         p.setstatus(nitems);
 | |
|       }
 | |
| 
 | |
|       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=fopen(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.eod() = ni;
 | |
|       }
 | |
|     }
 | |
|     if (err==NOERR)
 | |
|     {    
 | |
|       dir.set_len(lenr);
 | |
|       dir.put(num(), _nordir, _sysdirop);
 | |
|       wrec.put(num());
 | |
|       prefix().update_recdes(num());
 | |
| 
 | |
|       if (toconvert)
 | |
|         packindex();
 | |
|       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 <t TIsamerr>).
 | |
| int TSystemisamfile::packfile(
 | |
|     bool vis, // @parm Indica se visualizzare lo stato dell'operazione
 | |
|     bool zap) // @parm Indica se distruggere tutti i records
 | |
| 
 | |
| // @xref <mf TSystemisamfile::packindex>
 | |
|   
 | |
| {
 | |
|   TDir d;
 | |
|   d.get(num(),_nolock, _nordir,_sysdirop);  // Chi commenta muore!
 | |
|   d.get(num(),_nolock, (d.is_com()) ? _comdir : _nordir);
 | |
|   
 | |
| //  CHECKS(filehnd() == NULL, "Can't pack open file", (const char*)filename());
 | |
|   
 | |
|   int err = DB_packfile(vis, d.name(), zap ? 0L : d.eod());
 | |
|   
 | |
|   if (zap && err == NOERR)
 | |
|     err = packindex(vis, FALSE);
 | |
|   if (err == NOERR && curr().has_memo())
 | |
|     err = DB_packmemo(vis,d.name());
 | |
|   
 | |
|   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 <t TIsamerr>).
 | |
| 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 <mf TSystemisamfile::packfile>
 | |
|   
 | |
| {
 | |
|   int err=NOERR;
 | |
|   TRecnotype peod;
 | |
|   TTrec r;
 | |
|   TDir  d;
 | |
|   
 | |
|   r.get(num());                
 | |
|   d.get(num(),_nolock, _nordir,_sysdirop);               
 | |
|   bool is_com = d.is_com();
 | |
|   d.get(num(),_nolock, is_com ? _comdir : _nordir);
 | |
|   err=DB_packindex(vis,d.name(),r.rec(),&peod,ask);
 | |
|   if (err != NOERR) 
 | |
|     err = get_error(err);
 | |
|   if (err != NOERR) 
 | |
|     error_box("Errore in compattamento indici.\nFile %d : %d", num(),err);
 | |
|   else
 | |
|     if (peod >= 0 && peod != d.eod())
 | |
|     {
 | |
|       d.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);
 | |
|   }
 | |
| }
 | |
| 
 | |
| 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 <t TIsamerr>).
 | |
| int TSystemisamfile::load(
 | |
|     const char* from, // @parm Nome del file da importare 
 | |
|     char fs,    // @parm Carattere separatore di campo (default <pipe>)
 | |
|     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 <p extended> e' TRUE e trova alcune stringhe col formato %stringa% (es. %frm%)
 | |
| //       ne sostituisce i valori (es. ditta corrente).
 | |
|                                       
 | |
| // @xref <mf TSystemisamfile::dump>
 | |
|   
 | |
| {
 | |
|   int err=NOERR;
 | |
|   FILE* fl = fopen(from, "r");
 | |
|   if (fl == NULL) 
 | |
|   {
 | |
|     error_box("Impossibile aprire il file %s",from);
 | |
|     // clearerr(fl);  Bravo merlo: fl = NULL
 | |
|     setstatus(2);
 | |
|     return 2;
 | |
|   }
 | |
|   TRecnotype r = 0, e = 0, nitems = 0;
 | |
|   TString8 firm, year, attprev("00000");
 | |
| 
 | |
|   if (extended)
 | |
|   {
 | |
|     TDate d(TODAY);
 | |
|     TLocalisamfile ditte(LF_NDITTE);
 | |
| 
 | |
|     firm.format("%05ld", prefix().get_codditta());
 | |
|     year.format("%04d", d.year());
 | |
|     ditte.zero();
 | |
|     ditte.put("CODDITTA", firm);
 | |
|     if (ditte.read() == NOERR)
 | |
|       attprev = ditte.get("CODATTPREV");
 | |
|   }
 | |
| 
 | |
|   fseek(fl, 0L, SEEK_END);
 | |
|   nitems = ftell(fl);
 | |
|   fclose(fl);
 | |
| 
 | |
|   err = _open_ex(_excllock, indexed);
 | |
|   if (err != NOERR)
 | |
|   {
 | |
|     error_box("Impossibile aprire il file %d", _logicnum);
 | |
|     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);
 | |
|   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();
 | |
|           nflds++;
 | |
|         }
 | |
|       }  
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   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 = (const TString & ) fld[j];
 | |
|       len[j] = (curr().type(wfld) == _datefld) ? 10 : curr().length(wfld);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   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, TRUE, TRUE, 70);
 | |
| 
 | |
|   long pos = 16*nflds;
 | |
|   for (s = f.line(); s.not_empty() && !p.iscancelled(); s = f.line())
 | |
|   {
 | |
|     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);
 | |
|     }
 | |
| 
 | |
|     pos += s.len()+2;
 | |
|     p.setstatus(pos);
 | |
|     zero();
 | |
|     if (fixedlen)
 | |
|     {
 | |
|       int pos = 0;
 | |
|       for (int j = 0; j < nflds; j++)
 | |
|       {
 | |
|         s1 = s.mid(pos,len[j]);
 | |
|         s1.rtrim();
 | |
|         put((const TString&) fld[j], s1);
 | |
|         pos += len[j];
 | |
|       }
 | |
|     }
 | |
|     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 
 | |
|     {
 | |
| //      error_box("Errore di scrittura alla riga %ld", r+e+1);
 | |
|       e++;
 | |
|       last = status();
 | |
| //      break;
 | |
|     }
 | |
|   }
 | |
|   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 <t TIsamerr>).
 | |
| int TSystemisamfile::overwrite(
 | |
|     const char* from, // @parm Nome del file da importare 
 | |
|     char fs,    // @parm Carattere separatore di campo (default <pipe>)
 | |
|     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 <p extended> e' TRUE e trova alcune stringhe col formato %stringa% (es. %frm%)
 | |
| //       ne sostituisce i valori (es. ditta corrente).
 | |
|                                       
 | |
| // @xref <mf TSystemisamfile::dump>
 | |
|   
 | |
| {
 | |
|   int err=NOERR;
 | |
|   FILE* fl = fopen(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();
 | |
|   if (err != NOERR)
 | |
|   {
 | |
|     error_box("Impossibile aprire il file %d", _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();
 | |
|           nflds++;
 | |
|         }
 | |
| 				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 = (const TString & ) fld[j];
 | |
|       len[j] = (curr().type(wfld) == _datefld) ? 10 : curr().length(wfld);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   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 <t TIsamerr>).
 | |
| 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 <pipe>)
 | |
|     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 <mf TSystemisamfile::load>
 | |
| 
 | |
| {
 | |
|   FILE* f = fopen(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();
 | |
|   TArray  fld(nflds);
 | |
|   TBit_array rjust(nflds);
 | |
|   int        len[MaxFields];
 | |
|   int j;
 | |
| 
 | |
|   for (j = 0; j < nflds; j++)
 | |
|   {
 | |
|     fld.add(TString(curr().fieldname(j)), j);
 | |
|     const TString & wfld = (const TString&) fld[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)
 | |
| 			return error_box("Non e' possibile scaricare a lunghezza fissa un file con campi memo");
 | |
|   }
 | |
|   TRecnotype i = 0;
 | |
|   const TRecnotype nitems = items();
 | |
|   
 | |
|   s.format("Esportazione archivio %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 = "";
 | |
|       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);
 | |
|     }
 | |
|   }
 | |
|   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 <pipe>)
 | |
|     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 <mf TSystemisamfile::load>
 | |
| 
 | |
| {
 | |
|   FILE* f = fopen(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("Non e' possibile scaricare a lunghezza fissa un file con campi memo");
 | |
|   }
 | |
|   TRecnotype i = 0;
 | |
|   const TRecnotype nitems = items();
 | |
|   
 | |
|   s.format("Esportazione archivio %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);
 | |
| 
 | |
|   const bool has_memo_fld = _length > 0 && lf_has_memo(_logicnum);
 | |
|   
 | |
| 	if(has_memo_fld)
 | |
|     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(_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);
 | |
|   TCodeb_handle cb_handle = prefix().get_handle(file);
 | |
|   DB_go( cb_handle, recno);
 | |
|   for( int i = _memo_data->last( ); i > 0; i = _memo_data->pred( i ) )
 | |
| 	{
 | |
|     if (_memo_data->is_dirty(i))
 | |
| 			DB_memowrite( cb_handle, r->Fd[ i ].Name, ( char * )( const char * )_memo_data->row( i ) );
 | |
| 	}
 | |
|   *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(128);
 | |
|   __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 <f strcmp>:
 | |
| //
 | |
| // @flag 0 | Se le due chiavi sono uguali
 | |
| // @flag <lt><gt>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 <mf TRectype::build_key>
 | |
| {
 | |
| /* 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)
 | |
|   {
 | |
|     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 i;
 | |
|   for (i = 0; i < len && *a == *b; b++, a++, i++);
 | |
|   if (i == len) return 0;
 | |
|   int res = *a - *b;      
 | |
|   if (number)
 | |
|   {
 | |
|     b -= i;
 | |
|     i  = 0;
 | |
|   }
 | |
|   return fld_empty(b, len - i, number) ? 0 : res;
 | |
| }
 | |
| 
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TRectype (record di un file)
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| RecDes* TRectype::rec_des() const  
 | |
| {
 | |
|   return (RecDes*)&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();
 | |
|   int p = findfld(recd, fieldname);
 | |
| 
 | |
|   if (p != FIELDERR) 
 | |
|     return (TFieldtypes) recd->Fd[p].TypeF;
 | |
|   else 
 | |
|     return _nullfld;
 | |
| }
 | |
| 
 | |
| 
 | |
| int TRectype::length(const char* fieldname) const
 | |
| {
 | |
|   const RecDes * recd = rec_des();
 | |
|   int p = findfld(recd, fieldname); 
 | |
| 
 | |
|   if (p != FIELDERR) 
 | |
|     return(recd->Fd[p].Len);
 | |
|   else 
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| int TRectype::ndec(const char* fieldname) const
 | |
| 
 | |
| {
 | |
|   const RecDes * recd = rec_des();
 | |
|   int p = findfld(recd, fieldname); 
 | |
| 
 | |
|   if (p != FIELDERR) 
 | |
|     return(recd->Fd[p].Dec);
 | |
|   else 
 | |
|     return(0);
 | |
| }
 | |
| 
 | |
| 
 | |
| bool TRectype::exist(const char* fieldname) const
 | |
| {                   
 | |
|   const bool ok = findfld(rec_des(), fieldname) != FIELDERR;
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| 
 | |
| 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);
 | |
|   const RecFieldDes& fd = recd->Fd[nf];
 | |
|   if (nf != FIELDERR)
 | |
|   {
 | |
|     TString& tmp = get_tmp_string(fd.Len + (fd.TypeF == _datefld ? 2 : 0));
 | |
|     __getfieldbuff(fd.Len, fd.TypeF, _rec + fd.RecOff, tmp.get_buffer(), __file_is_crypted(num()));
 | |
|     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 int orig = _memo_data->file();
 | |
|       if (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
 | |
| {
 | |
|   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
 | |
| {
 | |
|   return *(get_str(fieldname)) == 'X';
 | |
| }
 | |
| 
 | |
| TDate TRectype::get_date(const char* fieldname) const
 | |
| {
 | |
|   TDate d(get_str(fieldname));
 | |
|   return d;
 | |
| }
 | |
| 
 | |
| void TRectype::put(const char* fieldname, int val)
 | |
| {           
 | |
| 	TString16 tmp;
 | |
|   tmp.format("%d", val);
 | |
|   put_str(fieldname, tmp);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRectype::put(const char* fieldname, long val)
 | |
| {
 | |
| 	TString16 tmp;
 | |
|   tmp.format("%ld", val);
 | |
|   put_str(fieldname, tmp);
 | |
| }
 | |
| 
 | |
| 
 | |
| void TRectype::put(const char* fieldname, word val)
 | |
| {
 | |
| 	TString16 tmp; tmp.format("%u", val);
 | |
|   put_str( fieldname, tmp);
 | |
| }
 | |
| 
 | |
| 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_str( fieldname, val.string(full));
 | |
|   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)
 | |
| {
 | |
|   const char s[2] = { val ? 'X' : ' ', '\0' };
 | |
|   put_str( fieldname, s);
 | |
| }
 | |
| 
 | |
| 
 | |
| 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, __file_is_crypted(num()));
 | |
|   }
 | |
| 
 | |
|   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, __file_is_crypted(num()));
 | |
|         break;
 | |
|       case _memofld:
 | |
|         __putfieldbuff(len, dec, _memofld, "", p, __file_is_crypted(num()));
 | |
|         _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(_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); 
 | |
| }
 | |
| 
 | |
| // Certified ??%
 | |
| int TRectype::remove(TBaseisamfile& f) const
 | |
| { 
 | |
|   return f._remove(*this); 
 | |
| }
 | |
| 
 | |
| void TRectype::renum_key(const char* field, const char* val)
 | |
| {
 | |
|   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();
 | |
|     if (ok) // Test qualunque per usare {}
 | |
|     {
 | |
|       TConfig ini(ininame, "Transaction");
 | |
|       ini.set("Action", action);
 | |
|       ini.set("Mode", "A");
 | |
|       fill_transaction(ini);
 | |
|     }
 | |
|     ok = ::dispatch_transaction(*this, ininame);
 | |
|     ::remove(ininame);
 | |
|   }
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| bool TRectype::get_relapp(TString& app) const
 | |
| {            
 | |
|   if (*_tab)
 | |
|   {                 
 | |
|     TString4 cod(_tab);
 | |
|     if (num() == LF_TABCOM)
 | |
|       cod.insert("%");
 | |
|     else
 | |
|       if (num() == LF_TABGEN)
 | |
|         cod.insert("#");
 | |
|     return ::get_tabapp(cod, app);
 | |
|   }
 | |
|   else
 | |
|     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.empty())
 | |
|     r.get_relapp(app);
 | |
|   if (app.not_empty())
 | |
|   {
 | |
|     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();
 | |
|     {
 | |
|       TConfig ini(ininame, "Transaction");
 | |
|       ini.set("Action", "LINK");
 | |
|       TString16 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)
 | |
|     {
 | |
|       TConfig ini(ininame, "Transaction");
 | |
|       const TString& result = ini.get("Result");
 | |
|       ok = result == "OK";
 | |
|     }
 | |
| 
 | |
|     xvt_fsys_removefile(ininame);
 | |
| 
 | |
|     if (ok)
 | |
|       rec_cache(logicnum).notify_change();
 | |
|   }      
 | |
|   return ok;
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TRecfield (campo/sottocampo di un record)
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| void TRecfield::set(int from, int to)
 | |
| {
 | |
|   const RecDes* rd = _rec->rec_des();
 | |
| 
 | |
|   _subfield = strchr(_name, ':');
 | |
| 	if (_subfield != NULL)
 | |
| 	{
 | |
|     *_subfield = '\0';
 | |
| 		_subfield++;
 | |
| 		strcat(_subfield, "=");
 | |
| 	}
 | |
| 
 | |
|   const int nf = findfld(rd, _name);
 | |
| 
 | |
|   if (nf == FIELDERR)
 | |
|   {
 | |
|     NFCHECK("File n. %d unknown field %s", _rec->num(), _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 (_subfield == NULL)
 | |
| 		{
 | |
| 			_p += from;
 | |
| 			if  (to >= 0)
 | |
| 			{
 | |
| 				CHECK(from <= to && to <= rd->Fd[nf].Len, "Invalid Range");
 | |
| 				_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;
 | |
| 		}
 | |
|   }
 | |
| }
 | |
| 
 | |
| TRecfield::TRecfield(TRectype& rec, const char* name, int from, int to)
 | |
| {
 | |
|   strcpy(_name, name);
 | |
|   _rec = &rec;
 | |
|   set(from, to);
 | |
| }
 | |
| 
 | |
| void TRecfield::put_subfield(const char* s)
 | |
| {
 | |
|   const TString& str = _rec->get(_name);
 | |
|   int p = str.find(_subfield);
 | |
|       
 | |
| 	if (p == 0 || (p > 0 && str[p - 1] < ' '))
 | |
|   {
 | |
|     p += strlen(_subfield);
 | |
|     
 | |
| 		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)
 | |
| {
 | |
|   char buff[32];
 | |
|   sprintf(buff, "%d", i);
 | |
| 	if (_subfield == NULL)
 | |
| 		__putfieldbuff( _len, _dec, _type, buff, _p, __file_is_crypted(_rec->num()));
 | |
| 	else
 | |
| 		put_subfield(buff);
 | |
|   _rec->setempty(FALSE);
 | |
|   return i;
 | |
| }
 | |
| 
 | |
| 
 | |
| long TRecfield::operator =(long l)
 | |
| {
 | |
|   char buff[32];
 | |
|   sprintf(buff, "%ld", l);
 | |
| 	if (_subfield == NULL)
 | |
| 		__putfieldbuff( _len, _dec, _type, buff, _p, __file_is_crypted(_rec->num()));
 | |
| 	else
 | |
| 		put_subfield(buff);
 | |
|   _rec->setempty(FALSE);
 | |
|   return l;
 | |
| }
 | |
| 
 | |
| const real& TRecfield::operator =(const real& r)
 | |
| {
 | |
|   char buff[80];
 | |
|   strcpy(buff, r.string());
 | |
| 	if (_subfield == NULL)
 | |
| 		__putfieldbuff( _len, _dec, _type, buff, _p, __file_is_crypted(_rec->num()));
 | |
| 	else
 | |
| 		put_subfield(buff);
 | |
|   _rec->setempty(FALSE);
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| const TDate& TRecfield::operator =(const TDate& d)
 | |
| {
 | |
|   char buff[16];
 | |
|   strcpy(buff, (const char*)d);
 | |
| 	if (_subfield == NULL)
 | |
| 		__putfieldbuff( _len, _dec, _type, buff, _p, __file_is_crypted(_rec->num()));
 | |
| 	else
 | |
| 		put_subfield(buff);
 | |
|   _rec->setempty(FALSE);
 | |
|   return d;
 | |
| }
 | |
| 
 | |
| const char* TRecfield::operator =(const char* s)
 | |
| {
 | |
| 	if (_subfield == NULL)
 | |
|   {
 | |
| 		if (_type == _memofld)
 | |
| 			_rec->put(_name, s);
 | |
| 	  else
 | |
| 			__putfieldbuff( _len, _dec, _type, s, _p, __file_is_crypted(_rec->num()));
 | |
| 	}
 | |
| 	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(char* s) const
 | |
| {
 | |
|   const TString& str = _rec->get(_name);
 | |
|   int p = str.find(_subfield);
 | |
|       
 | |
| 	if (p == 0 || (p > 0 && str[p - 1] < ' '))
 | |
|   {
 | |
|     p += strlen(_subfield);
 | |
|     
 | |
| 		int e = str.find('\n', p);
 | |
| 
 | |
| 		if (_to > 0 && p + _to < e)
 | |
| 			e = p + _to;
 | |
| 		p += _from;
 | |
| 		if (p < e)
 | |
| 			strcpy(s, str.sub(p, e));
 | |
| 		else *s = '\0';
 | |
|   }
 | |
| 	else *s = '\0';
 | |
| }
 | |
| 
 | |
| TRecfield::operator int() const
 | |
| {
 | |
| 	char tmp[32];
 | |
| 	if (_subfield == NULL)
 | |
| 	{
 | |
| 		if (_type == _intfld || _type == _intzerofld || _type == _longfld || _type == _longzerofld)
 | |
| 		{
 | |
| 			strncpy(tmp, _p, _len);
 | |
| 			tmp[_len] = '\0';
 | |
| 		}  
 | |
| 		else
 | |
| 			__getfieldbuff( _len, _type, _p, tmp, __file_is_crypted(_rec->num()));
 | |
| 	}
 | |
| 	else
 | |
| 		get_subfield(tmp);
 | |
|   return atoi(tmp);
 | |
| }
 | |
| 
 | |
| 
 | |
| TRecfield::operator long() const
 | |
| {
 | |
| 	char tmp[32];
 | |
| 
 | |
| 	if (_subfield == NULL)
 | |
| 	{
 | |
| 		if (_type == _longfld || _type == _longzerofld || _type == _intfld || _type == _intzerofld)
 | |
| 		{
 | |
| 			strncpy(tmp, _p, _len);
 | |
| 			tmp[_len] = '\0';
 | |
| 		}
 | |
| 		else  
 | |
| 			__getfieldbuff( _len, _type, _p, tmp, __file_is_crypted(_rec->num()));
 | |
| 	}
 | |
| 	else
 | |
| 		get_subfield(tmp);
 | |
|   
 | |
|   return atol(tmp);
 | |
| }
 | |
| 
 | |
| 
 | |
| TRecfield::operator const real() const
 | |
| {
 | |
|   char tmp[32];
 | |
| 
 | |
| 	if (_subfield == NULL)
 | |
| 	{
 | |
| 		if (_type == _realfld)
 | |
| 		{
 | |
| 			strncpy(tmp, _p, _len);
 | |
| 			tmp[_len] = '\0';
 | |
| 		}
 | |
| 		else
 | |
| 			__getfieldbuff( _len, _type, _p, tmp, __file_is_crypted(_rec->num()));
 | |
| 	}
 | |
| 	else
 | |
| 		get_subfield(tmp);
 | |
| 
 | |
|   real r(tmp);
 | |
|   return r;
 | |
| }
 | |
| 
 | |
| 
 | |
| TRecfield::operator TDate() const
 | |
| {    
 | |
|   char tmp[16];
 | |
| 	
 | |
| 	if (_subfield == NULL)
 | |
| 	{
 | |
| 		if (_type == _datefld)                          
 | |
| 		{
 | |
| 			strncpy(tmp, _p, 8);
 | |
| 			tmp[8] = '\0';
 | |
| 			return TDate(atol(tmp));
 | |
| 		}  
 | |
| 		__getfieldbuff(_len, _type, _p, tmp, __file_is_crypted(_rec->num()));
 | |
| 	}
 | |
| 	else
 | |
| 		get_subfield(tmp);
 | |
| 
 | |
|   return TDate(tmp);
 | |
| }
 | |
| 
 | |
| 
 | |
| TRecfield::operator const char*() const
 | |
| {    
 | |
| 	TString& tmp = get_tmp_string(_len);
 | |
| 	
 | |
| 	if (_subfield == NULL)
 | |
| 	{
 | |
| 	  if (_type == _memofld)
 | |
| 		  return _rec->get(_name);
 | |
| 		else
 | |
| 			__getfieldbuff(_len, _type, _p, tmp.get_buffer(), __file_is_crypted(_rec->num()));
 | |
| 	}
 | |
| 	else
 | |
| 		get_subfield((char *) (const char *)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;
 | |
| } |