419 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			419 lines
		
	
	
		
			9.6 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(NULL)
 | |
| {          
 | |
|   CHECK(CUR_DDE == NULL, "Double DDE");
 | |
|   CUR_DDE = this;
 | |
|   _hwnd = (word)xvt_vobj_get_attr(TASK_WIN, ATTR_NATIVE_WINDOW);
 | |
| }
 | |
| 
 | |
| TDDE::~TDDE()
 | |
| {
 | |
|   terminate();
 | |
|   _hwnd = 0;
 | |
|   CUR_DDE = NULL;  
 | |
| }
 | |
| 
 | |
| bool TDDE::initiate(const char* app, const char* topic)
 | |
| { 
 | |
|   if (_old_hook == NULL)
 | |
|   {
 | |
|     _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 == NULL)
 | |
|   {
 | |
|     _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)
 | |
|   {
 | |
|     xvt_vobj_set_attr(NULL_WIN, ATTR_EVENT_HOOK, _old_hook);   
 | |
|     _old_hook = NULL;
 | |
|     PostMessage((HWND)_server, (WPARAM)_hwnd, WM_DDE_TERMINATE, (LPARAM)0);
 | |
|     _server = 0;
 | |
|   }
 | |
| }
 | |
| 
 | |
| #endif
 |