55a36762ef
checks.cpp Tolto include windows.h colors.cpp Tolto include windows.h controls.cpp Aggiunto cambiamento del font runtime dei TText_control execp.cpp Tolto include windows.h form.cpp Tolto include windows.h mask.cpp Corretta formattazione di due righe maskfld.cpp Aggiunto messaggio CHECK msksheet.cpp Tolto include windows.h relapp.cpp Tolto include windows.h strings.pp Corretto CHECK della TFixed_string::format() viswin.cpp Tolto include windows.h window.cpp Tolto include windows.h xvtility.cpp Corretto calcolo altezza righe delle maschere git-svn-id: svn://10.65.10.50/trunk@4085 c028cbd2-c16b-5b4b-a496-9718f37d4682
1522 lines
34 KiB
C++
Executable File
1522 lines
34 KiB
C++
Executable File
#include <ctype.h>
|
||
#include <stdio.h>
|
||
#include <stdarg.h>
|
||
#include <stdlib.h>
|
||
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
||
#include <strstrea.h>
|
||
#else
|
||
#include <strstream.h>
|
||
#endif
|
||
|
||
#include <strings.h>
|
||
#include <prefix.h>
|
||
#include <utility.h>
|
||
|
||
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
||
#include <process.h>
|
||
#else
|
||
#include <sys/types.h>
|
||
#include <sys/stat.h>
|
||
#include <unistd.h>
|
||
#endif
|
||
|
||
class TString512 : public TFixed_string
|
||
{
|
||
char _str512[513];
|
||
|
||
public:
|
||
TString512(const char* s = "") : TFixed_string(_str512, 513) { set(s); }
|
||
TString512(const TString& s) : TFixed_string(_str512, 513) { set(s); }
|
||
const TString& operator =(const char* s);
|
||
const TString& operator =(const TString& s) { return operator =((const char*)s); }
|
||
void strncpy(const char* s, int n);
|
||
};
|
||
|
||
const TString& TString512::operator =(const char* s)
|
||
{
|
||
#ifdef FOXPRO
|
||
if (_size == 0)
|
||
{
|
||
_str = _str512;
|
||
_size = 512;
|
||
}
|
||
#endif
|
||
return set(s);
|
||
}
|
||
|
||
void TString512::strncpy(const char* s, int n)
|
||
{
|
||
#ifdef FOXPRO
|
||
if (_size == 0)
|
||
{
|
||
_str = _str512;
|
||
_size = 512;
|
||
}
|
||
#endif
|
||
TFixed_string::strncpy(s, n);
|
||
}
|
||
|
||
|
||
HIDDEN TString512 spark;
|
||
|
||
inline bool is_space(char c)
|
||
{ return c >= '\t' && c <= ' '; }
|
||
|
||
// Certified 99%
|
||
// @doc EXTERNAL
|
||
//
|
||
// @mfunc Cambia la dimensione della stringa eventualmente preservandone il contenuto iniziale
|
||
void TString::resize(
|
||
int size, // @parm Nuova dimensione della stringa
|
||
bool cpy) // @parm Se TRUE mantiene il contenuto della stringa e alloca
|
||
// nuovo spazio
|
||
|
||
// @comm Non funziona con le stringhe static e per valori negativi di <p size>
|
||
{
|
||
char* s = new char[size+1];
|
||
if (cpy && _str) strcpy(s, _str);
|
||
else *s = '\0';
|
||
|
||
if (_str)
|
||
delete _str;
|
||
|
||
_str = s;
|
||
_size = size;
|
||
}
|
||
|
||
// Certified 99% (uses resize)
|
||
// @doc EXTERNAL
|
||
//
|
||
// @mfunc Inizializza con la stringa puntata da char* di lunghezza size
|
||
// (usa <mf TString::resize>)
|
||
TString& TString::set(
|
||
const char* s) // @parm Stringa da inizializzare
|
||
|
||
// @rdesc Ritorna l'indirizzo della stringa inizializzata
|
||
{
|
||
if (s == NULL) s = "";
|
||
const int sz = *s ? strlen(s) : 7;
|
||
if (sz > size()) resize(sz, FALSE);
|
||
strcpy(_str, s);
|
||
|
||
return *this;
|
||
}
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Espande la stringa per altri caratteri
|
||
int TString::make_room(
|
||
int s) // @parm Numero di caratteri di cui si cuole aspandere la stringa
|
||
|
||
// @comm La stringa viene espansa di un numero di caratteri doppio (per sicurezza) di
|
||
// quello passato per parametro
|
||
//
|
||
// @rdesc Ritorna il numero di caratteri della stringa prima della chiamata
|
||
{
|
||
const int lun = len();
|
||
const int spare = size() - lun;
|
||
if (spare < s)
|
||
resize(size() + 2*s, TRUE);
|
||
return lun;
|
||
}
|
||
|
||
TString::TString(const char* s) : _str(NULL), _size(0)
|
||
{ set(s); }
|
||
|
||
TString::TString(const TString& s) : _str(NULL), _size(0)
|
||
{ set(s); }
|
||
|
||
TString::TString(int size) : _str(NULL), _size(0)
|
||
{ resize(size, FALSE); }
|
||
|
||
TString::TString() : _str(NULL), _size(0)
|
||
{ resize(7, FALSE); }
|
||
|
||
TString::~TString()
|
||
{
|
||
if (_str)
|
||
delete _str;
|
||
}
|
||
|
||
TString& TString::operator <<(const char* s)
|
||
{
|
||
if (s && *s)
|
||
{
|
||
const int pos = make_room(strlen(s));
|
||
strcpy(&_str[pos], s);
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
TString& TString::operator <<(char c)
|
||
{
|
||
int pos = make_room(1);
|
||
_str[pos++] = c;
|
||
_str[pos] = '\0';
|
||
return *this;
|
||
}
|
||
|
||
|
||
TString& TString::operator <<(int n)
|
||
{
|
||
char s[16];
|
||
sprintf(s, "%d", n);
|
||
return operator <<(s);
|
||
}
|
||
|
||
|
||
TString& TString::operator <<(long n)
|
||
{
|
||
char s[16];
|
||
sprintf(s, "%ld", n);
|
||
return operator <<(s);
|
||
}
|
||
|
||
TString& TString::operator <<(double n)
|
||
{
|
||
char s[32];
|
||
sprintf(s, "%lf", n);
|
||
return operator <<(s);
|
||
}
|
||
|
||
// Appends an object to the string
|
||
// Certified 50%
|
||
// The object should be completely storable in spark
|
||
TString& TString::operator <<(const TObject& obj)
|
||
{
|
||
ostrstream out((char*)(const char*)spark, spark.size());
|
||
obj.print_on(out);
|
||
out << ends;
|
||
return operator <<(spark);
|
||
}
|
||
|
||
|
||
TString& TString::operator <<(const TString& str)
|
||
{ return operator <<(str._str); }
|
||
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Elimina tutti i caratteri contenuti in <p k>
|
||
TString& TString::strip(
|
||
const char* k) // @parm Stringa da controllarne l'esitenza nell'oggetto
|
||
|
||
{
|
||
int j = 0;
|
||
for (int i = 0; _str[i]; i++)
|
||
{
|
||
char c = _str[i];
|
||
if (strchr(k, c) == NULL) _str[j++] = c;
|
||
}
|
||
return cut(j);
|
||
}
|
||
|
||
|
||
bool TString::blank() const
|
||
{
|
||
for (int i = 0; _str[i]; i++)
|
||
if (!is_space(_str[i]))
|
||
return FALSE;
|
||
return TRUE;
|
||
}
|
||
|
||
TString& TString::strip_spaces()
|
||
{
|
||
char instring = '\0';
|
||
int j = 0;
|
||
for (int i = 0; _str[i]; i++)
|
||
{
|
||
char c = _str[i];
|
||
if (is_space(c) && !instring) continue;
|
||
if (c == '"' || c == '\'')
|
||
{
|
||
if (instring == c) instring = '\0';
|
||
else
|
||
if (instring == '\0') instring = c;
|
||
}
|
||
_str[j++] = c;
|
||
}
|
||
_str[j] = '\0';
|
||
return *this;
|
||
}
|
||
|
||
TString& TString::strip_d_spaces()
|
||
{
|
||
int j = 0;
|
||
bool spc = FALSE;
|
||
for (int i = 0; _str[i]; i++)
|
||
{
|
||
char c = _str[i];
|
||
if (is_space(c))
|
||
if (spc)
|
||
continue;
|
||
else
|
||
spc = TRUE;
|
||
else
|
||
if (spc) spc = FALSE;
|
||
_str[j++] = c;
|
||
}
|
||
_str[j] = '\0';
|
||
return *this;
|
||
}
|
||
|
||
// Certified 100%
|
||
const char* TString::class_name() const
|
||
{ return "String"; }
|
||
|
||
// Certified 100%
|
||
word TString::class_id() const
|
||
{ return CLASS_STRING; }
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Duplica una stringa
|
||
TObject* TString::dup() const
|
||
|
||
// @comm Alloca nuovo spazio per duplicare la stringa
|
||
//
|
||
// @rdesc Ritorna il puntatore alla stringa duplicata
|
||
{
|
||
TString* s = new TString(size());
|
||
s->set(_str);
|
||
return s;
|
||
}
|
||
|
||
|
||
void TString::read_from(istream& in)
|
||
{
|
||
in >> __tmp_string;
|
||
set(__tmp_string);
|
||
}
|
||
|
||
|
||
// Certified 100%
|
||
void TString::print_on(ostream& out) const
|
||
{ out << _str; }
|
||
|
||
|
||
// Certified 100%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna la posizione del carattere o della stringa nell'oggetto TString
|
||
//
|
||
// @rdesc Ritorna i seguneti parametri:
|
||
//
|
||
// @flag <gt>= 0 | Posizione dell'elemento nella stringa
|
||
// @flag -1 | L'elemento non e' stato trovato
|
||
int TString::find(
|
||
char c, // @parm Carattere da cercare
|
||
int from) const // @parm Posizione da cui iniziare la ricerca
|
||
// @parm const char* | s | Stringa da cercare
|
||
|
||
// @syntax find(char c, int from);
|
||
// @syntax find(const char* s, int from);
|
||
//
|
||
// @comm Cerca nella stringa, dalla posizione indicata, l'elemento passato.
|
||
// Nel caso <p from> sia maggiore della lunghezza della stringa manda
|
||
// un messaggio di errore
|
||
{
|
||
CHECKD(from <= len(), "Trying to find past end of string", from);
|
||
const char* p = strchr(_str + from, c);
|
||
return p ? int(p - _str) : -1;
|
||
}
|
||
|
||
|
||
#if XVT_OS == XVT_OS_SCOUNIX
|
||
HIDDEN char* strstr(const char* string1, const char* string2)
|
||
{
|
||
const int len = strlen(string2);
|
||
while (*string1)
|
||
{
|
||
if (strncmp(string1, string2, len) == 0) return (char*) string1;
|
||
string1++;
|
||
}
|
||
return NULL;
|
||
}
|
||
#endif
|
||
|
||
|
||
// Certified 100%
|
||
int TString::find(const char* s, int from) const
|
||
{
|
||
CHECKD(from <= len(), "Trying to find past end of string", from);
|
||
const char* p = strstr(_str + from, s);
|
||
return p ? int(p - _str) : -1;
|
||
}
|
||
|
||
int TString::replace(char find_char, char replace_char)
|
||
{
|
||
const int l = len();
|
||
int n = 0;
|
||
for (int i = 0; i < l; i++)
|
||
if (_str[i] == find_char)
|
||
{
|
||
_str[i] = replace_char;
|
||
n++;
|
||
}
|
||
return n;
|
||
}
|
||
|
||
|
||
// Certified 99%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna l'oggetto TString composto dai <p count> caratteri da sinistra
|
||
const TString& TString::left(
|
||
int count) const // @parm Indica fino quale carattere restituire la stringa
|
||
|
||
// @rdesc Ritorna l'indirizzo della stringa contenente i <p count> caratteri da sinistra
|
||
{
|
||
spark.strncpy(_str, count);
|
||
return spark;
|
||
}
|
||
|
||
// Certified 99%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna l'oggetto TString composto dai <p count> caratteri da destra
|
||
const TString& TString::right(
|
||
int count) const // @parm Indica da quale carattere restituire la stringa
|
||
|
||
// @rdesc Ritorna l'indirizzo della stringa contenente i <p count> caratteri da destra
|
||
{
|
||
int from = len()-count;
|
||
if (from < 0) from = 0;
|
||
spark = _str + from;
|
||
return spark;
|
||
}
|
||
|
||
|
||
// Certified 100%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna l'oggetto TString composto dai <p count> caratteri a partire
|
||
// da <p from>
|
||
const TString& TString::mid(
|
||
int from, // @parm Posizione dalla quale partire per l'estrazione
|
||
int count) const // @parm Numero di caratteri da estrarre
|
||
|
||
// @rdesc Ritorna l'indirizzo della stringa contenente i <p count> cartteri da <p from>
|
||
{
|
||
const int l = len();
|
||
|
||
#ifdef DBG
|
||
if (from < 0)
|
||
{
|
||
NFCHECK("Ivalid MID parameter: from = %d", from);
|
||
from = 0;
|
||
}
|
||
#endif
|
||
|
||
if (from > l) from = l;
|
||
if (count < 0) count = l-from;
|
||
|
||
spark.strncpy(&_str[from], count);
|
||
return spark;
|
||
}
|
||
|
||
|
||
// Certified 100%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna la stringa da <p from> a <p to> (escluso)
|
||
const TString& TString::sub(
|
||
int from, // @parm Posizione dalla quale estrarre la stringa
|
||
int to) const // @parm Posizione fin alla quale estrarre la stringa
|
||
|
||
// @rdesc Ritorna l'indirizzo della stringa da i <p from> a <p to>
|
||
{
|
||
const int count = to-from;
|
||
return mid(from, count);
|
||
}
|
||
|
||
// Certified 100%
|
||
TString& TString::cut(int n)
|
||
{
|
||
CHECKD(n >= 0, "Invalid TString::cut position ", n);
|
||
if (n <= _size)
|
||
_str[n] = '\0';
|
||
else
|
||
NFCHECK("Hai tagliato a %d la stringa '%s' lunga %d(%d)",
|
||
n, _str, len(), size());
|
||
return *this;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Elimina gli spazi da sinistra o i primi n caratteri (da sinistra).
|
||
TString& TString::ltrim(
|
||
int count) // @parm Indica il numero di caratteri da eliminare.
|
||
// Se uguale a 0 elimina tutti gli spazi da sinistra
|
||
|
||
// @comm Controlla se <p count> e' 0. Se non lo <20> ritorna l'indirizzo della
|
||
// stringa a partire dal <p count>-esimo carattere; altrimenti controlla
|
||
// se i primi caratteri sono spazi e li elimina fino a che non trova
|
||
// un carattere diverso da ' '
|
||
//
|
||
// @xref <mf TString::rtrim>
|
||
{
|
||
const char* s;
|
||
|
||
if (count > 0)
|
||
{
|
||
if (count >= len()) return cut(0);
|
||
s = &_str[count];
|
||
}
|
||
else for (s = _str; *s && is_space(*s); s++);
|
||
|
||
if (s != _str) strcpy(_str, s);
|
||
return *this;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Elimina gli spazi da destra o i primi n caratteri (da destra).
|
||
TString& TString::rtrim(
|
||
int count) // @parm Indica il numero di caratteri da eliminare.
|
||
// Se uguale a 0 elimina tutti gli spazi da destra
|
||
|
||
// @comm Controlla se <p count> e' 0. Se non lo <20> pone il fine stringa alla
|
||
// posizione <p count>; altrimenti controlla se gli ultimi caratteri
|
||
// sono spazi e li elimina fino a che non trova un carattere diverso da ' '
|
||
//
|
||
// @xref <mf TString::ltrim>
|
||
{
|
||
if (count > 0)
|
||
{
|
||
int i = len() - count;
|
||
if (i < 0) i = 0;
|
||
cut(i);
|
||
}
|
||
else
|
||
{
|
||
char* good = _str-1;
|
||
for (char* s = _str; *s; s++)
|
||
if (!is_space(*s)) good = s;
|
||
*(good+1) = '\0';
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
TString& TString::trim()
|
||
{
|
||
char* last = _str;
|
||
|
||
// Salta spazi iniziali
|
||
for (const char* s = _str; *s && is_space(*s); s++);
|
||
|
||
// Copia stringa
|
||
if (s > _str)
|
||
{
|
||
for(char* c = _str; *s; s++)
|
||
{
|
||
*c++ = *s;
|
||
if (!is_space(*s)) last = c;
|
||
}
|
||
// Elimina spazi finali
|
||
*last = '\0';
|
||
}
|
||
else rtrim();
|
||
|
||
return *this;
|
||
}
|
||
|
||
// Certified 50%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Compara due stringhe (o i primi <p max> caratteri)
|
||
//
|
||
// @rdesc Ritrna i seguenti valori:
|
||
//
|
||
// @flag 0 | Se le stringhe sono uguali
|
||
// @flag <gt><lt>0 | Se le stringhe sono diverse
|
||
int TString::compare(
|
||
const char* s, // @parm Stringa da comparare
|
||
int max, // @parm Numero di caratteri da conforntare (default tutta la stringa)
|
||
bool ignorecase) const // @parm Ignorare la differenza maiuscolo/minuscolo (default FALSE)
|
||
{
|
||
int res;
|
||
if (ignorecase)
|
||
{
|
||
if (max < 0)
|
||
res = stricmp(_str, s);
|
||
else
|
||
{
|
||
for (int i = 0; i < max; i++)
|
||
{
|
||
res = toupper(_str[i]) - toupper(s[i]);
|
||
if (res) break;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
res = max < 0 ? strcmp(_str, s) : strncmp(_str, s, max);
|
||
|
||
return res;
|
||
}
|
||
|
||
// Certified 100%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Riempe la stringa con n caratteri c
|
||
//
|
||
// @rdesc Ritorna l'indirizzo dell stringa
|
||
TString& TString::fill(
|
||
char c, // @parm Caratteri con cui riempire la stringa
|
||
int n) // @parm Numero di caratteri da inserire nella stringa
|
||
// (default per tutta la lungehzza)
|
||
|
||
// @comm Se il paramatro <p n> e' maggiore della dimensione della stringa, la
|
||
// stessa viene ridimensionata (chaimata alla <mf TString::resize>).
|
||
// <nl>Nel caso non venga passato il parametro <p n> la stringa viene
|
||
// riempita col carattere <p c> per tutta la lunghezza.
|
||
|
||
{
|
||
if (n < 0) n = size(); else
|
||
if (n > size()) resize(n, FALSE);
|
||
memset(_str, c, n);
|
||
_str[n] = '\0';
|
||
return *this;
|
||
}
|
||
|
||
// Certified 100%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Giustifica l'oggetto stringa a destra
|
||
TString& TString::right_just(
|
||
int n, // @parm Numero di colonne alla quali allineare (defualt larghezza della stringa)
|
||
char c) // @parm Carattere di riempimento (default ' ')
|
||
|
||
// @comm Nel caso venga passato un carattere in <p c>, questo viene inserito
|
||
// nel resto della stringa (a sinistra della stringa stessa)
|
||
//
|
||
// @xref <mf TString::left_just> <mf TString::center_just>
|
||
{
|
||
if (n < 0) n = size();
|
||
trim();
|
||
spark = _str;
|
||
fill(c, n);
|
||
overwrite(spark, n-spark.len());
|
||
|
||
return *this;
|
||
}
|
||
|
||
// Certified 100%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Centra l'oggetto stringa
|
||
TString& TString::center_just(
|
||
int n, // @parm Numero di colonne alla quali allineare (defualt larghezza della stringa)
|
||
char c) // @parm Carattere di riempimento (default ' ')
|
||
|
||
// @comm Nel caso venga passato un carattere in <p c>, questo viene inserito
|
||
// nel resto della stringa (a destra e a sinistra della stringa stessa)
|
||
//
|
||
// @xref <mf TString::left_just> <mf TString::right_just>
|
||
{
|
||
if (n < 0) n = size();
|
||
trim();
|
||
spark = _str;
|
||
fill(c, n);
|
||
const int p = (n-spark.len()) >> 1;
|
||
overwrite(spark, p);
|
||
|
||
return *this;
|
||
}
|
||
|
||
// Certified 100%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Giustifica l'oggetto stringa a sinistra
|
||
TString& TString::left_just(
|
||
int n, // @parm Numero di colonne alla quali allineare (defualt larghezza della stringa)
|
||
char c) // @parm Carattere di riempimento (default ' ')
|
||
|
||
// @comm Nel caso venga passato un carattere in <p c>, questo viene inserito
|
||
// nel resto della stringa (a destra della stringa stessa)
|
||
//
|
||
// @xref <mf TString::right_just> <mf TString::center_just>
|
||
{
|
||
if (n < 0) n = size();
|
||
trim();
|
||
spark = _str;
|
||
fill(c, n);
|
||
overwrite(spark, 0);
|
||
|
||
return *this;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Formatta una stringa usando il formato dato da <p pic>
|
||
TString& TString::picture(
|
||
const char* pic, // @parm Formato della stringa
|
||
const char* s) // @parm Stringa da formattare
|
||
{
|
||
if (pic == NULL || *pic == '\0')
|
||
return set(s);
|
||
|
||
set(pic);
|
||
|
||
int l = strlen(s)-1; // Prossimo carattere da sostituire a # o @
|
||
|
||
for (int i = len()-1; i >= 0; i--)
|
||
{
|
||
const char k = pic[i];
|
||
if (k == '#') _str[i] = (l >= 0) ? s[l--] : ' ';
|
||
else if (k == '@') _str[i] = (l >= 0) ? s[l--] : '0';
|
||
else if (k == '^') { _str[i] = ' '; l--; }
|
||
}
|
||
|
||
return *this;
|
||
}
|
||
|
||
// Certified 90% (spark size limited)
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Manda un output formattato alla stringa oggetto
|
||
TString& TString::format(
|
||
const char* fmt, // @parm Stringa da formattare
|
||
...) // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
|
||
|
||
// @comm Funziona come la funzione "sprintf" standard del C e ritorna la
|
||
// stringa formattata con i parametri passati.
|
||
{
|
||
va_list pars;
|
||
va_start(pars, fmt);
|
||
const int tot = vsprintf((char*)(const char*)spark, fmt, pars);
|
||
va_end(pars);
|
||
|
||
CHECK(tot >= 0 && tot < spark.size(), "Ue'! Quanto scrivi?");
|
||
if (tot > size()) resize(tot, FALSE);
|
||
strcpy(_str, spark);
|
||
|
||
return *this;
|
||
}
|
||
|
||
// Certified 99%
|
||
char* TString::get_buffer(int min_size)
|
||
{
|
||
if (min_size > size())
|
||
resize(min_size, TRUE);
|
||
return _str;
|
||
}
|
||
|
||
// Certified 100%
|
||
TString& TString::upper()
|
||
{
|
||
for (char* s = _str; *s; s++) *s = toupper(*s);
|
||
return *this;
|
||
}
|
||
|
||
// Certified 100%
|
||
TString& TString::lower()
|
||
{
|
||
for (char* s = _str; *s; s++) *s = tolower(*s);
|
||
return *this;
|
||
}
|
||
|
||
// Certified 50%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Permette di ttrovare il plurale di una stringa
|
||
TString& TString::add_plural(
|
||
long num, // @parm Numero di elementi per sapere la desineneza
|
||
const char* name) // @parm Stringa da modificare
|
||
|
||
// @comm A seconda del numero passato in <p num> permette di stabilire la
|
||
// corretta sintassi della stringa <p name> da scrivere nei messaggi
|
||
// dati all'utente. Nel caso <p num> sia 0 allora ritorna "nessuno".
|
||
{
|
||
const TFixed_string n(name);
|
||
const char last = n[n.len()-1];
|
||
|
||
if (num < 1)
|
||
{
|
||
*this << "nessun";
|
||
if (toupper(last) == 'A' || toupper(n[0]) == 'Z' ||
|
||
toupper(n[0]) == 'S' && strchr("aeiouAEIOU", n[1]) == NULL)
|
||
*this << tolower(last);
|
||
*this << ' ' << name;
|
||
}
|
||
else
|
||
{
|
||
*this << num << ' ' << name;
|
||
if (num > 1)
|
||
_str[len()-1] = (last == 'a') ? 'e' : 'i';
|
||
}
|
||
|
||
return *this;
|
||
}
|
||
|
||
// Certified 90%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Sovrascrive la stringa <p s> dalla posizione <p pos>
|
||
TString& TString::overwrite(
|
||
const char* s, // @parm Stringa da inserire
|
||
int pos) // @parm Posizione dalla quale iniziare a sovrascrivere
|
||
|
||
// @comm Sovrascrive dalla posizione <p pos> fino alla lunghezza di <p s> l'oggetto
|
||
// stringa. Nel caso la dimensione sia maggiore l'oggetto viene riallocato
|
||
// dinamicamente
|
||
//
|
||
// @xref <mf TString::insert>
|
||
{
|
||
const int l = len();
|
||
if (pos < 0) pos = l;
|
||
const int max = pos+strlen(s);
|
||
if (max > size()) resize(max, TRUE); // resize needed?
|
||
|
||
const bool over = max > l; // beyond end of string?
|
||
for (int i = l; i < pos; i++) _str[i] = ' '; // space padding
|
||
for (; *s; s++) _str[pos++] = *s; // write
|
||
if (over) _str[pos] = '\0'; // end of string
|
||
|
||
return *this;
|
||
}
|
||
|
||
|
||
// Certified 90%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Inserisce la stringa s dalla posizione pos
|
||
TString& TString::insert(
|
||
const char* s, // @parm Stringa da inserire
|
||
int pos) // @parm Posizione dalla quale iniziare a inserire
|
||
|
||
// @comm Inserisce dalla posizione <p pos> la stringa <p s> nell'oggetto
|
||
// stringa. Nel caso la dimensione sia maggiore l'oggetto viene riallocato
|
||
// dinamicamente
|
||
//
|
||
// @xref <mf TString::overwrite>
|
||
{
|
||
if (s && *s)
|
||
{
|
||
const int l = strlen(s);
|
||
make_room(l);
|
||
mid(pos); // Scrivi in spark la stringa da pos in poi
|
||
overwrite(s, pos); // Aggiungi s
|
||
strcpy(&_str[pos+l], spark); // Aggiungi spark
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
// Certified 90%
|
||
word TString::hash() const
|
||
{
|
||
/*
|
||
// Villa's megasmart hash function
|
||
word h = 0x0000;
|
||
for (int i = 0; _str[i]; i++)
|
||
h ^= (i & 0x1) ? (_str[i] << 8) : _str[i];
|
||
*/
|
||
// Peter Weinberger's (PJW) generic hashing
|
||
word h = 0;
|
||
for (const char* s = _str; *s; s++)
|
||
{
|
||
h = (h << 2) + *s;
|
||
const word i = h & 0xC000;
|
||
if (i) h = (h ^ (i >> 12)) & 0x3FFF;
|
||
}
|
||
return h;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TFixed_string
|
||
///////////////////////////////////////////////////////////
|
||
|
||
// Certified 100%
|
||
TFixed_string::TFixed_string(const char* str, int size)
|
||
: TString((char*)str, (size <= 0) ? strlen(str) : size-1)
|
||
{
|
||
CHECK(str, "NULL buffer for fixed string");
|
||
if (size > 0 && memchr(str, '\0', size) == NULL)
|
||
cut(0);
|
||
}
|
||
|
||
|
||
// Certified 100%
|
||
TFixed_string::~TFixed_string()
|
||
{ _str = NULL; } // Impedisce la deallocazione
|
||
|
||
|
||
// Certified 100%
|
||
void TFixed_string::resize(int size, bool)
|
||
{
|
||
#ifdef DBG
|
||
fatal_box("Impossibile ridimensionare una stringa fissa da %d a %d caratteri:\n'%s'",
|
||
_size, size, _str);
|
||
#endif
|
||
}
|
||
|
||
|
||
// Certified 99% (s != NULL)
|
||
void TFixed_string::strncpy(const char* s, int n)
|
||
{
|
||
CHECKD(n <= _size, "Fixed string can't be strncpyed: lenght ", n);
|
||
for (int i = 0; *s && i < n; i++) _str[i] = *s++;
|
||
_str[i] = '\0';
|
||
}
|
||
|
||
// Certified 99%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Manda un output formattato alla stringa oggetto
|
||
TString& TFixed_string::format(
|
||
const char* fmt, // @parm Formato della stringa
|
||
...) // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
|
||
|
||
// @comm Funziona come la funzione "sprintf" standard del C e ritorna la
|
||
// stringa formattata con i parametri passati.
|
||
// <nl>E' piu' efficiente di <mf TString::format> poiche' non usa spark
|
||
{
|
||
va_list pars;
|
||
va_start(pars, fmt);
|
||
const int tot = vsprintf(_str, fmt, pars);
|
||
va_end(pars);
|
||
CHECK(tot >= 0 && tot <= size(), "Ue'! Quanto scrivi con 'sta format?");
|
||
return *this;
|
||
}
|
||
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Filename
|
||
///////////////////////////////////////////////////////////
|
||
|
||
const char SLASH =
|
||
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
||
'\\';
|
||
#else
|
||
'/';
|
||
#endif
|
||
|
||
// Certified 90%
|
||
const char* TFilename::ext() const
|
||
{
|
||
const char* d = strrchr(name(), '.');
|
||
if (d && is_not_slash(*(++d))) return d;
|
||
return "";
|
||
}
|
||
|
||
// Certified 90%
|
||
void TFilename::ext(const char* e)
|
||
{
|
||
char* d = strrchr(name(), '.');
|
||
if (d && is_not_slash(*(d+1))) *d = '\0';
|
||
|
||
if (*e && *e != '.') *this << ".";
|
||
*this << e;
|
||
}
|
||
|
||
|
||
// Certified 90%
|
||
const char* TFilename::name() const
|
||
{
|
||
for (int i = strlen(_str)-1; i >= 0; i--)
|
||
if (_str[i] == '/' || _str[i] == '\\' || _str[i] == ':')
|
||
break;
|
||
|
||
return &_str[i+1];
|
||
}
|
||
|
||
// Certified 90%
|
||
const char* TFilename::path() const
|
||
{
|
||
for (int i = strlen(_str)-1; i >= 0; i--)
|
||
if (_str[i] == '/' || _str[i] == '\\' || _str[i] == ':')
|
||
break;
|
||
|
||
spark.strncpy(_str, i+1);
|
||
return spark;
|
||
}
|
||
|
||
|
||
TFilename& TFilename::add(const char* n)
|
||
{
|
||
if (not_empty() && is_not_slash(_str[len()-1]))
|
||
*this << SLASH;
|
||
*this << n;
|
||
return *this;
|
||
}
|
||
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Controlla il formato del nome del file
|
||
//
|
||
// @rdesc Ritorna i seguenti valori
|
||
//
|
||
// @flag TRUE | Se il nome del file e' sintatticamente corretto
|
||
// @flag FALSE | Se il nome del file non e' sintatticamente corretto
|
||
bool TFilename::ok() const
|
||
|
||
// @comm Controlla tutti i casi per cui un nome di file puo' non essere valido.
|
||
// <nl>Nel caso si lavori in Windows controlla anche che il nome del
|
||
// disco sia corretto.
|
||
{
|
||
const int l = len();
|
||
|
||
int len = 0; // lunghezza ultima sottostringa
|
||
bool ext = FALSE; // trovata estensione
|
||
|
||
for (int c = 0; c < l; c++)
|
||
{
|
||
switch(_str[c])
|
||
{
|
||
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
||
case ':':
|
||
if (c != 1 || !isalpha(_str[0])) return FALSE; // Nome disco errato
|
||
len = 0;
|
||
break;
|
||
case '\\':
|
||
#endif
|
||
case '/':
|
||
if (ext) return FALSE; // Slash dopo estensione
|
||
if (len > 8) return FALSE; // Nome troppo lungo
|
||
if (!isalnum(_str[++c])) return FALSE;
|
||
len = 1;
|
||
break;
|
||
case '.':
|
||
if (len == 0 || ext) return FALSE; // Nome nullo o Doppia estensione
|
||
ext = TRUE;
|
||
len = 0;
|
||
c++;
|
||
default:
|
||
if (isalnum(_str[c])) len++;
|
||
else return FALSE;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (ext && len > 3)
|
||
return FALSE;
|
||
|
||
return len > 0 && len < 9;
|
||
}
|
||
|
||
// Certified 70%
|
||
const TFilename& TFilename::tempdir()
|
||
{
|
||
static TFilename _tempdir;
|
||
const bool create = _tempdir.empty() || user().compare(_tempdir.right(user().len()), -1, TRUE);
|
||
|
||
if (create)
|
||
{
|
||
const char* dirpref = getenv("TEMP");
|
||
if (dirpref == NULL || *dirpref == '\0') dirpref = getenv("TMP");
|
||
if (dirpref == NULL || *dirpref == '\0')
|
||
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
||
dirpref = "\\tmp";
|
||
#else
|
||
dirpref = "/tmp";
|
||
#endif
|
||
_tempdir = dirpref;
|
||
|
||
const int last = len()-1;
|
||
if (!is_not_slash(_str[last]))
|
||
_tempdir.cut(last);
|
||
|
||
bool ok = TRUE;
|
||
|
||
_tempdir.lower();
|
||
if (!fexist(_tempdir))
|
||
ok = make_dir(_tempdir);
|
||
|
||
if (ok)
|
||
{
|
||
TString16 theuser(user());
|
||
|
||
if (theuser.empty())
|
||
theuser = "prassi";
|
||
theuser.lower();
|
||
if (theuser.not_empty() && _tempdir.find(theuser) != _tempdir.len() - theuser.len())
|
||
_tempdir << SLASH << theuser;
|
||
_tempdir.lower();
|
||
if (!fexist(_tempdir))
|
||
ok = make_dir(_tempdir);
|
||
}
|
||
|
||
if (!ok)
|
||
fatal_box("Impossibile creare la directory '%s' per i file temporanei", (const char*)_tempdir);
|
||
|
||
_tempdir.insert("TMP=", 0);
|
||
putenv(_tempdir);
|
||
}
|
||
|
||
set(_tempdir.mid(4));
|
||
return *this;
|
||
}
|
||
|
||
// Certified 50%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Genera il nome di un file temporaneo
|
||
const TFilename& TFilename::temp(
|
||
const char* prefix) // @parm Eventuale prefisso da assegnare al file temporaneo
|
||
|
||
// @comm Nel generare il nome del file controlla se esistone dei caratteri jolly
|
||
// e li elimina.
|
||
{
|
||
tempdir();
|
||
|
||
if (prefix && *prefix)
|
||
{
|
||
set(prefix); // Copia prefisso e ...
|
||
strip("$#*?."); // ... toglie caratteri jolly
|
||
|
||
const TFixed_string f(prefix);
|
||
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
||
if (f.find("$$") != -1)
|
||
{
|
||
char pid[8];
|
||
sprintf(pid, "%d", getpid());
|
||
pid[3] = '\0';
|
||
*this << pid;
|
||
}
|
||
#else
|
||
if (f.find("$$") != -1) *this << getpid();
|
||
if (f.find("##") != -1) *this << getuid();
|
||
#endif
|
||
}
|
||
else cut(0);
|
||
|
||
char* t = tempnam(NULL, (char*)_str);
|
||
|
||
CHECK(t != NULL, "Can't execute tempnam");
|
||
set(t);
|
||
free(t);
|
||
|
||
#ifdef DBG
|
||
if (fexist(_str))
|
||
fatal_box("Il file '%s' esiste gia'", _str);
|
||
#endif
|
||
|
||
return *this;
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Token string
|
||
///////////////////////////////////////////////////////////
|
||
|
||
// Certified 100%
|
||
TToken_string::~TToken_string()
|
||
{
|
||
}
|
||
|
||
// Certified 100%
|
||
TToken_string::TToken_string(const char* s, char separator)
|
||
: TString(s), _separator(separator)
|
||
{
|
||
CHECK(_separator, "NULL TToken_string separator");
|
||
restart();
|
||
}
|
||
|
||
// Certified 100%
|
||
TToken_string::TToken_string(int n, char separator)
|
||
: TString(n), _separator(separator), _last(-1)
|
||
{
|
||
CHECK(_separator, "NULL TToken_string separator");
|
||
}
|
||
|
||
// Certified 100%
|
||
TToken_string::TToken_string(const TToken_string& s)
|
||
: TString(s), _separator(s._separator), _last(s._last)
|
||
{
|
||
CHECK(_separator, "NULL TToken_string separator");
|
||
}
|
||
|
||
void TToken_string::separator(char s)
|
||
{
|
||
CHECK(s, "NULL TToken_string separator");
|
||
_separator = s;
|
||
}
|
||
|
||
|
||
// Certified 100%
|
||
TObject* TToken_string::dup() const
|
||
{
|
||
return new TToken_string(_str, _separator);
|
||
}
|
||
|
||
// Certified 90%
|
||
const char* TToken_string::get()
|
||
{
|
||
CHECK(_separator, "Corrupted TToken_string: NULL separator");
|
||
|
||
if (_last < 0) return NULL;
|
||
|
||
const int start = _last;
|
||
|
||
if (_str[start] == '\0')
|
||
{
|
||
_last = -1;
|
||
return NULL;
|
||
}
|
||
else
|
||
if (_str[start] == _separator)
|
||
{
|
||
_last = start+1;
|
||
}
|
||
else
|
||
{
|
||
const int k = find(_separator, start);
|
||
_last = (k >= 0) ? k+1 : -1;
|
||
return sub(start, k);
|
||
}
|
||
return "";
|
||
}
|
||
|
||
// Certified 50%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna un Token
|
||
//
|
||
// @rdesc Ritorne la stringa identificata dal Token passato come parametro <p n>
|
||
const char* TToken_string::get(
|
||
int n) // @parm Token da ritornare (-1 = prossimo, -2 = ultimo, n = n-simo)
|
||
|
||
// @syntax const char* get(int n);
|
||
// @syntax const char* get();
|
||
//
|
||
// @comm Se non viene passato il parametro <p n> ritorna il prossimo Token
|
||
// (come se <p n> == -1)
|
||
//
|
||
// @xref <mf TToken_string::get_char>
|
||
{
|
||
CHECK(_separator, "Corrupted TToken_string: NULL separator");
|
||
|
||
if (n < 0)
|
||
{
|
||
if (n == -2)
|
||
{
|
||
const char* sep = strrchr(_str, _separator);
|
||
_last = -1;
|
||
return sep ? sep+1 : _str;
|
||
}
|
||
else return get();
|
||
}
|
||
int sep = 0;
|
||
for (const char* s = _str; sep < n && *s; s++)
|
||
if (*s == _separator) sep++;
|
||
|
||
if (sep >= n)
|
||
{
|
||
char* p = strchr(s, _separator);
|
||
if (p == NULL)
|
||
{
|
||
spark = s;
|
||
_last = -1;
|
||
}
|
||
else
|
||
{
|
||
*p = '\0';
|
||
spark = s;
|
||
*p = _separator;
|
||
_last = (int)((const char*)p - _str) + 1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_last = -1;
|
||
return NULL;
|
||
}
|
||
|
||
return spark;
|
||
}
|
||
|
||
|
||
// Certified 99%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Ritorna un carattere
|
||
//
|
||
// @rdesc Ritorna il primo carattere del Token richiesto
|
||
char TToken_string::get_char(
|
||
int n) // @parm Token da ritornare
|
||
|
||
// @comm Chiama la <mf TToken_string::get> con tutti i relativi significati per
|
||
// il parametro <p n>
|
||
{
|
||
const char* const car = get(n);
|
||
return car ? *car : '\0';
|
||
}
|
||
|
||
// Certified 99%
|
||
int TToken_string::get_int(int n)
|
||
{
|
||
const char* const num = get(n);
|
||
return num ? atoi(num) : 0;
|
||
}
|
||
|
||
|
||
// Certified 99%
|
||
long TToken_string::get_long(int n)
|
||
{
|
||
const char* const num = get(n);
|
||
return num ? atol(num) : 0L;
|
||
}
|
||
|
||
|
||
// Certified 70%
|
||
bool TToken_string::set_item(const char* v, int n)
|
||
{
|
||
CHECK(_separator, "Corrupted TToken_string: NULL separator");
|
||
|
||
int sep = 0;
|
||
for (int i = 0; sep < n && _str[i]; i++)
|
||
if (_str[i] == _separator) sep++;
|
||
|
||
if (sep < n) // Aggiunge items mancanti prima della posizione n
|
||
{
|
||
for (;sep < n; sep++)
|
||
*this << _separator;
|
||
*this << v;
|
||
return FALSE;
|
||
}
|
||
|
||
int e = find(_separator, i);
|
||
if (e < 0) e = len();
|
||
|
||
spark = &_str[e]; // Salva items seguenti
|
||
cut(i); // Considera solo items precedenti
|
||
*this << v << spark; // Aggiunge item desiderato e seguenti
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
// Certified 80%
|
||
int TToken_string::get_pos(const char* s)
|
||
{
|
||
const char* item;
|
||
|
||
restart();
|
||
for (int i = 0; (item = get()) != NULL; i++)
|
||
if (strcmp(item, s) == 0) return i;
|
||
|
||
return -1;
|
||
}
|
||
|
||
// Certified 80%
|
||
int TToken_string::get_pos(long n)
|
||
{
|
||
char s[16]; sprintf(s, "%ld", n);
|
||
return get_pos(s);
|
||
}
|
||
|
||
|
||
|
||
// Certified 90%
|
||
bool TToken_string::empty_items() const
|
||
{
|
||
for (const char* c = _str; *c; c++)
|
||
if (!is_space(*c) && *c != _separator) return FALSE;
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
// Certified 80%
|
||
int TToken_string::items() const
|
||
{
|
||
int t = 0;
|
||
if (not_empty())
|
||
{
|
||
t++;
|
||
for (const char* s = _str; *s; s++)
|
||
if (*s == _separator) t++;
|
||
}
|
||
return t;
|
||
}
|
||
|
||
// Certified 99%
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Aggiunge un elemento alla token string
|
||
void TToken_string::add(
|
||
const char* s, // @parm Stringa da aggiungere
|
||
int pos) // @parm Posizione nella quale aggiungere l'elemento
|
||
// (default aggiunge come ultimo elemento)
|
||
// @parm char | c | Caratter da aggiungere
|
||
// @parm long | n | Long da aggiungere
|
||
// @parm int | n | Intero da aggiungere
|
||
|
||
// @syntax void add(const char* s, int n = -1);
|
||
// @syntax void add(char c, int pos = -1);
|
||
// @syntax void add(long n, int pos = -1);
|
||
// @syntax void add(int n, int pos = -1);
|
||
//
|
||
// @comm Permette, a seconda del parametro passato, di aggiungere alla Token
|
||
// string un nuovo elemnto gi<67> completo del carattere di separazione
|
||
{
|
||
if (s == NULL || *s == '\0') s = " ";
|
||
if (pos < 0)
|
||
{
|
||
if (not_empty()) *this << _separator;
|
||
*this << s;
|
||
}
|
||
else
|
||
set_item(s, pos);
|
||
if (_last < 0) _last = 0;
|
||
}
|
||
|
||
// Certified 0%
|
||
void TToken_string::add(char c, int pos)
|
||
{
|
||
const char s[2] = { c, '\0' };
|
||
add(s, pos);
|
||
}
|
||
|
||
// Adds an integer value to the token string
|
||
// Certified 100%
|
||
void TToken_string::add(long n, int pos)
|
||
{
|
||
char s[16];
|
||
sprintf(s, "%ld", n);
|
||
add(s, pos);
|
||
}
|
||
|
||
void TToken_string::add(int n, int pos)
|
||
{
|
||
char s[16];
|
||
sprintf(s, "%d", n);
|
||
add(s, pos);
|
||
}
|
||
|
||
// Certified 50%
|
||
void TToken_string::destroy(int n)
|
||
{
|
||
if (_last == -2) return ;
|
||
|
||
if (n < 0)
|
||
{
|
||
char* s = strrchr(_str, _separator);
|
||
if (s != NULL) *s = '\0';
|
||
}
|
||
else
|
||
{
|
||
int sep = 0;
|
||
for (char* s = _str; sep < n && *s; s++)
|
||
if (*s == _separator) sep++;
|
||
|
||
if (sep >= n)
|
||
{
|
||
const char* p = strchr(s, _separator);
|
||
*s = '\0';
|
||
if (p != NULL) strcat(s, p+1);
|
||
}
|
||
}
|
||
restart();
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// Paragraph string
|
||
///////////////////////////////////////////////////////////
|
||
|
||
TParagraph_string::TParagraph_string(const char* s, int width)
|
||
: TToken_string(s, '|'), _width(width)
|
||
{ tokenize(); }
|
||
|
||
const TString& TParagraph_string::operator =(const char* s)
|
||
{
|
||
TToken_string::operator=(s);
|
||
tokenize();
|
||
return *this;
|
||
}
|
||
|
||
void TParagraph_string::tokenize()
|
||
{
|
||
|
||
int last_space = 0, last_start = 0;
|
||
int num_chars = 0;
|
||
const int l = len();
|
||
TString stmp,sstr(_str),swork; // stringhe di lavoro
|
||
for (int start = 0; start < l;)
|
||
{
|
||
|
||
switch (_str[start])
|
||
{
|
||
case '\n': last_space = start; num_chars = _width; break;
|
||
case ' ' : last_space = start; num_chars++; break;
|
||
default : num_chars++; break;
|
||
}
|
||
|
||
if (num_chars == _width && (start < l-1))
|
||
{
|
||
int num_of_chars_in_row = (last_space+1) - last_start;
|
||
if (num_of_chars_in_row <= 0) num_of_chars_in_row = _width; // Se non ci sono spazi tronca la stringa a 25
|
||
swork=sstr.mid(last_start,num_of_chars_in_row);
|
||
stmp << swork.trim();
|
||
stmp << "|";
|
||
last_space = num_chars = 0;
|
||
start = start - (_width - num_of_chars_in_row); // riporta indietro (toglie il numero di caratteri effettivi della riga)
|
||
last_start = start;
|
||
}
|
||
start++;
|
||
}
|
||
swork=sstr.mid(last_start,l-last_start);
|
||
swork.trim();
|
||
stmp << swork;
|
||
if (stmp.empty()) stmp = sstr;
|
||
TToken_string::operator=(stmp);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////
|
||
// TString_array
|
||
///////////////////////////////////////////////////////////
|
||
|
||
int TString_array::add(const char* s, int n)
|
||
{
|
||
if (objptr(n) == NULL)
|
||
n = TArray::add(new TToken_string(s), n);
|
||
else row(n) = s;
|
||
return n;
|
||
}
|
||
|
||
int TString_array::add(const TToken_string& s, int n)
|
||
{
|
||
if (objptr(n) == NULL)
|
||
n = TArray::add(s);
|
||
else
|
||
row(n) = s;
|
||
return n;
|
||
}
|
||
|
||
// @doc EXTERNAL
|
||
|
||
// @mfunc Cerca una stringa nell'array
|
||
//
|
||
// @rdesc Ritorna la posizione nell'array in cui si trova la stringa (-1 se non
|
||
// e' stata trovata)
|
||
int TString_array::find(
|
||
const char* s, // @parm Stringa da cercare
|
||
int from) const // @parm Posizione dalla quale cercare la stringa
|
||
{
|
||
int found = -1;
|
||
for (int i = from; i < items(); i++)
|
||
if (row(i).compare(s, -1, TRUE) == 0)
|
||
{
|
||
found = i;
|
||
break;
|
||
}
|
||
return found;
|
||
}
|
||
|
||
HIDDEN int ascending_string(const TObject** o1, const TObject** o2)
|
||
{
|
||
const TString* s1 = (const TString*)*o1;
|
||
const TString* s2 = (const TString*)*o2;
|
||
return strcmp(*s1, *s2);
|
||
}
|
||
|
||
HIDDEN int descending_string(const TObject** o1, const TObject** o2)
|
||
{
|
||
return -ascending_string(o1, o2);
|
||
}
|
||
|
||
void TString_array::sort(bool ascending)
|
||
{
|
||
TArray::sort(ascending ? ascending_string : descending_string);
|
||
}
|
||
|