Patch level : 10.0 274
Files correlati : ca2.exe Ricompilazione Demo : [ ] Commento : Corretto comportamento dei sorted_cursor per le maschere. Ora la ricerca viene fatta sulla chiave di sort. Aggiunta modalità batch delle transazioni. Viene generato un log e l'esecuzione non viene interrotta da segnalazioni ( Da collaudare meglio alla prima occasione). Resa possibile la visualizzazione di record bloccati da un altro utente. Queste funzionalità sono presenti nelle relapp dall patch 274 e successive. git-svn-id: svn://10.65.10.50/branches/R_10_00@23210 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
parent
3469b56f48
commit
24ed90d54e
@ -1,6 +1,8 @@
|
||||
#include <dongle.h>
|
||||
#include <execp.h>
|
||||
#include <expr.h>
|
||||
#include <msksheet.h>
|
||||
#include <postman.h>
|
||||
#include <recarray.h>
|
||||
#include <recset.h>
|
||||
#include <relapp.h>
|
||||
@ -385,6 +387,67 @@ bool TBrowse::parse_copy(const TString& what, const TBrowse& b)
|
||||
return true;
|
||||
}
|
||||
|
||||
void TBrowse::update_filter(TEdit_field * f)
|
||||
{
|
||||
if (!f->in_key(0))
|
||||
{
|
||||
TString rf = get_user_read_filter(); rf.trim();
|
||||
|
||||
if (rf.not_empty())
|
||||
{
|
||||
TExpression e(rf);
|
||||
bool ok = true;
|
||||
|
||||
for (int i = e.numvar()-1; ok && i >= 0; i--)
|
||||
{
|
||||
TString s = e.varname(i);
|
||||
TString id;
|
||||
int fileid = 0;
|
||||
int pos = s.find("->");
|
||||
|
||||
if (pos > 0)
|
||||
{
|
||||
id = s.left(pos); id.strip(" ");
|
||||
fileid = name2log(id);
|
||||
pos += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = s.find('.');
|
||||
if (pos > 0)
|
||||
{
|
||||
id = s.left(pos); id.strip(" ");
|
||||
fileid = name2log(id);
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
pos = 0;
|
||||
}
|
||||
if (fileid < CNF_GENERAL)
|
||||
{
|
||||
s.ltrim(pos);
|
||||
int par = s.find('[', pos);
|
||||
|
||||
if (par >= 0)
|
||||
s.cut(par);
|
||||
TRelation * r = cursor()->relation();
|
||||
ok = (fileid == 0 && r->curr().exist(s)) || (r->log2ind(fileid) >= 0 && r->curr(fileid).exist(s));
|
||||
}
|
||||
}
|
||||
if (ok)
|
||||
{
|
||||
if (_filter.blank())
|
||||
_filter = rf;
|
||||
else
|
||||
{
|
||||
_filter.insert("(", 0);
|
||||
_filter << ")&&(" << rf << ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TBrowse::replace_cursor(TCursor* c)
|
||||
{
|
||||
if (_relation != NULL)
|
||||
|
@ -213,7 +213,10 @@ public:
|
||||
// @cmember Aggiorna la lista completa degli identificatori dei campi di output da un campo
|
||||
void copy_output(const TBrowse * b);
|
||||
|
||||
// @cmember Cambia il cursore senza darne il possesso (come nella COPY USE)
|
||||
// @cmember Aggiorna il filtro con l'espressione per l'utente
|
||||
void update_filter(TEdit_field * f);
|
||||
|
||||
// @cmember Cambia il cursore senza darne il possesso (come nella COPY USE)
|
||||
void replace_cursor(TCursor* c);
|
||||
|
||||
// @cmember Aggiunge un campo di output alla posizione <pos>
|
||||
|
@ -3,8 +3,44 @@
|
||||
#include <diction.h>
|
||||
#include <dongle.h>
|
||||
#include <keys.h>
|
||||
#include <strings.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define buildmsg() char msg[1024];va_list argptr;va_start(argptr,fmt);_vsnprintf_s(msg,sizeof(msg),_TRUNCATE,fmt,argptr);va_end(argptr);msg[1023] = '\0';
|
||||
#else
|
||||
#define buildmsg() char msg[1024];va_list argptr;va_start(argptr,fmt);vsprintf(msg,fmt,argptr);va_end(argptr)
|
||||
#endif
|
||||
|
||||
static bool __batch = false;
|
||||
TString_array __errors;
|
||||
TString_array __warnings;
|
||||
|
||||
bool is_batch()
|
||||
{
|
||||
return __batch;
|
||||
}
|
||||
|
||||
void batch(bool on)
|
||||
{
|
||||
__batch = on;
|
||||
if (on)
|
||||
{
|
||||
__errors.destroy();
|
||||
__warnings.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
TString_array & errors()
|
||||
{
|
||||
return __errors;
|
||||
}
|
||||
|
||||
TString_array & warnings()
|
||||
{
|
||||
return __warnings;
|
||||
}
|
||||
|
||||
|
||||
#define buildmsg() char msg[1024];va_list argptr;va_start(argptr,fmt);vsnprintf_s(msg,sizeof(msg),_TRUNCATE,fmt,argptr);va_end(argptr);
|
||||
|
||||
// @doc EXTERNAL
|
||||
|
||||
@ -15,7 +51,10 @@ bool fatal_box(
|
||||
// @comm Il programma viene interrotto al momento in cui si e' verificato l'errore.
|
||||
{
|
||||
buildmsg();
|
||||
xvt_dm_post_fatal_exit(msg);
|
||||
if (__batch)
|
||||
__errors.add(msg);
|
||||
else
|
||||
xvt_dm_post_fatal_exit(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -29,7 +68,10 @@ bool error_box(
|
||||
// e l'icona punto esclamativo.
|
||||
{
|
||||
buildmsg();
|
||||
xvt_dm_post_error(msg);
|
||||
if (__batch)
|
||||
__errors.add(msg);
|
||||
else
|
||||
xvt_dm_post_error(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -42,7 +84,10 @@ bool warning_box(
|
||||
// e l'icona punto di domanda.
|
||||
{
|
||||
buildmsg();
|
||||
xvt_dm_post_warning(msg);
|
||||
if (__batch)
|
||||
__warnings.add(msg);
|
||||
else
|
||||
xvt_dm_post_warning(msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -55,7 +100,10 @@ bool message_box(
|
||||
// e l'icona informazioni.
|
||||
{
|
||||
buildmsg();
|
||||
xvt_dm_post_message(msg);
|
||||
if (__batch)
|
||||
__warnings.add(msg);
|
||||
else
|
||||
xvt_dm_post_message(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -68,7 +116,10 @@ bool sorry_box(
|
||||
// e l'icona informazioni.
|
||||
{
|
||||
buildmsg();
|
||||
xvt_dm_post_note(msg);
|
||||
if (__batch)
|
||||
__warnings.add(msg);
|
||||
else
|
||||
xvt_dm_post_note(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -78,6 +129,11 @@ bool noyes_box(
|
||||
...) // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
|
||||
{
|
||||
buildmsg();
|
||||
if (__batch)
|
||||
{
|
||||
__errors.add(msg);
|
||||
return true;
|
||||
}
|
||||
ASK_RESPONSE r = xvt_dm_post_ask("No", "Si", NULL, msg);
|
||||
return r == RESP_DEFAULT;
|
||||
}
|
||||
@ -88,6 +144,11 @@ int noyesall_box(
|
||||
...) // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
|
||||
{
|
||||
buildmsg();
|
||||
if (__batch)
|
||||
{
|
||||
__errors.add(msg);
|
||||
return K_NO;
|
||||
}
|
||||
ASK_RESPONSE r = xvt_dm_post_ask("No", "Si", "Si Tutti", msg);
|
||||
return r == RESP_DEFAULT ? K_YES : (r == RESP_2 ? K_NO : K_SPACE);
|
||||
}
|
||||
@ -106,6 +167,11 @@ bool yesno_box(
|
||||
// @flag 0 | Se viene premuto il taso NO
|
||||
{
|
||||
buildmsg();
|
||||
if (__batch)
|
||||
{
|
||||
__errors.add(msg);
|
||||
return false;
|
||||
}
|
||||
ASK_RESPONSE r = xvt_dm_post_ask("Si", "No", NULL, msg);
|
||||
return r == RESP_DEFAULT;
|
||||
}
|
||||
@ -116,6 +182,11 @@ int yesnoall_box(
|
||||
...) // @parmvar Uno o piu' parametri corrispondenti ai codici in <p fmt>
|
||||
{
|
||||
buildmsg();
|
||||
if (__batch)
|
||||
{
|
||||
__errors.add(msg);
|
||||
return K_NO;
|
||||
}
|
||||
ASK_RESPONSE r = xvt_dm_post_ask("No", "Si", "No Tutti", msg);
|
||||
return r == RESP_DEFAULT ? K_NO : (r == RESP_2 ? K_YES : K_SPACE);
|
||||
}
|
||||
@ -139,7 +210,7 @@ bool yesnofatal_box(
|
||||
//
|
||||
// @xref <m yesno_box> <m yesnofatal_box>
|
||||
{
|
||||
buildmsg();
|
||||
buildmsg();
|
||||
|
||||
#ifdef DBG
|
||||
char user[32]; xvt_sys_get_user_name(user, sizeof(user));
|
||||
@ -170,6 +241,11 @@ int yesnocancel_box(
|
||||
// @xref <m yesno_box> <m yesnofatal_box>
|
||||
{
|
||||
buildmsg();
|
||||
if (__batch)
|
||||
{
|
||||
__errors.add(msg);
|
||||
return K_NO;
|
||||
}
|
||||
ASK_RESPONSE r = xvt_dm_post_ask("Si", "No", "Annulla", msg);
|
||||
return r == RESP_DEFAULT ? K_YES : (r == RESP_2 ? K_NO : K_ESC);
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
#ifndef __CHECKS_H
|
||||
#define __CHECKS_H
|
||||
|
||||
|
||||
#ifndef __STDTYPES_H
|
||||
#include <stdtypes.h>
|
||||
#endif
|
||||
|
||||
class TString_array;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -21,6 +27,11 @@ extern "C" {
|
||||
bool cantaccess_box(const char* filename);
|
||||
bool __trace(const char* fmt, ...);
|
||||
bool __tracemem(const char* fmt);
|
||||
|
||||
void batch(bool on = true);
|
||||
bool is_batch();
|
||||
TString_array & errors();
|
||||
TString_array & warnings();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -90,7 +90,7 @@ WINDOW TMask::curr_win() const
|
||||
return page_win(_page > 0 && _page < _pages ? _page : 0);
|
||||
}
|
||||
|
||||
TMask::TMask() : _mask_num(0)
|
||||
TMask::TMask() : _mask_num(0), _sheet_first_selection_row(-1)
|
||||
{ init_mask(); }
|
||||
|
||||
TMask::TMask(const char* title, int pages, int cols, int rows,
|
||||
@ -870,6 +870,13 @@ long TMask::handler(WINDOW w, EVENT* ep)
|
||||
case 2: _last_sheet->reset_columns_order(); break;
|
||||
case 3: _last_sheet->on_key(K_F11); break;
|
||||
case 4: _last_sheet->esporta(); break;
|
||||
case 5: _last_sheet->clear_range_selection(); break;
|
||||
case 6:
|
||||
_last_sheet->select_range(_sheet_first_selection_row);
|
||||
_sheet_first_selection_row = -1;
|
||||
break;
|
||||
case 7: _last_sheet->copy_rows(); break;
|
||||
case 8: _last_sheet->paste_rows(); break;
|
||||
default: break;
|
||||
}
|
||||
return 0L;
|
||||
@ -2687,9 +2694,27 @@ void TMask::post_error_message(const char* msg, int sev)
|
||||
if (_error_message == msg)
|
||||
return; // Ignora messaggio duplicato;
|
||||
on_idle();
|
||||
}
|
||||
}
|
||||
if (is_batch())
|
||||
{
|
||||
if (sev > 2)
|
||||
errors().add(msg);
|
||||
else
|
||||
warnings().add(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
_error_message = msg;
|
||||
_error_severity = sev;
|
||||
}
|
||||
}
|
||||
|
||||
KEY TMask::check_mask()
|
||||
|
||||
// @comm Se la finestra non era aperta la apre in modo modale
|
||||
{
|
||||
start_run();
|
||||
return stop_run(K_ENTER) ? K_ENTER : K_ESC;
|
||||
}
|
||||
|
||||
// @doc INTERNAL
|
||||
|
@ -98,6 +98,9 @@ class TMask : public TWindow
|
||||
// @cmember:(INTERNAL) Puntatore allo sheet che contiene la maschera (puo' essere NULL)
|
||||
TSheet_field* _sheet;
|
||||
|
||||
// @cmember:(INTERNAL) Numero della prima riga di selezione nello sheet
|
||||
long _sheet_first_selection_row;
|
||||
|
||||
// @cmember:(INTERNAL) Handler per gestire i tasti speciali nelle maschere
|
||||
MASK_HANDLER _handler;
|
||||
|
||||
@ -475,6 +478,8 @@ public:
|
||||
{ return _toolwin; }
|
||||
WINDOW toolbar() const
|
||||
{ return _toolbar; }
|
||||
// @cmember verifica la mascher senza eseguirla
|
||||
KEY check_mask();
|
||||
};
|
||||
|
||||
// @doc EXTERNAL
|
||||
|
@ -788,7 +788,7 @@ bool TMask_field::warning_box(
|
||||
xvt_dm_post_speech(_msg, 1, true);
|
||||
xvtil_statbar_set(_msg);
|
||||
beep(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mask().post_error_message(_msg, 2);
|
||||
@ -805,6 +805,15 @@ bool TMask_field::yesno_box(const char* fmt, ...) const
|
||||
return yes;
|
||||
}
|
||||
|
||||
bool TMask_field::noyes_box(const char* fmt, ...) const
|
||||
{
|
||||
set_focus();
|
||||
build_msg();
|
||||
const bool yes = ::noyes_box("%s", _msg);
|
||||
set_focus();
|
||||
return yes;
|
||||
}
|
||||
|
||||
KEY TMask_field::yesnocancel_box(const char* fmt, ...) const
|
||||
{
|
||||
set_focus();
|
||||
@ -2035,7 +2044,6 @@ word TEdit_field::class_id() const
|
||||
|
||||
void TEdit_field::set_len(short w)
|
||||
{
|
||||
CHECKD(w > 0 && w <= 50, "Invalid field length ", w);
|
||||
_size = w;
|
||||
}
|
||||
|
||||
@ -2256,7 +2264,7 @@ bool TEdit_field::parse_item(TScanner& scanner)
|
||||
scanner.line();
|
||||
}
|
||||
scanner.push();
|
||||
|
||||
browse()->update_filter(this);
|
||||
if (tablename.full())
|
||||
{
|
||||
tablename.insert("MTB", 0);
|
||||
|
@ -256,6 +256,9 @@ public:
|
||||
// @cmember Ritorna true se si tratta di campo fantasma
|
||||
bool ghost() const
|
||||
{ return _flags.ghost; }
|
||||
// @cmember Ritorna true se il campo e' un numero romano
|
||||
bool persistent() const
|
||||
{ return _flags.persistent; }
|
||||
|
||||
// @cmember Controlla se il campo appartiene ad una chiave di ricerca
|
||||
virtual bool in_key(word) const
|
||||
@ -403,6 +406,8 @@ public:
|
||||
virtual bool error_box(const char* fmt, ...) const;
|
||||
// @cmember Crea una yesno-box relativamente al campo (chiama <f yesno_box>)
|
||||
virtual bool yesno_box(const char* fmt, ...) const;
|
||||
// @cmember Crea una noyes-box relativamente al campo (chiama <f yesno_box>)
|
||||
virtual bool noyes_box(const char* fmt, ...) const;
|
||||
// @cmember Crea una yesnocancel-box relativamente al campo (chiama <f yesnocancel_box>)
|
||||
virtual KEY yesnocancel_box(const char* fmt, ...) const;
|
||||
|
||||
|
@ -25,6 +25,11 @@ class TCell_property : public TObject
|
||||
public:
|
||||
void set(COLOR back, COLOR fore) { _back = back; _fore = fore; }
|
||||
bool get(COLOR& back, COLOR& fore) const;
|
||||
|
||||
virtual TCell_property & copy(const TCell_property & p);
|
||||
virtual TObject* dup() const { return new TCell_property(*this); }
|
||||
|
||||
TCell_property(const TCell_property & p);
|
||||
TCell_property();
|
||||
};
|
||||
|
||||
@ -38,6 +43,19 @@ bool TCell_property::get(COLOR& back, COLOR& fore) const
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
TCell_property & TCell_property::copy(const TCell_property & p)
|
||||
{
|
||||
_back = p._back;
|
||||
_fore = p._fore;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TCell_property::TCell_property(const TCell_property & p)
|
||||
{
|
||||
copy
|
||||
(p);
|
||||
}
|
||||
|
||||
TCell_property::TCell_property() : _back(COLOR_INVALID), _fore(COLOR_INVALID)
|
||||
{ }
|
||||
@ -58,10 +76,33 @@ public:
|
||||
|
||||
TBit_array & disabled() { return _disabled;}
|
||||
const TBit_array & disabled() const { return _disabled;}
|
||||
|
||||
virtual TRow_property & copy(const TRow_property & r);
|
||||
virtual TObject* dup() const { return new TRow_property(*this); }
|
||||
|
||||
TRow_property(const TRow_property & p);
|
||||
TRow_property();
|
||||
virtual ~TRow_property() { }
|
||||
};
|
||||
|
||||
TRow_property & TRow_property::copy(const TRow_property & p)
|
||||
{
|
||||
_disabled = p._disabled;
|
||||
_back = p._back;
|
||||
_fore = p._fore;
|
||||
_height = p._height;
|
||||
if (p._cell_prop != NULL)
|
||||
_cell_prop = new TArray(*p._cell_prop);
|
||||
else
|
||||
_cell_prop = NULL;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TRow_property::TRow_property(const TRow_property & p)
|
||||
{
|
||||
copy(p);
|
||||
}
|
||||
|
||||
TRow_property::TRow_property()
|
||||
: _back(COLOR_INVALID), _fore(COLOR_INVALID), _height(-1), _cell_prop(NULL)
|
||||
{ }
|
||||
@ -146,13 +187,18 @@ class TSpreadsheet : public TControl
|
||||
|
||||
// @cmember:(INTERNAL) Array di TToken_strings contenenti le righe
|
||||
TString_array _str;
|
||||
// @cmember:(INTERNAL) Array di TToken_strings contenenti le righe copiate
|
||||
TString_array _copied_rows;
|
||||
// @cmember:(INTERNAL) Array delle colonne disattivate (solo visualizzazione)
|
||||
TBit_array _column_disabled;
|
||||
|
||||
// @cmember:(INTERNAL) righe selezionate
|
||||
int _from;
|
||||
int _to;
|
||||
|
||||
// @cmember:(INTERNAL) Array delle proprieta' delle righe
|
||||
TArray _properties;
|
||||
// @cmember:(INTERNAL) Array delle proprieta' standard di tutte le righe
|
||||
TRow_property* _row_properties;
|
||||
TArray * _saved_properties;
|
||||
|
||||
// @cmember:(INTERNAL) Maschera in cui e' contenuto lo spreadsheet
|
||||
TMask _mask;
|
||||
@ -403,6 +449,12 @@ public:
|
||||
|
||||
bool point2cell(const PNT& pnt, short& id, long& row) const;
|
||||
|
||||
bool get_range_selection(int & from, int & to) const ;
|
||||
void clear_range_selection();
|
||||
void select_range(int row);
|
||||
void copy_rows();
|
||||
void paste_rows();
|
||||
|
||||
// @cmember Costruttore
|
||||
TSpreadsheet(WINDOW parent, short dlg, short x, short y, short dx, short dy, const char* maskname, int maskno, const char* head, TSheet_field* owner);
|
||||
// @cmember Distruttore
|
||||
@ -436,8 +488,8 @@ TSpreadsheet::TSpreadsheet(
|
||||
_edit_field(NULL), _cur_row(0), _cur_rec(0), _cur_col(1),
|
||||
_row_dirty(false), _cell_dirty(false), _check_enabled(true),
|
||||
_needs_update(-1), _selection_posted(-1), _ignore_button(0), _save_columns_order(false),
|
||||
_f9_target(NULL), _auto_append(false), _first_nav_column_id(-1),_last_nav_column_id(-1),
|
||||
_row_properties(NULL)
|
||||
_f9_target(NULL), _auto_append(false), _first_nav_column_id(-1), _last_nav_column_id(-1),
|
||||
_from(-1), _to(-1), _saved_properties(NULL)
|
||||
{
|
||||
int m_width[MAX_COL], v_width[MAX_COL];
|
||||
int fixed_cols = 0; // Number of fixed columns
|
||||
@ -512,6 +564,15 @@ TSpreadsheet::TSpreadsheet(
|
||||
|
||||
XI_OBJ* itf = get_interface(parent);
|
||||
XI_RCT rct = coord2rct(itf, x, y, dx, dy);
|
||||
|
||||
if (x > 0 && dx < 0)
|
||||
{
|
||||
RCT max_rct; xvt_vobj_get_client_rect((WINDOW)xi_get_window(itf), &max_rct);
|
||||
const short MAXX = max_rct.right;
|
||||
|
||||
if (MAXX > 80 * CHARX)
|
||||
rct.left += (MAXX - 80 * CHARX) / 2;
|
||||
}
|
||||
rct.right -= 2*XI_FU_MULTIPLE; // toglie scroll-bar
|
||||
|
||||
// Controlla se posso bloccare anche questa colonna
|
||||
@ -547,7 +608,10 @@ TSpreadsheet::TSpreadsheet(
|
||||
l->active_back_color = FOCUS_BACK_COLOR;
|
||||
l->white_space_color = MASK_DARK_COLOR;
|
||||
l->rule_color = MASK_DARK_COLOR;
|
||||
|
||||
#ifdef LINUX
|
||||
l->scroll_on_thumb_track = true;
|
||||
#endif
|
||||
|
||||
// Definizione della prima colonna (numero di riga)
|
||||
word attr = XI_ATR_RJUST;
|
||||
if (sheet_mask().id2pos(FIRST_FIELD-1) >= 0)
|
||||
@ -640,7 +704,8 @@ TSpreadsheet::TSpreadsheet(
|
||||
|
||||
TSpreadsheet::~TSpreadsheet()
|
||||
{
|
||||
delete _row_properties;
|
||||
if (_saved_properties != NULL)
|
||||
delete _saved_properties;
|
||||
}
|
||||
|
||||
TMask& TSpreadsheet::sheet_mask() const
|
||||
@ -2345,21 +2410,15 @@ void TSpreadsheet::set_row_height(const int row, const int height)
|
||||
|
||||
TRow_property* TSpreadsheet::get_property(int row, bool create)
|
||||
{
|
||||
if (row < 0)
|
||||
{
|
||||
if (_row_properties == NULL && create)
|
||||
_row_properties = new TRow_property;
|
||||
return _row_properties;
|
||||
}
|
||||
if (row < 0)
|
||||
row = 0;
|
||||
|
||||
TRow_property* p = (TRow_property*)_properties.objptr(row);
|
||||
if (p == NULL)
|
||||
|
||||
if (p == NULL && create)
|
||||
{
|
||||
if (create)
|
||||
{
|
||||
p = new TRow_property;
|
||||
_properties.add(p, row);
|
||||
}
|
||||
p = new TRow_property;
|
||||
_properties.add(p, row);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
@ -2639,6 +2698,11 @@ bool TSpreadsheet::error_box(const char* msg)
|
||||
const int r = _cur_row;
|
||||
const int c = _cur_col;
|
||||
|
||||
if (is_batch())
|
||||
{
|
||||
errors().add(msg);
|
||||
return false;
|
||||
}
|
||||
if (ADVANCED_GRAPHICS && ANIMATED_BOXES)
|
||||
xvt_dm_popup_error(msg);
|
||||
else
|
||||
@ -2691,6 +2755,101 @@ bool TSpreadsheet::point2cell(const PNT& pnt, short& id, long& row) const
|
||||
return inside;
|
||||
}
|
||||
|
||||
bool TSpreadsheet::get_range_selection(int & from, int & to) const
|
||||
{
|
||||
from = _from;
|
||||
to = _to;
|
||||
return _from >= 0;
|
||||
}
|
||||
|
||||
void TSpreadsheet::clear_range_selection()
|
||||
{
|
||||
_from = _to = -1;
|
||||
if (_saved_properties)
|
||||
{
|
||||
const int it = items();
|
||||
for (int r = 0; r < it; r++)
|
||||
{
|
||||
TRow_property* prop = (TRow_property*)_saved_properties->objptr(r);
|
||||
COLOR back = NORMAL_BACK_COLOR;
|
||||
COLOR fore = NORMAL_COLOR;
|
||||
|
||||
if (prop != NULL)
|
||||
prop->get(-1, back, fore);
|
||||
set_back_and_fore_color(back, fore, r, -1);
|
||||
}
|
||||
delete _saved_properties;
|
||||
_saved_properties = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void TSpreadsheet::select_range(int row)
|
||||
{
|
||||
int from = _from;
|
||||
int to = _to;
|
||||
|
||||
if (row < 0)
|
||||
row = selected();
|
||||
if (_saved_properties == NULL)
|
||||
_saved_properties = new TArray(_properties);
|
||||
|
||||
if (_from < 0)
|
||||
_from = _to = row;
|
||||
else
|
||||
{
|
||||
if (row < _from)
|
||||
from = _from = row;
|
||||
else
|
||||
from = _to = row;
|
||||
}
|
||||
if (from < 0)
|
||||
from = 0;
|
||||
if (from >_from)
|
||||
from = _from;
|
||||
if (to < 0)
|
||||
to = items();
|
||||
if (to < _to)
|
||||
to = _to;
|
||||
for (int r = from; r <= to; r++)
|
||||
{
|
||||
TRow_property* prop = (TRow_property*)_saved_properties->objptr(r);
|
||||
COLOR back = NORMAL_BACK_COLOR;
|
||||
COLOR fore = NORMAL_COLOR;
|
||||
|
||||
if (prop != NULL)
|
||||
prop->get(-1, back, fore);
|
||||
if (r >= _from && r <= _to)
|
||||
back = blend_colors(back, FOCUS_BACK_COLOR, 0.75);
|
||||
set_back_and_fore_color(back, fore, r, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void TSpreadsheet::copy_rows()
|
||||
{
|
||||
int from = _from > 0 ? _from : 0;
|
||||
int to = _to < items() - 1 ? _to : items() - 1;
|
||||
|
||||
_copied_rows.destroy();
|
||||
for (int i = from; i <= to; i++)
|
||||
_copied_rows.add(_str.row(i));
|
||||
}
|
||||
|
||||
void TSpreadsheet::paste_rows()
|
||||
{
|
||||
int row = selected();
|
||||
int nrows = _copied_rows.items();
|
||||
|
||||
if (row >= _str.items() - 1)
|
||||
{
|
||||
row = _str.items() - 1;
|
||||
_str.add(_copied_rows.row(--nrows));
|
||||
}
|
||||
|
||||
for (int i = nrows - 1; i >= 0; i--)
|
||||
_str.insert(_copied_rows.row(i), row + 1);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// TSheet_field
|
||||
///////////////////////////////////////////////////////////
|
||||
@ -3692,6 +3851,47 @@ static TString& clean_white_space(TString& str)
|
||||
return str;
|
||||
}
|
||||
|
||||
bool TSheet_field::get_range_selection(int &from, int & to) const
|
||||
{
|
||||
TSpreadsheet* s = (TSpreadsheet*)_ctl;
|
||||
|
||||
return s->get_range_selection(from, to);
|
||||
}
|
||||
|
||||
void TSheet_field::clear_range_selection()
|
||||
{
|
||||
TSpreadsheet* s = (TSpreadsheet*)_ctl;
|
||||
|
||||
s->clear_range_selection();
|
||||
force_update();
|
||||
s->set_focus_cell(s->_cur_row, s->_cur_col);
|
||||
}
|
||||
|
||||
void TSheet_field::select_range(int row)
|
||||
{
|
||||
TSpreadsheet* s = (TSpreadsheet*)_ctl;
|
||||
|
||||
s->select_range(row);
|
||||
force_update();
|
||||
s->set_focus_cell(s->_cur_row, s->_cur_col);
|
||||
}
|
||||
|
||||
void TSheet_field::copy_rows()
|
||||
{
|
||||
TSpreadsheet* s = (TSpreadsheet*)_ctl;
|
||||
|
||||
s->copy_rows();
|
||||
}
|
||||
|
||||
void TSheet_field::paste_rows()
|
||||
{
|
||||
TSpreadsheet* s = (TSpreadsheet*)_ctl;
|
||||
|
||||
s->paste_rows();
|
||||
on_key(K_CTRL + 'V');
|
||||
force_update();
|
||||
s->set_focus_cell(s->_cur_row, s->_cur_col);
|
||||
}
|
||||
///////////////////////////////////////////////////////////
|
||||
// TSheet_recordset
|
||||
///////////////////////////////////////////////////////////
|
||||
|
@ -285,6 +285,12 @@ public:
|
||||
// @cmember Trasferisce i valori dalla riga alla maschera <p n>
|
||||
void update_mask(int n) { row2mask(n, row(n)); }
|
||||
|
||||
bool get_range_selection(int & from, int & to) const ;
|
||||
void clear_range_selection();
|
||||
void select_range(int row = -1);
|
||||
void copy_rows();
|
||||
void paste_rows();
|
||||
|
||||
bool esporta() const;
|
||||
|
||||
// @cmember Restituisce il numero della colonna corrente
|
||||
|
@ -16,7 +16,8 @@
|
||||
|
||||
TRelation_application::TRelation_application()
|
||||
: _mask(NULL), _search_id(-1), _lnflag(0),
|
||||
_autodelete(0), _navigating(false)
|
||||
_autodelete(0), _navigating(false),
|
||||
_locked(false)
|
||||
{ }
|
||||
|
||||
TRelation_application::~TRelation_application()
|
||||
@ -34,16 +35,22 @@ bool TRelation_application::has_filtered_cursor() const
|
||||
}
|
||||
|
||||
|
||||
TCursor& TRelation_application::get_filtered_cursor() const
|
||||
TCursor * TRelation_application::get_filtered_cursor() const
|
||||
{
|
||||
const TEdit_field& f = get_search_field();
|
||||
return *f.browse()->cursor();
|
||||
if (has_filtered_cursor())
|
||||
{
|
||||
const TEdit_field& f = get_search_field();
|
||||
|
||||
return f.browse()->cursor();
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void TRelation_application::setkey()
|
||||
{
|
||||
if (has_filtered_cursor())
|
||||
get_filtered_cursor().setkey();
|
||||
get_filtered_cursor()->setkey();
|
||||
else
|
||||
file().setkey(1);
|
||||
}
|
||||
@ -99,19 +106,19 @@ void TRelation_application::set_limits(
|
||||
if (f.browse() != NULL)
|
||||
f.browse()->do_input(true);
|
||||
|
||||
TCursor& cur = get_filtered_cursor();
|
||||
cur.setkey();
|
||||
if (cur.items() > 0)
|
||||
TCursor* cur = get_filtered_cursor();
|
||||
cur->setkey();
|
||||
if (cur->items() > 0)
|
||||
{
|
||||
TBaseisamfile& f = cur.file();
|
||||
TBaseisamfile& f = cur->file();
|
||||
if (what & 0x1)
|
||||
{
|
||||
cur = 0;
|
||||
*cur = 0;
|
||||
_first = f.recno();
|
||||
}
|
||||
if (what & 0x2)
|
||||
{
|
||||
cur = cur.items() - 1;
|
||||
*cur = cur->items() - 1;
|
||||
_last = f.recno();
|
||||
}
|
||||
}
|
||||
@ -270,7 +277,7 @@ void TRelation_application::enable_query()
|
||||
}
|
||||
|
||||
bool TRelation_application::can_I_write(const TRelation* rel) const
|
||||
{ return user_can_write(rel); }
|
||||
{ return !_locked && user_can_write(rel); }
|
||||
|
||||
bool TRelation_application::can_I_read(const TRelation* rel) const
|
||||
{ return user_can_read(rel); }
|
||||
@ -542,24 +549,30 @@ void TRelation_application::insert_mode()
|
||||
bool TRelation_application::modify_mode()
|
||||
{
|
||||
TRelation* rel = get_relation();
|
||||
const TReclock block = can_I_write(rel) ? _testandlock : _nolock;
|
||||
int err = rel->read(_isequal, block);
|
||||
|
||||
if (!can_I_read(rel))
|
||||
{
|
||||
warning_box(TR("I dati non sono accessibili per l'utente %s"), (const char*)user());
|
||||
query_mode();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const TReclock block = can_I_write(rel) ? _testandlock : _nolock;
|
||||
int err = rel->read(_isequal, block);
|
||||
_locked = false;
|
||||
if (err != NOERR)
|
||||
{
|
||||
if (err == _islocked)
|
||||
message_box(TR("I dati sono già usati da un altro utente"));
|
||||
{
|
||||
_locked = true;
|
||||
message_box(TR("I dati sono già usati da un altro programma, scrittura disabilitata"));
|
||||
}
|
||||
else
|
||||
{
|
||||
error_box(FR("Impossibile leggere i dati: errore %d"), err);
|
||||
if (!is_transaction())
|
||||
query_mode();
|
||||
return FALSE;
|
||||
if (!is_transaction())
|
||||
query_mode();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const bool changing = changing_mask(MODE_MOD);
|
||||
@ -890,7 +903,9 @@ int TRelation_application::delete_mode()
|
||||
r.restore_status();
|
||||
can_delete = remove();
|
||||
}
|
||||
cur.freeze(false);
|
||||
query_mode();
|
||||
cur.freeze(true);
|
||||
}
|
||||
_autodelete = FALSE;
|
||||
}
|
||||
@ -1395,7 +1410,14 @@ void TRelation_application::main_loop()
|
||||
}
|
||||
}
|
||||
|
||||
k = _mask->run();
|
||||
if (_curr_trans_mode == TM_BATCH)
|
||||
{
|
||||
batch();
|
||||
k = _mask->check_mask();
|
||||
batch(false);
|
||||
}
|
||||
else
|
||||
k = _mask->run();
|
||||
|
||||
switch (k)
|
||||
{
|
||||
@ -1445,7 +1467,7 @@ void TRelation_application::main_loop()
|
||||
else
|
||||
insert_mode();
|
||||
}
|
||||
if (_curr_trans_mode == TM_AUTOMATIC)
|
||||
if (_curr_trans_mode == TM_AUTOMATIC || _curr_trans_mode == TM_BATCH)
|
||||
_mask->send_key(K_CTRL+'R', 0);
|
||||
break;
|
||||
case K_SAVE:
|
||||
@ -1489,7 +1511,7 @@ void TRelation_application::main_loop()
|
||||
else
|
||||
insert_mode();
|
||||
}
|
||||
if (_curr_trans_mode == TM_AUTOMATIC)
|
||||
if (_curr_trans_mode == TM_AUTOMATIC || _curr_trans_mode == TM_BATCH)
|
||||
_mask->send_key(K_CTRL+'R', 0);
|
||||
break;
|
||||
case K_DEL:
|
||||
@ -1525,32 +1547,82 @@ void TRelation_application::main_loop()
|
||||
err = file().readat(_first, _testandlock);
|
||||
break;
|
||||
case K_NEXT:
|
||||
err = file().reread();
|
||||
if (has_filtered_cursor())
|
||||
{
|
||||
TCursor& cur = get_filtered_cursor();
|
||||
cur.curr() = file().curr();
|
||||
cur.read();
|
||||
++cur;
|
||||
file().curr() = cur.curr();
|
||||
err = get_relation()->read(_isequal, _testandlock);
|
||||
TCursor* c = get_filtered_cursor();
|
||||
|
||||
if (!has_filtered_cursor() || c->curr().num() != file().curr().num())
|
||||
{
|
||||
for (TEdit_field* e = (TEdit_field *) _mask->get_key_field(1, TRUE); e; e = (TEdit_field *) _mask->get_key_field(1, FALSE))
|
||||
{
|
||||
if (e->shown() && e->browse() != NULL) // Ignora campi invisibili o senza check
|
||||
{
|
||||
TCursor* b = e->browse()->cursor();
|
||||
|
||||
if (b && b->curr().num() == file().curr().num())
|
||||
{
|
||||
c = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TCursor* cur = c ;
|
||||
|
||||
if (c == NULL)
|
||||
cur = new TCursor(get_relation());
|
||||
|
||||
err = file().reread();
|
||||
cur->curr() = file().curr();
|
||||
cur->read();
|
||||
++(*cur);
|
||||
while (cur->pos() < cur->items() && !can_I_read(cur->relation()))
|
||||
++(*cur);
|
||||
file().curr() = cur->curr();
|
||||
if (can_I_read(cur->relation()))
|
||||
err = get_relation()->read(_isequal, _testandlock);
|
||||
if (c == NULL)
|
||||
delete cur;
|
||||
}
|
||||
else
|
||||
err = file().next(_testandlock);
|
||||
break;
|
||||
case K_PREV:
|
||||
file().reread();
|
||||
if (has_filtered_cursor())
|
||||
{
|
||||
TCursor& cur = get_filtered_cursor();
|
||||
cur.curr() = file().curr();
|
||||
cur.read();
|
||||
--cur;
|
||||
file().curr() = cur.curr();
|
||||
err = get_relation()->read(_isequal, _testandlock);
|
||||
TCursor* c = get_filtered_cursor();
|
||||
|
||||
if (!has_filtered_cursor() || c->curr().num() != file().curr().num())
|
||||
{
|
||||
for (TEdit_field* e = (TEdit_field *) _mask->get_key_field(1, TRUE); e; e = (TEdit_field *) _mask->get_key_field(1, FALSE))
|
||||
{
|
||||
if (e->shown() && e->browse() != NULL) // Ignora campi invisibili o senza check
|
||||
{
|
||||
TCursor* b = e->browse()->cursor();
|
||||
|
||||
if (b && b->curr().num() == file().curr().num())
|
||||
{
|
||||
c = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TCursor* cur = c ;
|
||||
|
||||
if (c == NULL)
|
||||
cur = new TCursor(get_relation());
|
||||
|
||||
file().reread();
|
||||
cur->curr() = file().curr();
|
||||
cur->read();
|
||||
--(*cur);
|
||||
while (cur->pos() > 0 && !can_I_read(cur->relation()))
|
||||
--(*cur);
|
||||
file().curr() = cur->curr();
|
||||
if (can_I_read(cur->relation()))
|
||||
err = get_relation()->read(_isequal, _testandlock);
|
||||
if (c == NULL)
|
||||
delete cur;
|
||||
}
|
||||
else
|
||||
err = file().prev(_testandlock);
|
||||
break;
|
||||
case K_END:
|
||||
err = file().readat(_last, _testandlock);
|
||||
@ -1601,6 +1673,18 @@ void TRelation_application::main_loop()
|
||||
ini.set("Result", err == NOERR ? "CANCEL" : "ERROR");
|
||||
ini.set("Error", err);
|
||||
}
|
||||
if (_curr_trans_mode == TM_BATCH)
|
||||
{
|
||||
TString_array & errs = errors();
|
||||
|
||||
FOR_EACH_ARRAY_ROW(errs, r, s)
|
||||
ini.set("ErrMsg", *s, "Main", false, r);
|
||||
|
||||
TString_array & warns = warnings();
|
||||
|
||||
FOR_EACH_ARRAY_ROW(warns, r1, s1)
|
||||
ini.set("WarningMsg", *s1, "Main", false, r1);
|
||||
}
|
||||
|
||||
}
|
||||
_trans_counter++;
|
||||
|
568
include/relapp.h
568
include/relapp.h
@ -1,283 +1,285 @@
|
||||
#ifndef __RELAPP_H
|
||||
#define __RELAPP_H
|
||||
|
||||
#ifndef __APPLICAT_H
|
||||
#include <applicat.h>
|
||||
#endif
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef __RELATION_H
|
||||
#include <relation.h>
|
||||
#endif
|
||||
|
||||
#ifndef __MASK_H
|
||||
#include <mask.h>
|
||||
#endif
|
||||
|
||||
#define TRANSACTION_RUN "RUN" // Run application (eventually sets firm)
|
||||
#define TRANSACTION_INSERT "INSERT" // Create a new record and fill it
|
||||
#define TRANSACTION_MODIFY "MODIFY" // Load and modify an existing record
|
||||
#define TRANSACTION_DELETE "DELETE" // Delete an existing record
|
||||
#define TRANSACTION_LINK "LINK" // Load an existing record and interactively edit it
|
||||
#define TM_INTERACTIVE 'I'
|
||||
#define TM_AUTOMATIC 'A'
|
||||
#define TM_REMAIN 'R'
|
||||
// @doc EXTERNAL
|
||||
|
||||
// @class TRelation_application | Classe per la gestione di una applicazione di manutenzione di uno
|
||||
// o piu' archivi utilizzando una relazione
|
||||
//
|
||||
// @base public | TApplication
|
||||
class TRelation_application : public TSkeleton_application
|
||||
|
||||
// @author:(INTERNAL) Guido
|
||||
|
||||
// @access:(INTERNAL) Private Member
|
||||
{
|
||||
// @cmember:(INTERNAL) Maschera corrente dell'applicazione
|
||||
TMask* _mask;
|
||||
// @cmember:(INTERNAL) Primo record
|
||||
TRecnotype _first;
|
||||
// @cmember:(INTERNAL) Ultimo record
|
||||
TRecnotype _last;
|
||||
// @cmember:(INTERNAL) Campo da utilizzare col bottone Ricerca
|
||||
int _search_id;
|
||||
|
||||
// @cmember:(INTERNAL) Nome del programma chiamante
|
||||
TString _autoins_caller;
|
||||
// @cmember:(INTERNAL) Numero del record nuovo/editato
|
||||
long _recins;
|
||||
|
||||
// @cmember:(INTERNAL) Indica se e' stato chiamato col messaggio di link
|
||||
byte _lnflag;
|
||||
// @cmember:(INTERNAL) Contiene il codice del campo e il valore fisso
|
||||
TToken_string _fixed;
|
||||
// @cmember:(INTERNAL) Messaggio da passare all'utente per indicare che e' stata fatta la rinumerazione
|
||||
TString _renum_message;
|
||||
|
||||
// @cmember:(INTERNAL) Nomi dei file .ini con la transazione da eseguire
|
||||
TString_array _trans_ini;
|
||||
// @cmember:(INTERNAL) Numero di file .ini di transazioni
|
||||
int _ntransactions;
|
||||
// @cmember:(INTERNAL) Indice del file .ini di _ini con la transazione da eseguire
|
||||
int _trans_counter;
|
||||
// @cmember:(INTERNAL) Azione della transazione corrente
|
||||
TString _curr_transaction;
|
||||
// @cmember:(INTERNAL) Modalità di esecuzione della transazione corrente (Automatica o interattiva)
|
||||
char _curr_trans_mode;
|
||||
// @cmember:(INTERNAL) Transazione ricevuta da .....
|
||||
TString _curr_trans_from;
|
||||
// @cmember:(INTERNAL) Flag di cancellazione automatica veloce
|
||||
int _autodelete;
|
||||
// @cmember:(INTERNAL) Flag di navigazione tramite toolbar
|
||||
bool _navigating;
|
||||
|
||||
private:
|
||||
// @cmember:(INTERNAL) Carica la transazione corrente (protocollo via .ini)
|
||||
bool load_transaction() ;
|
||||
|
||||
// @cmember:(INTERNAL) Setta i campi fissati da <md TRelation_application::_fixed>
|
||||
bool filter();
|
||||
// @cmember:(INTERNAL) Controlla se una chiave e' completa ed esiste su file
|
||||
bool test_key(word k, bool err);
|
||||
// @cmember:(INTERNAL) Abilita la ricerca sulla maschera
|
||||
void enable_query();
|
||||
// @cmember:(INTERNAL) Setta i limiti
|
||||
void set_limits(byte what = 0x3);
|
||||
// @cmember:(INTERNAL) Abilita i vari bottoni di ricerca della toolbar
|
||||
void set_toolbar();
|
||||
|
||||
// @Setta i filtri di lettura
|
||||
void set_key_filter();
|
||||
// @cmember:(INTERNAL) Posiziona l'applicazione in modo richiesta/inserimento (chiama <mf TRelation_application::query_mode>)
|
||||
void query_insert_mode()
|
||||
{ query_mode(TRUE); }
|
||||
// @cmember:(INTERNAL) Entra in modo inserimento
|
||||
void insert_mode();
|
||||
// @cmember:(INTERNAL) Cancella il record corrente
|
||||
bool relation_remove();
|
||||
// @cmember:(INTERNAL) Ritorna il campo di ricerca della maschera
|
||||
TEdit_field& get_search_field() const;
|
||||
|
||||
// @cmember:(INTERNAL) Permette di autonumerare un record
|
||||
bool autonum(TMask* m, bool rec);
|
||||
// @cmember:(INTERNAL) Controlla se il <c TCursor> ha un filtro
|
||||
virtual bool has_filtered_cursor() const;
|
||||
virtual TCursor& get_filtered_cursor() const;
|
||||
|
||||
// @cmember:(INTERNAL) Sistema il bottone ricerca se necessario
|
||||
void set_find_button();
|
||||
short mask_field_dirty() const;
|
||||
|
||||
// @access Protected Member
|
||||
protected: // TApplication
|
||||
// @cmember Effettua i controlli all'inizio dell'applicazione
|
||||
virtual bool create();
|
||||
// @cmember Effettua i controlli alla fine dell'applicazione
|
||||
virtual bool destroy();
|
||||
// @cmember Controlla se e' possibile modificare la ditta corrente durante l'esecuzione dell'applicazione
|
||||
virtual bool firm_change_enabled() const;
|
||||
// @cmember Aggiorna i limiti di ricerca sul cambio ditta
|
||||
virtual void on_firm_change();
|
||||
|
||||
// @access Protected Member
|
||||
protected:
|
||||
// @cmember Ritorna il descrittore del file principale della relazione
|
||||
TLocalisamfile& file() const
|
||||
{ return get_relation()->lfile(); }
|
||||
// @cmember Ritorna il primo record
|
||||
TRecnotype first() const
|
||||
{ return _first;}
|
||||
// @cmember Ritorna l'ultimo record
|
||||
TRecnotype last() const
|
||||
{ return _last;}
|
||||
// @cmember Ritorna il nome del programma chiamante
|
||||
const TString& autoins_caller() const
|
||||
{ return _autoins_caller;}
|
||||
// @cmember:(INTERNAL) Seleziona il nuovo modo e ritorna il vecchio
|
||||
int set_mode(int mode);
|
||||
|
||||
// @cmember Ciclo principale
|
||||
virtual void main_loop();
|
||||
|
||||
// @cmember Inizializzazione dei dati dell'utente
|
||||
virtual bool user_create() pure;
|
||||
// @cmember Distruzione dei dati dell'utente
|
||||
virtual bool user_destroy() pure;
|
||||
|
||||
// @cmember Fissa i campi non modificabili
|
||||
void set_fixed();
|
||||
// @cmember Attiva la maschera di ricerca
|
||||
bool search_mode();
|
||||
// @cmember Attiva la maschera di eliminazione
|
||||
int delete_mode();
|
||||
// @cmember Entra in modo di ricerca
|
||||
void query_mode(bool pre_ins = FALSE);
|
||||
// @cmember Entra in modo modifica
|
||||
bool modify_mode();
|
||||
// @cmember Legge i campi chiave della maschera e setta il cursore relativo
|
||||
void setkey();
|
||||
// @cmember Indica se la futura <mf TRelation_application::get_mask> ritornera' una maschera diversa
|
||||
// dalla corrente.
|
||||
// <nl>La richiesta della maschera da utilizzare per ogni fase di lavoro
|
||||
// (ricerca, inserimento, modifica) avviene sempre in due tempi: <mf TRelation_application::changing_mask> e
|
||||
// <mf TRelation_application::get_mask>. Cio' serve per gestire correttamente le applicazioni
|
||||
// con maschere multiple.
|
||||
virtual bool changing_mask(int mode) { return false; }
|
||||
// @cmember Richiede la maschera da usare
|
||||
virtual TMask* get_mask(int mode) pure;
|
||||
|
||||
// @cmember:(INTERNAL) Annulla la modifica di un record: toglie il lock
|
||||
void edit_cancel();
|
||||
// @cmember:(INTERNAL) Salva i contenuti della maschera su file
|
||||
virtual bool save(bool check_dirty);
|
||||
// @cmember Legge dalla relazione i valori nella maschera <p m>
|
||||
virtual int read(TMask& m);
|
||||
// @cmember Scrive sulla relazione i valori dalla maschera <p m>
|
||||
virtual int write(const TMask& m);
|
||||
// @cmember Riscrive sulla relazione i valori dalla maschera <p m>
|
||||
virtual int rewrite(const TMask& m);
|
||||
// @cmember Cancella il record corrente
|
||||
virtual bool remove();
|
||||
|
||||
// @cmember Deve ritornare una stringa nella forma CAMPO1<pipe>VALORE1<pipe>CAMPO2<pipe>VALORE2<pipe>...
|
||||
// <pipe>CAMPOn<pipe>VALOREn contenente le coppie NUMERO_CAMPO_MASCHERA - VALORE_DA_ASSEGNARE
|
||||
// che descrivono il prossimo codice libero da utilizzare per la autonumerazione.
|
||||
// <nl>Nel caso di banale numerazione progressiva potrebbe essere implementata come
|
||||
// return format("%d<pipe>%s", F_NUM, get_relation()-<gt>items());
|
||||
virtual const char* get_next_key()
|
||||
{ return ""; }
|
||||
virtual bool get_next_key(TToken_string& key)
|
||||
{ return false; }
|
||||
|
||||
// @cmember Richiede se il record corrente e' protetto (non cancellabile)
|
||||
virtual bool protected_record(TRectype&)
|
||||
{ return false; }
|
||||
|
||||
// @cmember Richiede se il record corrente e' protetto (non cancellabile)
|
||||
virtual bool protected_record(TRelation &);
|
||||
|
||||
virtual bool can_I_write(const TRelation* rel) const;
|
||||
virtual bool can_I_read(const TRelation* rel) const;
|
||||
|
||||
// @cmember Inizializza la maschera per il modo ricerca
|
||||
virtual void init_query_mode(TMask&)
|
||||
{ }
|
||||
// @cmember Inizializza la maschera per il modo ricerca ed inserimento (chiama <mf TRelation_application::init_query_mode>)
|
||||
virtual void init_query_insert_mode(TMask& m)
|
||||
{ init_query_mode(m); }
|
||||
// @cmember Inizializza la maschera per il modo inserimento
|
||||
virtual void init_insert_mode(TMask&)
|
||||
{ }
|
||||
// @cmember Inizializza la maschera per il modo modifica
|
||||
virtual void init_modify_mode(TMask&)
|
||||
{ }
|
||||
|
||||
// @cmember Indica se abilitare/disabilitare la scrittura sul file
|
||||
// principale (vedi <mf TRealtion::write_enable>)
|
||||
virtual void write_enable(bool on = TRUE)
|
||||
{ get_relation()->write_enable(0, on); }
|
||||
// @cmember Indica se disabilitare la scrittura sul file principale (vedi <mf TRealtion::write_enable>)
|
||||
void write_disable()
|
||||
{ write_enable(FALSE); }
|
||||
|
||||
// @cmember Dopo aver salvato si predispone per un nuovo inserimento
|
||||
virtual bool save_and_new() const;
|
||||
// @cmember Deve uscire dal programma dopo aver salvato con successo?
|
||||
virtual bool save_and_quit() const;
|
||||
|
||||
// @cmember Impone il campo da utilizzare col bottone Ricerca
|
||||
void set_search_field(short id)
|
||||
{ _search_id = id;}
|
||||
byte autodeleting() const { return _autodelete; }
|
||||
bool navigating() const { return _navigating; }
|
||||
bool parse_command_line();
|
||||
void ini2query_mask();
|
||||
void ini2insert_mask();
|
||||
void edit_mask2ini();
|
||||
virtual void ini2sheet(TConfig& ini, TSheet_field &sheet);
|
||||
virtual void sheet2ini(TSheet_field &sheet,TConfig& ini);
|
||||
virtual void ini2mask(TConfig& ini, TMask& m, bool query);
|
||||
virtual bool mask2mail(const TMask& m);
|
||||
// @cmember Breve descrizione del tipo documento corrente
|
||||
virtual const char* record_description(const TRelation& r) const;
|
||||
|
||||
// @access Public Member
|
||||
public:
|
||||
virtual void mask2ini(const TMask& m, TConfig& ini);
|
||||
// @cmember Ritorna la relazione da modificare
|
||||
virtual TRelation* get_relation() const pure;
|
||||
|
||||
// @cmember Ricalcola l'attivazione dei bottoni di navigazione
|
||||
void update_navigation_bar();
|
||||
|
||||
// @cmember Ritorna la maschera corrente
|
||||
TMask& curr_mask() const
|
||||
{ return *_mask; }
|
||||
|
||||
// @cmember Ritorna se sono stati posti dei filtri sul file corrente
|
||||
virtual bool filtered() const
|
||||
{ return _fixed.not_empty(); }
|
||||
// @cmember Cerca un record corrispondente alla chiave <p key> (0 prima chiave completa)
|
||||
virtual bool find(word key = 0);
|
||||
// @cmember Costruisce il membro <md TRelation_application::_fixed>
|
||||
void set_link(TMask & m, const char * keyexpr);
|
||||
// @cmember Ritorna TRUE se e' stato chiamato col messaggio di link
|
||||
bool lnflag() const { return _lnflag != 0;}
|
||||
// @cmember Ritorna TRUE se e' una transazione
|
||||
virtual bool is_transaction() const { return _curr_transaction.not_empty(); }
|
||||
|
||||
virtual word class_id() const { return CLASS_RELATION_APPLICATION; }
|
||||
|
||||
// @cmember Costruttore
|
||||
TRelation_application();
|
||||
// @cmember Distruttore
|
||||
virtual ~TRelation_application();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef __RELAPP_H
|
||||
#define __RELAPP_H
|
||||
|
||||
#ifndef __APPLICAT_H
|
||||
#include <applicat.h>
|
||||
#endif
|
||||
|
||||
#ifndef __CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef __RELATION_H
|
||||
#include <relation.h>
|
||||
#endif
|
||||
|
||||
#ifndef __MASK_H
|
||||
#include <mask.h>
|
||||
#endif
|
||||
|
||||
#define TRANSACTION_RUN "RUN" // Run application (eventually sets firm)
|
||||
#define TRANSACTION_INSERT "INSERT" // Create a new record and fill it
|
||||
#define TRANSACTION_MODIFY "MODIFY" // Load and modify an existing record
|
||||
#define TRANSACTION_DELETE "DELETE" // Delete an existing record
|
||||
#define TRANSACTION_LINK "LINK" // Load an existing record and interactively edit it
|
||||
#define TM_INTERACTIVE 'I'
|
||||
#define TM_AUTOMATIC 'A'
|
||||
#define TM_REMAIN 'R'
|
||||
#define TM_BATCH 'B'
|
||||
// @doc EXTERNAL
|
||||
|
||||
// @class TRelation_application | Classe per la gestione di una applicazione di manutenzione di uno
|
||||
// o piu' archivi utilizzando una relazione
|
||||
//
|
||||
// @base public | TApplication
|
||||
class TRelation_application : public TSkeleton_application
|
||||
|
||||
// @author:(INTERNAL) Guido
|
||||
|
||||
// @access:(INTERNAL) Private Member
|
||||
{
|
||||
// @cmember:(INTERNAL) Maschera corrente dell'applicazione
|
||||
TMask* _mask;
|
||||
// @cmember:(INTERNAL) Primo record
|
||||
TRecnotype _first;
|
||||
// @cmember:(INTERNAL) Ultimo record
|
||||
TRecnotype _last;
|
||||
// @cmember:(INTERNAL) Campo da utilizzare col bottone Ricerca
|
||||
int _search_id;
|
||||
|
||||
// @cmember:(INTERNAL) Nome del programma chiamante
|
||||
TString _autoins_caller;
|
||||
// @cmember:(INTERNAL) Numero del record nuovo/editato
|
||||
long _recins;
|
||||
|
||||
// @cmember:(INTERNAL) Indica se e' stato chiamato col messaggio di link
|
||||
byte _lnflag;
|
||||
// @cmember:(INTERNAL) Contiene il codice del campo e il valore fisso
|
||||
TToken_string _fixed;
|
||||
// @cmember:(INTERNAL) Messaggio da passare all'utente per indicare che e' stata fatta la rinumerazione
|
||||
TString _renum_message;
|
||||
|
||||
// @cmember:(INTERNAL) Nomi dei file .ini con la transazione da eseguire
|
||||
TString_array _trans_ini;
|
||||
// @cmember:(INTERNAL) Numero di file .ini di transazioni
|
||||
int _ntransactions;
|
||||
// @cmember:(INTERNAL) Indice del file .ini di _ini con la transazione da eseguire
|
||||
int _trans_counter;
|
||||
// @cmember:(INTERNAL) Azione della transazione corrente
|
||||
TString _curr_transaction;
|
||||
// @cmember:(INTERNAL) Modalità di esecuzione della transazione corrente (Automatica o interattiva)
|
||||
char _curr_trans_mode;
|
||||
// @cmember:(INTERNAL) Transazione ricevuta da .....
|
||||
TString _curr_trans_from;
|
||||
// @cmember:(INTERNAL) Flag di cancellazione automatica veloce
|
||||
int _autodelete;
|
||||
// @cmember:(INTERNAL) Flag di navigazione tramite toolbar
|
||||
bool _navigating;
|
||||
bool _locked;
|
||||
|
||||
private:
|
||||
// @cmember:(INTERNAL) Carica la transazione corrente (protocollo via .ini)
|
||||
bool load_transaction() ;
|
||||
|
||||
// @cmember:(INTERNAL) Setta i campi fissati da <md TRelation_application::_fixed>
|
||||
bool filter();
|
||||
// @cmember:(INTERNAL) Controlla se una chiave e' completa ed esiste su file
|
||||
bool test_key(word k, bool err);
|
||||
// @cmember:(INTERNAL) Abilita la ricerca sulla maschera
|
||||
void enable_query();
|
||||
// @cmember:(INTERNAL) Setta i limiti
|
||||
void set_limits(byte what = 0x3);
|
||||
// @cmember:(INTERNAL) Abilita i vari bottoni di ricerca della toolbar
|
||||
void set_toolbar();
|
||||
|
||||
// @Setta i filtri di lettura
|
||||
void set_key_filter();
|
||||
// @cmember:(INTERNAL) Posiziona l'applicazione in modo richiesta/inserimento (chiama <mf TRelation_application::query_mode>)
|
||||
void query_insert_mode()
|
||||
{ query_mode(TRUE); }
|
||||
// @cmember:(INTERNAL) Entra in modo inserimento
|
||||
void insert_mode();
|
||||
// @cmember:(INTERNAL) Cancella il record corrente
|
||||
bool relation_remove();
|
||||
// @cmember:(INTERNAL) Ritorna il campo di ricerca della maschera
|
||||
TEdit_field& get_search_field() const;
|
||||
|
||||
// @cmember:(INTERNAL) Permette di autonumerare un record
|
||||
bool autonum(TMask* m, bool rec);
|
||||
// @cmember:(INTERNAL) Controlla se il <c TCursor> ha un filtro
|
||||
virtual bool has_filtered_cursor() const;
|
||||
virtual TCursor* get_filtered_cursor() const;
|
||||
|
||||
// @cmember:(INTERNAL) Sistema il bottone ricerca se necessario
|
||||
void set_find_button();
|
||||
short mask_field_dirty() const;
|
||||
|
||||
// @access Protected Member
|
||||
protected: // TApplication
|
||||
// @cmember Effettua i controlli all'inizio dell'applicazione
|
||||
virtual bool create();
|
||||
// @cmember Effettua i controlli alla fine dell'applicazione
|
||||
virtual bool destroy();
|
||||
// @cmember Controlla se e' possibile modificare la ditta corrente durante l'esecuzione dell'applicazione
|
||||
virtual bool firm_change_enabled() const;
|
||||
// @cmember Aggiorna i limiti di ricerca sul cambio ditta
|
||||
virtual void on_firm_change();
|
||||
|
||||
// @access Protected Member
|
||||
protected:
|
||||
// @cmember Ritorna il descrittore del file principale della relazione
|
||||
TLocalisamfile& file() const
|
||||
{ return get_relation()->lfile(); }
|
||||
// @cmember Ritorna il primo record
|
||||
TRecnotype first() const
|
||||
{ return _first;}
|
||||
// @cmember Ritorna l'ultimo record
|
||||
TRecnotype last() const
|
||||
{ return _last;}
|
||||
// @cmember Ritorna il nome del programma chiamante
|
||||
const TString& autoins_caller() const
|
||||
{ return _autoins_caller;}
|
||||
// @cmember:(INTERNAL) Seleziona il nuovo modo e ritorna il vecchio
|
||||
int set_mode(int mode);
|
||||
|
||||
// @cmember Ciclo principale
|
||||
virtual void main_loop();
|
||||
|
||||
// @cmember Inizializzazione dei dati dell'utente
|
||||
virtual bool user_create() pure;
|
||||
// @cmember Distruzione dei dati dell'utente
|
||||
virtual bool user_destroy() pure;
|
||||
|
||||
// @cmember Fissa i campi non modificabili
|
||||
void set_fixed();
|
||||
// @cmember Attiva la maschera di ricerca
|
||||
bool search_mode();
|
||||
// @cmember Attiva la maschera di eliminazione
|
||||
int delete_mode();
|
||||
// @cmember Entra in modo di ricerca
|
||||
void query_mode(bool pre_ins = FALSE);
|
||||
// @cmember Entra in modo modifica
|
||||
bool modify_mode();
|
||||
// @cmember Legge i campi chiave della maschera e setta il cursore relativo
|
||||
void setkey();
|
||||
// @cmember Indica se la futura <mf TRelation_application::get_mask> ritornera' una maschera diversa
|
||||
// dalla corrente.
|
||||
// <nl>La richiesta della maschera da utilizzare per ogni fase di lavoro
|
||||
// (ricerca, inserimento, modifica) avviene sempre in due tempi: <mf TRelation_application::changing_mask> e
|
||||
// <mf TRelation_application::get_mask>. Cio' serve per gestire correttamente le applicazioni
|
||||
// con maschere multiple.
|
||||
virtual bool changing_mask(int mode) { return false; }
|
||||
// @cmember Richiede la maschera da usare
|
||||
virtual TMask* get_mask(int mode) pure;
|
||||
|
||||
// @cmember:(INTERNAL) Annulla la modifica di un record: toglie il lock
|
||||
void edit_cancel();
|
||||
// @cmember:(INTERNAL) Salva i contenuti della maschera su file
|
||||
virtual bool save(bool check_dirty);
|
||||
// @cmember Legge dalla relazione i valori nella maschera <p m>
|
||||
virtual int read(TMask& m);
|
||||
// @cmember Scrive sulla relazione i valori dalla maschera <p m>
|
||||
virtual int write(const TMask& m);
|
||||
// @cmember Riscrive sulla relazione i valori dalla maschera <p m>
|
||||
virtual int rewrite(const TMask& m);
|
||||
// @cmember Cancella il record corrente
|
||||
virtual bool remove();
|
||||
|
||||
// @cmember Deve ritornare una stringa nella forma CAMPO1<pipe>VALORE1<pipe>CAMPO2<pipe>VALORE2<pipe>...
|
||||
// <pipe>CAMPOn<pipe>VALOREn contenente le coppie NUMERO_CAMPO_MASCHERA - VALORE_DA_ASSEGNARE
|
||||
// che descrivono il prossimo codice libero da utilizzare per la autonumerazione.
|
||||
// <nl>Nel caso di banale numerazione progressiva potrebbe essere implementata come
|
||||
// return format("%d<pipe>%s", F_NUM, get_relation()-<gt>items());
|
||||
virtual const char* get_next_key()
|
||||
{ return ""; }
|
||||
virtual bool get_next_key(TToken_string& key)
|
||||
{ return false; }
|
||||
|
||||
// @cmember Richiede se il record corrente e' protetto (non cancellabile)
|
||||
virtual bool protected_record(TRectype&)
|
||||
{ return _locked; }
|
||||
|
||||
// @cmember Richiede se il record corrente e' protetto (non cancellabile)
|
||||
virtual bool protected_record(TRelation &);
|
||||
|
||||
virtual bool can_I_write(const TRelation* rel) const;
|
||||
virtual bool can_I_read(const TRelation* rel) const;
|
||||
|
||||
// @cmember Inizializza la maschera per il modo ricerca
|
||||
virtual void init_query_mode(TMask&)
|
||||
{ _locked = false; }
|
||||
// @cmember Inizializza la maschera per il modo ricerca ed inserimento (chiama <mf TRelation_application::init_query_mode>)
|
||||
virtual void init_query_insert_mode(TMask& m)
|
||||
{ init_query_mode(m); }
|
||||
// @cmember Inizializza la maschera per il modo inserimento
|
||||
virtual void init_insert_mode(TMask&)
|
||||
{ }
|
||||
// @cmember Inizializza la maschera per il modo modifica
|
||||
virtual void init_modify_mode(TMask&)
|
||||
{ }
|
||||
|
||||
// @cmember Indica se abilitare/disabilitare la scrittura sul file
|
||||
// principale (vedi <mf TRealtion::write_enable>)
|
||||
virtual void write_enable(bool on = TRUE)
|
||||
{ get_relation()->write_enable(0, on); }
|
||||
// @cmember Indica se disabilitare la scrittura sul file principale (vedi <mf TRealtion::write_enable>)
|
||||
void write_disable()
|
||||
{ write_enable(FALSE); }
|
||||
|
||||
// @cmember Dopo aver salvato si predispone per un nuovo inserimento
|
||||
virtual bool save_and_new() const;
|
||||
// @cmember Deve uscire dal programma dopo aver salvato con successo?
|
||||
virtual bool save_and_quit() const;
|
||||
|
||||
// @cmember Impone il campo da utilizzare col bottone Ricerca
|
||||
void set_search_field(short id)
|
||||
{ _search_id = id;}
|
||||
byte autodeleting() const { return _autodelete; }
|
||||
bool navigating() const { return _navigating; }
|
||||
bool parse_command_line();
|
||||
void ini2query_mask();
|
||||
void ini2insert_mask();
|
||||
void edit_mask2ini();
|
||||
virtual void ini2sheet(TConfig& ini, TSheet_field &sheet);
|
||||
virtual void sheet2ini(TSheet_field &sheet,TConfig& ini);
|
||||
virtual void ini2mask(TConfig& ini, TMask& m, bool query);
|
||||
virtual bool mask2mail(const TMask& m);
|
||||
// @cmember Breve descrizione del tipo documento corrente
|
||||
virtual const char* record_description(const TRelation& r) const;
|
||||
|
||||
// @access Public Member
|
||||
public:
|
||||
virtual void mask2ini(const TMask& m, TConfig& ini);
|
||||
// @cmember Ritorna la relazione da modificare
|
||||
virtual TRelation* get_relation() const pure;
|
||||
|
||||
// @cmember Ricalcola l'attivazione dei bottoni di navigazione
|
||||
void update_navigation_bar();
|
||||
|
||||
// @cmember Ritorna la maschera corrente
|
||||
TMask& curr_mask() const
|
||||
{ return *_mask; }
|
||||
|
||||
// @cmember Ritorna se sono stati posti dei filtri sul file corrente
|
||||
virtual bool filtered() const
|
||||
{ return _fixed.not_empty(); }
|
||||
// @cmember Cerca un record corrispondente alla chiave <p key> (0 prima chiave completa)
|
||||
virtual bool find(word key = 0);
|
||||
// @cmember Costruisce il membro <md TRelation_application::_fixed>
|
||||
void set_link(TMask & m, const char * keyexpr);
|
||||
// @cmember Ritorna TRUE se e' stato chiamato col messaggio di link
|
||||
bool lnflag() const { return _lnflag != 0;}
|
||||
// @cmember Ritorna TRUE se e' una transazione
|
||||
virtual bool is_transaction() const { return _curr_transaction.not_empty(); }
|
||||
|
||||
virtual word class_id() const { return CLASS_RELATION_APPLICATION; }
|
||||
|
||||
// @cmember Costruttore
|
||||
TRelation_application();
|
||||
// @cmember Distruttore
|
||||
virtual ~TRelation_application();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -1533,7 +1533,7 @@ void TCursor::setkey(int nkey)
|
||||
}
|
||||
}
|
||||
|
||||
int TCursor::test(TIsamop op, TReclock lockop) const
|
||||
int TCursor::test(TIsamop op, TReclock lockop)
|
||||
{
|
||||
TLocalisamfile& curfile = file();
|
||||
const TRectype& currec = curfile.curr();
|
||||
@ -2049,7 +2049,9 @@ const char* TSorted_cursor::fill_sort_key(TString& k)
|
||||
{
|
||||
const bool is_up = is_upper(s);
|
||||
const char last = s.right(1)[0];
|
||||
if (last == '-' || last == '+')
|
||||
const bool align = last == '*';
|
||||
|
||||
if (last == '-' || last == '+' || align)
|
||||
s.rtrim(1);
|
||||
|
||||
const TFieldref f(s,0);
|
||||
@ -2072,7 +2074,7 @@ const char* TSorted_cursor::fill_sort_key(TString& k)
|
||||
}
|
||||
else
|
||||
{
|
||||
// if (is_up) // Test inutile: tutte le chiavi sono maiuscole 08-02-2016
|
||||
if (is_up) // Test inutile: tutte le chiavi sono maiuscole 08-02-2016
|
||||
sf.upper();
|
||||
}
|
||||
switch (fld_type)
|
||||
@ -2080,9 +2082,24 @@ const char* TSorted_cursor::fill_sort_key(TString& k)
|
||||
case _boolfld:
|
||||
case _charfld:
|
||||
case _memofld:
|
||||
case _alfafld: sf.left_just(fld_len); break;
|
||||
case _alfafld: sf.left_just(fld_len > 0 ? fld_len : 50); break;
|
||||
case _intfld:
|
||||
case _longfld:
|
||||
case _intzerofld:
|
||||
case _longzerofld: sf.right_just(fld_len > 0 ? fld_len : 50); break;
|
||||
case _datefld: break; // Gia' lungo 8!
|
||||
default : sf.right_just(fld_len); break;
|
||||
case _realfld:
|
||||
if (align)
|
||||
{
|
||||
real r(sf);
|
||||
sf = r.string(fld_len > 0 ? fld_len : 50, fld_len > 0 ? (fld_len-4)/2 : 10);
|
||||
}
|
||||
else
|
||||
sf.right_just(fld_len > 0 ? fld_len : 50);
|
||||
break;
|
||||
default :
|
||||
sf.left_just(fld_len > 0 ? fld_len : 50);
|
||||
break;
|
||||
}
|
||||
k << sf;
|
||||
}
|
||||
@ -2103,6 +2120,96 @@ bool TSorted_cursor::changed()
|
||||
return rt;
|
||||
}
|
||||
|
||||
int TSorted_cursor::test(TIsamop op, TReclock lockop)
|
||||
|
||||
{
|
||||
int err = NOERR;
|
||||
|
||||
if (items() == 0L)
|
||||
{
|
||||
err = _isemptyfile;
|
||||
file().setstatus(err);
|
||||
return err;
|
||||
}
|
||||
|
||||
TString256 searching; fill_sort_key(searching);
|
||||
searching.rtrim();
|
||||
const int cmplen = searching.len();
|
||||
|
||||
TRecnotype first = 0L;
|
||||
TRecnotype last = items()-1;
|
||||
TRecnotype found = -1L;
|
||||
|
||||
FOR_EACH_ARRAY_ROW(fpkey(), i, s)
|
||||
{
|
||||
const int cmp = searching.compare(*s, cmplen);
|
||||
if (cmp <= 0)
|
||||
last = (i + 1) * pagesize() - 1;
|
||||
else
|
||||
first = i * pagesize();
|
||||
}
|
||||
|
||||
const bool ghiacciato = !frozen();
|
||||
if (ghiacciato) freeze(true);
|
||||
|
||||
TString256 testing;
|
||||
while (first <= last)
|
||||
{
|
||||
const TRecnotype test = (first+last)/2;
|
||||
TCursor::operator=(test); // verif
|
||||
fill_sort_key(testing);
|
||||
const int cmp = searching.compare(testing, cmplen);
|
||||
if (cmp == 0)
|
||||
{
|
||||
if (op != _isgreat)
|
||||
{
|
||||
if (found < 0l || test < found)
|
||||
found = test;
|
||||
last = test-1;
|
||||
}
|
||||
else
|
||||
first = test+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cmp < 0)
|
||||
{
|
||||
last = test-1;
|
||||
if (op != _isequal)
|
||||
{
|
||||
if (found < 0l || test < found)
|
||||
found = test;
|
||||
}
|
||||
}
|
||||
else
|
||||
first = test+1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found >= 0L)
|
||||
{
|
||||
TCursor::operator=(found); // verif
|
||||
file().setstatus(NOERR);
|
||||
if (lockop != _nolock)
|
||||
lock(lockop);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
found = items()-1;
|
||||
if (found >= 0)
|
||||
TCursor::operator=(found);
|
||||
err = op == _isequal ? _iskeynotfound : _iseof;
|
||||
file().setstatus(err);
|
||||
}
|
||||
|
||||
if (ghiacciato)
|
||||
freeze(false);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
TRecnotype TSorted_cursor::read(TIsamop op, TReclock lockop)
|
||||
{
|
||||
TString256 searching; fill_sort_key(searching);
|
||||
|
@ -367,8 +367,8 @@ public:
|
||||
// @cmember Ritorna il descrittore della tabella
|
||||
TRectype& curr(const char * tab) const
|
||||
{ return _if->lfile(tab).curr(); }
|
||||
//@cmember Testa la presenza di un record senza spostare il cursore
|
||||
int test(TIsamop op = _isequal, TReclock lockop = _nolock) const;
|
||||
//@cmember Testa la presenza di un record
|
||||
virtual int test(TIsamop op = _isequal, TReclock lockop = _nolock);
|
||||
// @cmember Legge il record
|
||||
virtual TRecnotype read(TIsamop op = _isgteq, TReclock lockop = _nolock);
|
||||
// @cmember Mette un lock sul record
|
||||
@ -508,6 +508,10 @@ public:
|
||||
// @cmember Si sposta alla posizione <p nr>
|
||||
TRecnotype operator =(const TRecnotype nr)
|
||||
{ return TCursor::operator =(nr); }
|
||||
|
||||
//@cmember Testa la presenza di un record
|
||||
virtual int test(TIsamop op = _isequal, TReclock lockop = _nolock);
|
||||
|
||||
// @cmember Trova l'indice del record corrente
|
||||
virtual TRecnotype read(TIsamop op = _isgteq, TReclock lockop = _nolock);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user