golem.cpp Migliorata gestione degli hook agli handler di finestra msksheet.cpp Eliminati molti sfarfallamenti duante cambio focus relapp.cpp Corretta gestione messaggio ED sheet.cpp Corretto posizionamento iniziale su righe disabilitate xvtility.cpp Migliorata gestione dell'event hook. git-svn-id: svn://10.65.10.50/trunk@3328 c028cbd2-c16b-5b4b-a496-9718f37d4682
420 lines
9.7 KiB
C++
Executable File
420 lines
9.7 KiB
C++
Executable File
#define STRICT
|
|
#define XVT_INCL_NATIVE
|
|
#include <applicat.h>
|
|
#include <config.h>
|
|
#include <execp.h>
|
|
#include <golem.h>
|
|
#include <mask.h>
|
|
#include <prefix.h>
|
|
#include <relation.h>
|
|
#include <urldefid.h>
|
|
#include <utility.h>
|
|
|
|
#include <bagn006.h>
|
|
|
|
long TGolem::_count = 0;
|
|
TFilename* TGolem::_path = NULL;
|
|
TConfig* TGolem::_config = NULL;
|
|
TRelation* TGolem::_golem = NULL;
|
|
|
|
TGolem::TGolem(const char* cls, long id)
|
|
: _class(cls), _id(id)
|
|
{
|
|
CHECK(_class.not_empty() && id >= 0, "Invalid Golem creation");
|
|
_class.upper();
|
|
|
|
if (_count == 0)
|
|
{
|
|
CHECK(_path == NULL, "Golem construction count error");
|
|
_path = new TFilename;
|
|
_config = new TConfig(CONFIG_GOLEM, _class);
|
|
_golem = new TRelation(LF_GOLEM);
|
|
}
|
|
_count++;
|
|
}
|
|
|
|
TGolem::~TGolem()
|
|
{
|
|
_count--;
|
|
if (_count == 0)
|
|
{
|
|
CHECK(_path != NULL, "Golem destruction count error");
|
|
delete _golem; _golem = NULL;
|
|
delete _config; _config = NULL;
|
|
delete _path; _path = NULL;
|
|
}
|
|
}
|
|
|
|
TConfig& TGolem::config() const
|
|
{
|
|
_config->set_paragraph(_class);
|
|
return *_config;
|
|
}
|
|
|
|
|
|
bool TGolem::ok() const
|
|
{
|
|
return _id > 0 && fexist(path());
|
|
}
|
|
|
|
const char* TGolem::class_name() const
|
|
{
|
|
*_path = "GOLEM_";
|
|
*_path << _class << "_CLASS";
|
|
return *_path;
|
|
}
|
|
|
|
word TGolem::class_id() const
|
|
{
|
|
return CLASS_GOLEM;
|
|
}
|
|
|
|
short TGolem::icon() const
|
|
{
|
|
const short id = config().get_int("Icon", NULL, -1, DLG_F9);
|
|
return id;
|
|
}
|
|
|
|
|
|
const char* TGolem::ext() const
|
|
{
|
|
return config().get("Extension", NULL, -1, _class.left(3));
|
|
}
|
|
|
|
|
|
const TFilename& TGolem::path(bool test) const
|
|
{
|
|
const char* e = ext();
|
|
*_path = firm2dir(-1); // C:\PRASSI\DATI
|
|
_path->add("golem"); // C:\PRASSI\DATI\GOLEM
|
|
if (test && !fexist(*_path))
|
|
make_dir(*_path);
|
|
|
|
_path->add(_class); // C:\PRASSI\DATI\GOLEM\BITMAP
|
|
if (test && !fexist(*_path))
|
|
make_dir(*_path);
|
|
|
|
if (_id > 0)
|
|
{
|
|
_path->add(format("%ld", _id));// C:\PRASSI\DATI\GOLEM\BMP\883
|
|
_path->ext(e); // C:\PRASSI\DATI\GOLEM\BMP\883.BMP
|
|
}
|
|
return *_path;
|
|
}
|
|
|
|
int TGolem::compare(const TSortable& s) const
|
|
{
|
|
if (s.class_id() != class_id())
|
|
return UNDEFINED;
|
|
const TGolem& g = (const TGolem&)s;
|
|
return int(_id - g._id);
|
|
}
|
|
|
|
bool TGolem::edit()
|
|
{
|
|
const TFilename& p = path();
|
|
bool ok = fexist(p);
|
|
if (ok)
|
|
{
|
|
TFilename e(config().get("Editor"));
|
|
e << ' ' << p;
|
|
|
|
TExternal_app app(e);
|
|
ok = app.run(FALSE, FALSE) == 0;
|
|
}
|
|
|
|
return ok;
|
|
}
|
|
|
|
|
|
long TGolem::new_id() const
|
|
{
|
|
long id = 0;
|
|
|
|
TLocalisamfile& gol = _golem->lfile();
|
|
gol.zero();
|
|
gol.put("CLASSE", _class);
|
|
gol.put("CHIAVE", "99999999");
|
|
|
|
const int err = gol.read(_isgteq);
|
|
switch (err)
|
|
{
|
|
case NOERR:
|
|
id = 0; break;
|
|
case _isemptyfile:
|
|
id = 1; break;
|
|
default:
|
|
if (gol.get("CLASSE") != _class)
|
|
gol.prev();
|
|
if (gol.get("CLASSE") == _class)
|
|
id = gol.get_long("CHIAVE")+1;
|
|
else
|
|
id = 1;
|
|
break;
|
|
}
|
|
return id;
|
|
}
|
|
|
|
bool TGolem::import()
|
|
{
|
|
FILE_SPEC fs;
|
|
const char* const e = ext();
|
|
xvt_fsys_convert_str_to_dir(".", &fs.dir);
|
|
strcpy(fs.type, e);
|
|
sprintf(fs.name, "*.%s", e);
|
|
strcpy(fs.creator, "GOLEM");
|
|
|
|
xvt_fsys_save_dir();
|
|
FL_STATUS ok = xvt_dm_post_file_open(&fs, "Selezionare il file ...");
|
|
xvt_fsys_restore_dir();
|
|
if (ok == FL_OK)
|
|
{
|
|
TFilename from;
|
|
xvt_fsys_convert_dir_to_str(&fs.dir, (char*)(const char*)from, 80);
|
|
from.add(fs.name); from.ext(e);
|
|
|
|
TMask msk("bagn006");
|
|
msk.set(F_CLASSE, _class);
|
|
msk.set(F_CODICE, new_id());
|
|
|
|
bool correct = msk.run() == K_ENTER;
|
|
if (correct)
|
|
{
|
|
_id = msk.get_long(F_CODICE);
|
|
correct = fcopy(from, path(TRUE));
|
|
if (correct)
|
|
{
|
|
msk.autosave(*_golem);
|
|
int err = _golem->write();
|
|
if (err == _isreinsert)
|
|
err = _golem->rewrite();
|
|
if (err != NOERR)
|
|
{
|
|
error_box("Errore nell'aggiornamento del file degli oggetti");
|
|
ok = FL_BAD;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
error_box("Spazio su disco insufficiente per l'oggetto");
|
|
ok = FL_BAD;
|
|
}
|
|
}
|
|
else ok = FL_CANCEL;
|
|
|
|
}
|
|
|
|
return ok == FL_OK;
|
|
}
|
|
|
|
|
|
#if XVT_OS == XVT_OS_WIN || XVT_OS == XVT_OS_NT
|
|
|
|
#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())
|
|
{
|
|
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_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;
|
|
}
|
|
}
|
|
|
|
#endif
|