Files correlati : bagn001a.msk Ricompilazione Demo : [ ] Commento : 0001607: 002422 - stampa schede Descrizione il bottone di esportazione excell non produce risultati; da impostazione stampante, scelgo di stampare su file, chiede il nome del file (che è già impostato) git-svn-id: svn://10.65.10.50/trunk@20431 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			999 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			999 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <printer.h>
 | |
| #include <relation.h>
 | |
| #include <text.h>
 | |
| #include <window.h>
 | |
| #include <xvtility.h>
 | |
| 
 | |
| #define TEXT_TMP_SIZE 1024
 | |
| static TString _TEXT_TMP(TEXT_TMP_SIZE);
 | |
| static char* TEXT_TMP = (char*)(const char*)_TEXT_TMP;
 | |
| 
 | |
| class _HotSpot : public TObject
 | |
| {
 | |
| public:
 | |
|   //      TArray _spots;  // tokenstrings
 | |
|   char _bg, _fg;
 | |
| 
 | |
|   _HotSpot (char fg, char bg)
 | |
|   {
 | |
|     _fg = fg;
 | |
|     _bg = bg;
 | |
|   }
 | |
|   virtual ~ _HotSpot ()
 | |
|   {
 | |
|   }
 | |
| };
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Permette di settare gli hot_spot
 | |
| void TTextfile::set_hotspots (
 | |
|   char fg,      // @parm Colore di foreground da utilizzare per l'hotspot
 | |
|   char bg)      // @parm Colore di background da utilizzare per l'hotspot
 | |
| 
 | |
|   // @comm Aggiunge all'array gli hotspots relativi alla pagina in memoria 
 | |
|   //     (come <c TToken_string> con x<pipe>y<pipe>text)
 | |
| {
 | |
|   _HotSpot *hp = new _HotSpot (fg, bg);
 | |
|   _hotspots.add (hp);
 | |
| }
 | |
| 
 | |
| style TTextfile::_trans_style (char ch)
 | |
| {
 | |
|   switch (ch)
 | |
|   {
 | |
|   case 'r':
 | |
|     return normal;
 | |
|   case 'i':
 | |
|     return italic;
 | |
|   case 'b':
 | |
|     return bold;
 | |
|   case 'u':
 | |
|     return underlined;
 | |
|   case 't':
 | |
|     return tabbed;  
 | |
|   default:
 | |
|     return normal;
 | |
|   }
 | |
| }
 | |
| 
 | |
| 
 | |
| void TTextfile::_save_changes()
 | |
| {
 | |
|   TWait_cursor hourglass;
 | |
|   
 | |
|   // fa i dovuti replace anche sul disco (solo replace di linee esistenti)
 | |
|   long line = 0l;
 | |
|   
 | |
|   fclose(_index);
 | |
|   remove(_indname); 
 | |
| 
 | |
|   const TString oldfile(_filename);
 | |
|   _filename.temp("txtf");
 | |
| 
 | |
|   FILE* newf = fopen(_filename, "a+"); 
 | |
| 
 | |
|   if ((_index = fopen(_indname, "w+b")) == NULL || newf == NULL)
 | |
|   {
 | |
|     NFCHECK("Impossibile aprire files temporanei");
 | |
|     freeze();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // fseek(_instr, 0l, SEEK_SET);
 | |
|   rewind(_instr);
 | |
|   
 | |
|   while (!feof(_instr))
 | |
|   {
 | |
|     const long l = ftell(newf);
 | |
|     fwrite (&l, sizeof(long), 1, _index);
 | |
| 
 | |
|     if (ferror(_index) || ferror(newf))
 | |
|     {
 | |
|       error_box ("Errore di scrittura file temporaneo: scrittura interrotta");
 | |
|       freeze ();
 | |
|     }  
 | |
|     
 | |
|     if (fgets(TEXT_TMP, TEXT_TMP_SIZE, _instr) == NULL) 
 | |
|       break;                                  
 | |
|     
 | |
|     if (line >= _page_start && line <= _page_end)
 | |
|     {         
 | |
|       TString& lin = (TString&)(_page[(int)(line - _page_start)]);
 | |
|       if (_dirty_lines[line - _page_start])
 | |
|       {
 | |
|         strcpy(TEXT_TMP, lin); 
 | |
|         strcat(TEXT_TMP, "\n"); 
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     fprintf(newf, "%s", TEXT_TMP);    
 | |
|     line++;
 | |
|   }
 | |
| 
 | |
|   fflush(_index);
 | |
|   fclose(_instr); 
 | |
|   fclose(newf);
 | |
|   remove(oldfile);
 | |
|   rename(_filename, oldfile); 
 | |
|   _filename = oldfile;
 | |
|   _instr = fopen(_filename, "a+");
 | |
| }
 | |
| 
 | |
| void TTextfile::_read_page (long n)
 | |
| { 
 | |
|   if (_dirty_lines.ones() > 0l)
 | |
|   {
 | |
|     _save_changes();
 | |
|     _dirty_lines.reset();
 | |
|   }
 | |
|   
 | |
|   switch (_direction)
 | |
|   {
 | |
|   case down:
 | |
|     _page_start = n;
 | |
|     break;
 | |
|   case up:
 | |
|     _page_start = n + _page_size;
 | |
|     break;
 | |
|   case updown:
 | |
|     _page_start = n - (_page_size / 2l);
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   if (_page_start < 0l)
 | |
|     _page_start = 0l;
 | |
|   if ((_page_start + _page_size) > _lines)
 | |
|     _page_end = _lines - 1;
 | |
|   else
 | |
|     _page_end = _page_start + _page_size - 1;
 | |
| 
 | |
|   // zap hotspots
 | |
|   _spots.destroy ();
 | |
| 
 | |
|   long l = 0l;
 | |
|   if (_page_start != 0l)
 | |
|   {
 | |
|     fseek (_index, _page_start * (long) sizeof (long), SEEK_SET);
 | |
|     fread (&l, sizeof (long), 1, _index);
 | |
|   }  
 | |
|   fseek (_instr, l, SEEK_SET);
 | |
|   
 | |
|   for (long i = _page_start; i <= _page_end; i++)
 | |
|   {
 | |
|     if (feof (_instr))
 | |
|       break;
 | |
|     fgets (TEXT_TMP, TEXT_TMP_SIZE, _instr);
 | |
|     TEXT_TMP[strlen (TEXT_TMP) - 1] = '\0';
 | |
|     TString & ts = (TString &) _page[(int) (i - _page_start)];
 | |
|     CHECK(ts.size() > 0, "Corrupted string");
 | |
|     ts = TEXT_TMP;
 | |
|     if (_interactive)
 | |
|     { 
 | |
|       TString hcol (6);
 | |
|       // find hotspots and compile list                           
 | |
| 
 | |
|       int len = 0;
 | |
|       const char *cp;
 | |
|       read_line (i, 0, FALSE);
 | |
|       while ((cp = piece ()))
 | |
|       {
 | |
|         for (int z = 0; z < _hotspots.items (); z++)
 | |
|         {
 | |
|           _HotSpot & hs = (_HotSpot &) _hotspots[z];
 | |
|           if (hs._fg == get_foreground () && hs._bg == get_background ())
 | |
|           {
 | |
|             TToken_string *tts = new TToken_string (50);
 | |
|             tts->add (i); // line number                        
 | |
| 
 | |
|             tts->add (len);
 | |
|             tts->add (len + (int) strlen (cp));
 | |
|             tts->add (cp);
 | |
|             tts->add (z);
 | |
|             _spots.add (tts);
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|         len += strlen (cp);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Legge il testo formattato
 | |
| void TTextfile::read_line (
 | |
|   long n,       // @parm Numero della linea da leggere
 | |
|   long pos,     // @parm Numero della colonna da leggere (mai utilizzata)
 | |
|   bool pg)      // @parm Fa si' che se la linea non e' nella pagina corrente non si faccia nulla,
 | |
|   //     diversamente rilegge una nuova pagina dal file.
 | |
| 
 | |
| {
 | |
|   CHECK (_isopen, "Attempt operation on closed file");
 | |
| //  CHECKD (n >= 0 && n < _lines, "Line not present", n);
 | |
| 
 | |
|   if (pg && !_in_page (n))
 | |
|     _read_page (n);
 | |
| 
 | |
|   TString *tp = (TString *) _page.objptr (int (n - _page_start));
 | |
|   if (tp == NULL)
 | |
|     return;
 | |
| 
 | |
|   const char *sp = (const char *) (*tp);
 | |
|   _item = 0;
 | |
|   _line = "";
 | |
|   int ndx = 0, p = 0;
 | |
|   bool first = TRUE;
 | |
|   _cur_line = n;
 | |
|   char ch;
 | |
| 
 | |
|   int col = ((int) 'w' << 8) | (int) 'n';
 | |
|   long stl = (long) col << 16;
 | |
| 
 | |
|   while ((ch = *sp++))
 | |
|   {                 
 | |
|     if (ch == '<' && *(sp) == '@')
 | |
|     {
 | |
|       // merge field if rel != NULL; 
 | |
|       // else fill with whitespace  
 | |
|       const char * save_sp = sp;
 | |
|       
 | |
|       TToken_string id(80, '@');        
 | |
|       sp++;
 | |
|       bool terminated = FALSE;
 | |
|       while ((ch = *sp++) != '>' && !terminated)
 | |
|         if (ch != '\0')
 | |
|           id << ch;
 | |
|         else terminated = TRUE;
 | |
|       if (!terminated)  // Prosegue normalmente se non trova la matching >
 | |
|       {
 | |
|         // id contains tokenstring separated by @
 | |
|         // but with casinations for possible lack of spacing
 | |
|         // add spaces if needed
 | |
|         for (int i = 0; i < id.len(); i++)
 | |
|         { 
 | |
|           if (id[i] == '@' && id [i+1] == '@')
 | |
|           {
 | |
|             id.insert(" ", i+1);
 | |
|             i+= 2;
 | |
|           }
 | |
|         }  
 | |
|         // parse string
 | |
|         int len;
 | |
|         TString80 file;
 | |
|         TString16 field;
 | |
|         TString80 format;     
 | |
|         char just;
 | |
|         
 | |
|         file   = id.get();
 | |
|         format = id.get();
 | |
|         len    = (int)id.get_long();  
 | |
|         just   = id.get_char();   
 | |
|         
 | |
|         int pos = 0;
 | |
|         if ((pos = file.find("->")) == -1) 
 | |
|           error_box("field specification error"); 
 | |
|         else
 | |
|         {
 | |
|           file.cut(pos);
 | |
|           field = file.mid(pos+2);
 | |
|         }
 | |
|         
 | |
|         if (len == 0) len = id.len();
 | |
|         
 | |
|         TString txt(512);  
 | |
|         TFieldtypes type;
 | |
|         
 | |
|         if (_rel != NULL)
 | |
|         {                                  
 | |
|           // retrieve file and field
 | |
|           if (atoi(file) == 0)
 | |
|           {
 | |
|             // tabella                                  
 | |
|             TLocalisamfile& t =  _rel->lfile(file);  
 | |
|             txt  = t.get(field);   
 | |
|             type = t.curr().type(field);
 | |
|           }
 | |
|           else
 | |
|           {           
 | |
|             TLocalisamfile& f = _rel->lfile(atoi(file));
 | |
|             txt = f.get(field);
 | |
|             type = f.curr().type(field);
 | |
|           }                         
 | |
|           // apply format to date and number  
 | |
|           switch (type)
 | |
|           {
 | |
|           case _longfld:
 | |
|           case _realfld:  
 | |
|           {
 | |
|             real r(txt);
 | |
|             txt = r.string(format);
 | |
|           }
 | |
|           break;
 | |
|         case _datefld:    
 | |
|         {
 | |
|           TDate dd(txt);
 | |
|           TFormatted_date d(dd, format);
 | |
|           txt = d.string();    
 | |
|         }
 | |
|           break;
 | |
|         default:
 | |
|           break;
 | |
|         }
 | |
|           // justify as requested
 | |
|           if (txt.len() < len)
 | |
|           {
 | |
|             switch(type)
 | |
|             {
 | |
|             case _longfld:
 | |
|             case _realfld:
 | |
|               txt.right_just(len);
 | |
|               break;  
 | |
|             default:
 | |
|               txt.left_just(len);
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|         else
 | |
|         {
 | |
|           txt.left_just(len);
 | |
|         }
 | |
|         // ficca il testo cola' dove si puote
 | |
|         const int txtlen = txt.len();
 | |
|         for (int k = 0; k < txtlen; k++)
 | |
|           TEXT_TMP[ndx++] = txt[k];
 | |
|       } // see (!terminated) above
 | |
|       else // Restore sp pointer
 | |
|       {
 | |
|         sp = save_sp;
 | |
|         ch = '<';
 | |
|       }
 | |
|     }
 | |
|     
 | |
|     if (ch == '@' || (ch == '$' && *(sp) == '['))
 | |
|     {
 | |
|       if (!first && p >= pos)
 | |
|       {         
 | |
|         CHECKD(ndx < TEXT_TMP_SIZE, "Bad TEXT_TMP index ", ndx);
 | |
|         _styles[_item++] = stl;
 | |
|         TEXT_TMP[ndx] = '\0';
 | |
|         _line.add (TEXT_TMP);
 | |
|         ndx = 0;
 | |
|       }
 | |
|       while (ch && (ch == '@' || (ch == '$' && *sp == '[')))
 | |
|       {
 | |
|         if (ch == '@')  // font style change ? 
 | |
|         {              
 | |
|           const char c = *sp++;
 | |
|           if (c == '@')
 | |
|           {
 | |
|             _styles[_item++] = stl;
 | |
|             _line.add("@");
 | |
|           }
 | |
|           else
 | |
|           {
 | |
|             style sss = _trans_style (c);
 | |
|             if (sss == normal)
 | |
|               stl = (long) col << 16;
 | |
|             else
 | |
|               stl |= (long) sss;
 | |
|           }    
 | |
|         }
 | |
|         else if (ch == '$' && *sp == '[')               // color change
 | |
|         {
 | |
|           ++sp;         // eat '['
 | |
| 
 | |
|           col = *sp++;
 | |
|           ++sp;         // eat ','                        
 | |
| 
 | |
|           col |= ((int) (*sp++) << 8);
 | |
|           ++sp;         // eat ']'
 | |
| 
 | |
|           stl = (stl & 0x0000ffff) | ((long) col << 16);
 | |
|         }
 | |
|         ch = *sp++;
 | |
|       }                 // while
 | |
| 
 | |
|     }
 | |
|     if (ch && p >= pos)
 | |
|     {         
 | |
|       CHECKD(ndx < TEXT_TMP_SIZE, "Bad TEXT_TMP index ", ndx);
 | |
|       first = FALSE;
 | |
|       TEXT_TMP[ndx++] = ch;
 | |
|     }
 | |
|     p++;
 | |
|   }
 | |
|   _styles[_item++] = stl;
 | |
|   TEXT_TMP[ndx] = '\0';
 | |
|   _line.add(TEXT_TMP);
 | |
|   _item = 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Ritorna la stringa di caratteri senza formattazione
 | |
| //
 | |
| // @rdesc Ritorna la stringa di caratteri ed eventualmente con i campi sostituiti 
 | |
| //        se la relazione non e' NULL
 | |
| const char* TTextfile::line(
 | |
|   long j,               // @parm Riga di cui ritornare la stringa
 | |
|   long pos,             // @parm Colonna di cui ritornare la stringa
 | |
|   int howmuch)          // @parm Numero di caratteri utili della stringa da ritornare (default -1)
 | |
| 
 | |
|   // @comm Se <p howmuch> assume valore -1 ritorna tutta la pagina
 | |
| {
 | |
|   if (_cur_line != j)
 | |
|     read_line (j);
 | |
| 
 | |
|   *TEXT_TMP = '\0';
 | |
|   FOR_EACH_TOKEN(_line, l)    
 | |
|     strcat (TEXT_TMP, l);      
 | |
| 
 | |
|   if (howmuch >= 0)
 | |
|   {
 | |
|     if (((unsigned int)pos+howmuch) < strlen(TEXT_TMP))
 | |
|       TEXT_TMP[pos+howmuch] = '\0';
 | |
|   }
 | |
|   return strlen(TEXT_TMP) > (word)pos ? &(TEXT_TMP[pos]) : "";
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Cerca una stringa di testo all'interno di una riga
 | |
| //
 | |
| // @rdesc Ritorna la posizione in cui e' stato rintracciato il testo. Ritorna -1 se non e' stato
 | |
| //        trovato il testo passato.
 | |
| long TTextfile::search(
 | |
|   const char* txt,      // @parm Testo da cercare
 | |
|   int& ret,             // @parm Intero in cui posizionare la posizne del carattere
 | |
|   long from,    // @parm Posizione all'interno della riga da cui iniziare la ricerca (default 0)
 | |
|   bool down,            // @parm Indica se la ricerca va effettuata all'indietro:
 | |
|   //
 | |
|   // @flag TRUE | Ricerca dalla posizione indicata all'inizio della riga (default)
 | |
|   // @flag FALSE | Ricerca dalla posizione indicata alla fine della riga
 | |
|   bool casesens,        // @parm Indica se ricerca il testo con criterio case sensitive (default FALSE)
 | |
|   bool regexp)          // @parm indica se considerare la stringa un'espressione regolare (def. FALSE)
 | |
| 
 | |
|   // @comm Cerca in una riga per volta rispettando i formati
 | |
| {                        
 | |
|   TString text(txt);
 | |
|   if (!casesens) 
 | |
|     text.lower();
 | |
|   if (regexp && !text.ends_with("*"))  
 | |
|     text << '*';
 | |
|   
 | |
|   TString lin(512); 
 | |
|   for (long i = from; down ? (i < lines()) : (i >= 0); down ? i++ : i--)
 | |
|   {              
 | |
|     lin = line(i);  
 | |
|     if (!casesens) 
 | |
|       lin.lower();
 | |
|     if (regexp) 
 | |
|     { 
 | |
|       for (ret = 0; lin[ret]; ret++)
 | |
|       {
 | |
|         if (lin.mid(ret).match(text))
 | |
|           return i;
 | |
|       }    
 | |
|     }
 | |
|     else
 | |
|     {      
 | |
|       ret = lin.find(text);
 | |
|       if (ret >= 0)
 | |
|         return i;
 | |
|     }
 | |
|   }     
 | |
|   return -1l;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Sostituisce un testo all'interno di una riga
 | |
| //
 | |
| // @rdesc Ritorna la posizione in cui e' stato sostituito il testo. Ritorna -1 se non e' stata
 | |
| //        fatto nessuna operazione di sostituzione.
 | |
| int TTextfile::replace(
 | |
|   long l,               // @parm Numero della riga nella quale sostituire il testo
 | |
|   const char* txt,      // @parm Test da inserire nella riga
 | |
|   int pos,              // @parm Posizione nella quale inserire il testo (default 0)
 | |
|   int len)              // @parm Lunghezza del testo da sostituire (default 0)
 | |
| {
 | |
|   if (_cur_line != l)
 | |
|     read_line(l);
 | |
| 
 | |
|   TString& line = (TString&)_page[int(l-_page_start)];
 | |
|   
 | |
|   char ch; int i = 0, cnt = 0, skip = 0;  
 | |
|   bool sforating = FALSE;
 | |
|   
 | |
|   // here's a nice casin
 | |
|   while(i < 256)
 | |
|   {     
 | |
|     if (!sforating) 
 | |
|     {
 | |
|       ch = line[i++]; 
 | |
|       if (ch == '\0') 
 | |
|         sforating = TRUE;
 | |
|       else if (ch == '@' && strchr("ribuokt",line[i]) != NULL)
 | |
|       { 
 | |
|         skip +=2; i++; cnt--;
 | |
|       }
 | |
|       else if (ch == '$' && line[i] == '[')
 | |
|       {               
 | |
|         skip +=3; i++; cnt--;
 | |
|         while(line[i++] != ']') 
 | |
|           if (line[i] == '\0') 
 | |
|             return -1;
 | |
|           else skip++;
 | |
|       }
 | |
|     } 
 | |
|     
 | |
|     if (cnt == pos)
 | |
|     { 
 | |
|       line.overwrite(txt, cnt+skip);
 | |
|       _dirty_lines.set(l-_page_start);
 | |
|       return cnt;
 | |
|     }
 | |
|     else cnt++;
 | |
|   }
 | |
|   
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Ritorna la stringa di caratteri con la formattazione
 | |
| //
 | |
| // @rdesc La stringa ritornata ha la formattazione (ovvere tutti i @codes, in modo che anche
 | |
| //        la printer la possa utilizzare)
 | |
| const char *TTextfile::line_formatted(
 | |
|   long j)       //parm Numero della riga da ritornare
 | |
| {
 | |
|   if (_cur_line != j)
 | |
|     read_line (j);
 | |
|   TString* tp = (TString*)_page.objptr(int(j-_page_start));
 | |
|   strcpy(TEXT_TMP, (const char*)(*tp));
 | |
|   return TEXT_TMP;
 | |
| }
 | |
| 
 | |
| long TTextfile::get_attribute (int pos)
 | |
| {
 | |
|   long stl = 0;
 | |
|   if (pos == -1)
 | |
|   {
 | |
|     CHECK (_item > 0, "must execute piece() before style()!");
 | |
|     stl = _styles[_item - 1];
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     int x = 0, nd = 0;
 | |
|     const char *c;
 | |
|     _line.restart ();
 | |
|     while ((c = _line.get ()) != NULL)
 | |
|     {
 | |
|       x += strlen (c);
 | |
|       stl = _styles[nd++];
 | |
|       if ((x - 1) >= pos)
 | |
|         break;
 | |
|     }
 | |
|   }
 | |
|   return stl;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Ritorna lo stile del piece
 | |
| //
 | |
| // @rdesc Ritorna un numero (vedi <t style>) indicante lo stile
 | |
| int TTextfile::get_style (
 | |
|   int pos)      // @parm Posizione del carattere di cui ritornare lo stile (default -1)
 | |
| 
 | |
|   // @comm Se viene passato a <p pos> valore -1 ritorna lo stile di tutta la piece, altrimente
 | |
|   //     solamente quello del carattere selezionato.
 | |
| {
 | |
|   const long x = get_attribute(pos) & ~tabbed;
 | |
|   return (int) (x & 0x0000ffff);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Ritorna il colore di background del piece
 | |
| //
 | |
| // @rdesc Ritorna il codice del colore, NULL se il carattere non esiste
 | |
| char TTextfile::get_background (
 | |
|   int pos)      // @parm Posizione del carattere di cui conoscere il colore di background (default -1)
 | |
| 
 | |
|   // @comm Se <p pos> e' minore di 0 ritorna il colore dell'intero piece, altrimenti solamente
 | |
|   //     quello del carattere selezionato.
 | |
|   //
 | |
|   // @xref <mf TTextfile::get_foreground>
 | |
| {
 | |
|   long x = get_attribute (pos);
 | |
|   return (char) (x >> 24);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Ritorna il colore di foreground del piece
 | |
| //
 | |
| // @rdesc Ritorna il codice del colore, NULL se il carattere non esiste
 | |
| char TTextfile::get_foreground (
 | |
|   int pos) // @parm Posizione del carattere di cui conoscere il colore di background (default -1)
 | |
| 
 | |
|   // @comm Se <p pos> e' minore di 0 ritorna il colore dell'intero piece, altrimenti solamente
 | |
|   //     quello del carattere selezionato.
 | |
|   //
 | |
|   // @xref <mf TTextfile::get_bakcground>
 | |
| {
 | |
|   long x = get_attribute (pos);
 | |
|   return (char) ((x >> 16) & 0x000000ff);
 | |
| }
 | |
| 
 | |
| const char* TTextfile::piece()
 | |
| {                     
 | |
|   const char* l = _line.get(_item);
 | |
|   if (l == NULL)
 | |
|     return NULL;
 | |
|   _item++;  
 | |
|   return strcpy(TEXT_TMP, l);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Ritorna la parola alla posizione indicata
 | |
| //
 | |
| // @rdesc Stringa indicante la parola cercate
 | |
| const char *TTextfile::word_at (
 | |
|   long x,       // @parm Numero della parola da ritornare
 | |
|   long y)       // @parm Numero della linea su cui cercare la parole
 | |
| {
 | |
|   CHECK (_isopen, "Attempt operation on closed file");
 | |
|   TString s (line (y));
 | |
|   int x2 = 0;
 | |
| 
 | |
|   if (x < s.len ())
 | |
|   {
 | |
|     while (isspace (s[(int) x]))
 | |
|     {
 | |
|       if (x == (s.len () - 1) && y < (_lines - 1l))
 | |
|       {
 | |
|         s = line (++y);
 | |
|         x = 0l;
 | |
|       }
 | |
|       else if (x < (s.len () - 1))
 | |
|         x++;
 | |
|       else
 | |
|         break;
 | |
|     }
 | |
|     while (isalnum (s[(int) x]))
 | |
|       TEXT_TMP[x2++] = s[(int) x++];
 | |
|   }
 | |
|   TEXT_TMP[x2] = '\0';
 | |
|   return TEXT_TMP;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Aggiunge una riga al text (con i formati del caso)
 | |
| //
 | |
| // @rdesc Ritorna il risultato dell'operazione:
 | |
| //
 | |
| // @flag TRUE | Se la riga e' stat aggiuntac correttamente
 | |
| // @flag FALSE | Se non e' riuscot ad aggiungere la riga
 | |
| bool TTextfile::append (
 | |
|   const char *l) // @parm Riga da aggiungere
 | |
| {
 | |
|   CHECK (_isopen, "Attempt operation on closed file");
 | |
| 
 | |
|   if (!_accept)
 | |
|     return FALSE;
 | |
| 
 | |
|   fseek (_instr, 0l, SEEK_END);
 | |
|   fseek (_index, 0l, SEEK_END);
 | |
|   long cpos = ftell (_instr);
 | |
|   fprintf (_instr, "%s\n", l);
 | |
|   fwrite (&cpos, sizeof (long), 1, _index);
 | |
|   if (ferror (_index) || ferror (_instr))
 | |
|   {
 | |
|     error_box ("Errore di scrittura file temporaneo: scrittura interrotta");
 | |
|     freeze ();
 | |
|   }
 | |
|   fflush (_index);
 | |
|   fflush (_instr);
 | |
| 
 | |
|   _lines++;
 | |
|   _dirty = TRUE;    
 | |
|   
 | |
|   if ((_lines) < (_page_start + _page_size))
 | |
|   { 
 | |
|     if (_interactive)
 | |
|     {
 | |
|       _page.add (new TString(l), int(_lines - _page_start - 1));
 | |
|       _page_end++;
 | |
| 
 | |
|       int len = 0;
 | |
|       const char *cp;
 | |
|       read_line (_lines - 1);
 | |
|       while ((cp = piece ()))
 | |
|       {
 | |
|         for (int z = 0; z < _hotspots.items (); z++)
 | |
|         {
 | |
|           _HotSpot & hs = (_HotSpot &) _hotspots[z];
 | |
|           if (hs._fg == get_foreground () && hs._bg == get_background ())
 | |
|           {
 | |
|             TToken_string *tts = new TToken_string (50);
 | |
|             tts->add (_lines - 1l);       // line number
 | |
|             // 
 | |
| 
 | |
|             tts->add (len);
 | |
|             tts->add (len + (int) strlen (cp));
 | |
|             tts->add (cp);
 | |
|             tts->add (z);
 | |
|             _spots.add (tts);
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
|         len += strlen (cp);
 | |
|       }
 | |
|     }
 | |
|     return TRUE;
 | |
|   }
 | |
|   return FALSE;
 | |
| }
 | |
| 
 | |
| void TTextfile::close ()
 | |
| {
 | |
|   if (_isopen)
 | |
|   {
 | |
|     fclose (_instr);
 | |
|     fclose (_index);
 | |
|     _instr = _index = NULL;
 | |
|     _isopen = FALSE;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void TTextfile::print ()
 | |
| {
 | |
|   printer().print_txt(*this);
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Scrive il testo (non formattato) su file
 | |
| //
 | |
| // @rdesc Ritorna il risultato dell'operazione di scrittura
 | |
| //
 | |
| // @flag TRUE | Se e' riuscito a scrivere il testo
 | |
| // @flag FALSE | Se ha avuto qualche problema nella gestione del file in cui scrivere
 | |
| bool TTextfile::write (
 | |
|   const char *path,     // @parm Nome del file in cui scrivere il testo
 | |
|   TPoint * from,        // @parm Punto da cui iniziare a scrivere il testo
 | |
|   TPoint * to)  // @parm Punto a cui terminare di scrivere il testo
 | |
| {
 | |
|   FILE* fp = fopen(path, "w");
 | |
|   if (fp != NULL)
 | |
|   {
 | |
|     TString s(512);
 | |
|     long starty = from == NULL ? 0l : from->y;
 | |
|     int startx = from == NULL ? 0 : (int) from->x;
 | |
|     long endy = to == NULL ? _lines - 1l : to->y;
 | |
|     int endx = to == NULL ? -1 : (int) to->x;
 | |
|     for (long j = starty; j <= endy; j++)
 | |
|     {
 | |
|       s = line(j);
 | |
|       if (j == endy && endx == -1)
 | |
|         endx = s.len();
 | |
| 
 | |
|       if (j == starty && j == endy)
 | |
|         s = s.sub(startx, endx);
 | |
|       else if (j == starty)
 | |
|         s = s.mid(startx);
 | |
|       else if (j == endy)
 | |
|         s = s.left(endx);
 | |
| 
 | |
|       fprintf(fp, "%s\n", (const char *) s);
 | |
|     }
 | |
|     fclose (fp);
 | |
|   }
 | |
|   else
 | |
|     warning_box ("Impossibile scrivere il file %s; scrittura fallita", path);
 | |
|   return fp != NULL;
 | |
| }
 | |
| 
 | |
| // @doc EXTERNAL
 | |
| 
 | |
| // @mfunc Scrive il testo da punto a punto (non formattato) su string_array
 | |
| void TTextfile::write(
 | |
|   TString_array& arr,   // @parm Array in cui scrivere il testo
 | |
|   TPoint * from,        // @parm Punto da cui iniziare a scrivere il testo
 | |
|   TPoint * to)          // @parm Punto a cui terminare di scrivere il testo
 | |
| {
 | |
|   arr.destroy();  
 | |
|   TString s(512);
 | |
|   long starty = from == NULL ? 0l : from->y;
 | |
|   int startx = from == NULL ? 0 : (int) from->x;
 | |
|   long endy = to == NULL ? _lines - 1l : to->y;
 | |
|   int endx = to == NULL ? -1 : (int) to->x;
 | |
|   for (long j = starty; j <= endy; j++)
 | |
|   {
 | |
|     s = line(j);
 | |
|     if (j == endy && endx == -1)
 | |
|      endx = s.len();
 | |
| 
 | |
|     if (j == starty && j == endy)
 | |
|       s = s.sub(startx, endx);
 | |
|     else if (j == starty)
 | |
|       s = s.mid(startx);
 | |
|     else if (j == endy)
 | |
|       s = s.left(endx);
 | |
| 
 | |
|     arr.add(s);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Determina il tipo di una stringa: 0=ignoto; 1=stringa; 2=numero
 | |
| static int str_type(TString& str)
 | |
| {
 | |
|   str.trim();
 | |
|   bool is_string = false;
 | |
|   bool is_number = str.full();
 | |
|   for (int i=0; str[i]; i++)
 | |
|   {
 | |
|     if (isalnum(str[i]))
 | |
|       is_string = true;
 | |
|     if (strchr("0123456789,.", str[i]) == NULL)
 | |
|       is_number = false;
 | |
|   }
 | |
|   if (is_number)
 | |
|   {
 | |
|     str.strip(".");
 | |
|     str.replace(',', '.');
 | |
|     const real r(str);
 | |
|     str = r.stringe();
 | |
|   }
 | |
|   return is_number ? 2 : (is_string ? 1 : 0);
 | |
| }
 | |
| 
 | |
| bool TTextfile::write_xls(const TFilename& xls)
 | |
| {
 | |
|   const int headerlen = printer().headersize();
 | |
|   const int footerlen = printer().footersize();
 | |
|   const int pagelen   = printer().formlen();
 | |
|   TString str;
 | |
| 
 | |
|   TTabulator tab;
 | |
|   for (long j = headerlen; j < _lines && j < pagelen; j++)
 | |
|   {
 | |
|     const int row = j % pagelen;
 | |
|     if (row >= headerlen && row < pagelen-footerlen)
 | |
|     {
 | |
|       read_line(j);
 | |
|       int x = 0;
 | |
|       for (const char* cp = piece(); cp; cp = piece())
 | |
|       {
 | |
|         str = cp;
 | |
|         const int len = str.len();
 | |
|         if (str.full() && str_type(str) > 0)
 | |
|           tab.add_field(x, len);
 | |
|         x += len;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   tab.sort();
 | |
| 
 | |
|   TToken_string riga(256, '\t');
 | |
| 
 | |
|   ofstream out(xls);
 | |
|   for (long j = 0; j < _lines; j++)
 | |
|   {
 | |
|     const int row = j % pagelen;
 | |
|     // Esporto la testata solo nella prima pagina ed il footer solo nell'ultima
 | |
|     if ((row < headerlen && j >= pagelen) || (row >= pagelen-footerlen && row < _lines-pagelen))
 | |
|       continue;
 | |
| 
 | |
|     read_line(j);
 | |
|     riga.cut(0);
 | |
|     int x = 0;
 | |
|     for (const char* cp = piece(); cp; cp = piece())
 | |
|     {
 | |
|       str = cp; 
 | |
|       const int len = str.len();
 | |
|       const int st = str_type(str);
 | |
|       if (st > 0)
 | |
|       {
 | |
|         const int pos = tab.find_column(x, len);
 | |
|         if (pos >= 0)
 | |
|           riga.add(str, pos);
 | |
|       }
 | |
|       x += len;
 | |
|     }
 | |
|     if (riga.full())
 | |
|       out << riga << endl;
 | |
|   }
 | |
|   return xls.exist();
 | |
| }
 | |
| 
 | |
| void TTextfile::destroy ()
 | |
| {
 | |
|   CHECK(_istemp, "destroy() chiamata su testo permanente!");
 | |
|   if (_page.items () > 0)
 | |
|   {
 | |
|     if (_index)
 | |
|       fclose (_index);
 | |
|     if (_instr)
 | |
|       fclose (_instr);
 | |
|     _filename.fremove();
 | |
|     _indname.fremove();
 | |
|     _page_start = _lines = 0l;
 | |
|     _page_end = _cur_line = -1l;
 | |
|     _accept = TRUE;
 | |
|     _instr = fopen (_filename, "a+");
 | |
|     _indname.temp ();
 | |
|     _index = fopen (_indname, "w+b");
 | |
|     if (_index == NULL || _instr == NULL)
 | |
|     {
 | |
|       cantwrite_box (_filename);
 | |
|       freeze ();
 | |
|     }
 | |
|     _isopen = TRUE;
 | |
|     //  _page.destroy ();
 | |
|     _spots.destroy ();
 | |
|   }
 | |
| }
 | |
| 
 | |
| TTextfile ::TTextfile (const char *file, int pagesize, direction preferred,
 | |
|                        bool interactive):
 | |
|                        _page (pagesize), _dirty_lines(pagesize), _page_start (0l), _page_end (-1l), _page_size (pagesize),
 | |
|                        _lines (0l), _cur_line (-1), _filename (file), _index (NULL),
 | |
|                        _direction (preferred), _item (0), _line (256), _hotspots (4), _dirty (FALSE),
 | |
|                        _istemp (FALSE), _accept (TRUE), _interactive(interactive), _rel(NULL)
 | |
| 
 | |
| {
 | |
|   // open file & build index
 | |
|   if (file == NULL || *file <= ' ')
 | |
|   {
 | |
|     _filename.temp("txtf");
 | |
|     _istemp = TRUE;
 | |
|   }             
 | |
|   for (int i = 0; i < pagesize; i++)
 | |
|     _page.add(new TString(132));
 | |
|   _isopen = TRUE;
 | |
| 
 | |
|   _instr = fopen (_filename, "a+");
 | |
|   _indname.temp("txti");
 | |
|   _index = fopen (_indname, "w+b");
 | |
| 
 | |
|   if (_index == NULL || _instr == NULL)
 | |
|   {
 | |
|     cantwrite_box(_filename);
 | |
|     freeze ();
 | |
|   }
 | |
|   if (!_istemp)
 | |
|     while (!feof(_instr))
 | |
|     {
 | |
|       const long l = ftell (_instr);
 | |
|       fwrite (&l, sizeof (long), 1, _index);
 | |
|       if (ferror(_index) || ferror(_instr))
 | |
|       {
 | |
|         cantwrite_box(_indname);
 | |
|         freeze();
 | |
|       }
 | |
|       if (fgets (TEXT_TMP, TEXT_TMP_SIZE, _instr) == NULL) 
 | |
|         break;                                  
 | |
|       _lines++;
 | |
|     }
 | |
| }
 | |
| 
 | |
| TTextfile::~TTextfile ()
 | |
| {
 | |
|   if (_index)
 | |
|     fclose (_index);
 | |
|   if (_instr)
 | |
|     fclose (_instr);
 | |
|   if (_istemp) remove ((const char *) _filename);
 | |
|   remove ((const char *) _indname);
 | |
| }
 |