campo-sirio/include/golem.cpp
alex cbb608d183 Patch level : xx.811
Files correlati     :
Ricompilazione Demo : [ ]
Commento           : Riportata la versione 1.5 fino alla patch 811


git-svn-id: svn://10.65.10.50/trunk@8985 c028cbd2-c16b-5b4b-a496-9718f37d4682
2000-05-05 15:25:49 +00:00

1550 lines
39 KiB
C++
Executable File

#define STRICT
#define WIN32_EXTRA_LEAN
#define XVT_INCL_NATIVE
#include <controls.h>
#include <execp.h>
#include <golem.h>
#include <msksheet.h>
#include <os_dep.h>
#include <prefix.h>
#include <relation.h>
#include <urldefid.h>
#include <utility.h>
#include <window.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;
// Non so se questo debba rimanere
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(".eml");
if (icon == 0)
icon = file2icon(".msg");
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 edit_url(const char* url)
{
bool retflag = FALSE;
HINSTANCE hinst = ShellExecute(NULL, "edit", url, NULL, NULL, SW_SHOWNORMAL);
DWORD winst = DWORD((DWORD*)hinst);
UINT error = UINT(winst); // Tutto 'sto giro per evitare un warning
if (error <= 32)
{
TFilename app;
if (fexist(url) && file2app(".wri", app))
{
app << ' ' << url;
error = WinExec(app, SW_SHOWNORMAL);
if (error > 32)
retflag = TRUE;
}
else
retflag = goto_url(url);
}
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;
if (!f.empty())
{
const TFilename n = f.get();
xvt_fsys_convert_str_to_dir((char*)(const char*)n.path(), &fs.dir);
}
else
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;
}
f.set_focus();
}
if (k == K_TAB && f.focusdirty())
{
TFilename file = m.get(S_FILE);
if (file.exist())
{
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;
unsigned 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_native_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)
{
unsigned 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_native_icon(icon);
else
btn->set_bmp(BMP_OLE, 0);
RCT rct; btn->get_rect(rct);
xvt_dwin_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(), '\n');
if (roman())
{
FOR_EACH_TOKEN(tmp, row)
{
if (*row > ' ')
sheet.row(-1) = row;
}
if (msk->run() == K_ENTER)
{
tmp.cut(0);
FOR_EACH_SHEET_ROW(sheet, r, row)
{
if ((*row)[0] > ' ')
tmp.add(*row);
}
set(tmp);
_selected = sheet.selected();
do_message(0);
}
}
else
{
tmp.separator('|');
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);
do_message(0);
}
}
delete msk;
}
return ok;
}
TGolem_field::TGolem_field(TMask* m)
: TEditable_field(m), _selected(0), _old_value(80, '\n')
{ }
TGolem_field::~TGolem_field()
{ }
///////////////////////////////////////////////////////////
// TGolem_client_field
///////////////////////////////////////////////////////////
class TGolem_window : public TField_window
{
TFilename _last_file;
unsigned long _last_handle;
protected:
virtual bool on_key(KEY k);
virtual void update();
virtual void handler(WINDOW win, EVENT* ep);
public:
TGolem_field* driver() const { return ((TGolem_client_field&)owner()).driver(); }
const TFilename& get_current_file(TFilename& fn) const;
TGolem_window(int x, int y, int dx, int dy, WINDOW parent, TGolem_client_field* owner);
virtual ~TGolem_window();
};
const TFilename& TGolem_window::get_current_file(TFilename& fn) const
{
TGolem_field* gf = driver();
if (gf != NULL)
{
TToken_string list(gf->get(), '\n');
TToken_string tok = list.get(gf->selected());
fn = tok.get();
}
else
fn.cut(0);
return fn;
}
void TGolem_window::update()
{
bool drawn = FALSE;
TField_window::update();
TFilename file; get_current_file(file);
if (file.not_empty() && file.exist())
{
const TString16 ext = file.ext();
if (ext.compare("bmp", -1, TRUE) == 0)
{
TImage img(file);
if (img.ok())
{
RCT cli; xvt_vobj_get_client_rect(win(), &cli);
if (owner().automagic())
{
const double ratiox = double(cli.right-cli.left) / img.width();
const double ratioy = double(cli.bottom-cli.top) / img.height();
const double ratio = min(ratiox, ratioy);
const int maxx = int(ratio * img.width());
const int maxy = int(ratio * img.height());
RCT dst; xvt_rect_set(&dst, 0, 0, maxx, maxy);
img.draw(win(), dst);
}
else
{
long sx = img.width() - (cli.right-cli.left); if (sx < 0) sx = 0;
long sy = img.height() - (cli.bottom-cli.top); if (sy < 0) sy = 0;
set_scroll_max(sx, sy); // Setta le scroll bar
const TPoint orig = origin();
img.draw(win(), -int(orig.x), -int(orig.y));
}
drawn = TRUE;
}
}
}
if (!drawn)
{
set_scroll_max(0, 0); // Toglie le scroll bar
RCT cli; xvt_vobj_get_client_rect(win(), &cli);
set_pen(COLOR_RED, 5);
line(cli.right/4, cli.bottom/4, 3*cli.right/4, 3*cli.bottom/4);
line(cli.right/4, 3*cli.bottom/4, 3*cli.right/4, cli.bottom/4);
}
}
bool TGolem_window::on_key(KEY k)
{
if (k == K_SPACE)
{
TFilename file; get_current_file(file);
if (file != _last_file)
{
if (_last_handle)
{
if (IsWindow(HWND(_last_handle)))
SendMessage(HWND(_last_handle), WM_CLOSE, 0, 0);
_last_handle = NULL;
}
_last_file = file;
if (!file.blank() && file.exist())
{
const TString16 ext = file.ext();
if (ext != "BMP")
{
TFilename cmd;
const char* good_ext[] = { "BAT", "COM", "DLL", "DOC", "EXE", "INI", "TXT", "WRI", "XLS", NULL };
for (int i = 0; good_ext[i]; i++)
{
if (ext == good_ext[i])
{
GetSystemDirectory(cmd.get_buffer(), cmd.size());
cmd.add("viewers");
cmd.add("quikview.exe");
break;
}
}
if (!cmd.exist())
file2app(file, cmd);
if (cmd.not_empty())
{
cmd << ' ' << file;
_last_handle = os_execute_in_window(cmd, win());
}
}
}
force_update();
}
}
return TField_window::on_key(k);
}
void TGolem_window::handler(WINDOW win, EVENT* ep)
{
switch (ep->type)
{
case E_USER:
switch (ep->v.user.id)
{
case E_DROP_FILES:
if (driver())
{
HDROP hdrop = (HDROP)(DWORD)ep->v.user.ptr;
const int num_files = DragQueryFile(hdrop, -1, NULL, 0); // Numero totale di files
TToken_string file_list(driver()->get(), '\n');
TFilename fname; // File corrente
for (int i = 0; i < num_files; i++)
{
DragQueryFile(hdrop, i, (char*)(const char*)fname, fname.size());
fname << '|' << fname.name() << "|X";
if (driver()->roman())
{
file_list.add(fname);
}
else
{
file_list = fname;
break;
}
}
DragFinish(hdrop);
driver()->set(file_list);
on_key(K_SPACE);
}
break;
default:
break;
}
break;
case E_MOUSE_DBL:
on_key(K_SPACE);
break;
default:
break;
}
TField_window::handler(win, ep);
}
TGolem_window::TGolem_window(int x, int y, int dx, int dy, WINDOW parent, TGolem_client_field* owner)
: TField_window(x, y, dx, dy, parent, owner), _last_handle(0)
{
_pixmap = TRUE;
HWND nat = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW);
DragAcceptFiles(nat, TRUE);
}
TGolem_window::~TGolem_window()
{
if (_last_handle)
PostMessage(HWND(_last_handle), WM_CLOSE, 0, 0);
HWND nat = (HWND)xvt_vobj_get_attr(win(), ATTR_NATIVE_WINDOW);
DragAcceptFiles(nat, FALSE);
}
word TGolem_client_field::class_id() const
{ return CLASS_GOLEM_CLIENT_FIELD; }
bool TGolem_client_field::is_kind_of(word cid) const
{ return cid == CLASS_GOLEM_CLIENT_FIELD || TWindowed_field::is_kind_of(cid); }
TField_window* TGolem_client_field::create_window(int x, int y, int dx, int dy, WINDOW parent)
{ return new TGolem_window(x, y, dx, dy, parent, this); }
bool TGolem_client_field::parse_item(TScanner& scan)
{
if (scan.key() == "DR")
{
TMask& m = mask();
const short driver = atodlg(scan.pop());
const int pos = m.id2pos(driver);
if (pos >= 0)
{
_driver = (TGolem_field*)&m.fld(pos);
TString16 msg;
msg.format("PUSH,%d", dlg());
_driver->message(0, TRUE)->add(msg);
}
else
yesnofatal_box("Non esiste il campo driver %d", driver);
return TRUE;
}
return TWindowed_field::parse_item(scan);
}
bool TGolem_client_field::on_hit()
{
dispatch_e_char(win().win(), K_SPACE);
return TWindowed_field::on_hit();
}
TGolem_client_field::TGolem_client_field(TMask* m)
: TWindowed_field(m), _driver(NULL)
{ }
TGolem_client_field::~TGolem_client_field()
{ }
///////////////////////////////////////////////////////////
// MAPI session
///////////////////////////////////////////////////////////
class TMAPI_session : public TObject
{
HINSTANCE _hlibMAPI;
LHANDLE _hSession;
LONG _hWnd;
protected:
bool load_mapi();
void unload_mapi();
public:
operator LHANDLE() const { return _hSession; }
LONG hWnd() const { return _hWnd; }
bool open();
bool send(MapiMessage& msg, FLAGS flags = MAPI_DIALOG);
bool remove(const TString& id);
void close();
virtual bool ok() const
{ return _hlibMAPI != NULL && _hSession != NULL; }
TMAPI_session();
virtual ~TMAPI_session();
};
#ifdef _WIN32
const char* const szMAPIDLL = "MAPI32.DLL";
const int MAPI_USE_DEFAULT = 0;
#else
const char* const szMAPIDLL = "MAPI.DLL";
#endif
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 TMAPI_session::load_mapi()
{
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)
{
_hlibMAPI = NULL;
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 TMAPI_session::unload_mapi()
{
if (_hlibMAPI)
{
FreeLibrary(_hlibMAPI);
_hlibMAPI = NULL;
}
}
bool TMAPI_session::open()
{
if (_hSession == NULL)
{
TWait_cursor hourglass;
if (!load_mapi())
return error_box("Impossibile inizializzare MAPI");
FLAGS flags = MAPI_USE_DEFAULT | MAPI_LOGON_UI;
ULONG err = lpfnMAPILogon(_hWnd, NULL, NULL, flags, 0L, &_hSession);
if (err != SUCCESS_SUCCESS)
return error_box("Impossibile collegarsi a MAPI: %lu", err);
_hWnd = xvt_vobj_get_attr(cur_win(), ATTR_NATIVE_WINDOW);
}
return TRUE;
}
void TMAPI_session::close()
{
if (_hlibMAPI)
{
if (_hSession)
{
lpfnMAPILogoff(_hSession, _hWnd, 0L, 0L);
_hSession = NULL;
}
unload_mapi();
}
}
bool TMAPI_session::send(MapiMessage& msg, FLAGS flags)
{
bool ok = FALSE;
if (open())
{
LONG err = lpfnMAPISendMail(_hSession, _hWnd, &msg, flags, 0L);
if (err == SUCCESS_SUCCESS)
ok = TRUE;
else
error_box("Can't send mail message: %ld", err);
}
return ok;
}
bool TMAPI_session::remove(const TString& id)
{
bool ok = FALSE;
if (open())
{
LONG err = lpfnMAPIDeleteMail(_hSession, _hWnd,
(char*)(const char*)id, 0L, 0L);
if (err == SUCCESS_SUCCESS)
ok = TRUE;
else
error_box("Can't delete mail message: %ld", err);
}
return ok;
}
TMAPI_session::TMAPI_session()
: _hlibMAPI(NULL), _hSession(NULL), _hWnd(NULL)
{ }
TMAPI_session::~TMAPI_session()
{ close(); }
///////////////////////////////////////////////////////////
// TMail_message
///////////////////////////////////////////////////////////
bool TMail_message::send(TMAPI_session& lhSession, bool hide_ui)
{
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();
nr++;
}
FOR_EACH_ARRAY_ROW(_copy_recipients, cc_rec, cc_recipient)
{
msgRecipient[nr].ulRecipClass = MAPI_CC;
msgRecipient[nr].lpszName = cc_recipient->get_buffer();
nr++;
}
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();
na++;
}
MapiMessage msgSend;
memset(&msgSend, 0, sizeof(MapiMessage));
msgSend.lpszNoteText = empty() ? NULL : get_buffer();
msgSend.lpszSubject = _subject.empty() ? NULL : _subject.get_buffer();
msgSend.nRecipCount = nr;
msgSend.lpRecips = nr == 0 ? NULL : msgRecipient;
msgSend.nFileCount = na;
msgSend.lpFiles = na == 0 ? NULL : msgAttachment;
bool ok = lhSession.send(msgSend, hide_ui ? 0 : MAPI_DIALOG);
delete msgRecipient;
delete msgAttachment;
return ok;
}
bool TMail_message::send(bool hide_ui)
{
TMAPI_session lhSession; // Open MAPI session
return send(lhSession, hide_ui);
}
bool TMail_message::remove(TMAPI_session& lhSession)
{
bool ok = _id.not_empty() && lhSession.remove(_id);
return ok;
}
bool TMail_message::remove()
{
TMAPI_session lhSession; // Open MAPI session
return remove(lhSession);
}
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;
}
// Certified 99%
void TMail_message::set_date_time(const char* str)
{
if (str == NULL)
str = "";
int anno, mese, giorno;
int ora = 12, minuto = 0, secondo = 0;
const int num = sscanf(str, "%d/%d/%d %d:%d:%d",
&anno, &mese, &giorno, &ora, &minuto, &secondo);
if (num >= 3)
{
_date = TDate(giorno, mese, anno);
_hms = ora*10000L + minuto*100L + secondo;
}
else
{
_date = TODAY;
_hms = 0;
}
}
// Certified 100%
const TString& TMail_message::recipient(int n) const
{
if (n >= 0 && n < recipients())
return _recipients.row(n);
return EMPTY_STRING;
}
TMail_message::TMail_message(const char* recipient, const char* subject,
const char* text, const char* sender)
: TString(text), _subject(subject), _sender(sender), _hms(0)
{
add_recipient(recipient);
}
///////////////////////////////////////////////////////////
// TMail_messages
///////////////////////////////////////////////////////////
TMail_messages::TMail_messages()
{ }
int TMail_messages::get(const char* senderFilter,
const char* subjectFilter,
const char* bodyFilter,
bool attach, bool mark)
{
TMAPI_session lhSession;
if (!lhSession.open())
return 0;
TString str_msg_id(512); // Accept MAPI_LONG_MSGID
char* msg_id = str_msg_id.get_buffer();
TString str_msg_next(512); // Next MAPI message
LONG err = lpfnMAPIFindNext(lhSession, lhSession.hWnd(), NULL, NULL,
MAPI_GUARANTEE_FIFO | MAPI_LONG_MSGID,
0, msg_id);
FLAGS flags = 0;
if (!mark) flags |= MAPI_PEEK;
if (!attach) flags |= MAPI_SUPPRESS_ATTACH;
while (err == SUCCESS_SUCCESS)
{
MapiMessage FAR* pMessage = NULL;
err = lpfnMAPIReadMail(lhSession, lhSession.hWnd(), msg_id,
flags, 0, &pMessage);
if (err == SUCCESS_SUCCESS)
{
const char* id = NULL;
const char* sender = NULL;
const char* subject = NULL;
const char* body = NULL;
const char* recipient = NULL;
bool should_add = TRUE;
if (should_add)
{
const MapiRecipDesc* pSender = pMessage->lpOriginator;
sender = pSender->lpszName;
if (senderFilter && *senderFilter)
should_add = stricmp(senderFilter, sender) == 0;
}
if (should_add)
{
subject = pMessage->lpszSubject;
if (subjectFilter && *subjectFilter)
{
const unsigned lenFilter = strlen(subjectFilter);
should_add = strncmp(subject, subjectFilter, lenFilter) == 0;
}
}
if (should_add)
{
body = pMessage->lpszNoteText;
if (bodyFilter && *bodyFilter)
should_add = strstr(body, bodyFilter) != NULL;
// Toglie eventuale = finale derivante da cattiva traduzione quoted-printable
char* tail = pMessage->lpszNoteText + strlen(body)-2;
if (tail[0] == '\n' && tail[1] == '=')
*tail = '\0';
}
if (should_add)
{
TMail_message* msg = new TMail_message(recipient, subject, body, sender);
msg->set_date_time(pMessage->lpszDateReceived);
msg->set_id(msg_id);
add(msg);
}
lpfnMAPIFreeBuffer(pMessage);
}
err = lpfnMAPIFindNext(lhSession, lhSession.hWnd(), NULL,
msg_id, MAPI_LONG_MSGID, 0, str_msg_next.get_buffer());
str_msg_id = str_msg_next;
}
return items();
}
bool TMail_messages::send(bool hide_ui)
{
TMAPI_session lhSession;
bool ok = TRUE;
for (int i = 0; i < items(); i++)
ok &= msg(i).send(lhSession, hide_ui);
return ok;
}
bool TMail_messages::remove()
{
TMAPI_session lhSession;
bool ok = TRUE;
for (int i = 0; ok && i < items(); i++)
ok &= msg(i).remove(lhSession);
return ok;
}
///////////////////////////////////////////////////////////
// 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)) != 0;
}
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;
}
}