Aggiunto supporto campi memo
git-svn-id: svn://10.65.10.50/trunk@1465 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
d435d011d1
commit
22fbb28fb3
@ -446,7 +446,7 @@ void TFormatted_date::set_format(
|
||||
// della data:
|
||||
// <nl>1° carattere -<gt> FORMATO. Puo' assumere i seguenti valori:
|
||||
// <nl> 1 = giorno-mese-anno
|
||||
// <nl> 2 = mese-anno-giorno
|
||||
// <nl> 2 = mese-anno-giorno
|
||||
// <nl> 3 = anno-giorno-mese
|
||||
// <nl> 4 = solo anno
|
||||
// <nl> 5 = solo mese
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <relation.h>
|
||||
#include <scanner.h>
|
||||
#include <utility.h>
|
||||
|
||||
#include <memo.h>
|
||||
|
||||
#if XVT_OS==XVT_OS_WIN
|
||||
#include <process.h>
|
||||
@ -533,7 +533,11 @@ int TBaseisamfile::rewriteat(const TRectype& rec, TRecnotype nrec)
|
||||
int TBaseisamfile::remove(TDate& atdate)
|
||||
|
||||
{
|
||||
NOT_OPEN();
|
||||
NOT_OPEN();
|
||||
|
||||
// TBI rimozione campi memo
|
||||
|
||||
|
||||
if ((!_historicfile) || (atdate == botime))
|
||||
cisdelete(_isamfile, curr().string(), &_lasterr);
|
||||
else
|
||||
@ -1781,6 +1785,21 @@ bool TRectype::get_bool(const char* fieldname) const
|
||||
return *_isam_string == 'X';
|
||||
}
|
||||
|
||||
|
||||
bool TRectype::get_memo(const char* fieldname, TTextfile& txt) const
|
||||
{
|
||||
long val = get_long(fieldname);
|
||||
bool ok = FALSE;
|
||||
if (ok = (val != 0l))
|
||||
{
|
||||
TLocalisamfile f(_logicnum);
|
||||
TMemo_file memo(f.filename());
|
||||
|
||||
ok |= memo.get_field(txt, val);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
#endif // FOXPRO
|
||||
|
||||
|
||||
@ -1793,7 +1812,6 @@ TDate TRectype::get_date(const char* fieldname) const
|
||||
return (TDate) f;
|
||||
}
|
||||
|
||||
|
||||
#ifndef FOXPRO
|
||||
|
||||
void TRectype::put(const char* fieldname, int val)
|
||||
@ -1815,6 +1833,22 @@ void TRectype::put(const char* fieldname, long val)
|
||||
setempty(FALSE);
|
||||
}
|
||||
|
||||
void TRectype::put(const char* fieldname, const TTextfile& txt)
|
||||
{
|
||||
long val = get_long(fieldname);
|
||||
bool isnew = id == 0;
|
||||
TLocalisamfile f(_logicnum);
|
||||
|
||||
TMemo_file memo(f.filename());
|
||||
|
||||
long id = memo.set_field(txt, isnew ? -1 : val);
|
||||
if (isnew) id = val;
|
||||
|
||||
if (CPutField((char*) fieldname, rec_des(), &val, _rec) == -1)
|
||||
UNKNOWN_FIELD(num(), fieldname);
|
||||
setempty(FALSE);
|
||||
}
|
||||
|
||||
|
||||
void TRectype::put(const char* fieldname, word val)
|
||||
|
||||
|
@ -29,6 +29,9 @@
|
||||
#include <lffiles.h>
|
||||
#endif
|
||||
|
||||
#ifndef __TEXT_H
|
||||
#include <text.h>
|
||||
#endif
|
||||
|
||||
// @M
|
||||
#define FIELDERR -1
|
||||
@ -96,6 +99,7 @@ public:
|
||||
char get_char(const char* fieldname) const ;
|
||||
bool get_bool(const char* fieldname) const ;
|
||||
real get_real(const char* fieldname) const ;
|
||||
bool get_memo(const char* fieldname, TTextfile& txt) const ;
|
||||
#endif
|
||||
TDate get_date(const char* fieldname) const ;
|
||||
|
||||
@ -111,6 +115,7 @@ public:
|
||||
void put(const char* fieldname, char val);
|
||||
void put(const char* fieldname, bool val);
|
||||
void put(const char* fieldname, const real& val);
|
||||
void put(const char* fieldname, const TTextfile& txt);
|
||||
#else
|
||||
#endif
|
||||
|
||||
@ -254,6 +259,8 @@ public:
|
||||
{ return curr().get_bool(fieldname);}
|
||||
real get_real(const char* fieldname) const
|
||||
{ return curr().get_real(fieldname);}
|
||||
bool get_memo(const char* fieldname, TTextfile& txt)
|
||||
{ return curr().get_memo(fieldname, txt); }
|
||||
#endif
|
||||
TDate get_date(const char* fieldname) const
|
||||
{ return curr().get_date(fieldname);}
|
||||
@ -274,7 +281,9 @@ public:
|
||||
void put(const char* fieldname, bool val)
|
||||
{ curr().put(fieldname, val);}
|
||||
void put(const char* fieldname, const real& val)
|
||||
{ curr().put(fieldname, val);}
|
||||
{ curr().put(fieldname, val);}
|
||||
void put(const char* fieldname, const TTextfile& txt)
|
||||
{ curr().put(fieldname, txt); }
|
||||
#else
|
||||
const char* get_str(const char* fieldname) const
|
||||
{ return curr().get_str(fieldname);}
|
||||
|
338
include/memo.cpp
Executable file
338
include/memo.cpp
Executable file
@ -0,0 +1,338 @@
|
||||
#include <memo.h>
|
||||
#include <utility.h>
|
||||
|
||||
#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)
|
||||
#define BLOCK_SIZE 1024
|
||||
|
||||
TMemo_file::TMemo_file(const char* a) :
|
||||
_fname(a), _fp(NULL), _isnew(NULL)
|
||||
{
|
||||
// handles: open file or create
|
||||
_fname.ext("mem");
|
||||
if (!(_fp = fopen(_fname,"rb+")))
|
||||
{
|
||||
_fp = fopen(_fname,"wb+");
|
||||
_isnew = TRUE;
|
||||
}
|
||||
|
||||
if (_fp == NULL)
|
||||
error_box("File memo %s non creato per errori di disco", _fname);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
bool TMemo_file::_find_id(long id)
|
||||
{
|
||||
if (id > _id_max && id < 0)
|
||||
error_box("File memo inconsistente");
|
||||
|
||||
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;
|
||||
|
||||
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 :
|
||||
_next_ofs+INFO_SIZE;
|
||||
|
||||
ok = fseek(_fp, ofs, SEEK_CUR);
|
||||
}
|
||||
if (ok) break;
|
||||
}
|
||||
|
||||
_current = ok ? -1l : id;
|
||||
return _current == id;
|
||||
}
|
||||
|
||||
bool TMemo_file::get_field(TTextfile& t, long id)
|
||||
{
|
||||
bool ok = _find_id(id);
|
||||
if (ok)
|
||||
{
|
||||
_current = id;
|
||||
|
||||
// te lo faccio io, poi so' cazzi tua se sbagli
|
||||
t.destroy();
|
||||
|
||||
TString256 line;
|
||||
|
||||
// block read until done; transfer block to txt
|
||||
// block by block
|
||||
|
||||
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)
|
||||
error_box("%s: unexpected end of file", _fname);
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
long TMemo_file::set_field(TTextfile& t, long id)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
int ok = 0;
|
||||
|
||||
while (_current < id)
|
||||
{
|
||||
fread(&_current, sizeof(long), 1, _fp);
|
||||
fread(&_next_ofs, sizeof(long), 1, _fp);
|
||||
if (_current < id)
|
||||
{
|
||||
long ofs = _next_ofs+INFO_SIZE;
|
||||
ok = fseek(_fp, ofs, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
// position the luridissim cazz at bighinnin
|
||||
// of privius bifor riding ids
|
||||
long oo = (long)INFO_SIZE * -1l;
|
||||
fseek(_fp, oo, SEEK_CUR);
|
||||
break;
|
||||
}
|
||||
if (ok) error_box("file error in %s", _fname);
|
||||
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);
|
||||
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;
|
||||
|
||||
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);
|
||||
fwrite(&_id_max, sizeof(long), 1, _fp);
|
||||
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);
|
||||
|
||||
long size = BLOCK_SIZE;
|
||||
bool stop = FALSE;
|
||||
|
||||
// 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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
long size = BLOCK_SIZE;
|
||||
bool stop = FALSE;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
bool TMemo_file::edit_field(long id)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
45
include/memo.h
Executable file
45
include/memo.h
Executable file
@ -0,0 +1,45 @@
|
||||
#ifndef __MEMO_H
|
||||
#define __MEMO_H
|
||||
|
||||
#ifndef __TEXT_H
|
||||
#include <text.h>
|
||||
#endif
|
||||
|
||||
// quick and dirty memofile class
|
||||
// to be used with isamfiles
|
||||
// memo field is a long integer, memo file is <isamname>.mem
|
||||
|
||||
class TMemo_file : public TObject
|
||||
{
|
||||
bool _dirty;
|
||||
FILE* _fp;
|
||||
long _current;
|
||||
TFilename _fname;
|
||||
bool _isnew;
|
||||
long _id_max;
|
||||
long _next_ofs;
|
||||
|
||||
bool _find_id(long id);
|
||||
|
||||
public:
|
||||
|
||||
// retrieves text with specified ID (or last one passed);
|
||||
// returns TRUE if successful
|
||||
bool get_field(TTextfile& t, long id = -1l);
|
||||
// sets field to specified text; if not present
|
||||
// returns new ID; if error returns -1, otherwise 0
|
||||
long set_field(const TTextfile& t, long id = -1l);
|
||||
// removes field and pakkettates file
|
||||
bool remove_field(long id);
|
||||
// calls editor to edit text (specified as mem into config)
|
||||
bool edit_field(long id = -1l);
|
||||
|
||||
// returns the maximum ID used (<= n. of fields in file)
|
||||
long max_id() const { return _id_max; }
|
||||
|
||||
// must be passed the basename of archive
|
||||
TMemo_file(const char* archive);
|
||||
~TMemo_file();
|
||||
};
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user