#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';
/*  
  _line.restart ();
  for (int i = 0; i < _line.items (); i++)
    strcat (TEXT_TMP, (const char *) _line.get ());      
*/
  FOR_EACH_TOKEN(_line, l)    
    strcat (TEXT_TMP, l);      
  if (howmuch != -1)
  {
    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
{
  bool ok = FALSE;
  FILE *fp;
  if ((fp = fopen (path, "w")) != NULL)
  {
    ok = TRUE;
    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 ok;
}

// @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);
  }
}

void TTextfile::destroy ()
{
  CHECK(_istemp, "destroy() chiamata su testo permanente!");
  if (_page.items () > 0)
  {
    if (_index)
      fclose (_index);
    if (_instr)
      fclose (_instr);
    remove ((const char *) _filename);
    remove ((const char *) _indname);
    _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)
    {
      error_box ("Impossibile aprire files temporanei");
      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)
  {
    yesnofatal_box ("Impossibile aprire files temporanei");
    freeze ();
  }
  if (!_istemp)
    while (!feof(_instr))
    {
      const long l = ftell (_instr);
      fwrite (&l, sizeof (long), 1, _index);
      if (ferror(_index) || ferror(_instr))
      {
        error_box("Errore di scrittura file temporaneo: scrittura interrotta");
        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);
}