assoc.h Aggiunta macro di iterazione sugli elementi golem.h Aggiunta gestione della posta golem.cpp Suvvia c'e' la postaa, la posta eletrronicaaa mailbox.h Aggiunto vitrtual davanti al distruttore dei TMessage msksheet.h Aggiunte macro di iterazione sulle righe regexp.h Tolta #define di NULL strings.cpp Aggiunti metodi a TFilename: is_absolute_path, is_relative_path e make_absolute_path strings.h Tolta #include <regexp.h> (-1K nel file .mak) git-svn-id: svn://10.65.10.50/trunk@5626 c028cbd2-c16b-5b4b-a496-9718f37d4682
1030 lines
26 KiB
C++
Executable File
1030 lines
26 KiB
C++
Executable File
#define STRICT
|
|
#define XVT_INCL_NATIVE
|
|
|
|
#include <controls.h>
|
|
#include <execp.h>
|
|
#include <golem.h>
|
|
#include <msksheet.h>
|
|
#include <prefix.h>
|
|
#include <relation.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
|
|
#include <mapi.h>
|
|
#include <shellapi.h>
|
|
|
|
#include "bagn006.h"
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// GotoURL
|
|
// Liberamente tradotto da Windows Developer Journal August 1997
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
HIDDEN long get_reg_key(HKEY key, const char* subkey, TString& retdata)
|
|
{
|
|
HKEY hkey;
|
|
long retval = RegOpenKey(key, subkey, &hkey);
|
|
if (retval == ERROR_SUCCESS)
|
|
{
|
|
long datasize = retdata.size();
|
|
RegQueryValue(hkey, NULL, retdata.get_buffer(), &datasize);
|
|
RegCloseKey(hkey);
|
|
}
|
|
return retval;
|
|
}
|
|
|
|
HIDDEN bool file2app(const char* filename, TString& app)
|
|
{
|
|
bool ok = FALSE;
|
|
|
|
if (*filename != '.')
|
|
{
|
|
HINSTANCE hinst = FindExecutable(filename, ".", app.get_buffer());
|
|
DWORD* pinst = (DWORD*)hinst;
|
|
UINT err = LOWORD(pinst);
|
|
ok = err > 32;
|
|
}
|
|
|
|
if (!ok)
|
|
{
|
|
TString ext(_MAX_EXT);
|
|
if (*filename == '.')
|
|
ext = filename;
|
|
else
|
|
_splitpath(filename, NULL, NULL, NULL, ext.get_buffer());
|
|
ext.lower();
|
|
|
|
TFilename key;
|
|
if (get_reg_key(HKEY_CLASSES_ROOT, ext, key) == ERROR_SUCCESS)
|
|
{
|
|
key << "\\shell\\open\\command";
|
|
if (get_reg_key(HKEY_CLASSES_ROOT, key, key) == ERROR_SUCCESS)
|
|
{
|
|
key.strip("\"");
|
|
int pos = key.find("%1");
|
|
if (pos > 0)
|
|
key.cut(pos);
|
|
key.trim();
|
|
app = key;
|
|
ok = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
HIDDEN bool internet_address(const char* filename)
|
|
{
|
|
const TFilename url(filename);
|
|
if (url.find("://") > 0)
|
|
return TRUE;
|
|
if (url.find("www.") >= 0)
|
|
return TRUE;
|
|
|
|
const char* extensions[] = { "com","edu","gov","it","mil","net","org", NULL };
|
|
const char* ext = url.ext();
|
|
for (int e = 0; extensions[e]; e++)
|
|
if (stricmp(ext, extensions[e]) == 0)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
HIDDEN word file2icon(const char* filename)
|
|
{
|
|
TFilename key;
|
|
|
|
word icon = 0;
|
|
int icon_number = 0;
|
|
|
|
TString ext(_MAX_EXT);
|
|
if (*filename == '.' && strlen(filename) < _MAX_EXT)
|
|
ext = filename;
|
|
else
|
|
{
|
|
if (internet_address(filename))
|
|
ext = ".htm";
|
|
else
|
|
_splitpath(filename, NULL, NULL, NULL, ext.get_buffer());
|
|
}
|
|
ext.lower();
|
|
|
|
if (ext != ".exe")
|
|
{
|
|
if (get_reg_key(HKEY_CLASSES_ROOT, ext, key) == ERROR_SUCCESS)
|
|
{
|
|
key << "\\DefaultIcon";
|
|
if (get_reg_key(HKEY_CLASSES_ROOT, key, key) == ERROR_SUCCESS) // Windows 95 only
|
|
{
|
|
const int comma = key.find(',');
|
|
if (comma > 0)
|
|
{
|
|
icon_number = atoi(key.mid(comma+1));
|
|
key.cut(comma);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!file2app(filename, key))
|
|
file2app(".htm", key);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
key = filename;
|
|
|
|
// Toglie eventuali parametri sulla riga si comando
|
|
const int space_pos = key.find(' ');
|
|
if (space_pos > 0) key.cut(space_pos);
|
|
|
|
HINSTANCE hInst = (HINSTANCE)xvt_vobj_get_attr(NULL_WIN, ATTR_WIN_INSTANCE);
|
|
HICON hicon = ExtractIcon(hInst, key, icon_number);
|
|
if (hicon == NULL && icon_number != 0)
|
|
hicon = ExtractIcon(hInst, key, 0);
|
|
if (hicon != NULL)
|
|
{
|
|
DWORD dwicon = DWORD((DWORD*)hicon);
|
|
icon = LOWORD(dwicon);
|
|
}
|
|
|
|
return icon;
|
|
}
|
|
|
|
HIDDEN word mail2icon()
|
|
{
|
|
word icon = 0;
|
|
TFilename key;
|
|
if (get_reg_key(HKEY_CLASSES_ROOT, "msgfile\\shell\\open\\command", key) == ERROR_SUCCESS)
|
|
{
|
|
const int space = key.find(' ');
|
|
if (space) key.cut(space);
|
|
icon = file2icon(key);
|
|
}
|
|
if (icon == 0)
|
|
icon = file2icon(".mmf");
|
|
return icon;
|
|
}
|
|
|
|
bool goto_url(const char* url)
|
|
{
|
|
TFilename app(url);
|
|
app.lower();
|
|
const TString ext(app.ext());
|
|
|
|
TConfig link(CONFIG_USER, "Link");
|
|
app = link.get(ext);
|
|
if (app.not_empty())
|
|
{
|
|
app << ' ' << url;
|
|
UINT error = WinExec(app, SW_SHOWNORMAL);
|
|
if (error > 32)
|
|
return TRUE;
|
|
else
|
|
link.set(ext, "");
|
|
}
|
|
|
|
bool retflag = FALSE;
|
|
|
|
HINSTANCE hinst = ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
|
|
DWORD winst = DWORD((DWORD*)hinst);
|
|
UINT error = UINT(winst); // Tutto 'sto giro per evitare un warning
|
|
if (error <= 32)
|
|
{
|
|
if (file2app(".htm", app))
|
|
{
|
|
app << ' ' << url;
|
|
error = WinExec(app, SW_SHOWNORMAL);
|
|
if (error > 32)
|
|
retflag = TRUE;
|
|
}
|
|
}
|
|
else
|
|
retflag = TRUE;
|
|
|
|
return retflag;
|
|
}
|
|
|
|
|
|
bool print_url(const char* url)
|
|
{
|
|
HINSTANCE hinst = ShellExecute(NULL, "print", url, NULL, NULL, SW_SHOWNORMAL);
|
|
DWORD winst = DWORD((DWORD*)hinst);
|
|
UINT error = UINT(winst); // Tutto 'sto giro per evitare un warning
|
|
return error >= 32;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Maschera GOLEM
|
|
///////////////////////////////////////////////////////////
|
|
|
|
class TGolem_mask : public TMask
|
|
{
|
|
protected:
|
|
static bool file_handler(TMask_field& f, KEY k);
|
|
static bool link_handler(TMask_field& f, KEY k);
|
|
static bool main_link_handler(TMask_field& f, KEY k);
|
|
static bool ole_handler(TMask_field& f, KEY k);
|
|
|
|
public:
|
|
TGolem_mask();
|
|
virtual ~TGolem_mask() { }
|
|
};
|
|
|
|
bool TGolem_mask::file_handler(TMask_field& f, KEY k)
|
|
{
|
|
TMask& m = f.mask();
|
|
|
|
if (k == K_F9)
|
|
{
|
|
FILE_SPEC fs;
|
|
xvt_fsys_convert_str_to_dir(".", &fs.dir);
|
|
strcpy(fs.type, "");
|
|
strcpy(fs.name, "*.*");
|
|
strcpy(fs.creator, "GOLEM");
|
|
|
|
DIRECTORY dir; xvt_fsys_get_dir(&dir);
|
|
FL_STATUS ok = xvt_dm_post_file_open(&fs, "Selezionare il file ...");
|
|
xvt_fsys_set_dir(&dir);
|
|
|
|
if (ok == FL_OK)
|
|
{
|
|
TFilename file;
|
|
xvt_fsys_convert_dir_to_str(&fs.dir, file.get_buffer(), file.size());
|
|
file.add(fs.name);
|
|
m.set(S_FILE, file);
|
|
k = K_TAB;
|
|
}
|
|
}
|
|
|
|
if (k == K_TAB && f.focusdirty())
|
|
{
|
|
TFilename file = m.get(S_FILE);
|
|
if (fexist(file))
|
|
{
|
|
char ext[_MAX_EXT];
|
|
char name[_MAX_FNAME];
|
|
_splitpath(file, NULL, NULL, name, ext);
|
|
file = name; file.ext(ext);
|
|
m.enable(S_LINK);
|
|
m.disable(F_NEWREC);
|
|
m.enable(F_LINK);
|
|
m.enable(F_PRINT);
|
|
}
|
|
else
|
|
{
|
|
const bool full = file.not_empty();
|
|
m.set(S_LINK, full ? "X" : "");
|
|
m.disable(S_LINK);
|
|
m.enable(F_NEWREC, full);
|
|
m.enable(F_LINK, full);
|
|
m.disable(F_PRINT);
|
|
file.cut(0);
|
|
}
|
|
m.set(S_ALIAS, file);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
bool TGolem_mask::link_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TMask& m = f.mask();
|
|
TFilename url = m.get(S_FILE);
|
|
short id = f.dlg();
|
|
if (id == F_NEWREC && url.not_empty())
|
|
{
|
|
if (!fexist(url))
|
|
{
|
|
TFilename name;
|
|
char ext[_MAX_EXT];
|
|
_splitpath(url, NULL, NULL, name.get_buffer(), ext);
|
|
if (name.not_empty() && *ext)
|
|
{
|
|
name.ext(ext);
|
|
url.tempdir();
|
|
url.add(name);
|
|
ofstream out(url); // Crea un file vuoto
|
|
}
|
|
else
|
|
url.cut(0);
|
|
m.set(S_FILE, url, TRUE); // ... memorizza il suo nome ...
|
|
m.reset(S_LINK); // Non puo' essere un collegamento
|
|
}
|
|
else
|
|
id = F_LINK;
|
|
}
|
|
|
|
if (url.not_empty())
|
|
{
|
|
bool open = TRUE;
|
|
if (id == DLG_PRINT)
|
|
open = !print_url(url);
|
|
if (open)
|
|
goto_url(url);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TGolem_mask::main_link_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TSheet_field& sheet = f.mask().sfield(F_SHEET);
|
|
if (sheet.items() > 0)
|
|
{
|
|
sheet.check_row(sheet.selected());
|
|
TMask& sm = sheet.sheet_mask();
|
|
TMask_field& link = sm.field(f.dlg());
|
|
link_handler(link, K_SPACE);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
bool TGolem_mask::ole_handler(TMask_field& f, KEY k)
|
|
{
|
|
if (k == K_SPACE)
|
|
{
|
|
TSheet_field& sheet = f.mask().sfield(F_SHEET);
|
|
TMask& sm = sheet.sheet_mask();
|
|
|
|
int selected = sheet.selected();
|
|
if (sheet.items() == 0 || !sm.field(S_FILE).empty())
|
|
{
|
|
sheet.row(-1);
|
|
selected = sheet.items()-1;
|
|
}
|
|
sheet.check_row(selected);
|
|
|
|
TString16 ext = f.prompt();
|
|
if (ext == "mailto")
|
|
{
|
|
TMail_message msg("");
|
|
msg.send();
|
|
}
|
|
else
|
|
{
|
|
TFilename file;
|
|
file.temp(NULL, ext);
|
|
sm.set(S_FILE, file);
|
|
ofstream out(file);
|
|
sheet.row(selected) = file;
|
|
sheet.force_update();
|
|
|
|
TFilename app; file2app(ext, app);
|
|
app << ' ' << file;
|
|
WinExec(app, SW_SHOWNORMAL);
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
TGolem_mask::TGolem_mask()
|
|
: TMask("bagn006")
|
|
{
|
|
TSheet_field& sheet = sfield(F_SHEET);
|
|
|
|
set_handler(F_NEWREC, main_link_handler);
|
|
set_handler(F_LINK, main_link_handler);
|
|
set_handler(F_PRINT, main_link_handler);
|
|
|
|
TMask& sm = sheet.sheet_mask();
|
|
sm.set_handler(S_FILE, file_handler);
|
|
sm.set_handler(F_NEWREC, link_handler);
|
|
sm.set_handler(F_LINK, link_handler);
|
|
sm.set_handler(F_PRINT, link_handler);
|
|
|
|
TConfig ini(CONFIG_USER, "Link");
|
|
TString_array list;
|
|
ini.list_variables(list);
|
|
|
|
// Elimina la posta se c'e'
|
|
const int mmf_pos = list.find("mailto");
|
|
if (mmf_pos >= 0) list.destroy(mmf_pos);
|
|
|
|
// Ordina alfabeticamente
|
|
list.sort();
|
|
|
|
const int ITEMS_PER_ROW = 15;
|
|
const int MAX_ITEMS = ITEMS_PER_ROW * 2;
|
|
|
|
// Aggiungi la posta se attiva
|
|
if (GetProfileInt("Mail", "MAPI", 0))
|
|
{
|
|
const int items = list.items();
|
|
const int mmf_pos = (items >= MAX_ITEMS) ? MAX_ITEMS-1 : -1;
|
|
list.add("mailto", mmf_pos);
|
|
}
|
|
|
|
int i = 0;
|
|
FOR_EACH_ARRAY_ROW(list, r, row)
|
|
{
|
|
TString16 ext = *row;
|
|
word icon;
|
|
|
|
if (ext == "mailto")
|
|
{
|
|
icon = mail2icon();
|
|
}
|
|
else
|
|
{
|
|
ext.insert(".", 0);
|
|
icon = file2icon(ext);
|
|
}
|
|
if (icon)
|
|
{
|
|
const int x = (i < ITEMS_PER_ROW ? i*5 : (i-ITEMS_PER_ROW)*5) + 1;
|
|
const int y = i < ITEMS_PER_ROW ? 0 : 2;
|
|
TButton_field& btn = add_button(301+i, 0, ext, x, y, 3, 2);
|
|
btn.set_handler(ole_handler);
|
|
btn.set_icon(icon);
|
|
i++;
|
|
if (i > MAX_ITEMS)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Campi GOLEM
|
|
///////////////////////////////////////////////////////////
|
|
|
|
TString& TGolem_field::get_window_data()
|
|
{
|
|
return _str;
|
|
}
|
|
|
|
void TGolem_field::set_window_data(const char* data)
|
|
{
|
|
WORD icon = 0;
|
|
|
|
char* pipe = strchr(data, '|');
|
|
if (pipe)
|
|
{
|
|
*pipe = '\0'; // Poor man TToken_string
|
|
icon = file2icon(data);
|
|
*pipe = '|';
|
|
}
|
|
|
|
TPushbutton_control* btn = (TPushbutton_control*)_ctl;
|
|
if (icon)
|
|
btn->set_icon(icon);
|
|
else
|
|
btn->set_bmp(BMP_OLE, 0);
|
|
|
|
RCT rct; btn->get_rect(rct);
|
|
xi_invalidate_rect(btn->parent(), &rct);
|
|
}
|
|
|
|
bool TGolem_field::is_editable() const
|
|
{ return FALSE; }
|
|
|
|
void TGolem_field::parse_head(TScanner& scanner)
|
|
{
|
|
_ctl_data._width = scanner.integer();
|
|
if (_ctl_data._width <= 0) _ctl_data._width = 10;
|
|
_ctl_data._height = scanner.integer(); // Height
|
|
if (_ctl_data._height <= 0) _ctl_data._height = 1;
|
|
_ctl_data._bmp_up = BMP_OLE;
|
|
}
|
|
|
|
void TGolem_field::create(WINDOW parent)
|
|
{
|
|
_ctl = new TPushbutton_control(parent, _ctl_data._dlg,
|
|
_ctl_data._x, _ctl_data._y,
|
|
_ctl_data._width+2, _ctl_data._height,
|
|
_ctl_data._flags, _ctl_data._prompt,
|
|
_ctl_data._bmp_up, _ctl_data._bmp_dn);
|
|
}
|
|
|
|
bool TGolem_field::autoload(const TRelation& r)
|
|
{
|
|
const bool ok = TEditable_field::autoload(r);
|
|
if (ok)
|
|
_old_value = get();
|
|
else
|
|
_old_value.cut(0);
|
|
return ok;
|
|
}
|
|
|
|
bool TGolem_field::autosave(TRelation& r)
|
|
{
|
|
if (field() != NULL)
|
|
{
|
|
TToken_string new_value(get(), '\n');
|
|
if (new_value != _old_value)
|
|
{
|
|
TDir dir;
|
|
const int logicnum = r.lfile().num();
|
|
dir.get(logicnum, _nolock, _nordir, _sysdirop);
|
|
const long ditta = dir.is_com() ? 0 : prefix().get_codditta();
|
|
|
|
TFilename golem_path;
|
|
golem_path = firm2dir(ditta);
|
|
golem_path.add("golem");
|
|
if (!fexist(golem_path))
|
|
make_dir(golem_path);
|
|
|
|
const int old_items = _old_value.items();
|
|
const int new_items = new_value.items();
|
|
const int items = new_items > old_items ? new_items : old_items;
|
|
|
|
TToken_string old_row, new_row;
|
|
TFilename old_file, new_file;
|
|
for (int i = 0; i < items; i++)
|
|
{
|
|
old_row = _old_value.get(i); // Devo usare l'indice ogni volta ...
|
|
new_row = new_value.get(i); // ... perche' le TToken_string cambiano!
|
|
|
|
old_file = old_row.get(0);
|
|
new_file = new_row.get(0);
|
|
|
|
if (old_file != new_file)
|
|
{
|
|
const was_stored = old_row.get_char(2) <= ' ' &&
|
|
golem_path.compare(old_file, golem_path.len(), TRUE) == 0;
|
|
const tobe_stored = new_row.get_char(2) <= ' ';
|
|
if (was_stored && fexist(old_file))
|
|
::remove(old_file);
|
|
if (tobe_stored && !new_file.blank())
|
|
{
|
|
char ext[_MAX_EXT];
|
|
_splitpath(new_file, NULL, NULL, NULL, ext);
|
|
old_file.temp(golem_path, ext);
|
|
|
|
fcopy(new_file, old_file);
|
|
new_row.add(old_file, 0);
|
|
new_value.add(new_row, i);
|
|
|
|
// Cancella il file originale se temporaneo
|
|
TFilename tmp; tmp.tempdir();
|
|
if (tmp.compare(new_file, tmp.len(), TRUE) == 0)
|
|
::remove(new_file);
|
|
}
|
|
}
|
|
}
|
|
set(_old_value = new_value);
|
|
}
|
|
}
|
|
return TEditable_field::autosave(r);
|
|
}
|
|
|
|
bool TGolem_field::on_key(KEY key)
|
|
{
|
|
bool ok = TRUE;
|
|
if (key == K_SPACE)
|
|
{
|
|
TMask* msk = new TGolem_mask;
|
|
TSheet_field& sheet = msk->sfield(F_SHEET);
|
|
|
|
TToken_string tmp = get();
|
|
if (roman())
|
|
{
|
|
tmp.separator('\n');
|
|
// for (const char* row = tmp.get(0); row; row = tmp.get())
|
|
FOR_EACH_TOKEN(tmp, row)
|
|
{
|
|
if (*row > ' ')
|
|
sheet.row(-1) = row;
|
|
}
|
|
if (msk->run() == K_ENTER)
|
|
{
|
|
tmp.cut(0);
|
|
// for (int r = 0; r < sheet.items(); r++)
|
|
FOR_EACH_SHEET_ROW(sheet, r, row)
|
|
{
|
|
// TToken_string& row = sheet.row(r);
|
|
if ((*row)[0] > ' ')
|
|
tmp.add(*row);
|
|
}
|
|
set(tmp);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TMask& sm = sheet.sheet_mask();
|
|
for (int i = 0; i < 3; i++)
|
|
sm.set(S_FILE+i, tmp.get());
|
|
|
|
if (sm.run() == K_ENTER)
|
|
{
|
|
tmp.cut(0);
|
|
for (int i = 0; i < 3; i++)
|
|
tmp.add(sm.get(S_FILE+i));
|
|
set(tmp);
|
|
}
|
|
}
|
|
|
|
delete msk;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
TGolem_field::TGolem_field(TMask* m)
|
|
: TEditable_field(m), _old_value(80, '\n')
|
|
{ }
|
|
|
|
TGolem_field::~TGolem_field()
|
|
{ }
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Mail message
|
|
///////////////////////////////////////////////////////////
|
|
|
|
#ifdef _WIN32
|
|
const char* const szMAPIDLL = "MAPI32.DLL";
|
|
#else
|
|
const char* const szMAPIDLL = "MAPI.DLL";
|
|
#endif
|
|
|
|
static HINSTANCE _hlibMAPI = NULL;
|
|
|
|
LPMAPILOGON lpfnMAPILogon = NULL;
|
|
LPMAPILOGOFF lpfnMAPILogoff = NULL;
|
|
LPMAPISENDMAIL lpfnMAPISendMail = NULL;
|
|
LPMAPISENDDOCUMENTS lpfnMAPISendDocuments = NULL;
|
|
LPMAPIFINDNEXT lpfnMAPIFindNext = NULL;
|
|
LPMAPIREADMAIL lpfnMAPIReadMail = NULL;
|
|
LPMAPISAVEMAIL lpfnMAPISaveMail = NULL;
|
|
LPMAPIDELETEMAIL lpfnMAPIDeleteMail = NULL;
|
|
LPMAPIFREEBUFFER lpfnMAPIFreeBuffer = NULL;
|
|
LPMAPIADDRESS lpfnMAPIAddress = NULL;
|
|
LPMAPIDETAILS lpfnMAPIDetails = NULL;
|
|
LPMAPIRESOLVENAME lpfnMAPIResolveName = NULL;
|
|
|
|
bool TMail_message::load_mapi(void)
|
|
{
|
|
if (_hlibMAPI) // Check in already loaded
|
|
return TRUE;
|
|
|
|
// Check if MAPI is installed on the system
|
|
BOOL MAPI_installed = GetProfileInt("Mail", "MAPI", 0);
|
|
if(!MAPI_installed)
|
|
return FALSE;
|
|
|
|
UINT fuError = SetErrorMode(SEM_NOOPENFILEERRORBOX);
|
|
_hlibMAPI = LoadLibrary(szMAPIDLL);
|
|
SetErrorMode(fuError);
|
|
|
|
DWORD* err = (DWORD*)_hlibMAPI;
|
|
if ((DWORD)err < 32)
|
|
return FALSE;
|
|
|
|
if (!(lpfnMAPILogon = (LPMAPILOGON) GetProcAddress (_hlibMAPI, "MAPILogon")))
|
|
return FALSE;
|
|
if (!(lpfnMAPILogoff = (LPMAPILOGOFF) GetProcAddress (_hlibMAPI, "MAPILogoff")))
|
|
return FALSE;
|
|
if (!(lpfnMAPISendMail = (LPMAPISENDMAIL) GetProcAddress (_hlibMAPI, "MAPISendMail")))
|
|
return FALSE;
|
|
if (!(lpfnMAPISendDocuments = (LPMAPISENDDOCUMENTS) GetProcAddress (_hlibMAPI, "MAPISendDocuments")))
|
|
return FALSE;
|
|
if (!(lpfnMAPIFindNext = (LPMAPIFINDNEXT) GetProcAddress (_hlibMAPI, "MAPIFindNext")))
|
|
return FALSE;
|
|
if (!(lpfnMAPIReadMail = (LPMAPIREADMAIL) GetProcAddress (_hlibMAPI, "MAPIReadMail")))
|
|
return FALSE;
|
|
if (!(lpfnMAPISaveMail = (LPMAPISAVEMAIL) GetProcAddress (_hlibMAPI, "MAPISaveMail")))
|
|
return FALSE;
|
|
if (!(lpfnMAPIDeleteMail = (LPMAPIDELETEMAIL) GetProcAddress (_hlibMAPI, "MAPIDeleteMail")))
|
|
return FALSE;
|
|
if (!(lpfnMAPIFreeBuffer = (LPMAPIFREEBUFFER) GetProcAddress (_hlibMAPI, "MAPIFreeBuffer")))
|
|
return FALSE;
|
|
if (!(lpfnMAPIAddress = (LPMAPIADDRESS) GetProcAddress (_hlibMAPI, "MAPIAddress")))
|
|
return FALSE;
|
|
if (!(lpfnMAPIDetails = (LPMAPIDETAILS) GetProcAddress (_hlibMAPI, "MAPIDetails")))
|
|
return FALSE;
|
|
if (!(lpfnMAPIResolveName = (LPMAPIRESOLVENAME) GetProcAddress (_hlibMAPI, "MAPIResolveName")))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void TMail_message::unload_mapi()
|
|
{
|
|
if (_hlibMAPI)
|
|
{
|
|
FreeLibrary(_hlibMAPI);
|
|
_hlibMAPI = NULL;
|
|
}
|
|
}
|
|
|
|
bool TMail_message::send()
|
|
{
|
|
TWait_cursor hourglass;
|
|
bool ok = load_mapi();
|
|
if (!ok)
|
|
return error_box("Impossibile inizializzare MAPI");
|
|
|
|
LHANDLE lhSession = 0;
|
|
ULONG err = lpfnMAPILogon(0L, "", "",
|
|
MAPI_LOGON_UI | MAPI_USE_DEFAULT,
|
|
0L, &lhSession);
|
|
if (err == SUCCESS_SUCCESS)
|
|
{
|
|
const int MAX_RECIPIENTS = _recipients.items() + _copy_recipients.items() + 1;
|
|
MapiRecipDesc* msgRecipient = new MapiRecipDesc[MAX_RECIPIENTS];
|
|
memset(msgRecipient, 0, MAX_RECIPIENTS*sizeof(MapiRecipDesc));
|
|
|
|
int nr = 0;
|
|
if (_sender.not_empty())
|
|
{
|
|
msgRecipient[nr].ulRecipClass = MAPI_ORIG;
|
|
msgRecipient[nr++].lpszName = _sender.get_buffer();
|
|
}
|
|
FOR_EACH_ARRAY_ROW(_recipients, rec, recipient)
|
|
{
|
|
msgRecipient[nr].ulRecipClass = MAPI_TO;
|
|
msgRecipient[nr++].lpszName = recipient->get_buffer();
|
|
}
|
|
FOR_EACH_ARRAY_ROW(_copy_recipients, cc_rec, cc_recipient)
|
|
{
|
|
msgRecipient[nr].ulRecipClass = MAPI_CC;
|
|
msgRecipient[nr++].lpszName = cc_recipient->get_buffer();
|
|
}
|
|
|
|
const int MAX_ATTACHMENTS = _attachments.items() + 1;
|
|
MapiFileDesc* msgAttachment = new MapiFileDesc[MAX_ATTACHMENTS];
|
|
memset(msgAttachment, 0, MAX_ATTACHMENTS*sizeof(MapiFileDesc));
|
|
int na = 0;
|
|
FOR_EACH_ARRAY_ROW(_attachments, att, attachment)
|
|
{
|
|
TString80 tmp; tmp.spaces(32);
|
|
*this << '\n' << tmp;
|
|
msgAttachment[na].nPosition = len()-1;
|
|
msgAttachment[na++].lpszPathName = attachment->get_buffer();
|
|
}
|
|
|
|
MapiMessage msgSend;
|
|
memset(&msgSend, 0, sizeof(MapiMessage));
|
|
msgSend.lpszNoteText = get_buffer();
|
|
msgSend.lpszSubject = _subject.get_buffer();
|
|
msgSend.nRecipCount = nr;
|
|
msgSend.lpRecips = msgRecipient;
|
|
msgSend.nFileCount = na;
|
|
msgSend.lpFiles = msgAttachment;
|
|
|
|
err = lpfnMAPISendMail(lhSession, 0, &msgSend, MAPI_DIALOG, 0L);
|
|
|
|
delete msgRecipient;
|
|
delete msgAttachment;
|
|
|
|
err = lpfnMAPILogoff(lhSession, 0L, 0L, 0L);
|
|
}
|
|
else
|
|
ok = error_box("Impossibile collegarsi a MAPI");
|
|
|
|
unload_mapi();
|
|
return ok;
|
|
}
|
|
|
|
bool TMail_message::add_recipient_ex(const char* recipient, int type)
|
|
{
|
|
TFilename rec(recipient);
|
|
rec.trim();
|
|
bool ok = rec.not_empty();
|
|
if (ok) switch(type)
|
|
{
|
|
case 1:
|
|
_copy_recipients.add(rec);
|
|
break;
|
|
case 2:
|
|
if (rec.is_relative_path())
|
|
rec.make_absolute_path();
|
|
ok = fexist(rec);
|
|
if (ok)
|
|
_attachments.add(rec);
|
|
break;
|
|
default:
|
|
_recipients.add(rec);
|
|
break;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
TMail_message::TMail_message(const char* recipient, const char* subject,
|
|
const char* text, const char* sender)
|
|
: TString(text), _subject(subject), _sender(sender)
|
|
{
|
|
add_recipient(recipient);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Obsolete DDE management
|
|
///////////////////////////////////////////////////////////
|
|
|
|
#include <dde.h>
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// DDE
|
|
///////////////////////////////////////////////////////////
|
|
|
|
static TDDE* CUR_DDE = NULL;
|
|
|
|
HIDDEN BOOLEAN hook(HWND hwnd,
|
|
UINT msg,
|
|
UINT wparam,
|
|
ULONG lparam,
|
|
long* ret)
|
|
{
|
|
CHECK(CUR_DDE, "No DDE available");
|
|
bool normal_process = TRUE;
|
|
|
|
if (CUR_DDE->hwnd() == (word)hwnd) switch (msg)
|
|
{
|
|
case WM_DDE_INITIATE:
|
|
if (wparam != CUR_DDE->hwnd()) // Non initiarti da solo!
|
|
{
|
|
ATOM app = LOWORD(lparam);
|
|
ATOM topic = HIWORD(lparam);
|
|
TString a(256), t(256);
|
|
if (app)
|
|
GlobalGetAtomName(app, (char*)(const char*)a, a.size());
|
|
if (topic)
|
|
GlobalGetAtomName(topic, (char*)(const char*)t, t.size());
|
|
|
|
bool ok = FALSE;
|
|
const char* an = CUR_DDE->get_app_name();
|
|
if (an && *an)
|
|
ok = a.empty() || a.compare(an, -1, TRUE) == 0;
|
|
if (ok) // Server name ok
|
|
{
|
|
const bool query_topics = t.empty() || t == "*";
|
|
TToken_string topics = CUR_DDE->get_topics();
|
|
ok = !topics.empty_items(); // No topics?
|
|
if (ok && !query_topics)
|
|
{
|
|
ok = FALSE;
|
|
// for (const char* topo = topics.get(0); topo; topo = topics.get())
|
|
FOR_EACH_TOKEN(topics, topo)
|
|
{
|
|
if (t.compare(topo, -1, TRUE) == 0)
|
|
{
|
|
ok = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (ok) // Topic ok
|
|
{
|
|
ok = CUR_DDE->do_initiate(wparam, t);
|
|
if (ok) // Connection ok
|
|
{
|
|
if (!query_topics)
|
|
topics = t;
|
|
for (t = topics.get(0); t.not_empty(); t = topics.get())
|
|
{ // E' obbligatorio crearne dei nuovi! Non spostare fuori dal ciclo!
|
|
app = GlobalAddAtom(CUR_DDE->get_app_name());
|
|
topic = GlobalAddAtom(t);
|
|
SendMessage((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, MAKELPARAM(app,topic));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
normal_process = FALSE;
|
|
}
|
|
break;
|
|
case WM_DDE_ACK:
|
|
{
|
|
ATOM a = LOWORD(lparam); if (a) GlobalDeleteAtom(a);
|
|
ATOM t = HIWORD(lparam); if (t) GlobalDeleteAtom(t);
|
|
CUR_DDE->do_ack(wparam);
|
|
normal_process = FALSE;
|
|
}
|
|
break;
|
|
case WM_DDE_DATA:
|
|
{
|
|
ATOM i = HIWORD(lparam); if (i) GlobalDeleteAtom(i);
|
|
}
|
|
break;
|
|
case WM_DDE_EXECUTE:
|
|
{
|
|
const TString cmd((const char*)lparam);
|
|
DDEACK ack; memset(&ack, 0, sizeof(ack));
|
|
ack.fAck = CUR_DDE->do_execute(wparam, cmd);
|
|
// Ritorna indietro l'handle globale che verra' distrutto dal chiamante
|
|
PostMessage((HWND)wparam, WM_DDE_ACK, (WPARAM)hwnd, lparam);
|
|
normal_process = FALSE;
|
|
}
|
|
break;
|
|
case WM_DDE_TERMINATE:
|
|
CUR_DDE->do_terminate(wparam);
|
|
normal_process = FALSE;
|
|
break;
|
|
case WM_DROPFILES:
|
|
if (CUR_DDE->do_custom_message(msg, wparam, lparam))
|
|
{
|
|
*ret = 0;
|
|
normal_process = FALSE;
|
|
}
|
|
break;
|
|
default:
|
|
if (msg > (UINT)WM_USER && msg < 0x7FFF)
|
|
{
|
|
if (CUR_DDE->do_custom_message(msg, wparam, lparam))
|
|
normal_process = FALSE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return normal_process;
|
|
}
|
|
|
|
TDDE::TDDE()
|
|
: _server(0), _old_hook(-1)
|
|
{
|
|
CHECK(CUR_DDE == NULL, "Double DDE");
|
|
CUR_DDE = this;
|
|
_hwnd = (word)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW);
|
|
}
|
|
|
|
TDDE::~TDDE()
|
|
{
|
|
do_events(); // Flush degli venti in coda prima di sganciare tutto
|
|
terminate();
|
|
_hwnd = 0;
|
|
CUR_DDE = NULL;
|
|
}
|
|
|
|
bool TDDE::initiate(const char* app, const char* topic)
|
|
{
|
|
if (_old_hook == -1)
|
|
{
|
|
_old_hook = xvt_vobj_get_attr(NULL_WIN, ATTR_EVENT_HOOK);
|
|
xvt_vobj_set_attr(NULL_WIN, ATTR_EVENT_HOOK, (long)hook);
|
|
}
|
|
|
|
_server = 0;
|
|
ATOM a_app = GlobalAddAtom(app);
|
|
ATOM a_topic = GlobalAddAtom(topic);
|
|
SendMessage(HWND_BROADCAST, WM_DDE_INITIATE, (WPARAM)_hwnd, MAKELPARAM(a_app, a_topic));
|
|
GlobalDeleteAtom(a_app);
|
|
GlobalDeleteAtom(a_topic);
|
|
|
|
return _server != 0;
|
|
}
|
|
|
|
bool TDDE::execute(const char* cmd) const
|
|
{
|
|
HGLOBAL hg = GlobalAlloc(GMEM_DDESHARE, strlen(cmd)+1);
|
|
char* c = (char*)GlobalLock(hg);
|
|
strcpy(c, cmd);
|
|
GlobalUnlock(hg);
|
|
return PostMessage((HWND)_server, WM_DDE_EXECUTE, (WPARAM)_hwnd, MAKELPARAM(0, hg));
|
|
}
|
|
|
|
bool TDDE::execute(const char* app, const char* topic, const char* cmd, const char* filename)
|
|
{
|
|
bool running = initiate(app, topic);
|
|
if (!running)
|
|
{
|
|
if (filename == NULL || *filename == '\0')
|
|
filename = app;
|
|
|
|
TExternal_app server(filename);
|
|
if (server.run(TRUE) == 0)
|
|
{
|
|
for (int failures = 0; !running && failures < 10; failures++)
|
|
{
|
|
const clock_t end = clock() + 3*CLOCKS_PER_SEC;
|
|
while (clock() < end)
|
|
do_events();
|
|
running = initiate(app, topic);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (running)
|
|
{
|
|
if (cmd && *cmd)
|
|
execute(cmd);
|
|
terminate();
|
|
}
|
|
|
|
return running;
|
|
}
|
|
|
|
bool TDDE::start_server()
|
|
{
|
|
if (_old_hook == -1)
|
|
{
|
|
_old_hook = xvt_vobj_get_attr(NULL_WIN, ATTR_EVENT_HOOK);
|
|
xvt_vobj_set_attr(NULL_WIN, ATTR_EVENT_HOOK, (long)hook);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
void TDDE::terminate()
|
|
{
|
|
if (_old_hook != -1)
|
|
{
|
|
xvt_vobj_set_attr(NULL_WIN, ATTR_EVENT_HOOK, _old_hook);
|
|
_old_hook = -1;
|
|
PostMessage((HWND)_server, (WPARAM)_hwnd, WM_DDE_TERMINATE, (LPARAM)0);
|
|
_server = 0;
|
|
}
|
|
}
|
|
|