1995-06-12 10:49:19 +00:00
|
|
|
#include <memo.h>
|
|
|
|
#include <utility.h>
|
1995-06-22 09:30:05 +00:00
|
|
|
#include <sys/locking.h>
|
1995-06-12 10:49:19 +00:00
|
|
|
|
|
|
|
#define HEADER_SIZE (sizeof(long)+sizeof(char))
|
|
|
|
#define INFO_SIZE (sizeof(long)+sizeof(long))
|
|
|
|
|
|
|
|
// block size used in writes
|
|
|
|
// must not exceed sizeof(__tmp_string)
|
1995-06-22 09:30:05 +00:00
|
|
|
#define BLOCK_SIZE (1024)
|
|
|
|
// max allowed size for locking is 100k
|
|
|
|
#define MAX_SIZE (100000l)
|
1995-06-12 10:49:19 +00:00
|
|
|
|
|
|
|
TMemo_file::TMemo_file(const char* a) :
|
1996-01-29 14:03:03 +00:00
|
|
|
_fname(a), _fp(NULL), _isnew(FALSE)
|
1995-06-12 10:49:19 +00:00
|
|
|
{
|
|
|
|
// handles: open file or create
|
|
|
|
_fname.ext("mem");
|
|
|
|
if (!(_fp = fopen(_fname,"rb+")))
|
|
|
|
{
|
|
|
|
_fp = fopen(_fname,"wb+");
|
|
|
|
_isnew = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_fp == NULL)
|
1996-01-29 14:03:03 +00:00
|
|
|
error_box("File memo %s non creato per errori di disco", (const char *) _fname);
|
1995-06-12 10:49:19 +00:00
|
|
|
|
|
|
|
// read (write) header
|
|
|
|
if (_isnew)
|
|
|
|
{
|
|
|
|
_id_max = 0;
|
|
|
|
fwrite(&_id_max, sizeof(long), 1, _fp);
|
|
|
|
char eof = 26; // only to inhibit 'type'
|
|
|
|
fwrite(&eof, sizeof(char), 1, _fp);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fread(&_id_max, sizeof(long), 1, _fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
TMemo_file::~TMemo_file()
|
|
|
|
{
|
|
|
|
if (_fp) fclose(_fp);
|
|
|
|
}
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
bool TMemo_file::_find_id(long id)
|
|
|
|
{
|
|
|
|
if (id > _id_max && id < 0)
|
|
|
|
error_box("File memo inconsistente");
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
bool dndir = FALSE /* id > (_id_max/2l) */ ;
|
|
|
|
|
|
|
|
_current = -1l;
|
|
|
|
|
|
|
|
long pos = dndir ? INFO_SIZE : HEADER_SIZE;
|
|
|
|
fseek(_fp, pos, dndir ? SEEK_END : SEEK_SET);
|
|
|
|
|
|
|
|
int ok = 0;
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
while (_current < id)
|
|
|
|
{
|
|
|
|
// se si va all'indietro, questa non funzia: nonostante
|
|
|
|
// fflush il file non e' tutto scritto su disco, e fread
|
|
|
|
// ritorna 0 lasciando tutto al valore precedente
|
|
|
|
// Perche'? Eh?
|
|
|
|
fread(&_current, sizeof(long), 1, _fp);
|
|
|
|
fread(&_next_ofs, sizeof(long), 1, _fp);
|
|
|
|
if (_current < id)
|
|
|
|
{
|
|
|
|
long ofs = dndir ? -_next_ofs-INFO_SIZE-INFO_SIZE :
|
1995-06-12 16:05:26 +00:00
|
|
|
_next_ofs+INFO_SIZE;
|
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
ok = fseek(_fp, ofs, SEEK_CUR);
|
|
|
|
}
|
|
|
|
if (ok) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
_current = ok ? -1l : id;
|
|
|
|
return _current == id;
|
|
|
|
}
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
bool TMemo_file::get_field(TTextfile& t, long id)
|
|
|
|
{
|
|
|
|
bool ok = _find_id(id);
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
_current = id;
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
// te lo faccio io, poi so' cazzi tua se sbagli
|
|
|
|
t.destroy();
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
TString256 line;
|
|
|
|
|
|
|
|
// block read until done; transfer block to txt
|
|
|
|
// block by block
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
long size = _next_ofs < BLOCK_SIZE ? _next_ofs : BLOCK_SIZE;
|
|
|
|
int lcnt = 0;
|
|
|
|
|
|
|
|
for (long cnt = 0; cnt < _next_ofs; cnt += size)
|
|
|
|
{
|
|
|
|
if (fread(__tmp_string, sizeof(char), (int)size, _fp) != (size_t)size)
|
1996-01-29 14:03:03 +00:00
|
|
|
error_box("%s: unexpected end of file", (const char *) _fname);
|
1995-06-12 10:49:19 +00:00
|
|
|
|
|
|
|
// move block into text
|
|
|
|
for(long j = 0; j <= size; j++)
|
|
|
|
{
|
|
|
|
char ch = j < size ? __tmp_string[j] : '\0';
|
|
|
|
if (ch == '\n' || j == size)
|
|
|
|
{
|
|
|
|
line[lcnt] = '\0';
|
|
|
|
t.append(line);
|
|
|
|
lcnt = 0;
|
|
|
|
}
|
|
|
|
else line[lcnt++] = ch;
|
|
|
|
}
|
|
|
|
|
|
|
|
// size of next read
|
|
|
|
size = cnt + size < BLOCK_SIZE ? _next_ofs - cnt : BLOCK_SIZE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
|
|
|
|
1995-06-13 08:23:45 +00:00
|
|
|
long TMemo_file::set_field(TTextfile& t, long id)
|
1995-06-12 10:49:19 +00:00
|
|
|
{
|
|
|
|
bool ok = TRUE;
|
|
|
|
long ret = 0;
|
|
|
|
|
|
|
|
// append se -1 o se l'ID e' maggiore dell'ultima presente
|
|
|
|
bool at_end = id == -1 || (id != -1 && id > _id_max);
|
|
|
|
// the casinating insertion in the middol
|
|
|
|
bool in_mid = FALSE;
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
if (!at_end)
|
|
|
|
{
|
|
|
|
ok = _find_id(id);
|
|
|
|
if (!ok)
|
|
|
|
{
|
|
|
|
// va inserito al posto di uno scancellato
|
|
|
|
// vediamo dove
|
|
|
|
long pos = HEADER_SIZE;
|
|
|
|
fseek(_fp, pos, SEEK_SET);
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
int ok = 0;
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
while (_current < id)
|
|
|
|
{
|
|
|
|
fread(&_current, sizeof(long), 1, _fp);
|
|
|
|
fread(&_next_ofs, sizeof(long), 1, _fp);
|
|
|
|
if (_current < id)
|
|
|
|
{
|
1995-06-12 16:05:26 +00:00
|
|
|
long ofs = _next_ofs+INFO_SIZE;
|
|
|
|
ok = fseek(_fp, ofs, SEEK_CUR);
|
1995-06-12 10:49:19 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// position the luridissim cazz at bighinnin
|
|
|
|
// of privius bifor riding ids
|
|
|
|
long oo = (long)INFO_SIZE * -1l;
|
|
|
|
fseek(_fp, oo, SEEK_CUR);
|
|
|
|
break;
|
|
|
|
}
|
1996-01-29 14:03:03 +00:00
|
|
|
if (ok) error_box("file error in %s", (const char *) _fname);
|
1995-06-12 10:49:19 +00:00
|
|
|
in_mid = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (at_end) // the easy case
|
|
|
|
{
|
|
|
|
if (id == -1) id = ++_id_max;
|
|
|
|
// append test, update info
|
|
|
|
long cnt = 0l;
|
|
|
|
fseek(_fp, 0, SEEK_END);
|
1995-06-22 09:30:05 +00:00
|
|
|
|
|
|
|
// lock file
|
1996-05-14 10:16:31 +00:00
|
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
1995-06-22 09:30:05 +00:00
|
|
|
_locking(_fileno(_fp), _LK_LOCK, MAX_SIZE);
|
1996-01-29 14:03:03 +00:00
|
|
|
#else
|
|
|
|
locking(fileno(_fp), LK_LOCK, MAX_SIZE);
|
|
|
|
#endif
|
1995-06-22 09:30:05 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
fwrite(&id, sizeof(long), 1, _fp);
|
|
|
|
// will overwrite later with byte count
|
|
|
|
long cpos = ftell(_fp);
|
|
|
|
fwrite(&id, sizeof(long), 1, _fp);
|
|
|
|
|
|
|
|
TString256 line;
|
|
|
|
for (int i = 0; i < t.lines(); i++)
|
|
|
|
{
|
|
|
|
line = t.line(i);
|
|
|
|
char c;
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
for (int k = 0; c = line[k]; k++)
|
|
|
|
{
|
|
|
|
fwrite(&c, sizeof(char), 1, _fp);
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
if (i < t.lines() - 1)
|
|
|
|
{
|
|
|
|
c = '\n';
|
|
|
|
fwrite(&c, sizeof(char), 1, _fp);
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
fwrite(&id, sizeof(long), 1, _fp);
|
|
|
|
fwrite(&cnt, sizeof(long), 1, _fp);
|
|
|
|
// update count
|
|
|
|
fseek(_fp, cpos, SEEK_SET);
|
|
|
|
fwrite(&cnt, sizeof(long), 1, _fp);
|
|
|
|
fseek(_fp, 0, SEEK_SET);
|
1995-06-22 09:30:05 +00:00
|
|
|
fwrite(&_id_max, sizeof(long), 1, _fp);
|
|
|
|
|
1996-05-14 10:16:31 +00:00
|
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
1995-06-22 09:30:05 +00:00
|
|
|
_locking(_fileno(_fp), _LK_UNLCK, MAX_SIZE);
|
1996-01-29 14:03:03 +00:00
|
|
|
#else
|
|
|
|
locking(fileno(_fp), LK_UNLCK, MAX_SIZE);
|
|
|
|
#endif
|
|
|
|
|
1995-06-22 09:30:05 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
fflush(_fp);
|
|
|
|
ret = _find_id(id) ? id : -1;
|
|
|
|
}
|
|
|
|
else // the rognous one
|
|
|
|
{
|
|
|
|
long to = ftell(_fp) - INFO_SIZE;
|
|
|
|
long from = in_mid ? to : to + _next_ofs + (2*INFO_SIZE);
|
|
|
|
|
|
|
|
TFilename tmp; tmp.temp();
|
|
|
|
FILE* tfp = fopen(tmp, "wb+");
|
|
|
|
|
|
|
|
fseek(_fp, 0, SEEK_SET);
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
long size = BLOCK_SIZE;
|
|
|
|
bool stop = FALSE;
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
// copy file into temp up to TO pos
|
|
|
|
// use 1k blocks for speed
|
|
|
|
for (int i = 0; !stop; i++)
|
|
|
|
{
|
|
|
|
if (to < (BLOCK_SIZE * (i+1)))
|
|
|
|
{
|
|
|
|
size = to - i*BLOCK_SIZE;
|
|
|
|
stop = TRUE;
|
|
|
|
}
|
|
|
|
fread (__tmp_string, sizeof(char), (int)size, _fp);
|
|
|
|
fwrite(__tmp_string, sizeof(char), (int)size, tfp);
|
|
|
|
}
|
|
|
|
|
|
|
|
// write new text and update info
|
|
|
|
fwrite(&id, sizeof(long), 1, tfp);
|
|
|
|
// will overwrite later with byte count
|
|
|
|
long cpos = ftell(tfp);
|
|
|
|
fwrite(&id, sizeof(long), 1, tfp);
|
|
|
|
|
|
|
|
TString256 line; long cnt = 0l;
|
|
|
|
for (i = 0; i < t.lines(); i++)
|
|
|
|
{
|
|
|
|
line = t.line(i);
|
|
|
|
char c;
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
for (int k = 0; c = line[k]; k++)
|
|
|
|
{
|
|
|
|
fwrite(&c, sizeof(char), 1, tfp);
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
if (i < t.lines() - 1)
|
|
|
|
{
|
|
|
|
c = '\n';
|
|
|
|
fwrite(&c, sizeof(char), 1, tfp);
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
fwrite(&id, sizeof(long), 1, tfp);
|
|
|
|
fwrite(&cnt, sizeof(long), 1, tfp);
|
|
|
|
|
|
|
|
// write the rest of the file
|
|
|
|
stop = FALSE;
|
|
|
|
fseek(_fp, from, SEEK_SET);
|
|
|
|
for (i = 0; !stop; i++)
|
|
|
|
{
|
|
|
|
int size = fread (__tmp_string, sizeof(char), BLOCK_SIZE, _fp);
|
|
|
|
if (size) fwrite(__tmp_string, sizeof(char), size, tfp);
|
|
|
|
stop = size < BLOCK_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// update count
|
|
|
|
fseek(tfp, cpos, SEEK_SET);
|
|
|
|
fwrite(&cnt, sizeof(long), 1, tfp);
|
|
|
|
fclose(tfp);
|
|
|
|
// move files
|
|
|
|
fclose(_fp);
|
|
|
|
fcopy(tmp, _fname);
|
|
|
|
remove(tmp);
|
|
|
|
_fp = fopen(_fname, "rb+");
|
|
|
|
ret = _find_id(id) ? 0 : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_dirty = TRUE;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
bool TMemo_file::remove_field(long id)
|
|
|
|
{
|
|
|
|
bool ok = _find_id(id);
|
|
|
|
if (ok)
|
|
|
|
{
|
|
|
|
long to = ftell(_fp) - INFO_SIZE;
|
|
|
|
long from = to + _next_ofs + (2*INFO_SIZE);
|
|
|
|
|
|
|
|
TFilename tmp; tmp.temp();
|
|
|
|
FILE* tfp = fopen(tmp, "wb+");
|
|
|
|
|
|
|
|
fseek(_fp, 0, SEEK_SET);
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
long size = BLOCK_SIZE;
|
|
|
|
bool stop = FALSE;
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
// copy file into temp up to TO pos
|
|
|
|
// use 1k blocks for speed
|
|
|
|
for (int i = 0; !stop; i++)
|
|
|
|
{
|
|
|
|
if (to < (BLOCK_SIZE * (i+1)))
|
|
|
|
{
|
|
|
|
size = to - i*BLOCK_SIZE;
|
|
|
|
stop = TRUE;
|
|
|
|
}
|
|
|
|
fread (__tmp_string, sizeof(char), (int)size, _fp);
|
|
|
|
fwrite(__tmp_string, sizeof(char), (int)size, tfp);
|
|
|
|
}
|
|
|
|
// write the rest of the file
|
|
|
|
stop = FALSE;
|
|
|
|
fseek(_fp, from, SEEK_SET);
|
|
|
|
for (i = 0; !stop; i++)
|
|
|
|
{
|
|
|
|
int size = fread (__tmp_string, sizeof(char), BLOCK_SIZE, _fp);
|
|
|
|
if (size) fwrite(__tmp_string, sizeof(char), size, tfp);
|
|
|
|
stop = size < BLOCK_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// move files
|
|
|
|
fclose(tfp);
|
|
|
|
fclose(_fp);
|
|
|
|
fcopy(tmp, _fname);
|
|
|
|
remove(tmp);
|
|
|
|
_fp = fopen(_fname, "rb+");
|
|
|
|
}
|
|
|
|
return ok;
|
|
|
|
}
|
1995-06-12 16:05:26 +00:00
|
|
|
|
1995-06-22 09:30:05 +00:00
|
|
|
|
1995-06-12 10:49:19 +00:00
|
|
|
bool TMemo_file::edit_field(long id)
|
|
|
|
{
|
|
|
|
return TRUE;
|
|
|
|
}
|