assoc.cpp Diminuita HASH_SIZE che era un po' esagerata
isam.cpp Corretta cancellazione dei memo nei file temporanei maskfld.* Aggiunta keyword FSELECT agli edit field multirec.* Aggiunto metodo compare prefix.cpp Corretta gestione autochiusura e nome dei file temporanei strins.cpp Aggiunti delete [] qua e la' git-svn-id: svn://10.65.10.50/trunk@6775 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
feb451e50d
commit
017422bc2c
@ -1,7 +1,7 @@
|
||||
#include <assoc.h>
|
||||
|
||||
// @ccost:(INTERNAL) HASH_SIZE | 10883 | Dimensione della tabella hash
|
||||
const int HASH_SIZE = 10883;
|
||||
// @ccost:(INTERNAL) HASH_SIZE | 883 | Dimensione della tabella hash
|
||||
const int HASH_SIZE = 883;
|
||||
|
||||
TArray& TAssoc_array::bucket(int index)
|
||||
{
|
||||
|
@ -605,8 +605,7 @@ const char* TBaseisamfile::name() const
|
||||
const char* TBaseisamfile::filename() const
|
||||
{
|
||||
const int n = _isam_handle > 0 ? _isam_handle : num();
|
||||
const FileDes& d = prefix().get_filedes(n);
|
||||
strcpy(_isam_string, d.SysName);
|
||||
strcpy(_isam_string, prefix().get_filename(n));
|
||||
strcat(_isam_string, ".dbf");
|
||||
return _isam_string;
|
||||
}
|
||||
@ -1251,7 +1250,7 @@ TIsamtempfile::~TIsamtempfile()
|
||||
// generato (vedi <t TIsamerr>).
|
||||
int TIsamtempfile::open(
|
||||
const char* radix, // @parm Radice del path del file
|
||||
bool create, // @parm Indica se va creatoun nuovo file (se FALSE il file esiste gia')
|
||||
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
|
||||
|
||||
@ -1263,7 +1262,7 @@ int TIsamtempfile::open(
|
||||
|
||||
TFilename filename;
|
||||
if (radix[0] == '%')
|
||||
filename << &radix[1] ;
|
||||
filename = radix+1;
|
||||
else
|
||||
filename.temp(radix);
|
||||
filename.ext("");
|
||||
@ -1311,10 +1310,17 @@ int TIsamtempfile::close()
|
||||
int err = prefix().close_isamfile(_isam_handle);
|
||||
if (err == NOERR && _autodel)
|
||||
{
|
||||
long c = DB_getconf();
|
||||
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
|
||||
@ -1322,7 +1328,7 @@ int TIsamtempfile::close()
|
||||
if (c & 8 || c & 2) // CLIPPER and DBIII format
|
||||
{
|
||||
f.ext("cgp");
|
||||
FILE *fp=fopen((const char*)f,"r");
|
||||
FILE *fp=fopen(f,"r");
|
||||
char in[16];
|
||||
while (fgets(in,16,fp)!=NULL)
|
||||
{
|
||||
|
@ -1574,8 +1574,6 @@ TEditable_field& TBrowse_button::field(short id) const
|
||||
// TList_sheet
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// Certified 100%
|
||||
TList_sheet::TList_sheet(TEdit_field* f, const char* caption, const char* head)
|
||||
: TBrowse_button(f), _row(-1), _caption(caption), _head(head)
|
||||
@ -2509,6 +2507,70 @@ bool TBrowse::empty_check()
|
||||
return do_input() > 0;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// TFile_select
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
TFile_select::TFile_select(TEdit_field* ef, const char* filter)
|
||||
: TBrowse_button(ef), _filter(filter)
|
||||
{ }
|
||||
|
||||
void TFile_select::parse_input(TScanner& scanner)
|
||||
{
|
||||
scanner.pop();
|
||||
}
|
||||
|
||||
void TFile_select::parse_output(TScanner& scanner)
|
||||
{
|
||||
scanner.pop();
|
||||
}
|
||||
|
||||
KEY TFile_select::run()
|
||||
{
|
||||
DIRECTORY savedir;
|
||||
FILE_SPEC fs;
|
||||
|
||||
xvt_fsys_get_dir(&savedir);
|
||||
xvt_fsys_get_dir(&fs.dir);
|
||||
|
||||
strcpy(fs.type, _filter.ext());
|
||||
strcpy(fs.name, field().get());
|
||||
strcpy(fs.creator, "AGA");
|
||||
|
||||
bool good = xvt_dm_post_file_open(&fs, (char*)field().prompt()) == FL_OK;
|
||||
xvt_fsys_set_dir(&savedir);
|
||||
|
||||
if (good)
|
||||
{
|
||||
TString str = fs.name;
|
||||
good = _filter.not_empty() && str.match(_filter);
|
||||
if (good)
|
||||
field().set(str);
|
||||
}
|
||||
return good ? K_ENTER : K_ESC;
|
||||
}
|
||||
|
||||
|
||||
// CHECK_NONE Nessun controllo
|
||||
// CHECK_NORMAL Se non e' vuoto deve esistere
|
||||
// CHECK_REQUIRED Deve esistere
|
||||
// CHECK_SEARCH Puo' essere vuoto altrimenti deve matchare il filtro
|
||||
|
||||
bool TFile_select::check(CheckTime)
|
||||
{
|
||||
bool ok = TRUE;
|
||||
const CheckType ct = field().check_type();
|
||||
if (ct != CHECK_NONE)
|
||||
{
|
||||
const TFilename name = field().get();
|
||||
if (name.empty() && ct != CHECK_REQUIRED)
|
||||
return TRUE;
|
||||
ok = _filter.not_empty() && name.match(_filter);
|
||||
if (ok && ct != CHECK_SEARCH)
|
||||
ok = name.exist();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// TEdit_field
|
||||
@ -2539,21 +2601,6 @@ void TEdit_field::set_width(short width, short dwidth)
|
||||
get_rect(rect);
|
||||
rect.right= rect.left+width;
|
||||
set_rect(rect);
|
||||
|
||||
/* _ctl_data.reset();
|
||||
_ctl_data._dlg = dlg();
|
||||
_ctl_data._x = x;
|
||||
_ctl_data._y = y;
|
||||
_ctl_data._prompt = prompt();
|
||||
|
||||
_ctl_data._size = size();
|
||||
|
||||
_ctl_data._flags = flags;
|
||||
_flags.update(flags);
|
||||
|
||||
_ctl_data._width = width;
|
||||
create(parent()); */
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -2564,7 +2611,7 @@ void TEdit_field::parse_head(TScanner& scanner)
|
||||
if (_ctl_data._size <= 0)
|
||||
{
|
||||
_ctl_data._size = 8;
|
||||
yesnofatal_box("Il campo %d ha dimensione nulla (uso %d)",
|
||||
NFCHECK("Il campo %d ha dimensione nulla: uso %d",
|
||||
_ctl_data._dlg, _ctl_data._size);
|
||||
}
|
||||
#endif
|
||||
@ -2679,7 +2726,6 @@ bool TEdit_field::parse_item(TScanner& scanner)
|
||||
|
||||
if (tabmaskname.not_empty())
|
||||
{
|
||||
// tabmaskname.insert("MBATB", 0);
|
||||
tabmaskname.insert("MTB", 0);
|
||||
browse()->set_insert(tabmaskname);
|
||||
}
|
||||
@ -2700,7 +2746,7 @@ bool TEdit_field::parse_item(TScanner& scanner)
|
||||
const TString16 what(scanner.popkey());
|
||||
const TBrowse* b = parse_browse(scanner);
|
||||
|
||||
CHECK(b,"Impossibile copiare la browse da un campo visto che quel campo non l'ha" );
|
||||
CHECK(b,"Impossibile copiare la browse da un campo visto che quel campo non ce l'ha" );
|
||||
if (b)
|
||||
{
|
||||
if (what == "US" || what == "AL")
|
||||
@ -2723,13 +2769,24 @@ bool TEdit_field::parse_item(TScanner& scanner)
|
||||
{
|
||||
#ifdef DBG
|
||||
if (_browse)
|
||||
return yesnofatal_box("SHEET duplicato nel campo %d", _ctl_data._dlg);
|
||||
NFCHECK("SHEET duplicato nel campo %d", _ctl_data._dlg);
|
||||
#endif
|
||||
_browse = new TList_sheet(this, _ctl_data._prompt, scanner.string());
|
||||
_check_enabled = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (scanner.key() == "FS") // FSELECT
|
||||
{
|
||||
#ifdef DBG
|
||||
if (_browse)
|
||||
NFCHECK("FSELECT duplicato nel campo %d", _ctl_data._dlg);
|
||||
#endif
|
||||
_browse = new TFile_select(this, scanner.string());
|
||||
_check_enabled = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (scanner.key() == "IT") // ITEM
|
||||
{
|
||||
#ifdef DBG
|
||||
@ -2983,21 +3040,21 @@ bool TEdit_field::on_key(KEY key)
|
||||
|
||||
if (_browse)
|
||||
{
|
||||
if (sheet())
|
||||
{
|
||||
ok = query || sheet()->check(); // Check consistency
|
||||
}
|
||||
else
|
||||
if (browse())
|
||||
{
|
||||
// if (check_enabled() && (!query || forced()) && vf != 21)
|
||||
if (check_enabled() && vf != 21)
|
||||
{
|
||||
if (!query || forced())
|
||||
ok = browse()->check();
|
||||
ok = _browse->check();
|
||||
else
|
||||
browse()->check();
|
||||
_browse->check();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = query || _browse->check(); // Check consistency
|
||||
}
|
||||
}
|
||||
if (ok)
|
||||
ok = on_hit();
|
||||
|
@ -742,6 +742,8 @@ public:
|
||||
virtual bool check(CheckTime = RUNNING_CHECK) pure;
|
||||
|
||||
virtual bool is_browse() const { return FALSE; }
|
||||
virtual bool is_sheet() const { return FALSE; }
|
||||
virtual bool is_filesel() const { return FALSE; }
|
||||
|
||||
TBrowse_button(TEdit_field* f);
|
||||
virtual ~TBrowse_button();
|
||||
@ -799,6 +801,8 @@ public:
|
||||
// @cmember Esegue la ricerca. Torna il tasto che ha terminato la ricerca
|
||||
virtual KEY run();
|
||||
|
||||
virtual bool is_sheet() const { return TRUE; }
|
||||
|
||||
TString_array& rows_array() { return _data; }
|
||||
|
||||
// @cmember Costruttore
|
||||
@ -930,6 +934,26 @@ public:
|
||||
virtual KEY run();
|
||||
};
|
||||
|
||||
class TFile_select : public TBrowse_button
|
||||
{
|
||||
TFilename _filter;
|
||||
|
||||
public:
|
||||
// @cmember Controlla la sintassi della input del campo e ne setta i membri
|
||||
virtual void parse_input(TScanner& scanner);
|
||||
|
||||
// @cmember Controlla la sintassi della output del campo e ne setta i membri
|
||||
virtual void parse_output(TScanner& scanner);
|
||||
|
||||
virtual KEY run();
|
||||
|
||||
// @cmember Controlla la validita' del campo
|
||||
virtual bool check(CheckTime = RUNNING_CHECK);
|
||||
|
||||
TFile_select(TEdit_field* ef, const char* filter);
|
||||
virtual ~TFile_select() { }
|
||||
};
|
||||
|
||||
|
||||
// @doc EXTERNAL
|
||||
|
||||
@ -1025,13 +1049,17 @@ public:
|
||||
// @cmember Esegue il controllo
|
||||
virtual bool check(CheckTime = RUNNING_CHECK);
|
||||
|
||||
// @cmember Ritorna l'oggetto _browse
|
||||
// @cmember Ritorna l'oggetto browse
|
||||
TBrowse* browse() const
|
||||
{ return (_browse && _browse->is_browse()) ? (TBrowse*)_browse : NULL; }
|
||||
|
||||
// @cmember Ritorna l'oggetto _sheet
|
||||
// @cmember Ritorna l'oggetto sheet
|
||||
TList_sheet* sheet() const
|
||||
{ return (_browse && !_browse->is_browse()) ? (TList_sheet*)_browse : NULL;}
|
||||
{ return (_browse && _browse->is_sheet()) ? (TList_sheet*)_browse : NULL;}
|
||||
|
||||
// @cmember Ritorna l'oggetto dirsheet
|
||||
TFile_select* filesel() const
|
||||
{ return (_browse && _browse->is_filesel()) ? (TFile_select*)_browse : NULL;}
|
||||
|
||||
// @cmember Permette di abilitare/disabilitare il campo
|
||||
virtual void enable(bool on = TRUE);
|
||||
|
@ -292,34 +292,9 @@ int TMultiple_rectype::loaded_rows(int logicnum) const
|
||||
return r->rows();
|
||||
}
|
||||
|
||||
// @mfunc confronta due record multipli
|
||||
int TMultiple_rectype::compare(const TSortable& s) const
|
||||
{
|
||||
int res = TRectype::compare(s);
|
||||
TMultiple_rectype & m = (TMultiple_rectype &) s;
|
||||
for (int i = 0 ; res == 0 && i < _nfiles; i++)
|
||||
{
|
||||
int logicnum = _logicnums[i];
|
||||
TRecord_array & r = body(logicnum);
|
||||
TRecord_array & r1 = m.body(logicnum);
|
||||
res = r.rows() - r1.rows();
|
||||
if (res == 0 && r.rows() > 0 && r1.rows() > 0)
|
||||
{
|
||||
for (int j = r.first_row(), k = r1.first_row(); res == 0 && j >= 0 && k >= 0; j = r.succ_row(j), k = r1.succ_row(k))
|
||||
{
|
||||
res = j - k;
|
||||
if (res == 0)
|
||||
res = r[j] != r1[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int TMultiple_rectype::remove(TBaseisamfile & f) const
|
||||
{
|
||||
int err = NOERR;
|
||||
|
||||
for (int i = _files.last(); err == NOERR && i >= 0 ; i = _files.pred(i))
|
||||
{
|
||||
TRecord_array & r = body(lognum(i));
|
||||
|
@ -111,7 +111,7 @@ public:
|
||||
virtual TRectype & operator =(const char * r);
|
||||
virtual void zero(char c = '\0');
|
||||
|
||||
virtual int read(TRectype & rec, word op = _isequal, word lockop = _nolock) {TLocalisamfile f(num()); *this = rec; return read(f, op, lockop); }
|
||||
virtual int read(const TRectype & rec, word op = _isequal, word lockop = _nolock) {TLocalisamfile f(num()); *this = rec; return read(f, op, lockop); }
|
||||
virtual int read(word op = _isequal, word lockop = _nolock) { TLocalisamfile f(num()); return read(f, op, lockop); }
|
||||
// @cmember Legge il file <p f> con il tipo di record alla posizione desiderata
|
||||
virtual int readat(TBaseisamfile& f, TRecnotype nrec, word lockop = _nolock);
|
||||
|
@ -287,7 +287,7 @@ int TFile_info::open_low(bool exclusive, bool index)
|
||||
_handle = DB_open(_name, exclusive, index);
|
||||
#ifdef DBG
|
||||
else
|
||||
NFCHECK("Can't reopen file %s", (const char*)_name);
|
||||
error_box("You shouldn't reopen file %s", (const char*)_name);
|
||||
#endif
|
||||
int err = NOERR;
|
||||
if (_handle >= 0)
|
||||
@ -327,7 +327,7 @@ int TFile_info::close_low()
|
||||
else
|
||||
{
|
||||
#ifdef DBG
|
||||
NFCHECK("Can't reclose file %s", (const char*)_name);
|
||||
error_box("You shouldn't reclose file %s", (const char*)_name);
|
||||
#endif
|
||||
err = _isnotopen;
|
||||
}
|
||||
@ -343,7 +343,7 @@ int TFile_info::open(bool exclusive, bool index)
|
||||
{
|
||||
#ifdef DBG
|
||||
if (_ref_count > 0)
|
||||
NFCHECK("Can't reopen file %d exclusively", _num);
|
||||
error_box("You shouldn't reopen file %d exclusively", num());
|
||||
#endif
|
||||
close_low();
|
||||
}
|
||||
@ -365,7 +365,7 @@ int TFile_info::close()
|
||||
if (is_open())
|
||||
{
|
||||
// Chiudi fisicamente solo se necessario
|
||||
if (_locked || _exclusive)
|
||||
if (_locked || _exclusive || dir_type() == _extdir)
|
||||
err = close_low();
|
||||
}
|
||||
_locked = _exclusive = FALSE;
|
||||
@ -485,7 +485,7 @@ TFile_info::~TFile_info()
|
||||
}
|
||||
|
||||
|
||||
TFile_info& TFile_manager::fileinfo(TIsam_handle num)
|
||||
TFile_info& TFile_manager::fileinfo(TIsam_handle num) const
|
||||
{
|
||||
TFile_info* i = (TFile_info*)_fileinfo.objptr(num);
|
||||
if (i == NULL && num > 0 && num < LF_EXTERNAL)
|
||||
@ -493,7 +493,7 @@ TFile_info& TFile_manager::fileinfo(TIsam_handle num)
|
||||
TFilename name;
|
||||
i = new TFile_info(num, name);
|
||||
if (i->ok())
|
||||
_fileinfo.add(i, num);
|
||||
((TFile_manager*)this)->_fileinfo.add(i, num);
|
||||
else
|
||||
{
|
||||
delete i;
|
||||
@ -505,13 +505,13 @@ TFile_info& TFile_manager::fileinfo(TIsam_handle num)
|
||||
return *i;
|
||||
}
|
||||
|
||||
TRecord_info& TFile_manager::recinfo(int logicnum)
|
||||
TRecord_info& TFile_manager::recinfo(int logicnum) const
|
||||
{
|
||||
TRecord_info* i = (TRecord_info*)_recinfo.objptr(logicnum);
|
||||
if (i == NULL)
|
||||
{
|
||||
i = new TRecord_info(logicnum);
|
||||
_recinfo.add(i, logicnum);
|
||||
((TFile_manager*)this)->_recinfo.add(i, logicnum);
|
||||
}
|
||||
return *i;
|
||||
}
|
||||
@ -610,11 +610,12 @@ int TFile_manager::close(TIsam_handle& name)
|
||||
{
|
||||
const bool was_open = i->is_open();
|
||||
err = i->close();
|
||||
if (err == NOERR && i->ref_count() == 0)
|
||||
// Se chiuso veramente ... (Per efficienza non chiude sempre)
|
||||
if (err == NOERR && !i->is_open())
|
||||
{
|
||||
if (was_open && !i->is_open())
|
||||
if (was_open)
|
||||
_open_files--;
|
||||
if (name >= LF_EXTERNAL)
|
||||
if (name >= LF_EXTERNAL && i->ref_count() <= 0)
|
||||
{
|
||||
_fileinfo.remove(name);
|
||||
_recinfo.remove(name);
|
||||
@ -629,7 +630,7 @@ TCodeb_handle TFile_manager::get_handle(TIsam_handle name, int key)
|
||||
{
|
||||
TFile_info& i = fileinfo(name);
|
||||
if (i.ref_count() == 0)
|
||||
NFCHECK("Can'use not open file %d", i.num());
|
||||
NFCHECK("Can't use closed file %d", i.num());
|
||||
|
||||
TCodeb_handle handle = i.handle();
|
||||
if (handle < 0)
|
||||
@ -663,7 +664,7 @@ void TFile_manager::unlock_record(TIsam_handle num, TRecnotype rec)
|
||||
}
|
||||
|
||||
|
||||
const RecDes& TFile_manager::get_recdes(int logicnum)
|
||||
const RecDes& TFile_manager::get_recdes(int logicnum) const
|
||||
{
|
||||
const TRecord_info& i = recinfo(logicnum);
|
||||
return i;
|
||||
@ -733,12 +734,19 @@ void TFile_manager::open_all()
|
||||
}
|
||||
}
|
||||
|
||||
const FileDes& TFile_manager::get_filedes(TIsam_handle name)
|
||||
const FileDes& TFile_manager::get_filedes(TIsam_handle id) const
|
||||
{
|
||||
TFile_info& i = fileinfo(name);
|
||||
TFile_info& i = fileinfo(id);
|
||||
return i;
|
||||
}
|
||||
|
||||
const TFilename& TFile_manager::get_filename(TIsam_handle id) const
|
||||
{
|
||||
TFile_info& i = fileinfo(id);
|
||||
return i.pathname();
|
||||
}
|
||||
|
||||
|
||||
TFile_manager::TFile_manager()
|
||||
: _open_files(0)
|
||||
{
|
||||
|
@ -27,8 +27,8 @@ class TFile_manager : public TObject
|
||||
int _open_files, _max_open_files;
|
||||
|
||||
protected:
|
||||
TFile_info& fileinfo(TIsam_handle handle);
|
||||
TRecord_info& recinfo(int logicnum);
|
||||
TFile_info& fileinfo(TIsam_handle handle) const;
|
||||
TRecord_info& recinfo(int logicnum) const;
|
||||
|
||||
bool close_oldest();
|
||||
|
||||
@ -39,8 +39,9 @@ public:
|
||||
void lock_record(TIsam_handle num, TRecnotype rec);
|
||||
void unlock_record(TIsam_handle num, TRecnotype rec);
|
||||
|
||||
const FileDes& get_filedes(TIsam_handle name);
|
||||
const RecDes& get_recdes(int logicnum);
|
||||
const TFilename& get_filename(TIsam_handle num) const;
|
||||
const FileDes& get_filedes(TIsam_handle num) const;
|
||||
const RecDes& get_recdes(int logicnum) const;
|
||||
const RecDes& update_recdes(int logicnum);
|
||||
TDirtype get_dirtype(int logicnum);
|
||||
bool add_recdes(int logicnum, TTrec& rec, TToken_string& keys);
|
||||
@ -143,7 +144,7 @@ public:
|
||||
int get_handle(TIsam_handle name, int key = 0)
|
||||
{ return _manager.get_handle(name, key); }
|
||||
|
||||
const RecDes& get_recdes(int logicnum)
|
||||
const RecDes& get_recdes(int logicnum) const
|
||||
{ return _manager.get_recdes(logicnum); }
|
||||
|
||||
bool add_recdes(int logicnum, TTrec& rec, TToken_string& keys)
|
||||
@ -155,9 +156,12 @@ public:
|
||||
int get_reclen(int logicnum)
|
||||
{ return _manager.get_reclen(logicnum); }
|
||||
|
||||
const FileDes& get_filedes(TIsam_handle name)
|
||||
const FileDes& get_filedes(TIsam_handle name) const
|
||||
{ return _manager.get_filedes(name); }
|
||||
|
||||
const TFilename& get_filename(TIsam_handle name) const
|
||||
{ return _manager.get_filename(name); }
|
||||
|
||||
// @cmember Costruttore
|
||||
TPrefix();
|
||||
// @cmember Distruttore
|
||||
|
@ -118,7 +118,7 @@ void TString::resize(
|
||||
else *s = '\0';
|
||||
|
||||
if (_str)
|
||||
delete _str;
|
||||
delete [] _str;
|
||||
|
||||
_str = s;
|
||||
_size = size;
|
||||
@ -193,7 +193,7 @@ TString::TString() : _str(NULL), _size(0)
|
||||
TString::~TString()
|
||||
{
|
||||
if (_str)
|
||||
delete _str;
|
||||
delete [] _str;
|
||||
}
|
||||
|
||||
char TString::shift(int n)
|
||||
|
Loading…
x
Reference in New Issue
Block a user