diff --git a/ha/ha0600.cpp b/ha/ha0600.cpp
new file mode 100644
index 000000000..f112428aa
--- /dev/null
+++ b/ha/ha0600.cpp
@@ -0,0 +1,299 @@
+#include "ha0600a.h"
+
+#include <applicat.h>
+#include <automask.h>
+#include <recarray.h>
+#include <recset.h>
+
+#include <clifo.h>
+#include "../mg/anamag.h"
+
+///////////////////////////////////////////////////////////
+// TCodcorr_msk
+///////////////////////////////////////////////////////////
+
+class TCodcorr_msk : public TAutomask
+{
+  char _mode;
+  TString8 _code;
+  bool _dirty;
+
+private:
+  bool load_articles();
+  bool load_customers();
+  bool load();
+  bool save();
+  bool save_if_needed();
+
+protected:
+  virtual bool on_field_event(TOperable_field& o, TField_event e, long jolly);
+
+public:
+  TCodcorr_msk() : TAutomask("ha0600a"), _mode(' '), _dirty(false) {}
+} ;
+
+// Salva le righe attuali (articoli o clienti)
+bool TCodcorr_msk::save()
+{
+  if (_mode <= ' ' || _code.blank())
+    return false;
+
+  TSheet_field& sf = sfield(_mode == 'A' ? F_ARTICOLI : F_CLIENTI);
+  TFast_isamfile multirel(LF_MULTIREL);
+
+  TString8 code, codalt;
+  TString80 descr, data;
+
+  FOR_EACH_SHEET_ROW(sf, r, row)
+  {
+    row->get(0, code);    // Puo' essere un articolo o un cliente
+    if (code.blank()) 
+      continue;
+
+    row->get(2, codalt);
+    row->get(3, descr);
+
+    multirel.zero();
+    multirel.put("COD", "HACOR");
+    // Compila opportunamente la chiave di multirel: FIRST=cliente; SECOND=articolo;
+    if (_mode == 'A')
+    {
+      multirel.put("FIRST", _code);  // Cliente
+      multirel.put("SECOND", code);  // Articolo
+    }
+    else
+    {
+      multirel.put("FIRST", code);   // Cliente
+      multirel.put("SECOND", _code); // Articolo
+    }
+
+    int err = NOERR;
+    if (codalt.full() || descr.full())  // Riga da aggiornare in quanto piena
+    {
+      // Il campo DATA � cos� organizzato: DATA[1,5]=codalt; DATA[6,50]=descr
+      data = codalt;
+      data.overwrite(descr, 5);
+      multirel.put("DATA", data);
+      err = multirel.rewrite_write();
+    }
+    else
+      err = multirel.remove();          // Riga da eliminare in quanto vuota 
+    if (err != NOERR)
+      return cantwrite_box(multirel.name());
+  }
+
+  _dirty = false;
+  return true;
+}
+
+// In caso ci siano state modifiche (_dirty) chiede di salvare i dati
+bool TCodcorr_msk::save_if_needed()
+{
+  if (_dirty && _mode > ' ' && _code.full())
+  {
+    const int ret = yesnocancel_box(TR("Si desidera salvare le righe modificate?"));
+    switch(ret)
+    {
+    case K_YES: save(); break;          // Salva e resetta _dirty
+    case K_NO : _dirty = false; break;  // Resetta _dirty ignorando le modifiche
+    default   : break;                  // Annulla l'operazione senza fare nulla
+    }
+  }
+  return !_dirty;
+}
+
+bool TCodcorr_msk::load_articles()
+{
+  TString query;
+  query << "USE MULTIREL SELECT FIRST==#CLIENTE" // Sembra inutile ... ma non lo �!
+        << "\nFROM COD=HACOR FIRST=#CLIENTE"
+        << "\nTO   COD=HACOR FIRST=#CLIENTE";
+         
+  TISAM_recordset multirel(query);
+  multirel.set_var("#CLIENTE", _code);
+
+  TSheet_field& sf = sfield(F_ARTICOLI);
+  sf.destroy();
+  for (bool ok = multirel.move_first(); ok; ok = multirel.move_next())
+  {
+    TToken_string& row = sf.row(-1);
+    TString8 cod = multirel.get("SECOND").as_string().left(5);
+    row.add(cod);                                       // Codice articolo
+    row.add(cache().get(LF_ANAMAG, cod, ANAMAG_DESCR)); // Descrizione articolo
+    
+    // Spezza il campo DATA in codice alternativo [1,5] e descrizione [6,50]
+    const TString& data = multirel.get("DATA").as_string();
+    cod = data.left(5);
+    row.add(cod);
+    if (data.len() > 5)
+      row.add(data.mid(5, 45));
+    else
+      row.add(cache().get(LF_ANAMAG, cod, ANAMAG_DESCR));
+
+    // Disabilita codice articolo e descrizione
+    const int r = sf.items()-1;
+    sf.disable_cell(r, 0);
+    sf.disable_cell(r, 1);
+  }
+  sf.force_update();
+  return true;
+}
+
+bool TCodcorr_msk::load_customers()
+{
+  TString query;
+  query << "USE MULTIREL KEY 2 SELECT SECOND==#CODART" // Sembra inutile ... ma non lo �!
+        << "\nFROM COD=HACOR SECOND=#CODART"
+        << "\nTO   COD=HACOR SECOND=#CODART";
+         
+  TISAM_recordset multirel(query);
+  multirel.set_var("#CODART", _code);
+
+  TSheet_field& sf = sfield(F_CLIENTI);
+  sf.destroy();
+  for (bool ok = multirel.move_first(); ok; ok = multirel.move_next())
+  {
+    TToken_string& row = sf.row(-1);
+    TString8 cod = multirel.get("FIRST").as_string(); // Codice cliente
+    row.add(cod);
+    cod.insert("C|");                                 // Chiave cliente
+    row.add(cache().get(LF_CLIFO, cod, CLI_RAGSOC));  // Ragione sociale
+
+    // Spezza il campo DATA in codice alternativo [1,5] e descrizione [6,50]
+    const TString& data = multirel.get("DATA").as_string();
+    cod = data.left(5);
+    row.add(cod);
+    if (data.len() > 5)
+      row.add(data.mid(5, 45));
+    else
+      row.add(cache().get(LF_ANAMAG, cod, ANAMAG_DESCR));
+    
+    // Disabilita codice e ragione sociale
+    const int r = sf.items()-1;
+    sf.disable_cell(r, 0);
+    sf.disable_cell(r, 1);
+  }
+  sf.force_update();
+
+  return true;
+}
+
+bool TCodcorr_msk::load()
+{
+  if (!check_fields())         // Controlla che tutto sia valido
+    return false;
+
+  bool done = false;           // Flag di operazione riuscita
+
+  _mode = ' ';                 // Modalit� indeterminata (n� A n� C)
+  _code.cut(0);                // Codice Cliente/Articolo nullo
+  _dirty = false;              // Nessuna modifica effettuata
+
+  if (get(F_TIPO)[0] == 'C')   // Selezione articoli di un 'C'liente
+  {
+    _code = get(F_CLIENTE);    // Legge codice cliente
+    if (_code.full())   
+    {
+      _mode = 'A';             // Imposta modalit� lista 'A'rticoli
+      done = load_articles();  // Carica articoli associati al cliente _code
+    }
+  }
+  else
+  {
+    _code = get(F_ARTICOLO);   // Legge codice articolo 
+    if (_code.full())          
+    {
+      _mode = 'C';             // Imposta modalit� lista 'A'rticoli
+      done = load_customers(); // Carica clienti dell'articolo _code
+    }
+  }
+
+  // Mostra solo lo sheet interessato nella modalit� corrente
+  sfield(F_ARTICOLI).show(_mode == 'A');
+  sfield(F_CLIENTI).show(_mode != 'A');
+
+  return done;
+}
+
+bool TCodcorr_msk::on_field_event(TOperable_field& o, TField_event e, long jolly)
+{
+  switch (o.dlg())
+  {
+  case DLG_SAVEREC:
+    if (e == fe_button)
+    {
+      if (save()) // Salva tutto lo sheet corrente
+        load();   // Lo ricarica per eliminare duplicati e riordinarlo
+    }
+    break;
+  case F_CLIENTE:
+  case F_ARTICOLO:
+    if (e == fe_modify || e == fe_init)   // fe_init scatta nel caso di collegamento da anagrafica
+    {    
+      if (!o.empty() && save_if_needed()) // Se il codice cliente � valido e dopo aver salvato ...
+        load();                           // ... carica lo sheet con gli articoli del nuovo cliente
+    }
+    break;
+  case F_ARTICOLI:
+  case F_CLIENTI:
+    switch (e)
+    {
+    case se_notify_modify:
+    case se_notify_add: _dirty = true; break; // Memorizza l'avventua modifica dello sheet
+    case se_query_del: return false;          // Impedisce cancellazione di righe: solo azzeramenti!
+    default: break;
+    }
+    break;
+  default: break;
+  }
+  return true;
+}
+
+///////////////////////////////////////////////////////////
+// TCodcorr_app
+///////////////////////////////////////////////////////////
+
+class TCodcorr_app : public TSkeleton_application
+{
+public:
+  virtual void main_loop();
+};
+
+void TCodcorr_app::main_loop()
+{
+  TCodcorr_msk msk;
+
+  // Gestione collegamento da parte dell'anagrafica clienti:
+  // ha0 -5 C 883  ->  Visualizza gli articoli del cliente "883"
+  // ha0 -5 A A/1  ->  Visualizza chi compra l'articolo "A/1"
+  if (argc() >= 4)
+  {
+    const TFixed_string tipo(argv(2));
+    const TFixed_string codice(argv(3));
+    if (tipo == "A") 
+    {
+      msk.set(F_TIPO, "A", 0x3);
+      msk.set(F_ARTICOLO, codice);
+    }
+    else
+    {
+      msk.set(F_TIPO, "C", 0x3);
+      msk.set(F_CLIENTE, codice);
+    }
+    // Una volta impostato il codice del cliente (o articolo),
+    // l'evento e_init del codice far� scattare il caricamento dello spreasheet opportuno
+  }
+
+  msk.run();
+}
+
+///////////////////////////////////////////////////////////
+// main
+///////////////////////////////////////////////////////////
+
+int ha0600(int argc, char* argv[])
+{
+  TCodcorr_app app;
+  app.run(argc, argv, TR("Prodotti corrispondenti"));
+  return 0;
+}
diff --git a/ha/ha0600a.h b/ha/ha0600a.h
new file mode 100644
index 000000000..70583be0e
--- /dev/null
+++ b/ha/ha0600a.h
@@ -0,0 +1,18 @@
+#define F_TIPO      201
+#define F_CLIENTE   211
+#define F_RAGSOC    212
+#define F_ARTICOLO  221
+#define F_DESCART   222
+
+#define F_ARTICOLI  231
+#define F_CLIENTI   232
+
+#define A_CODART    101
+#define A_DESCART   102
+#define A_CODALT    103
+#define A_DESCALT   104
+
+#define C_CLIENTE   101
+#define C_RAGSOC    102
+#define C_CODALT    103
+#define C_DESCALT   104
diff --git a/ha/ha0600a.uml b/ha/ha0600a.uml
new file mode 100644
index 000000000..704a97fcb
--- /dev/null
+++ b/ha/ha0600a.uml
@@ -0,0 +1,250 @@
+#include "ha0600a.h"
+
+TOOLBAR "" 0 0 0 2
+
+BUTTON DLG_SAVEREC 2 2
+BEGIN
+  PROMPT 1 1 "Registra"
+  PICTURE TOOL_SAVEREC
+END
+
+#include <helpbar.h>
+
+ENDPAGE
+
+PAGE "Articoli corrispondenti" -1 -1 78 23
+
+RADIOBUTTON F_TIPO 1 12
+BEGIN
+  PROMPT 1 0 "@bSelezione"
+  ITEM "C|Cliente" 
+    MESSAGE SHOW,1@|HIDE,2@
+  ITEM "A|Articolo" 
+    MESSAGE HIDE,1@|SHOW,2@
+END
+
+NUMBER F_CLIENTE 6
+BEGIN
+  PROMPT 15 1 ""
+  USE LF_CLIFO
+  INPUT TIPOCF "C"
+  INPUT CODCF F_CLIENTE
+  DISPLAY "Codice" CODCF
+  DISPLAY "Ragione Sociale@50" RAGSOC
+  DISPLAY "Partita IVA" PAIV
+  OUTPUT F_CLIENTE CODCF
+  OUTPUT F_RAGSOC RAGSOC
+  CHECKTYPE REQUIRED
+  ADD RUN cg0 -1
+  GROUP 1
+END
+
+STRING F_RAGSOC 50
+BEGIN
+  PROMPT 15 2 ""
+  USE LF_CLIFO KEY 2
+  INPUT TIPOCF "C"
+  INPUT RAGSOC F_RAGSOC
+  DISPLAY "Ragione Sociale@50" RAGSOC
+  DISPLAY "Codice" CODCF
+  DISPLAY "Partita IVA" PAIV
+  COPY OUTPUT F_CLIENTE
+  ADD RUN cg0 -1
+  GROUP 1
+END
+
+STRING F_ARTICOLO 5
+BEGIN
+  PROMPT 15 1 ""
+  USE LF_ANAMAG SELECT USER1!=""
+  INPUT CODART F_ARTICOLO 
+  DISPLAY "Codice" CODART
+  DISPLAY "Descrizione@50" DESCR
+  DISPLAY "Fascia" USER4
+  OUTPUT F_ARTICOLO CODART
+  OUTPUT F_DESCART DESCR
+  CHECKTYPE REQUIRED
+  ADD RUN ve2 -0
+  GROUP 2
+END
+
+STRING F_DESCART 50
+BEGIN
+  PROMPT 15 2 ""
+  USE LF_ANAMAG KEY 2
+  INPUT DESCR F_DESCART
+  DISPLAY "Descrizione@50" DESCR
+  DISPLAY "Codice" CODART
+  DISPLAY "Fascia" USER4
+  COPY OUTPUT F_ARTICOLO
+  ADD RUN ve2 -0
+  GROUP 2
+END
+
+SPREADHEET F_ARTICOLI 
+BEGIN
+  PROMPT 1 4 ""
+  ITEM "Codice\nArticolo@8"
+  ITEM "Descrizione@50"
+  ITEM "Codice\nAlt.@5"
+  ITEM "Descrizione@45"
+  FLAGS "H"
+END
+
+SPREADSHEET F_CLIENTI 
+BEGIN
+  PROMPT 1 4 ""
+  ITEM "Codice\nCliente@6"
+  ITEM "Ragione Sociale@50"
+  ITEM "Codice\nAlt.@5"
+  ITEM "Descrizione@45"
+  FLAGS "H"
+END
+
+ENDPAGE
+
+ENDMASK
+
+PAGE "Articolo" -1 -1 60 5
+
+STRING A_CODART 5
+BEGIN
+  PROMPT 1 1 "Articolo    "
+  USE LF_ANAMAG SELECT USER1!=""
+  INPUT CODART A_CODART
+  DISPLAY "Codice" CODART
+  DISPLAY "Descrizione@50" DESCR
+  DISPLAY "Fascia" USER4
+  OUTPUT A_CODART CODART
+  OUTPUT A_DESCART DESCR
+  CHECKTYPE REQUIRED
+  ADD RUN ve2 -0
+END
+
+STRING A_DESCART 50
+BEGIN
+  PROMPT 1 2 "Descrizione "
+  USE LF_ANAMAG KEY 2
+  INPUT DESCR A_DESCART
+  DISPLAY "Codice" CODART
+  DISPLAY "Descrizione@50" DESCR
+  DISPLAY "Fascia" USER4
+  COPY OUTPUT A_CODART
+  CHECKTYPE REQUIRED
+  ADD RUN ve2 -0
+END
+
+STRING A_CODALT 5
+BEGIN
+  PROMPT 1 3 "Alternativo "
+  COPY USE A_CODART
+  INPUT CODART A_CODALT
+  COPY DISPLAY A_CODART
+  OUTPUT A_CODALT CODART
+  OUTPUT A_DESCALT DESCR
+  ADD RUN ve2 -0
+END
+
+STRING A_DESCALT 45
+BEGIN
+  PROMPT 1 4 "Descrizione "
+END
+
+ENDPAGE
+
+TOOLBAR "topbar" 0 0 0 2
+
+BUTTON DLG_OK 2 2
+BEGIN
+  PROMPT 1 1 ""
+END
+
+BUTTON DLG_USER 2 2
+BEGIN
+  PROMPT 1 2 "Azzera"
+  MESSAGE RESET,A_CODALT|RESET,A_DESCALT
+  PICTURE TOOL_RESET
+END
+
+BUTTON DLG_CANCEL 2 2
+BEGIN
+  PROMPT 3 1 ""
+END
+
+ENDPAGE
+
+ENDMASK
+
+PAGE "Clienti" -1 -1 60 5
+
+NUMBER C_CLIENTE 6
+BEGIN
+  PROMPT 1 1 ""
+  USE LF_CLIFO
+  INPUT TIPOCF "C"
+  INPUT CODCF C_CLIENTE
+  DISPLAY "Codice" CODCF
+  DISPLAY "Ragione Sociale@50" RAGSOC
+  DISPLAY "Partita IVA" PAIV
+  OUTPUT C_CLIENTE CODCF
+  OUTPUT C_RAGSOC RAGSOC
+  CHECKTYPE REQIORED
+  ADD RUN cg0 -1
+END
+
+STRING C_RAGSOC 50
+BEGIN
+  PROMPT 1 2 ""
+  USE LF_CLIFO KEY 2
+  INPUT TIPOCF "C"
+  INPUT RAGSOC C_RAGSOC
+  DISPLAY "Ragione Sociale@50" RAGSOC
+  DISPLAY "Codice" CODCF
+  DISPLAY "Partita IVA" PAIV
+  COPY OUTPUT C_CLIENTE
+  CHECKTYPE REQUIRED
+  ADD RUN cg0 -1
+END
+
+STRING C_CODALT 5
+BEGIN
+  PROMPT 1 4 "Alternativo "
+  USE LF_ANAMAG SELECT USER1!=""
+  INPUT CODART C_CODALT
+  DISPLAY "Codice" CODART
+  DISPLAY "Descrizione@50" DESCR
+  DISPLAY "Fascia" USER4
+  OUTPUT C_CODALT CODART
+  OUTPUT C_DESCALT DESCR
+  ADD RUN ve2 -0
+END
+
+STRING C_DESCALT 45
+BEGIN
+  PROMPT 1 5 "Descrizione "
+END
+
+ENDPAGE
+
+TOOLBAR "topbar" 0 0 0 2
+
+BUTTON DLG_OK 2 2
+BEGIN
+  PROMPT 1 1 ""
+END
+
+BUTTON DLG_USER 2 2
+BEGIN
+  PROMPT 1 2 "Azzera"
+  PICTURE TOOL_RESET
+  MESSAGE RESET,C_CODALT|RESET,C_DESCALT
+END
+
+BUTTON DLG_CANCEL 2 2
+BEGIN
+  PROMPT 3 1 ""
+END
+
+ENDPAGE
+
+ENDMASK