1562 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1562 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
#include <conio.h>
 | 
						|
#include <direct.h>  
 | 
						|
#include <stdlib.h>  
 | 
						|
#include <time.h>
 | 
						|
#include <xvt.h>
 | 
						|
 | 
						|
#include <applicat.h>
 | 
						|
#include <assoc.h>
 | 
						|
#include <golem.h> 
 | 
						|
#include <mailbox.h>
 | 
						|
#include <msksheet.h>
 | 
						|
#include <prefix.h>
 | 
						|
#include <progind.h>
 | 
						|
#include <relation.h>
 | 
						|
#include <urldefid.h>
 | 
						|
#include <utility.h>
 | 
						|
#include <xvtility.h>
 | 
						|
 | 
						|
#include <anagr.h>
 | 
						|
#include <anagiu.h>
 | 
						|
#include <clifo.h>
 | 
						|
#include <nditte.h>
 | 
						|
 | 
						|
#include "bafax.h"
 | 
						|
 | 
						|
#define STRICT   
 | 
						|
#define WIN32_LEAN_AND_MEAN
 | 
						|
#include <windows.h>
 | 
						|
#include <windowsx.h>
 | 
						|
#include <shellapi.h>
 | 
						|
#include "faxdll.h"
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Finalmente un programma multimediale!
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
const word SPEAKER_PORT      = 0x61;
 | 
						|
const word PIT_CONTROL       = 0x43;
 | 
						|
const word PIT_CHANNEL_2     = 0x42;
 | 
						|
const unsigned long PIT_FREQ = 0x1234DD;
 | 
						|
 | 
						|
void sound(word frequency)
 | 
						|
{
 | 
						|
  const word counter = word(PIT_FREQ / frequency);
 | 
						|
  _outp(PIT_CONTROL, 0xB6);
 | 
						|
  _outp(PIT_CHANNEL_2, counter & 0xFF);
 | 
						|
  _outp(PIT_CHANNEL_2, counter >> 8);
 | 
						|
 | 
						|
  // Connect the speaker to the PIT
 | 
						|
  _outp(SPEAKER_PORT, _inp(SPEAKER_PORT) | 3);
 | 
						|
}
 | 
						|
 | 
						|
void nosound()
 | 
						|
{ 
 | 
						|
  // Sconnect the speaker from the PIT
 | 
						|
  _outp(SPEAKER_PORT, _inp(SPEAKER_PORT) & 0xFC);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Dati destinatario
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TFax_data : public TAssoc_array
 | 
						|
{           
 | 
						|
public:
 | 
						|
  void set(const char* key, const char* value);
 | 
						|
  const char* get(const char* key) const;
 | 
						|
  
 | 
						|
  void set_file(const char* file) { set("FILELIST", file); }
 | 
						|
  char* get_char_star(const char* name) const;
 | 
						|
  
 | 
						|
  TFax_data& operator=(const TAssoc_array& a) { copy(a); return *this; }
 | 
						|
  TFax_data& operator=(const TFax_data& d) { copy(d); return *this; }
 | 
						|
  
 | 
						|
  TFax_data();  
 | 
						|
  TFax_data(const TFax_data& d) { copy(d); }
 | 
						|
  virtual ~TFax_data();
 | 
						|
};
 | 
						|
 | 
						|
TFax_data::TFax_data()
 | 
						|
{          
 | 
						|
}
 | 
						|
 | 
						|
TFax_data::~TFax_data()
 | 
						|
{          
 | 
						|
}
 | 
						|
 | 
						|
void TFax_data::set(const char* key, const char* value)
 | 
						|
{
 | 
						|
  add(key, TString(value), TRUE);
 | 
						|
}
 | 
						|
 | 
						|
const char* TFax_data::get(const char* key) const
 | 
						|
{
 | 
						|
  const TString* s = (const TString*)((TAssoc_array*)this)->objptr(key);
 | 
						|
  return s ? (const char*)*s : "";
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
char* TFax_data::get_char_star(const char* name) const
 | 
						|
{     
 | 
						|
  if (stricmp(name, "FULLDESTFAX") == 0)
 | 
						|
  {
 | 
						|
    TString num(24);
 | 
						|
    num << get("DIALING");
 | 
						|
    num << get("PREFIX");
 | 
						|
    num << get("DESTFAX");
 | 
						|
    ((TFax_data*)this)->set(name, num);
 | 
						|
  }
 | 
						|
 | 
						|
  const TString* s = (const TString*)((TAssoc_array*)this)->objptr(name);
 | 
						|
  return  s ? (char*)(const char*)*s : "";
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Coda fax
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
           
 | 
						|
class TFax_queue : private TArray
 | 
						|
{ 
 | 
						|
  TFax_data _default;
 | 
						|
  
 | 
						|
public:
 | 
						|
  int push(TFax_data* data); 
 | 
						|
  TFax_data& peek_last();
 | 
						|
  const TFax_data& peek_last() const;
 | 
						|
  const TFax_data& peek_default();
 | 
						|
  
 | 
						|
  TFax_data& pop(); 
 | 
						|
  
 | 
						|
  bool empty() const { return items() == 0; } 
 | 
						|
  
 | 
						|
  void on_firm_change();
 | 
						|
  
 | 
						|
  TFax_queue();
 | 
						|
  virtual ~TFax_queue();
 | 
						|
};
 | 
						|
 | 
						|
TFax_queue::TFax_queue()
 | 
						|
{
 | 
						|
  TConfig ini(CONFIG_USER, "Fax");
 | 
						|
  _default = ini.list_variables();
 | 
						|
}
 | 
						|
 | 
						|
TFax_queue::~TFax_queue()
 | 
						|
{
 | 
						|
  TConfig ini(CONFIG_USER, "Fax");
 | 
						|
  _default.restart();          
 | 
						|
  for (THash_object* obj = _default.get_hashobj(); obj; obj = _default.get_hashobj())
 | 
						|
  {                     
 | 
						|
    const TString& name  = obj->key();
 | 
						|
    const TString& value = (const TString&)obj->obj();
 | 
						|
    ini.set(name, value);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TFax_data& TFax_queue::peek_last()
 | 
						|
{
 | 
						|
  const int l = last();
 | 
						|
  return l >= 0 ? (TFax_data&)*objptr(l) : _default;  
 | 
						|
}
 | 
						|
 | 
						|
const TFax_data& TFax_queue::peek_last() const
 | 
						|
{
 | 
						|
  const int l = last();
 | 
						|
  return l >= 0 ? (TFax_data&)*objptr(l) : _default;  
 | 
						|
}
 | 
						|
 | 
						|
const TFax_data& TFax_queue::peek_default()
 | 
						|
{
 | 
						|
  on_firm_change();
 | 
						|
  return _default;
 | 
						|
}
 | 
						|
 | 
						|
TFax_data& TFax_queue::pop()
 | 
						|
{
 | 
						|
  TFax_data* d = (TFax_data*)remove(0, TRUE);
 | 
						|
  if (d != NULL)
 | 
						|
  {
 | 
						|
    _default = *d;
 | 
						|
    delete d;
 | 
						|
  }  
 | 
						|
  return _default;  
 | 
						|
}
 | 
						|
 | 
						|
int TFax_queue::push(TFax_data* data)
 | 
						|
{
 | 
						|
  return add(data, -1);
 | 
						|
}
 | 
						|
 | 
						|
void TFax_queue::on_firm_change()
 | 
						|
{                        
 | 
						|
  static long old_firm = 0;
 | 
						|
 | 
						|
  TPrefix& pref = prefix();
 | 
						|
  pref.set("DEF");
 | 
						|
  const long firm = pref.get_codditta();
 | 
						|
  
 | 
						|
  if (firm != old_firm)
 | 
						|
  {
 | 
						|
    TLocalisamfile ditte(LF_NDITTE);
 | 
						|
    ditte.put(NDT_CODDITTA, firm);
 | 
						|
    if (ditte.read() == NOERR)
 | 
						|
    {             
 | 
						|
      old_firm = firm;
 | 
						|
    
 | 
						|
      TString tmp(80);
 | 
						|
      
 | 
						|
      tmp = ditte.get(NDT_PFAX);
 | 
						|
      if (tmp.not_empty()) tmp << ',';
 | 
						|
      tmp << ditte.get(NDT_FAX);
 | 
						|
      if (tmp.not_empty())
 | 
						|
        _default.set("FROMFAX", tmp);
 | 
						|
      
 | 
						|
      tmp = ditte.get(NDT_PERRIF);
 | 
						|
      if (tmp.not_empty())
 | 
						|
        _default.set("FROMNAME", tmp); 
 | 
						|
        
 | 
						|
      tmp = ditte.get(NDT_RAGSOC);
 | 
						|
      if (tmp.not_empty())
 | 
						|
        _default.set("FROMFIRM", tmp);
 | 
						|
    }
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TFax_list
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TFax_list : public TToken_string
 | 
						|
{ 
 | 
						|
public:
 | 
						|
  bool is_faxable(const TFilename& name) const;
 | 
						|
 | 
						|
  TFax_list();
 | 
						|
  TFax_list(const char* f); 
 | 
						|
  virtual ~TFax_list() { }
 | 
						|
};
 | 
						|
 | 
						|
TFax_list::TFax_list()
 | 
						|
         : TToken_string(80, '+')
 | 
						|
{ }
 | 
						|
 | 
						|
TFax_list::TFax_list(const char* name)
 | 
						|
         : TToken_string(name, '+')
 | 
						|
{ }        
 | 
						|
 | 
						|
bool TFax_list::is_faxable(const TFilename& name) const
 | 
						|
{
 | 
						|
  // Lista delle estensioni accettabili
 | 
						|
  const char* known_ext[] = { "BMP", "FMF", "PCX", "PMF", "TIF", "TXT", NULL };
 | 
						|
  
 | 
						|
  // Estensione del file da controllare
 | 
						|
  const TString16 ext = name.ext();
 | 
						|
  
 | 
						|
  // Se il file ha un'estensione riconosciuta lo aggiunge alla lista
 | 
						|
  for (int e = 0; known_ext[e]; e++)
 | 
						|
  {
 | 
						|
    if (ext.compare(known_ext[e], -1, TRUE) == 0)
 | 
						|
      return TRUE;
 | 
						|
  }    
 | 
						|
  
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TDDE_fax
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TLog_mask;       
 | 
						|
class TFax_mask;
 | 
						|
 | 
						|
class TDDE_fax : public TDDE
 | 
						|
{ 
 | 
						|
  PAPPINFO _pappinfo;
 | 
						|
  SEND_FAX _send_fax;
 | 
						|
  
 | 
						|
  TBit_array _port;
 | 
						|
  TString_array _pending, _sending, _failed, _complete;
 | 
						|
  TFax_queue _queue;
 | 
						|
  
 | 
						|
  TLog_mask* _log_mask; 
 | 
						|
  TFax_mask* _fax_mask;
 | 
						|
 | 
						|
  bool _close_when_idle;
 | 
						|
 | 
						|
protected:
 | 
						|
  TString_array* log2array(WORD log);
 | 
						|
  const char* error2string(FAXERROR e) const;
 | 
						|
  void add_log(WORD log, PSEND_FAX sf);
 | 
						|
  void remove_log(WORD log, PSEND_FAX sf);
 | 
						|
  void show_status(PSEND_FAX sf);
 | 
						|
  void update_all_logs();
 | 
						|
  void update_log(WORD log);
 | 
						|
  
 | 
						|
  bool send_next_fax(); 
 | 
						|
  void push_fax(const char* fax);
 | 
						|
 
 | 
						|
  TString& ragsoc2name(TString& ragsoc) const;
 | 
						|
  bool ricerca_clifo(char cf, const TString& codice, TFax_data& data) const;
 | 
						|
  bool ricerca_persone(char fg, const TString& codice, TFax_data& data) const;
 | 
						|
  bool ricerca_ditte(const TString& codice, TFax_data& data) const;
 | 
						|
  
 | 
						|
  void choose_temp_name(TFilename& name) const;
 | 
						|
  bool exec_command(const TString& comm, TToken_string& args);
 | 
						|
  void handle_fax_message(word wparam, long lparam);
 | 
						|
  void handle_drop_files(word wparam);
 | 
						|
 | 
						|
  // @cmember Ritorna TRUE se il server non e' in attesa di nessun lavoro
 | 
						|
  bool can_close() const;
 | 
						|
 | 
						|
public: // TObject
 | 
						|
  virtual bool ok() const { return _pappinfo != NULL; }
 | 
						|
 | 
						|
public: // TDDE
 | 
						|
  virtual const char* get_app_name() const { return "EASYFAX"; }
 | 
						|
  virtual const char* get_topics() const { return "FAX"; }
 | 
						|
 | 
						|
  virtual bool do_initiate(word id, const TString& topic);
 | 
						|
  virtual bool do_custom_message(word msg, word wparam, long lparam);
 | 
						|
  virtual bool do_execute(word id, const TString& cmd);
 | 
						|
 | 
						|
public:  
 | 
						|
  bool run_mask();
 | 
						|
 | 
						|
  void log_delete(WORD log, unsigned long id);
 | 
						|
  bool resend_fax(unsigned long id);
 | 
						|
  
 | 
						|
  void on_firm_change();
 | 
						|
 | 
						|
  bool set_destination(const TString& tipo, const TString& codice, TFax_data& data) const;
 | 
						|
  bool push_destination(const TString& tipo, const TString& codice);
 | 
						|
  
 | 
						|
  void auto_configure();
 | 
						|
  
 | 
						|
  TDDE_fax();
 | 
						|
  virtual ~TDDE_fax();
 | 
						|
};
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TFax_mask
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TFax_mask : public TMask
 | 
						|
{        
 | 
						|
  TDDE_fax* _fax;
 | 
						|
  TAssoc_array _table;
 | 
						|
 
 | 
						|
protected:
 | 
						|
  TMask_field* lookup(const char* field);
 | 
						|
 | 
						|
  static bool code_handler(TMask_field& f, KEY k);
 | 
						|
  static bool button_handler(TMask_field& f, KEY k);
 | 
						|
 | 
						|
public:
 | 
						|
  void set_field(const char* field, const char* value);
 | 
						|
  const TString& get_field(const char* field);
 | 
						|
  
 | 
						|
  void set_data(const TFax_data& data);
 | 
						|
  void get_data(TFax_data& data) const;
 | 
						|
  
 | 
						|
  TFax_mask(TDDE_fax* fax);
 | 
						|
  virtual ~TFax_mask();
 | 
						|
};
 | 
						|
 | 
						|
TFax_mask::TFax_mask(TDDE_fax* fax) 
 | 
						|
         : TMask("bafax01"), _fax(fax)
 | 
						|
{       
 | 
						|
  const char* pippe[] = { "DESTFAX", "FROMFAX", "PREFIX", NULL };
 | 
						|
 | 
						|
  for (int i = fields()-1; i >= 0; i--)
 | 
						|
  {
 | 
						|
    TMask_field& f = fld(i);
 | 
						|
    if (f.in_group(1))
 | 
						|
    {
 | 
						|
      f.set_handler(code_handler);
 | 
						|
      const TFieldref* c = f.field();
 | 
						|
      if (c != NULL)
 | 
						|
      {
 | 
						|
        for (int p = 0; pippe[p] != NULL; p++)
 | 
						|
          if (c->name() == pippe[p])
 | 
						|
            f.allow_pipe();
 | 
						|
      }  
 | 
						|
    }  
 | 
						|
    else
 | 
						|
      if (f.in_group(2))
 | 
						|
        f.set_handler(button_handler);
 | 
						|
  }   
 | 
						|
}
 | 
						|
 | 
						|
TFax_mask::~TFax_mask()
 | 
						|
{ }
 | 
						|
 | 
						|
TMask_field* TFax_mask::lookup(const char* field)
 | 
						|
{
 | 
						|
  TString* id = (TString*)_table.objptr(field);
 | 
						|
  if (id == NULL)
 | 
						|
  {
 | 
						|
    for (int i = fields()-1; i >= 0; i--)
 | 
						|
    {
 | 
						|
      TMask_field& f = fld(i);
 | 
						|
      const TFieldref* c = f.field();
 | 
						|
      if (c && c->name() == field)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
    id = new TString;
 | 
						|
    id->format("%d", i);
 | 
						|
    _table.add(field, id);
 | 
						|
  }
 | 
						|
  const int pos = atoi(*id);
 | 
						|
  return pos < 0 ? NULL : &fld(pos);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void TFax_mask::set_field(const char* field, const char* value)
 | 
						|
{
 | 
						|
  TMask_field* f = lookup(field);
 | 
						|
  if (f) f->set(value);
 | 
						|
}
 | 
						|
 | 
						|
const TString& TFax_mask::get_field(const char* field)
 | 
						|
{
 | 
						|
  TMask_field* f = lookup(field);
 | 
						|
  return f ? f->get() : "";
 | 
						|
}
 | 
						|
 | 
						|
bool TFax_mask::code_handler(TMask_field& f, KEY k)
 | 
						|
{   
 | 
						|
  bool ok = TRUE;
 | 
						|
  if (k == K_TAB && f.focusdirty())
 | 
						|
  {
 | 
						|
    TFax_mask& m = (TFax_mask&)f.mask();
 | 
						|
    const TString tipo = m.get_field("TIPO");
 | 
						|
    const TString codice = f.get();
 | 
						|
    TFax_data data;
 | 
						|
    ok = m._fax->set_destination(tipo, codice, data);
 | 
						|
    if (ok)
 | 
						|
      m.set_data(data);
 | 
						|
  }                                                                     
 | 
						|
  return ok;
 | 
						|
} 
 | 
						|
 | 
						|
bool TFax_mask::button_handler(TMask_field& f, KEY k)
 | 
						|
{
 | 
						|
  if (k == K_SPACE)
 | 
						|
  {        
 | 
						|
    TFax_mask& m = (TFax_mask&)f.mask();
 | 
						|
    TMask_field* fax = m.lookup("DESTFAX");
 | 
						|
    CHECK(fax, "Can't find fax number field");
 | 
						|
    
 | 
						|
    TString num = fax->get();
 | 
						|
    const TString& prompt = f.prompt();
 | 
						|
    if (prompt != "#")
 | 
						|
    {
 | 
						|
      if ((word)num.len() < fax->size())
 | 
						|
        num << prompt;
 | 
						|
    }    
 | 
						|
    else  
 | 
						|
      num.rtrim(1);
 | 
						|
    fax->set(num);
 | 
						|
    
 | 
						|
    const TMask_field* dialmode = m.lookup("DIALING");
 | 
						|
    CHECK(dialmode, "Can't find dial mode field");
 | 
						|
    const bool tone = dialmode->get()[0] == 'T';
 | 
						|
    
 | 
						|
    const char* keys[] = {  "1",  "2",  "3", 
 | 
						|
                            "4",  "5",  "6", 
 | 
						|
                            "7",  "8",  "9", 
 | 
						|
                            ",",  "0",  "#" };
 | 
						|
    const word freqs[] = { 1230, 1320, 1460, 
 | 
						|
                           1235, 1325, 1465, 
 | 
						|
                           1240, 1330, 1470, 
 | 
						|
                           1245, 1335, 1475 };
 | 
						|
    for (int i = 0; i < 12; i++) if (prompt == keys[i])
 | 
						|
    {       
 | 
						|
      if (tone)
 | 
						|
      {
 | 
						|
        sound(freqs[i]);      
 | 
						|
        const clock_t end = clock() + CLOCKS_PER_SEC / 5;
 | 
						|
        while (clock() < end);
 | 
						|
        nosound();
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {             
 | 
						|
        if (i >= 9 && i <= 11)
 | 
						|
          i = i == 10 ? 9 : 0;
 | 
						|
        for (int t = 0; t <= i; t++)
 | 
						|
        {
 | 
						|
          sound(50);      
 | 
						|
          clock_t end = clock();
 | 
						|
          while (clock() == end);
 | 
						|
          nosound();
 | 
						|
          end = clock();
 | 
						|
          while (clock() == end);
 | 
						|
        }
 | 
						|
      }  
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void TFax_mask::set_data(const TFax_data& ass)
 | 
						|
{      
 | 
						|
  TAssoc_array& data = (TAssoc_array&)ass;
 | 
						|
  data.restart();
 | 
						|
  for (THash_object* obj = data.get_hashobj(); obj; obj = data.get_hashobj())
 | 
						|
  {
 | 
						|
    const TString& name = obj->key();
 | 
						|
    const TString& value = (const TString&)obj->obj();
 | 
						|
    set_field(name, value);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TFax_mask::get_data(TFax_data& data) const
 | 
						|
{
 | 
						|
  for (int i = fields()-1; i >= 0; i--)
 | 
						|
  {                 
 | 
						|
    const TMask_field& f = fld(i);
 | 
						|
    const TFieldref* fr = f.field();
 | 
						|
    if (fr)
 | 
						|
      data.set(fr->name(), f.get());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// TQueues_mask
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TLog_mask : public TMask
 | 
						|
{          
 | 
						|
  TDDE_fax* _fax;
 | 
						|
 | 
						|
protected:
 | 
						|
  void update_sheet(short id, const TString_array& a);
 | 
						|
  
 | 
						|
  WORD sheet2log(const TSheet_field& s) const;
 | 
						|
  
 | 
						|
  void set_notify(short id);
 | 
						|
  static bool log_notify(TSheet_field& f, int row, KEY k);
 | 
						|
  static bool delrec_handler(TMask_field& f, KEY k);
 | 
						|
  static bool fax_handler(TMask_field& f, KEY k);
 | 
						|
 | 
						|
public:
 | 
						|
  void update_log(WORD log, const TString_array& a);
 | 
						|
 | 
						|
  TLog_mask(TDDE_fax* fax);
 | 
						|
  virtual ~TLog_mask() { }
 | 
						|
};
 | 
						|
 | 
						|
TLog_mask::TLog_mask(TDDE_fax* fax) 
 | 
						|
         : TMask("bafax02"), _fax(fax)
 | 
						|
{   
 | 
						|
  set_notify(F_PENDING);
 | 
						|
  set_notify(F_SENDING);
 | 
						|
  set_notify(F_FAILED);
 | 
						|
  set_notify(F_COMPLETE);
 | 
						|
}
 | 
						|
 | 
						|
WORD TLog_mask::sheet2log(const TSheet_field& s) const
 | 
						|
{
 | 
						|
  WORD log;
 | 
						|
  switch (s.dlg())
 | 
						|
  {
 | 
						|
    case F_PENDING:  log = SUBSCRIBE_LOG_PENDING;  break;
 | 
						|
    case F_SENDING:  log = SUBSCRIBE_LOG_SENDING;  break;
 | 
						|
    case F_COMPLETE: log = SUBSCRIBE_LOG_COMPLETE; break;
 | 
						|
    case F_FAILED:   log = SUBSCRIBE_LOG_FAILED;   break;
 | 
						|
    default:         log = 0; break;
 | 
						|
  }
 | 
						|
  return log;
 | 
						|
}
 | 
						|
 | 
						|
bool TLog_mask::log_notify(TSheet_field& s, int, KEY k)
 | 
						|
{            
 | 
						|
  if (k == K_INS)
 | 
						|
    return FALSE;
 | 
						|
/*
 | 
						|
  if (k == K_INS)
 | 
						|
  {   
 | 
						|
    const int last = s.items()-1;
 | 
						|
    if (last >= 0 && yesno_box("Si conferma l'eliminazione dei fax?"))
 | 
						|
    {
 | 
						|
      TLog_mask& m = (TLog_mask&)s.mask();
 | 
						|
      const WORD log = m.sheet2log(s);
 | 
						|
      for (int i = last; i >= 0; i--)
 | 
						|
      {
 | 
						|
        const char* strid = s.row(i).get(0);
 | 
						|
        unsigned long id; sscanf(strid, "%lu", &id);
 | 
						|
        m._fax->log_delete(log, id);
 | 
						|
        do_events();
 | 
						|
      }
 | 
						|
    }  
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
*/
 | 
						|
  return TRUE;  
 | 
						|
} 
 | 
						|
 | 
						|
bool TLog_mask::delrec_handler(TMask_field& f, KEY k)
 | 
						|
{
 | 
						|
  if (k == K_SPACE)
 | 
						|
  {
 | 
						|
    TMask& m = f.mask();
 | 
						|
 | 
						|
    const char* strid = m.get(101);
 | 
						|
    if (yesno_box("Si conferma l'eliminazione del fax %s?", strid))
 | 
						|
    {
 | 
						|
      TSheet_field& s = *m.get_sheet();
 | 
						|
      TLog_mask& l = (TLog_mask&)s.mask();
 | 
						|
      const WORD log = l.sheet2log(s);
 | 
						|
      CHECK(log, "Invalid Fax log");
 | 
						|
      unsigned long id; sscanf(strid, "%lu", &id);
 | 
						|
      l._fax->log_delete(log, id);
 | 
						|
    }  
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
bool TLog_mask::fax_handler(TMask_field& f, KEY k)
 | 
						|
{
 | 
						|
  if (k == K_SPACE)
 | 
						|
  {           
 | 
						|
    TMask& m = f.mask();
 | 
						|
    TSheet_field& s = *m.get_sheet();
 | 
						|
    TLog_mask& l = (TLog_mask&)s.mask();
 | 
						|
    const char* strid = m.get(101);
 | 
						|
    if (f.yesno_box("Si desidera rispedire il fax %s?", strid))
 | 
						|
    {
 | 
						|
      unsigned long id; sscanf(strid, "%lu", &id);
 | 
						|
      l._fax->resend_fax(id);
 | 
						|
    }  
 | 
						|
  }
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// @cmember Setta gli handlers dello sheet <p id> e del tasto elimina della sua maschera
 | 
						|
void TLog_mask::set_notify(short id)
 | 
						|
{
 | 
						|
  TMask_field& f = field(id);
 | 
						|
  CHECKD(f.is_kind_of(CLASS_SHEET_FIELD), "Not a sheet ", id);
 | 
						|
  TSheet_field& s = (TSheet_field&)f;
 | 
						|
  s.set_notify(log_notify);                
 | 
						|
  
 | 
						|
  TMask& sm = s.sheet_mask();
 | 
						|
  sm.set_handler(DLG_DELREC, delrec_handler);
 | 
						|
  if (id == F_FAILED) 
 | 
						|
    sm.set_handler(100, fax_handler);
 | 
						|
}
 | 
						|
 | 
						|
// @cmember Ricopia l'array <p a> nello sheet <p id>
 | 
						|
void TLog_mask::update_sheet(short id, const TString_array& a)
 | 
						|
{
 | 
						|
  TSheet_field& s = (TSheet_field&)field(id);
 | 
						|
  s.rows_array() = a;
 | 
						|
  s.force_update();
 | 
						|
}
 | 
						|
 | 
						|
void TLog_mask::update_log(WORD log, const TString_array& a)
 | 
						|
{    
 | 
						|
  // Convere il codice della coda nell'identificatore dello sheet
 | 
						|
  short id;
 | 
						|
  switch(log)
 | 
						|
  {
 | 
						|
    case SUBSCRIBE_LOG_PENDING:  id = F_PENDING;  break;
 | 
						|
    case SUBSCRIBE_LOG_SENDING:  id = F_SENDING;  break;
 | 
						|
    case SUBSCRIBE_LOG_COMPLETE: id = F_COMPLETE; break;
 | 
						|
    case SUBSCRIBE_LOG_FAILED:   id = F_FAILED;   break;
 | 
						|
    default: id = DLG_NULL; break;
 | 
						|
  } 
 | 
						|
  
 | 
						|
  // Aggiorna lo sheet, se l'ha trovato
 | 
						|
  if (id != DLG_NULL)
 | 
						|
    update_sheet(id, a);
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// DDE Fax server
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
 | 
						|
TDDE_fax::TDDE_fax() 
 | 
						|
        : _pappinfo(NULL), _log_mask(NULL), _fax_mask(NULL),
 | 
						|
          _close_when_idle(FALSE)
 | 
						|
{               
 | 
						|
  _pappinfo = FaxRegisterApp(get_app_name(), hwnd());
 | 
						|
  if (_pappinfo)
 | 
						|
  {    
 | 
						|
    start_server();                             // Inizia DDE server
 | 
						|
    FaxSubscribe(_pappinfo, SUBSCRIBE_LOG_ALL); // Connettiti a Faxman
 | 
						|
    update_all_logs();                          // Aggiorna tutte le code
 | 
						|
    DragAcceptFiles((HWND)hwnd(), TRUE);        // Attiva Drag'n'drop
 | 
						|
  }  
 | 
						|
  else
 | 
						|
  {
 | 
						|
    xvt_statbar_set("Impossibile connettersi a FAXMAN");
 | 
						|
    beep();
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
TDDE_fax::~TDDE_fax()
 | 
						|
{ 
 | 
						|
  if (_pappinfo)
 | 
						|
  {
 | 
						|
    DragAcceptFiles((HWND)hwnd(), FALSE);   // Non accettare piu' Drag'n'drop
 | 
						|
 | 
						|
    FaxUnregisterApp(_pappinfo);            // Sconnettiti da Faxman
 | 
						|
    _pappinfo = NULL;
 | 
						|
  }  
 | 
						|
 | 
						|
  if (_log_mask)
 | 
						|
  {
 | 
						|
    delete _log_mask;
 | 
						|
    _log_mask = NULL;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool TDDE_fax::do_initiate(word id, const TString& topic)
 | 
						|
{
 | 
						|
  return TRUE;                    
 | 
						|
}
 | 
						|
 | 
						|
bool TDDE_fax::exec_command(const TString& cmd, TToken_string& arg)
 | 
						|
{
 | 
						|
  if (cmd.compare("FileClose", -1, TRUE) == 0)
 | 
						|
  {
 | 
						|
    if (can_close())
 | 
						|
      main_app().stop_run();
 | 
						|
    else
 | 
						|
      _close_when_idle = TRUE;  
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (cmd.compare("SetRecipient", -1, TRUE) == 0)
 | 
						|
  {
 | 
						|
    TString tipo = arg.get(0); tipo.trim();
 | 
						|
    TString codice = arg.get(); codice.trim();
 | 
						|
    push_destination(tipo, codice);
 | 
						|
  }
 | 
						|
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
bool TDDE_fax::do_execute(word id, const TString& cmd)
 | 
						|
{           
 | 
						|
  bool ok = TRUE;
 | 
						|
 | 
						|
  TToken_string commands(cmd, ']');
 | 
						|
  TToken_string arguments(80, ',');
 | 
						|
  
 | 
						|
  for (TString command = commands.get(0); command.not_empty(); command = commands.get())
 | 
						|
  {
 | 
						|
    if (command[0] == '[')
 | 
						|
      command.ltrim(1);
 | 
						|
 | 
						|
    const int bracket = command.find('(');
 | 
						|
    if (bracket > 0)
 | 
						|
    { 
 | 
						|
      arguments = command.mid(bracket+1, -1);
 | 
						|
      arguments.rtrim(1);
 | 
						|
      arguments.trim();
 | 
						|
      command.cut(bracket);
 | 
						|
    }       
 | 
						|
    else
 | 
						|
      arguments.cut(0);
 | 
						|
    
 | 
						|
    command.trim();
 | 
						|
    ok = exec_command(command, arguments);
 | 
						|
    if (!ok) break;
 | 
						|
  } 
 | 
						|
  
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
// Genera il nome di un file temporaneo: se esiste gia' ripete il ciclo.
 | 
						|
void TDDE_fax::choose_temp_name(TFilename& name) const
 | 
						|
{   
 | 
						|
  static long lastfax = 0;
 | 
						|
   
 | 
						|
  TFilename path;                     
 | 
						|
  path.tempdir();                     // Directory temporanea
 | 
						|
  path.add("FAX");                    // Aggiunge la directory FAX
 | 
						|
  
 | 
						|
  if (lastfax == 0 && !fexist(path))
 | 
						|
    make_dir(path);
 | 
						|
  
 | 
						|
  do
 | 
						|
  {                 
 | 
						|
    TString16 f; f.format("FAX%05ld.FMF", ++lastfax);
 | 
						|
    name = path; name.add(f);
 | 
						|
  } while (fexist(name));
 | 
						|
} 
 | 
						|
 | 
						|
void TDDE_fax::on_firm_change() 
 | 
						|
{ 
 | 
						|
  _queue.on_firm_change(); 
 | 
						|
}
 | 
						|
 | 
						|
void TDDE_fax::handle_fax_message(word wparam, long lparam)
 | 
						|
{ 
 | 
						|
  switch(wparam)
 | 
						|
  {           
 | 
						|
  case FAXMODEMMSG:
 | 
						|
    if (lparam)
 | 
						|
    {
 | 
						|
      PFAXDEVICE dev = (PFAXDEVICE)lparam;
 | 
						|
      
 | 
						|
      TString msg(24);
 | 
						|
      msg = "E' stata ";
 | 
						|
      if (!dev->wFlags)  
 | 
						|
      {
 | 
						|
        _port.reset(dev->nPort);       // Removing a port
 | 
						|
        msg << "scollegata";
 | 
						|
        beep();
 | 
						|
      }  
 | 
						|
      else
 | 
						|
      {
 | 
						|
        _port.set(dev->nPort);         // Adding a port
 | 
						|
        msg << "collegata";
 | 
						|
      }  
 | 
						|
      msg << " la porta COM" << dev->nPort;
 | 
						|
      xvt_statbar_set(msg);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case FAXGETFILENAME:
 | 
						|
    if (lparam)
 | 
						|
    {
 | 
						|
      TFilename tmp; choose_temp_name(tmp);
 | 
						|
      strcpy((char*)lparam, tmp);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case FAXPRINTMSG:
 | 
						|
    if (lparam)
 | 
						|
    {                      
 | 
						|
      PPRINTSTAT ps = (PPRINTSTAT)lparam;
 | 
						|
 
 | 
						|
      if (ps->pStat == PRN_OK)
 | 
						|
      {
 | 
						|
        TFax_data& data = _queue.peek_last();
 | 
						|
        data.set_file(ps->FileName);
 | 
						|
        beep();
 | 
						|
        if (_fax_mask == NULL)
 | 
						|
          send_next_fax();
 | 
						|
      }    
 | 
						|
 | 
						|
      GlobalFree((HGLOBAL)lparam);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  case FAXLOGADD:
 | 
						|
    if (lparam)
 | 
						|
    {
 | 
						|
      PSEND_FAX sf = (PSEND_FAX)lparam;
 | 
						|
      add_log(sf->wLog, sf);
 | 
						|
    }  
 | 
						|
    break;  
 | 
						|
  case FAXLOGREMOVE:
 | 
						|
    if (lparam)
 | 
						|
    {
 | 
						|
      PSEND_FAX sf = (PSEND_FAX)lparam;
 | 
						|
      remove_log(sf->wLog, sf);
 | 
						|
    }  
 | 
						|
    break;  
 | 
						|
  case FAXSENDMSG:
 | 
						|
    if (lparam)  
 | 
						|
    {
 | 
						|
      PSEND_FAX sf = (PSEND_FAX)lparam;
 | 
						|
      show_status(sf);
 | 
						|
    }
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Gestione del Drag'n'drop
 | 
						|
void TDDE_fax::handle_drop_files(word wparam)
 | 
						|
{              
 | 
						|
  TTemp_window tw(TASK_WIN);
 | 
						|
  tw.maximize();
 | 
						|
  
 | 
						|
  xvt_statbar_set("Creazione fax...");
 | 
						|
  do_events();
 | 
						|
 | 
						|
  HDROP hdrop = (HDROP)wparam;
 | 
						|
  const int num_files = DragQueryFile(hdrop, -1, NULL, 0); // Numero totale di files
 | 
						|
 | 
						|
  TFilename fname;    // File corrente
 | 
						|
  
 | 
						|
  TFax_list file_list;
 | 
						|
  for (int i = 0; i < num_files; i++)
 | 
						|
  { 
 | 
						|
    DragQueryFile(hdrop, i, (char*)(const char*)fname, fname.size());
 | 
						|
    if (file_list.is_faxable(fname))
 | 
						|
      file_list.add(fname);
 | 
						|
  }
 | 
						|
  DragFinish(hdrop);
 | 
						|
  
 | 
						|
  // Spedisce un unico fax con tutti i files droppati
 | 
						|
  if (file_list.items() > 0)
 | 
						|
  {              
 | 
						|
    begin_wait();
 | 
						|
    TFilename fax; choose_temp_name(fax);
 | 
						|
    const word err = FaxCreate(_pappinfo, file_list, fax, 0L);
 | 
						|
    xvt_statbar_set("");
 | 
						|
    end_wait();
 | 
						|
    if (err == 0)
 | 
						|
      push_fax(fax);
 | 
						|
    else
 | 
						|
      error_box("Impossibile convertire il file %s", (const char*)file_list.get(err-1));
 | 
						|
  }  
 | 
						|
  else
 | 
						|
    xvt_statbar_set("");
 | 
						|
}                                
 | 
						|
 | 
						|
bool TDDE_fax::do_custom_message(word msg, word wparam, long lparam)
 | 
						|
{          
 | 
						|
  bool ok = TRUE;
 | 
						|
  switch(msg)
 | 
						|
  {       
 | 
						|
  case WM_DROPFILES:
 | 
						|
    handle_drop_files(wparam);
 | 
						|
    break;              
 | 
						|
  case WM_FAXMSG: 
 | 
						|
    handle_fax_message(wparam, lparam); 
 | 
						|
    break;
 | 
						|
  default: 
 | 
						|
    ok = FALSE;
 | 
						|
    break;
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}             
 | 
						|
 | 
						|
bool TDDE_fax::resend_fax(unsigned long id)
 | 
						|
{                                    
 | 
						|
  PSEND_FAX sf;
 | 
						|
  bool ok = FaxLogFind(_pappinfo, &sf, id) == 1;
 | 
						|
  if (ok)
 | 
						|
  {          
 | 
						|
    const TFilename old_name(sf->szFileList);
 | 
						|
    TFilename new_name(old_name); new_name.ext("FMP");
 | 
						|
    rename(old_name, new_name);             // Rinomina file
 | 
						|
    FaxLogDelete(_pappinfo, id, sf->wLog);  // Cancella fax
 | 
						|
    do_events();                            
 | 
						|
    rename(new_name, old_name);             // Ripristina file
 | 
						|
    FaxSchedule(_pappinfo, sf);
 | 
						|
    GlobalFreePtr(sf);
 | 
						|
  }  
 | 
						|
  return ok;  
 | 
						|
}
 | 
						|
 | 
						|
bool TDDE_fax::send_next_fax()
 | 
						|
{                
 | 
						|
  static bool no_fax_error = FALSE;
 | 
						|
 | 
						|
  TTemp_window tw(TASK_WIN);
 | 
						|
 | 
						|
#if XVT_OS == XVT_OS_WIN  
 | 
						|
  HWND hwnd = (HWND)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW);
 | 
						|
  SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 | 
						|
#endif  
 | 
						|
 | 
						|
  tw.maximize();
 | 
						|
  
 | 
						|
  if (_port.ones() == 0 && !no_fax_error)
 | 
						|
  {
 | 
						|
    no_fax_error = TRUE;
 | 
						|
    error_box("Non c'e nessun Modem/Fax collegato");
 | 
						|
  }
 | 
						|
 | 
						|
  CHECK(_fax_mask == NULL, "Double fax mask");
 | 
						|
  _fax_mask = new TFax_mask(this);
 | 
						|
 | 
						|
  bool sent = FALSE;
 | 
						|
  do
 | 
						|
  {
 | 
						|
    TFax_data& data = _queue.pop();
 | 
						|
    _fax_mask->set_data(data);
 | 
						|
    
 | 
						|
    if (_fax_mask->run() == K_ENTER)
 | 
						|
    {
 | 
						|
      _fax_mask->get_data(data);
 | 
						|
  
 | 
						|
      PSEND_FAX sf = &_send_fax; 
 | 
						|
      FaxInitSendStruct(_pappinfo, sf);
 | 
						|
      
 | 
						|
      sf->szDestFax     = data.get_char_star("FULLDESTFAX");
 | 
						|
      sf->szDestName    = data.get_char_star("DESTNAME");
 | 
						|
      sf->szToCompany   = data.get_char_star("DESTFIRM");
 | 
						|
      
 | 
						|
      sf->szFromFax     = data.get_char_star("FROMFAX");
 | 
						|
      sf->szFromLine    = data.get_char_star("FROMNAME");
 | 
						|
      sf->szFromCompany = data.get_char_star("FROMFIRM");
 | 
						|
   
 | 
						|
      sf->szFileList    = data.get_char_star("FILELIST");
 | 
						|
      
 | 
						|
      sf->szBanner = "%m %s| |Pagina %c di %p";
 | 
						|
      sf->szCover = "cover1.pg";
 | 
						|
      
 | 
						|
      const DWORD id = FaxSchedule(_pappinfo, sf);
 | 
						|
      sent = id > 0;
 | 
						|
    }        
 | 
						|
  } while (!_queue.empty());
 | 
						|
  
 | 
						|
  delete _fax_mask;
 | 
						|
  _fax_mask = NULL;
 | 
						|
 | 
						|
#if XVT_OS == XVT_OS_WIN
 | 
						|
  SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 | 
						|
#endif
 | 
						|
  
 | 
						|
  // Non iconizzare se ho aperta la finestra di stato
 | 
						|
  if (_log_mask == NULL)
 | 
						|
    tw.iconize();
 | 
						|
  
 | 
						|
  if (_close_when_idle && can_close())
 | 
						|
    main_app().stop_run();
 | 
						|
  
 | 
						|
  return sent;
 | 
						|
}
 | 
						|
 | 
						|
void TDDE_fax::push_fax(const char* fax)
 | 
						|
{                                                 
 | 
						|
  TFax_data* data = new TFax_data(_queue.peek_default());
 | 
						|
  data->set_file(fax);
 | 
						|
  _queue.push(data);
 | 
						|
  
 | 
						|
  if (_fax_mask == NULL)
 | 
						|
    send_next_fax();
 | 
						|
}
 | 
						|
 | 
						|
TString_array* TDDE_fax::log2array(WORD log)
 | 
						|
{
 | 
						|
  TString_array* array;
 | 
						|
  switch(log)
 | 
						|
  {
 | 
						|
    case SUBSCRIBE_LOG_PENDING : array = &_pending; break;
 | 
						|
    case SUBSCRIBE_LOG_SENDING : array = &_sending; break;
 | 
						|
    case SUBSCRIBE_LOG_COMPLETE: array = &_complete; break;
 | 
						|
    case SUBSCRIBE_LOG_FAILED  : array = &_failed; break;
 | 
						|
    default: array = NULL;
 | 
						|
  }
 | 
						|
  return array;
 | 
						|
}
 | 
						|
 | 
						|
const char* TDDE_fax::error2string(FAXERROR e) const
 | 
						|
{
 | 
						|
  static const char* msg[] = 
 | 
						|
  {
 | 
						|
    "",                                    // FAXERR_OK
 | 
						|
    "Comando non ricosciuto (nessun OK)",  // FAXERR_ACK
 | 
						|
    "Modem/Fax non riconosciuto",          // FAXERR_BADFAXMODEM
 | 
						|
    "Errore di inizializzazione",          // FAXERR_INIT
 | 
						|
    "Errore nei parametri FDIS",           // FAXERR_FDIS
 | 
						|
    "Errore nell'identificatore locale",   // FAXERR_FLID
 | 
						|
    "Errore di composizione del numero",   // FAXERR_DIAL
 | 
						|
    "Errore di connessione al fax remoto", // FAXERR_FCON_ERR
 | 
						|
    "Errore nella stringa FCSI",           // FAXERR_FCSI
 | 
						|
    "Errore di ricezione FDIS",            // FAXERR_NEG_FDIS
 | 
						|
    "Errore di stato errato",              // FAXERR_BADSTATE
 | 
						|
    "Linea occupata",                      // FAXERR_BUSY
 | 
						|
    "Segnale di libero non rilevato",      // FAXERR_NODIALTONE
 | 
						|
    "Messaggio CONNECT non ricevuto",      // FAXERR_NOCONNECT
 | 
						|
    "Interrotto dall'utente",              // FAXERR_CANCEL
 | 
						|
    "FPTS nullo o errato",                 // FAXERR_FPTS
 | 
						|
    "FHNG nullo o errato",                 // FAXERR_FHNG
 | 
						|
    "FDCS nullo o errato",                 // FAXERR_FDCS
 | 
						|
    "Errore di trasmissione",              // FAXERR_ERROR
 | 
						|
    "File in formato errato",              // FAXERR_FILE
 | 
						|
    "Fax Server incompatibile",            // FAXERR_VERSION
 | 
						|
    "Tempo di trasmissione scaduto",       // FAXERR_TIMEOUT
 | 
						|
    "Nessuna risposta a MPS",              // FAXERR_NO_MPS_RESP
 | 
						|
    "Nessuna risposta a EOP",              // FAXERR_NO_EOP_RESP
 | 
						|
    "Errore di connessione",               // FAXERR_NOTRAIN
 | 
						|
  };
 | 
						|
                
 | 
						|
  if (e < FAXERR_OK || e > FAXERR_NOTRAIN)
 | 
						|
    e = FAXERR_ERROR;
 | 
						|
  
 | 
						|
  return msg[e];
 | 
						|
}
 | 
						|
 | 
						|
void TDDE_fax::add_log(WORD log, PSEND_FAX sf)
 | 
						|
{
 | 
						|
  TString_array* arr = log2array(log);
 | 
						|
  if (arr)
 | 
						|
  {
 | 
						|
    TToken_string* l = new TToken_string(128);
 | 
						|
    
 | 
						|
    l->format("%lu", sf->dwID);                              // ID  
 | 
						|
    
 | 
						|
    l->add(sf->szDestFax);                                   // Dest. fax 
 | 
						|
    
 | 
						|
    TString destination(128);
 | 
						|
    destination = sf->szDestName;
 | 
						|
    destination.trim();
 | 
						|
    if (*sf->szToCompany)
 | 
						|
    { 
 | 
						|
      if (destination.not_empty())
 | 
						|
        destination << ", ";
 | 
						|
      destination << sf->szToCompany;
 | 
						|
    }  
 | 
						|
    l->add(destination);                                     // Dest. name
 | 
						|
    
 | 
						|
    l->add(TDate(sf->nDay, sf->nMonth, sf->nYear).string()); // Date and time
 | 
						|
    char ora[16]; sprintf(ora, "%02d:%02d:%02d", sf->nHour, sf->nMin, sf->nSecond);
 | 
						|
    l->add(ora);
 | 
						|
    
 | 
						|
    l->add(sf->szFileList);                                  // Files
 | 
						|
    
 | 
						|
    l->add(error2string(sf->fe));
 | 
						|
  
 | 
						|
    arr->add(l);        // Aggiorna array del log
 | 
						|
    if (_log_mask)      // Se aperta, aggiorna anche maschera
 | 
						|
      _log_mask->update_log(log, *arr);
 | 
						|
  }    
 | 
						|
}
 | 
						|
 | 
						|
void TDDE_fax::remove_log(WORD log, PSEND_FAX sf)
 | 
						|
{
 | 
						|
  TString_array* arr = log2array(log);
 | 
						|
  if (arr)
 | 
						|
  {
 | 
						|
    TString16 id; id.format("%lu", sf->dwID);
 | 
						|
    for (int i = arr->items()-1; i >= 0; i--)
 | 
						|
    {
 | 
						|
      TToken_string& r = arr->row(i);
 | 
						|
      if (id == r.get(0)) break;
 | 
						|
    }
 | 
						|
    if (i >= 0)
 | 
						|
    {
 | 
						|
      arr->destroy(i, TRUE);
 | 
						|
      if (_log_mask)
 | 
						|
        _log_mask->update_log(log, *arr);
 | 
						|
    }    
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
void TDDE_fax::update_all_logs()
 | 
						|
{      
 | 
						|
  SEND_FAX  tmpsf;
 | 
						|
  
 | 
						|
  _pending.destroy();
 | 
						|
  _sending.destroy();
 | 
						|
  _failed.destroy();
 | 
						|
  _complete.destroy();
 | 
						|
  
 | 
						|
  if (FaxLogInit(_pappinfo, SUBSCRIBE_LOG_PENDING) < MAXITERATORS) 
 | 
						|
  {
 | 
						|
    while (FaxLogNext(_pappinfo, &tmpsf) == LOGERR_CONTINUEIT)
 | 
						|
      do_custom_message(WM_FAXMSG, FAXLOGADD, (LPARAM)&tmpsf);
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (FaxLogInit(_pappinfo, SUBSCRIBE_LOG_SENDING) < MAXITERATORS) 
 | 
						|
  {
 | 
						|
    while (FaxLogNext(_pappinfo, &tmpsf) == LOGERR_CONTINUEIT)
 | 
						|
      do_custom_message(WM_FAXMSG, FAXLOGADD, (LPARAM)&tmpsf);
 | 
						|
  }
 | 
						|
 | 
						|
  if (FaxLogInit(_pappinfo, SUBSCRIBE_LOG_COMPLETE) < MAXITERATORS) 
 | 
						|
  {
 | 
						|
    while (FaxLogNext(_pappinfo, &tmpsf) == LOGERR_CONTINUEIT)
 | 
						|
      do_custom_message(WM_FAXMSG, FAXLOGADD, (LPARAM)&tmpsf);
 | 
						|
  }
 | 
						|
 | 
						|
  if (FaxLogInit(_pappinfo, SUBSCRIBE_LOG_FAILED) < MAXITERATORS) 
 | 
						|
  {
 | 
						|
    while (FaxLogNext(_pappinfo, &tmpsf) == LOGERR_CONTINUEIT)
 | 
						|
      do_custom_message(WM_FAXMSG, FAXLOGADD, (LPARAM)&tmpsf);
 | 
						|
  }
 | 
						|
  
 | 
						|
  _port.reset();
 | 
						|
  FaxEnumDevices(_pappinfo);
 | 
						|
}
 | 
						|
 | 
						|
void TDDE_fax::update_log(WORD log)
 | 
						|
{
 | 
						|
  if (_log_mask)
 | 
						|
  {
 | 
						|
    const TString_array* arr = log2array(log);
 | 
						|
    if (arr)
 | 
						|
      _log_mask->update_log(log, *arr);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TDDE_fax::show_status(PSEND_FAX sf)
 | 
						|
{                 
 | 
						|
  if (_log_mask)
 | 
						|
  {
 | 
						|
    TString msg(80);
 | 
						|
    switch(sf->fs)
 | 
						|
    {       
 | 
						|
      case FAXST_SEND_INIT     : msg = "Inizializzazione"; break;
 | 
						|
      case FAXST_SEND_DIALING  : msg = "Composizione del numero "; 
 | 
						|
                                 msg << sf->szDestFax; 
 | 
						|
                                 break;       
 | 
						|
      case FAXST_SEND_FCSI     : msg = "Connessione"; break;       
 | 
						|
      case FAXST_SENDING       : msg = "Spedizione pagina "; 
 | 
						|
                                 msg << sf->nTotCurPage << " di " << sf->nTotPages
 | 
						|
                                     << ": " << sf->nPercent << '%';
 | 
						|
                                 break;  
 | 
						|
      case FAXST_PAGE_END      : msg = "Fine pagina "; msg << sf->nTotCurPage; break;
 | 
						|
      case FAXST_COMPLETE      : msg = "Fine trasmissione"; break;     
 | 
						|
      case FAXST_ABORT         : msg = "Operazione abortita"; break;
 | 
						|
      case FAXST_PORTSHUT      : msg = "Chiusura COM"; msg << sf->nPort;
 | 
						|
                                 if (sf->fe != FAXERR_OK)
 | 
						|
                                   msg << ": " << error2string(sf->fe);
 | 
						|
                                 break;   
 | 
						|
      default                  : break;
 | 
						|
    }
 | 
						|
    if (msg.not_empty())
 | 
						|
      _log_mask->set(F_STATUS, msg);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TDDE_fax::log_delete(WORD log, unsigned long id)
 | 
						|
{   
 | 
						|
  if (log == SUBSCRIBE_LOG_SENDING)
 | 
						|
  {
 | 
						|
    const bool ok = FaxCancel(_pappinfo, id);
 | 
						|
    if (!ok)
 | 
						|
      FaxLogDelete(_pappinfo, id, log);
 | 
						|
  }
 | 
						|
  else
 | 
						|
    FaxLogDelete(_pappinfo, id, log);
 | 
						|
}
 | 
						|
 | 
						|
void TDDE_fax::auto_configure()
 | 
						|
{
 | 
						|
  const int err = FaxAddDevice(_pappinfo, 0);
 | 
						|
  if (err != 0)
 | 
						|
  {                    
 | 
						|
    const int seconds = 4;
 | 
						|
    TProgind pi(seconds, "Ricerca dei Modem/Fax collegati...", FALSE, TRUE, 48);
 | 
						|
    for (int i = 1; i <= seconds; i++)
 | 
						|
    {                
 | 
						|
      pi.setstatus(i);
 | 
						|
      const clock_t end = clock() + CLOCKS_PER_SEC;
 | 
						|
      while (clock() < end)
 | 
						|
        do_events();
 | 
						|
    }         
 | 
						|
    
 | 
						|
    _port.reset();                 // Azzera tutti i flag delle porte
 | 
						|
    FaxEnumDevices(_pappinfo);     // Richiede la lista delle porte
 | 
						|
 | 
						|
    pi.set_text("Controllo dei Modem/Fax trovati ...");
 | 
						|
    for (i = 1; i <= seconds; i++)
 | 
						|
    {                
 | 
						|
      pi.setstatus(i);
 | 
						|
      const clock_t end = clock() + CLOCKS_PER_SEC;
 | 
						|
      while (clock() < end)
 | 
						|
        do_events();
 | 
						|
    }         
 | 
						|
    
 | 
						|
    TString msg(24);
 | 
						|
    msg << "Modem/Fax collegati: ";
 | 
						|
    const long np = _port.ones();
 | 
						|
    if (np == 0) 
 | 
						|
      msg << "NESSUNO";
 | 
						|
    else 
 | 
						|
      msg << np;
 | 
						|
    xvt_statbar_set(msg);
 | 
						|
  }
 | 
						|
  else
 | 
						|
    error_box("Impossibile trovare il server Faxman");
 | 
						|
}  
 | 
						|
 | 
						|
bool TDDE_fax::run_mask()
 | 
						|
{   
 | 
						|
  const bool ok = _log_mask == NULL;
 | 
						|
  if (ok)
 | 
						|
  {             
 | 
						|
    TTemp_window tw(TASK_WIN);
 | 
						|
    tw.maximize();
 | 
						|
    _log_mask = new TLog_mask(this);
 | 
						|
    
 | 
						|
    update_log(SUBSCRIBE_LOG_PENDING );
 | 
						|
    update_log(SUBSCRIBE_LOG_SENDING );
 | 
						|
    update_log(SUBSCRIBE_LOG_FAILED  );
 | 
						|
    update_log(SUBSCRIBE_LOG_COMPLETE);
 | 
						|
    
 | 
						|
    _log_mask->run();
 | 
						|
    delete _log_mask;
 | 
						|
    _log_mask = NULL;
 | 
						|
  }
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
TString& TDDE_fax::ragsoc2name(TString& ragsoc) const
 | 
						|
{
 | 
						|
  TString first_name = ragsoc.left(30); first_name.trim(); 
 | 
						|
  if (first_name.len() < 30)
 | 
						|
  {
 | 
						|
    TString last_name = ragsoc.mid(30); last_name.trim();
 | 
						|
    ragsoc = first_name;
 | 
						|
    ragsoc << ' ' << last_name;
 | 
						|
  }  
 | 
						|
  return ragsoc;
 | 
						|
}
 | 
						|
 | 
						|
bool TDDE_fax::ricerca_clifo(char cf, const TString& codice, TFax_data& data) const
 | 
						|
{
 | 
						|
  TLocalisamfile f(LF_CLIFO);
 | 
						|
  f.put(CLI_TIPOCF, cf);
 | 
						|
  f.put(CLI_CODCF, codice);
 | 
						|
  const int err = f.read();
 | 
						|
  if (err == NOERR)
 | 
						|
  {
 | 
						|
    TToken_string s(80, ',');
 | 
						|
    s = f.get("PFAX"); s.add(f.get("FAX"));
 | 
						|
    data.set("DESTFAX", s);
 | 
						|
    
 | 
						|
    s = f.get("PTEL"); s.add(f.get("TEL"));
 | 
						|
    data.set("DESTTEL", s);
 | 
						|
    
 | 
						|
    data.set("DESTNAME", "");
 | 
						|
    
 | 
						|
    s = f.get("RAGSOC");
 | 
						|
    data.set("DESTFIRM", ragsoc2name(s));
 | 
						|
              
 | 
						|
    data.set("TIPO", cf == 'C' ? "Clienti" : "Fornitori");
 | 
						|
    data.set(cf == 'C' ? "CLIENTI" : "FORNITORI", codice);
 | 
						|
  }
 | 
						|
  return err == NOERR;
 | 
						|
}
 | 
						|
 | 
						|
bool TDDE_fax::ricerca_persone(char fg, const TString& codice, TFax_data& data) const
 | 
						|
{
 | 
						|
  TRelation r(LF_ANAG);
 | 
						|
  
 | 
						|
  if (fg == 'G')
 | 
						|
    r.add(LF_ANAGGIU, "CODANAGR=CODANAGR");
 | 
						|
  
 | 
						|
  TRectype& c = r.curr();
 | 
						|
  c.put(ANA_TIPOA, fg);
 | 
						|
  c.put(ANG_CODANAGR, codice);
 | 
						|
  
 | 
						|
  const int err = r.read();
 | 
						|
  if (err == NOERR)
 | 
						|
  {
 | 
						|
    TToken_string s(80, ',');
 | 
						|
    s = c.get("PFAXRF"); s.add(c.get("FAXRF"));
 | 
						|
    data.set("DESTFAX", s);
 | 
						|
    
 | 
						|
    s = c.get("PTELRF"); s.add(c.get("TELRF"));
 | 
						|
    data.set("DESTTEL", s);
 | 
						|
    
 | 
						|
    if (fg == 'G')
 | 
						|
    {
 | 
						|
      data.set("DESTFIRM", c.get("RAGSOC"));
 | 
						|
      data.set("DESTNAME", r.curr(LF_ANAGGIU).get("PERRIF"));
 | 
						|
      
 | 
						|
      data.set("TIPO", "Giuridiche");
 | 
						|
      data.set("GIURIDICHE", codice);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {                          
 | 
						|
      data.set("DESTFIRM", "");
 | 
						|
      s = c.get("RAGSOC");
 | 
						|
      data.set("DESTNAME", ragsoc2name(s));
 | 
						|
      
 | 
						|
      data.set("TIPO", "Fisiche");
 | 
						|
      data.set("FISICHE", codice);
 | 
						|
    }  
 | 
						|
  }
 | 
						|
  return err == NOERR;
 | 
						|
}
 | 
						|
 | 
						|
bool TDDE_fax::ricerca_ditte(const TString& codice, TFax_data& data) const
 | 
						|
{
 | 
						|
  TLocalisamfile f(LF_NDITTE);
 | 
						|
  f.put(NDT_CODDITTA, codice);
 | 
						|
  const int err = f.read();
 | 
						|
  if (err == NOERR)
 | 
						|
  {
 | 
						|
    TToken_string s(128, ',');
 | 
						|
    s.add(f.get(NDT_PFAX));
 | 
						|
    s.add(f.get(NDT_FAX));
 | 
						|
    data.set("DESTFAX", s);
 | 
						|
    data.set("DESTNAME", f.get(NDT_PERRIF));
 | 
						|
    data.set("DESTFIRM", f.get(NDT_RAGSOC));
 | 
						|
    data.set("TIPO", "Ditte");
 | 
						|
    data.set("DITTE", codice);
 | 
						|
  }
 | 
						|
  return err == NOERR;
 | 
						|
}
 | 
						|
 | 
						|
bool TDDE_fax::set_destination(const TString& tipo, const TString& codice, TFax_data& data) const
 | 
						|
{                                 
 | 
						|
  const char* tipi[] = { "CLI", "DIT", "FIS", "FOR", "GIU", NULL };
 | 
						|
  bool ok = TRUE;
 | 
						|
 | 
						|
  for (int i = 0; tipi[i]; i++)
 | 
						|
  {
 | 
						|
    if (tipo.compare(tipi[i], 3, TRUE) == 0)
 | 
						|
      break;
 | 
						|
  } 
 | 
						|
  
 | 
						|
  data = _queue.peek_last();  // Inizializza valori di default
 | 
						|
  switch(i)
 | 
						|
  {
 | 
						|
  case 0 : ricerca_clifo('C', codice, data); break;
 | 
						|
  case 1 : ricerca_ditte(codice, data); break;
 | 
						|
  case 2 : ricerca_persone('F', codice, data); break;
 | 
						|
  case 3 : ricerca_clifo('F', codice, data); break;
 | 
						|
  case 4 : ricerca_persone('G', codice, data); break;
 | 
						|
  default: ok = FALSE; break;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return ok;
 | 
						|
} 
 | 
						|
 | 
						|
bool TDDE_fax::push_destination(const TString& tipo, const TString& codice)
 | 
						|
{
 | 
						|
  TFax_data* data = new TFax_data;
 | 
						|
  const bool ok = set_destination(tipo, codice, *data);
 | 
						|
  _queue.push(data);
 | 
						|
  return ok;
 | 
						|
}
 | 
						|
 | 
						|
bool TDDE_fax::can_close() const
 | 
						|
{
 | 
						|
  return _log_mask == NULL && _queue.empty() &&
 | 
						|
         _pending.items() == 0 && _sending.items() == 0;
 | 
						|
}
 | 
						|
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
// Fax server application
 | 
						|
///////////////////////////////////////////////////////////
 | 
						|
 | 
						|
class TFax_server : public TApplication
 | 
						|
{                     
 | 
						|
  TDDE_fax* _fax;
 | 
						|
 | 
						|
protected:
 | 
						|
  virtual bool pre_create(); 
 | 
						|
  virtual bool create(); 
 | 
						|
  virtual bool destroy();
 | 
						|
  virtual bool menu(MENU_TAG mt);
 | 
						|
  virtual void on_firm_change();
 | 
						|
 | 
						|
public:
 | 
						|
  TFax_server() : _fax(NULL) { } 
 | 
						|
  virtual ~TFax_server() { } 
 | 
						|
};
 | 
						|
 | 
						|
bool TFax_server::pre_create()
 | 
						|
{ 
 | 
						|
  CHECK(_fax == NULL, "Double fax creation");
 | 
						|
  _fax = new TDDE_fax;
 | 
						|
  return _fax->ok();
 | 
						|
}
 | 
						|
 | 
						|
bool TFax_server::create()
 | 
						|
{ 
 | 
						|
  const bool ok = _fax->ok();
 | 
						|
  if (ok) 
 | 
						|
  {              
 | 
						|
    bool show_status = FALSE;
 | 
						|
    
 | 
						|
    if (argc() >= 2 && stricmp(argv(1), "-S") == 0)
 | 
						|
      show_status = TRUE;
 | 
						|
    
 | 
						|
    if (argc() > 2)
 | 
						|
    {
 | 
						|
      const TString tipo   = argv(1); 
 | 
						|
      const TString codice = argv(2);
 | 
						|
      _fax->push_destination(tipo, codice);
 | 
						|
    }
 | 
						|
    
 | 
						|
    TMailbox mb;                  
 | 
						|
    TToken_string topics = _fax->get_topics();
 | 
						|
    for (TString topic = topics.get(0); topic.not_empty(); topic = topics.get())
 | 
						|
    {
 | 
						|
      TMessage* msg = mb.next_s(topic);
 | 
						|
      while (msg)
 | 
						|
      {
 | 
						|
        const TString cmd(msg->body());
 | 
						|
        if (_fax->do_initiate(0, topic))
 | 
						|
          _fax->do_execute(0, cmd);
 | 
						|
        msg = mb.next_s(topic);  
 | 
						|
      }
 | 
						|
    }  
 | 
						|
    
 | 
						|
    if (show_status)
 | 
						|
    {
 | 
						|
      dispatch_e_menu(MENU_ITEM(1));
 | 
						|
    }  
 | 
						|
    else
 | 
						|
    {
 | 
						|
      TTemp_window w(TASK_WIN);
 | 
						|
      w.iconize();
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else 
 | 
						|
    destroy();      // Non verrebbe mai chiamata
 | 
						|
  return ok;  
 | 
						|
}
 | 
						|
 | 
						|
bool TFax_server::destroy()
 | 
						|
{   
 | 
						|
  if (_fax) 
 | 
						|
  {
 | 
						|
    delete _fax;
 | 
						|
    _fax = NULL;
 | 
						|
  }  
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
void TFax_server::on_firm_change()
 | 
						|
{          
 | 
						|
  TApplication::on_firm_change();
 | 
						|
  if (_fax)
 | 
						|
    _fax->on_firm_change();
 | 
						|
}
 | 
						|
 | 
						|
bool TFax_server::menu(MENU_TAG mt)
 | 
						|
{   
 | 
						|
  if (_fax)
 | 
						|
  {    
 | 
						|
    switch(mt)
 | 
						|
    {
 | 
						|
    case MENU_ITEM(1):
 | 
						|
      _fax->run_mask(); 
 | 
						|
      break;
 | 
						|
    case MENU_ITEM(2):
 | 
						|
      _fax->auto_configure();
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      break;
 | 
						|
    }  
 | 
						|
  }  
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
int main(int argc, char** argv)
 | 
						|
{         
 | 
						|
  TApplication::check_parameters(argc, argv);
 | 
						|
 | 
						|
  char drive[_MAX_DRIVE];
 | 
						|
  char path[_MAX_PATH];
 | 
						|
  _splitpath(argv[0], drive, path, NULL, NULL);
 | 
						|
  int err = _chdrive(toupper(*drive)-'A'+1);
 | 
						|
  if (err == 0) 
 | 
						|
  {
 | 
						|
    const int last = strlen(path)-1;
 | 
						|
    CHECKS(last >= 0, "Invalid directory ", path);
 | 
						|
    if (path[last] == '\\' || path[last] == '/')
 | 
						|
      path[last] = '\0';
 | 
						|
    err = _chdir(path);
 | 
						|
  }    
 | 
						|
  
 | 
						|
  if (err == 0)
 | 
						|
  {
 | 
						|
    TFax_server fs;
 | 
						|
    fs.run(argc, argv, "Fax server");
 | 
						|
  }
 | 
						|
  else
 | 
						|
    error_box("Impossibile entrare nella directory %s", (const char*)path);  
 | 
						|
  return TRUE;
 | 
						|
}
 |