campo-sirio/m770/770102.cpp
luca 4e24441a11 Patch level :10.0 992
Files correlati     :
Ricompilazione Demo : [ ]
Commento            :
0001852: 207705 - SRM - data competenza pagamento
Descrizione è richiesto che la data di competenza sulla scheda percipiente venga sempre compilata in automatico con la data del pagamento. Il dato deve rimanere modificabile dall'utente. Questo dovrebbe risolvere il problema delle stampe che attualmente selezionano per data competenza e sembrano non funzionare .


git-svn-id: svn://10.65.10.50/branches/R_10_00@22057 c028cbd2-c16b-5b4b-a496-9718f37d4682
2011-05-03 11:15:28 +00:00

895 lines
24 KiB
C++
Executable File
Raw Blame History

#include "770100a.h"
#include "770101.h"
#include "770102.h"
#include <tabutil.h>
void TSchedaPercipienti::init_mask(TMask& m, bool inserimento)
{
update_lasts(m);
// se collegamento
if (tipo_coll() != nessuno)
{
if (inserimento)
compila_testata(m);
else
{
// Recupera solo il numero di registrazione lasciando stare il resto
if (coll_numreg() > 0 && m.field(F_NUMREG).empty())
m.set(F_NUMREG, coll_numreg());
}
switch (tipo_coll())
{
case pagamento:
case occasionale:
// Compilo riga di pagamento SOLO SE NON ce ne sono gia'..
if ( (tipo_coll() == pagamento && _rel->pag_items() == 0) || tipo_coll() == occasionale )
{
const real totrit(m.get(F_TOTRIT));
const real totdoc(m.get(F_TOTDOC));
const real compenso(m.get(F_COMPENS));
const real spese(m.get(F_SPESE));
if ((tipo_coll() == pagamento && (_coll._compenso + totrit == totdoc) ) ||
(tipo_coll() == occasionale))
{
TSheet_field& pags = pag_sheet_enabled(m);
TRectype rpag(_rel->pag(0));
rpag.zero();
real& imponibile = _coll._compenso;
rpag.put("DATAPAG", _coll._datadoc);
rpag.put("COMPENSO", compenso);
rpag.put("SPESA", spese);
// Update spreadsheet
rec2row(pags.row(0), rpag, 0);
// ricalcolo riga pagamento
TString16 codcau(m.get(F_CODCAUS));
TTable cau("%ca7");
cau.zero();
cau.put("CODTAB", codcau);
if (cau.read() != NOERR)
warning_box("Causale non presente in tabella");
const real h_PercAssImp = cau.get_real("R4");
const real h_PercCassaPrev = cau.get_real("R5");
const real h_PercRitenuta = cau.get_real("R0");
const real h_PercInps = cau.get_real("R1");
const real h_PercAssImpInps = cau.get_real("R2");
const real h_PercCommitInps = cau.get_real("R3");
Pag_struct c;
Pag_struct s;
TToken_string& t = pags.row(0);
from_sheet_to_struct(t, s);
calcola_riga_pag(s,
c,
TRUE,
h_PercAssImp,
h_PercCassaPrev,
h_PercRitenuta,
h_PercInps,
h_PercAssImpInps,
h_PercCommitInps);
from_struct_to_sheet(s, t);
// forzo ridisegno sheet
pags.force_update();
}
}
default:
// per evitare di riscrivere tutto dopo registra
_coll._tipo_coll = nessuno;
break;
}
}
fill_sheet(m);
}
bool TSchedaPercipienti::vers_notify(TSheet_field& s, int r, KEY k)
{
switch(k)
{
// Inserimento riga
case K_INS:
// Impedisce inserimento di nuove righe
return FALSE;
// Inizio modifica riga
case K_SPACE:
{
// Pulisco descrizioni luogo e tipo versamento (solo se non gia' indicati!)
TSheet_field& vers = app().vers();
TMask& mp = vers.sheet_mask();
TString16 tipo(mp.get(F_TIPOVERS));
TString16 luo (mp.get(F_LUOVERS));
if (tipo.empty())
mp.reset(70);
if (luo.empty())
mp.reset(71);
break;
}
default:
break;
}
return TRUE;
}
bool TSchedaPercipienti::pags_notify(TSheet_field& s, int r, KEY k)
{
switch(k)
{
// Inserimento riga
case K_INS:
// Impedisce inserimento di nuove righe
return FALSE;
// Inizio modifica riga
case K_SPACE:
{
break;
}
// Fine modifica di una riga
case K_ENTER:
break;
default:
break;
}
return TRUE;
}
TSheet_field& TSchedaPercipienti::pags() const
{
TSheet_field& s = pag_sheet_enabled(curr_mask());
return s;
}
TSheet_field& TSchedaPercipienti::vers() const
{
TSheet_field& s = (TSheet_field&)curr_mask().field(F_VERSAMENTI);
return s;
}
bool TSchedaPercipienti::my_empty_items(TToken_string& r, bool vers)
{
TString rr;
// controlla se riga versamento significativa
if (vers)
for (int i=0; i < COLONNE_SIGNIFICATIVE_SPREADSHEET_VERSAMENTI; i++)
{
rr = r.get(i);
rr.trim();
switch (i) {
case 0: // 1015
if (rr.not_empty())
return FALSE;
break;
case 1:
if (rr.not_empty())
return FALSE;
break;
case 2: // lugo e tipo vers.
case 3:
if (rr.not_empty())
if (rr != "N")
return FALSE;
break;
case 4:
case 5:
if (rr.not_empty())
return FALSE;
break;
case 6:
if (rr.not_empty()) {
real rrr(real::ita2eng(rr));
if (rrr != ZERO)
return FALSE;
}
break;
default:
break;
}
}
// controlla se riga pagamento significativa
else
{
rr = r.get(token_pos("DATAPAG"));
rr.trim();
if (rr.not_empty())
return FALSE;
}
return TRUE;
}
void TSchedaPercipienti::pag_pack()
{
TString_array& rows = pags().rows_array();
const int max = rows.items();
for (int i = 0; i < max; i++)
{
TToken_string& r = (TToken_string&)rows[i];
if (my_empty_items(r, FALSE)) // Remove all empty strings
rows.destroy(i, FALSE);
}
rows.pack();
}
void TSchedaPercipienti::ver_pack()
{
TString_array& rows = vers().rows_array();
const int max = rows.items();
for (int i = 0; i < max; i++)
{
TToken_string& r = (TToken_string&)rows[i];
if (my_empty_items(r, TRUE)) // Remove all empty strings
rows.destroy(i, FALSE);
}
rows.pack();
}
// Inizializza array sheet dei pagamenti
void TSchedaPercipienti::load_pag_sheet(const long numvers)
{
real comp, spese, imp, ritpag;
int i, iNumRigaAS;
TSheet_field& pag = pags();
_pags->destroy();
// numero di riga dell'array-sheet. Viene incrementato
// solo quando si trovano pagamenti 'giusti' (cioe' solo
// quando si aggiungono elementi all'array-sheet)
iNumRigaAS = 0;
for ( i = 0; i < pag.items(); i++)
{
TToken_string* d = new TToken_string(64);
TToken_string& riga = pag.row(i);
// Scarto le righe non significative
if (my_empty_items(riga, FALSE)) continue;
const long nvers = riga.get_long(token_pos("NUMVERS"));
// "Se il pagamento e' gia' stato selezionato DA UN ALTRO versamento
// NON si deve vedere! "
if (nvers > 0 && nvers != numvers)
continue;
const long npag = i;
const int LARGHEZZA_COL = 15;
TString80 dep;
d->add(" "); // 0 spazio per la 'X' di selezione
dep = riga.get(token_pos("DATAPAG"));
d->add(dep); // 1 data pagamento
comp = riga.get(token_pos("COMPENSO"));
const TCurrency soldi_compenso(comp);
dep = soldi_compenso.string(TRUE);
dep.right_just(LARGHEZZA_COL);
d->add(dep); // 2 compenso
ritpag = riga.get(token_pos("RITENUTA"));
const TCurrency soldi_ritenuta(ritpag);
dep = soldi_ritenuta.string(TRUE);
dep.right_just(LARGHEZZA_COL);
d->add(dep); // 3 ritenuta
d->add(i); // 4 numero riga
d->add(nvers); // 5 numero versamento collegato
_pags->add(*d); // aggiungo la riga nell'array_sheet
// Setto il bit alla posizione numpag e metto la X
if (nvers == numvers)
{
_selected.set(npag);
_pags->check(iNumRigaAS, TRUE);
}
iNumRigaAS++; // ignoro in questo contatore i pagamenti che NON
// si vedono (se il pagamento e' scartato prima di qui
// non ci passa)
}
}
void TSchedaPercipienti::attach_pag_vers (int pag, long numvers)
{
TSheet_field& pag_s = pags();
TToken_string& riga = pag_s.row(pag);
// setta NUMVERS nello sheet
riga.destroy(token_pos("NUMVERS"));
riga.add(numvers, token_pos("NUMVERS"));
// setta NUMVERS nel record
_rel->pag(pag).put("NUMVERS", numvers);
}
void TSchedaPercipienti::detach_pag_vers (int pag)
{
TSheet_field& pag_s = pags();
TToken_string& riga = pag_s.row(pag);
riga.destroy(token_pos("NUMVERS"));
riga.add(-1L, token_pos("NUMVERS"));
// setta NUMVERS nel record
_rel->pag(pag).put("NUMVERS", -1L);
}
//
// VERS_ATTACHED ( numvers )
//
// Determina se c'e' ALMENO UN pagamento collegato al versamento NUMVERS
//
bool TSchedaPercipienti::vers_attached(const long numvers)
{
long numv = 0L;
// Aggiorna lo sheet dei pagamenti per questo versamento
app().load_pag_sheet(numvers);
for (int j = 0; j < _pags->items(); j++)
{
// Leggo NUMVERS
TToken_string& riga = _pags->row(j);
numv = riga.get_long(AS_POS_NVER);
if (numv > 0L)
if (numv == numvers)
return TRUE;
}
return FALSE;
}
//
// CHECK_PAGAMENTI
// Questo serve solo a impedire di uscire senza aver collegato almeno
// un pagamento
bool TSchedaPercipienti::check_pagamenti(TMask_field& f, KEY k)
{
const long numvers = get_numvers(f);
return app().vers_attached(numvers);
}
void TSchedaPercipienti::setta_ritvers(TMask_field& f, const real& ritenuta)
{
TString80 rit_str(ritenuta.string());
f.mask().set(F_RITVERS, rit_str);
f.mask().field(F_RITVERS).set_dirty(); // Forza on_hit()
}
// Guardo se ho compilato la data OPP. il flag 1015
// Leggo la maschera o la riga dello ss
bool TSchedaPercipienti::compilato_vers(TMask_field& f)
{
TString16 datav;
char v1015;
if (f.mask().is_running())
{
datav = f.mask().get(F_DATAVERS);
v1015 = f.mask().get(F_VERS_1015)[0];
}
else
{
TSheet_field& ver = app().vers();
const int riga_corr = ver.selected();
TToken_string& riga = ver.row(riga_corr);
v1015 = riga.get(0)[0];
datav = riga.get(1);
datav.trim();
}
return datav.not_empty() || v1015 == 'X';
}
// GET_NUMVERS
//
// Determina il numero di versamento corrente, prendendolo
// dalla riga corrente dello spreadsheet
long TSchedaPercipienti::get_numvers(TMask_field& f)
{
long numvers = 0L;
TSheet_field& ver = app().vers();
const int riga_corr = ver.selected();
TToken_string& riga = ver.row(riga_corr);
numvers = riga_corr + 1;
return numvers;
}
bool TSchedaPercipienti::pag_azzera(TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
Pag_struct s;
app().from_struct_to_mask(app().clear_struct(s), f.mask());
}
return TRUE;
}
bool TSchedaPercipienti::ver_azzera (TMask_field& f, KEY k)
{
long numvers = get_numvers(f);
int nriga = 0;
TNikArray_sheet& pags = *app()._pags;
if (k == K_SPACE)
{
app().load_pag_sheet(numvers);
for (int j = 0; j < pags.items(); j++)
{
TToken_string& riga = pags.row(j);
long numv = riga.get_long(AS_POS_NVER);
if (numv > 0L)
if (numv == numvers)
{
nriga = pags.row(j).get_int(AS_POS_NRIGA);
pags.row(j).add(-1L, AS_POS_NVER);
app().detach_pag_vers(nriga);
}
}
}
return TRUE;
}
//
// PAG_SELECT
//
// Collegamento tra versamenti e pagamenti
//
// Calcolo ritenuta = SUM(ritpag) {dei pagamenti collegati}
//
// Usa: load_pag_sheet() attach_pag_vers() e detach_pag_vers()
//
bool TSchedaPercipienti::pag_select (TMask_field& f, KEY k)
{
if (k == K_SPACE)
{
if (!app().compilato_vers(f))
return f.warning_box("Inserire prima la data del versamento");
long numvers = get_numvers(f);
long numpag = 0L;
int nriga = 0;
// 13.7.95 Ricalcola la ritenuta, azzerando contenuto precedente
real ritenuta = ZERO;
TBit_array& selected = app()._selected;
selected.reset();
// Costruisce array_sheet dei pagamenti
app().load_pag_sheet(numvers);
TNikArray_sheet& ASpags = *app()._pags;
// seleziona e aggiungi alle gia' selezionate
if (ASpags.run() == K_ENTER)
{
for (int j = 0; j < ASpags.items(); j++)
{
// get effettivo numero riga pag.
nriga = ASpags.row(j).get_int(AS_POS_NRIGA);
int mesec = -1;
int annoc = -1; // competenza
if (ASpags.checked(j))
{
// Scrive nello spread-sheet e nella relazione
app().attach_pag_vers(nriga, numvers);
// Scrive nell'array_sheet (e' da qui che leggo dopo)
ASpags.row(j).add((long)numvers, AS_POS_NVER);
TDate datapag(ASpags.row(j).get(1));
if (mesec < 0)
{
mesec = datapag.month();
annoc = datapag.year();
}
else
{
if (mesec != datapag.month() || annoc != datapag.year())
{
// TBI inserire un'altra riga di versamento (?)
}
}
selected.set(numpag);
real dep(real::ita2eng(ASpags.row(j).get(AS_POS_RITPAG)));
ritenuta += dep;
}
else // pags.checked()
{
// resetta se era stato settato prima
if (selected[numpag])
{
selected.reset(numpag);
ASpags.row(j).add(-1L, AS_POS_NVER);
app().detach_pag_vers(nriga);
}
}
}
setta_ritvers(f, ritenuta);
} // if k==K_ENTER
}
return TRUE;
}
void TSchedaPercipienti::work_tipoluogo(TMask_field& f)
{
TMask& m = f.mask();
char tipo = m.get(F_TIPOVERS)[0];
char luogo = m.get(F_LUOVERS)[0];
bool v1015 = m.get_bool(F_VERS_1015);
TSheet_field& ss = app().vers();
const int row = ss.selected();
m.hide (-2); // nasconde tutto
// disabilita CAB se versamento 1015
// perch<63> non appartenendo alla riga
// non viene disabilitato nella "rec2row"
if (v1015)
m.disable(F_CAB);
else
m.enable(F_CAB);
if (tipo == 'B')
{
// ABI e CAB
m.show (-6);
// abilita progressivo vers.banca
if (!v1015)
m.enable(SM_PROGRBANCA);
}
else
{
m.disable(SM_PROGRBANCA);
if (tipo == 'D')
{
if (luogo == 'T')
{
m.show(-3); // SOLO quietanza
ss.disable_cell(row,4);
}
else
{
m.show(-4); // serie e numero
ss.enable_cell(row,4);
}
}
// else
if (tipo == 'C')
{
m.show (-5); // SOLO numero versamento
ss.disable_cell(row,4);
}
}
}
bool TSchedaPercipienti::luo_hndl(TMask_field& f, KEY k)
{
if (k == K_TAB)
work_tipoluogo(f);
if (k == K_ENTER)
{
work_tipoluogo(f);
TMask& m = f.mask();
char tipo = m.get(F_TIPOVERS)[0];
char luogo = m.get(F_LUOVERS)[0];
// Se ho indicato il luogo => devo indicare anche il TIPO
if (isalpha(luogo))
return tipo == ' ' || tipo == '\0' ?
f.warning_box("Indicare il tipo del versamento") : TRUE;
}
return TRUE;
}
bool TSchedaPercipienti::abicab_hndl(TMask_field& f, KEY k)
{
if (f.to_check(k))
{
TString16 park(f.get());
TMask& m = f.mask();
char tipo = m.get(F_TIPOVERS)[0];
// ABI/CAB solo se tipo e' B
if (tipo != 'B')
return TRUE;
for (int i=0; i<park.len(); i++)
{
// controllo se codice CAB supera le 5 cifre
if (i > 5)
{
f.reset();
return f.warning_box("Codice CAB non valido");
}
// controllo numericit<69> del codice ABI/CAB
if (!isdigit(park[i]))
return f.warning_box("Il codice ABI/CAB deve essere numerico");
}
}
return TRUE;
}
bool TSchedaPercipienti::tipo_hndl(TMask_field& f, KEY k)
{
if (k == K_TAB)
work_tipoluogo(f);
if (k == K_ENTER || k == K_TAB)
{
TMask& m = f.mask();
char tipo = m.get(F_TIPOVERS)[0];
char luogo = m.get(F_LUOVERS)[0];
// Se ho indicato il tipo => devo indicare anche il LUOGO
if (isalpha(tipo))
return luogo == ' ' || luogo == '\0' ?
f.warning_box("Indicare il luogo del versamento") : TRUE;
}
return TRUE;
}
//
// VERS1015_HANDLER
//
bool TSchedaPercipienti::vers1015_handler(TMask_field& f, KEY k)
{
if (k == K_ENTER)
{
TString16 datas = f.mask().get(F_DATAVERS);
const bool v1015 = f.mask().get_bool(F_VERS_1015);
const bool attaccati = check_pagamenti(f,k);
if (attaccati)
if (!v1015 && datas.empty())
return f.warning_box("Manca la data del versamento");
// Non considerare versamenti non significativi
if (v1015 || datas.not_empty())
return attaccati ? TRUE : f.warning_box("Nessun pagamento collegato");
const real rite (f.mask().get(F_RITVERS));
// Pero' se c'e' la ritenuta non lo far passare
if (rite != ZERO)
return f.warning_box("Manca la data oppure il flag di versamento 1015");
return TRUE;
}
if (k == K_SPACE || k == K_F2)
{
TSheet_field& ss = app().vers();
const bool v1015 = (f.get() == "X");
const int row = ss.selected();
int i;
// Disabilito tutto MA NON ritenuta
if (v1015)
{
// Se son gia' disabilitati non fare nulla
if (ss.cell_disabled(row, 1))
return TRUE;
f.mask().reset(102);
f.mask().reset(103);
f.mask().reset(104);
f.mask().reset(105);
f.mask().reset(106);
f.mask().disable(102);
f.mask().disable(103);
f.mask().disable(104);
f.mask().disable(105);
f.mask().disable(106);
for (i=1; i<6; i++)
ss.disable_cell(row,i);
}
else
{
f.mask().enable(102);
f.mask().enable(103);
f.mask().enable(104);
f.mask().enable(105);
f.mask().enable(106);
for (i=1; i<6; i++)
ss.enable_cell(row,i);
}
}
return TRUE;
}
// handler codice causale
bool TSchedaPercipienti::check_causale(TMask_field& f, KEY k)
{
TMask& m = f.mask();
TString16 cod_qua(m.get(F_CODQUA));
// creo run-time gli items per la causale quadro
app().build_causqua_items(m, cod_qua);
if (k == K_TAB && m.is_running())
{
// leggo causale indicata
TFixed_string cod_caus(f.get(),3);
// cose da fare solo se viene modificato il codice causale
if (f.to_check(k))
{
// forzo causale quadro con il valore in tabella
TEdit_field& f_causqua = m.efield(F_CAUSQUA);
f_causqua.reset();
if (cod_qua == "LA")
f_causqua.set(m.get(F_TABCAUSQUASC));
if (cod_qua == "SE")
f_causqua.set(m.get(F_TABCAUSQUASE));
if (cod_qua == "SF")
f_causqua.set(m.get(F_TABCAUSQUASF));
if (cod_qua == "SG")
f_causqua.set(m.get(F_TABCAUSQUASG));
// attiva sheet pagamenti in base al quadro
app().activate_pag_sheet(m);
}
}
return TRUE;
}
bool TSchedaPercipienti::pag_standard_handler(TMask_field& f, KEY k)
{
static Pag_struct s;
static Pag_struct c;
static Pag_struct nullpag;
app().clear_struct(nullpag);
// reperisco dati documento
TMask& mm = app().curr_mask();
const bool d_forzatura = mm.get_bool(F_FORCED);
TString16 d_codqua(mm.get(F_CODQUA));
// eseguo calcolo solo per K_TAB (singolo campo),
// oppure per K_ENTER, ma solo per il primo campo,
// questo per migliorare le prestazioni
if (f.to_check(k))
{
if (k == K_TAB || (k == K_ENTER && f.dlg() == 101))
{
// reperisco valori nascosti compilati dalla tabella causali
const real h_PercAssImp = mm.get_real(F_QUOTAIMP);
const real h_PercCassaPrev = mm.get_real(F_CASSA_PREV);
const real h_PercRitenuta = mm.get_real(F_PERRIT);
const bool h_FlagInps = mm.get_bool(F_FLAG_INPS);
const real h_PercInps = mm.get_real(F_PERC_INPS);
const real h_PercAssImpInps = mm.get_real(F_PERC_ASS_INPS);
const real h_PercCommitInps = mm.get_real(F_PERC_COMMIT_INPS);
// inizializzo struttura calcolati
app().clear_struct(c);
// riempimento struttura pagamento
app().from_mask_to_struct(f.mask(), s);
// non proseguo se riga vuota
if (s == c) return true;
// richiamo calcolo di riga
app().calcola_riga_pag(s,
c,
FALSE,
h_PercAssImp,
h_PercCassaPrev,
h_PercRitenuta,
h_PercInps,
h_PercAssImpInps,
h_PercCommitInps);
// riporto valori a maschera
app().from_struct_to_mask(s, f.mask());
}
// eseguo controlli solo per K_ENTER
// utilizzando i valori memorizzati nelle strutture statiche
if (k == K_ENTER)
{
// non proseguo se riga vuota
if (s == nullpag) return TRUE;
// reperisco nome campo su record
const TString& name = f.field()->name();
// controllo data pagamento
if (name == "DATAPAG")
if (!s.datapag.ok() && (s.compenso != ZERO || s.spesa != ZERO))
return f.error_box("Data pagamento non indicata");
// controllo compenso e/o spese
if (name == "COMPENSO" || name == "SPESA")
if (s.compenso == ZERO && s.spesa == ZERO)
return f.error_box("Compenso o spese non indicati");
// controllo imponibile
if (name == "IMPONIBILE")
if (d_codqua != "E1" && abs(s.imponibile) > abs(s.compenso))
return f.error_box("Imponibile maggiore del compenso");
// controllo ritenuta
if (name == "RITENUTA" && !d_forzatura)
if (s.ritenuta != c.ritenuta)
return f.error_box("Ritenuta diversa da importo calcolato");
// controllo detrazioni lavoro dipendente
if (name == "DETLAVDIP")
if (s.detlavdip == ZERO && s.giolavdip != 0)
return f.error_box("Detrazioni lavoro dipendente non indicate");
// controllo CPA
if (name == "IMPCPA")
{
if ((d_codqua != "SC") && s.impcpa != ZERO)
return f.error_box("CPA valido solo per causali con quadro SC");
if (abs(s.impcpa) > abs(s.compenso))
return f.error_box("CPA maggiore del compenso");
}
// controllo somme reg.conv.
if (name == "SOMREGCONV")
{
// if ((d_codqua != "SC" && d_codqua != "SE") && s.somregconv != ZERO) nell'ultima versione dei quadri le SOMREGCONV valgono per tutti i tipi di quadro (SC,SE,SF,SG)
// return f.error_box("Somme reg.conv. valido solo per causali con quadro SC e SE"); 12/07/2000
if (!app()._soggnres && s.somregconv != ZERO)
return f.error_box("Somme reg.conv. valido solo se percipiente non residente");
}
// controllo contributo 10% percipiente
if (name == "CTSSNPERC" && !d_forzatura)
if (s.ctssnperc != c.ctssnperc)
return f.error_box("Contributo Inps percipiente diverso da importo calcolato");
// controllo contributo 10% complessivo
if (name == "CTSSNCOMP" && !d_forzatura)
if (s.ctssncomp != c.ctssncomp)
return f.error_box("Contributo Inps complessivo diverso da importo calcolato");
// controllo numero quote
if (name == "NQUOTE" && !d_forzatura)
if (s.nquote == ZERO)
return f.error_box("Numero quote non indicate");
}
}
return TRUE;
}