#define _WIN32_WINNT 0x0500 #include #include #include #include #include #include "SCENE.H" char ToUpper(char H) { if ((H >= 'a') && (H <= 'z')) return 'A' + H - 'a'; return H; } typedef void (CALLBACK *FileChangeCallback)(LPTSTR, void *M,DWORD action); typedef struct tagDIR_MONITOR { OVERLAPPED ol; HANDLE hDir; BYTE buffer[32 * 1024]; LPARAM lParam; DWORD notifyFilter; BOOL fStop; char szTrackedDir[MAX_PATH]; void *psCene; FileChangeCallback callback; } *HDIR_MONITOR; HDIR_MONITOR h = NULL; HDIR_MONITOR hLua = NULL; VOID CALLBACK MonitorCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) { TCHAR szFile[MAX_PATH]; PFILE_NOTIFY_INFORMATION pNotify; HDIR_MONITOR pMonitor = (HDIR_MONITOR) lpOverlapped; size_t offset = 0; BOOL RefreshMonitoring(HDIR_MONITOR pMonitor); if (pMonitor != h && pMonitor != hLua) return; if (dwErrorCode == ERROR_SUCCESS) { do { pNotify = (PFILE_NOTIFY_INFORMATION) &pMonitor->buffer[offset]; offset += pNotify->NextEntryOffset; # if defined(UNICODE) { lstrcpynW(szFile, pNotify->FileName, min(MAX_PATH, pNotify->FileNameLength / sizeof(WCHAR) + 1)); } # else { int count = WideCharToMultiByte(CP_ACP, 0, pNotify->FileName, pNotify->FileNameLength / sizeof(WCHAR), szFile, MAX_PATH - 1, NULL, NULL); szFile[count] = TEXT('\0'); } # endif pMonitor->callback(szFile, pMonitor,pNotify->Action); } while (pNotify->NextEntryOffset != 0); } if (!pMonitor->fStop) { RefreshMonitoring(pMonitor); } } //*/ /* * Refreshes the directory monitoring. */ BOOL RefreshMonitoring(HDIR_MONITOR pMonitor) { return ReadDirectoryChangesW(pMonitor->hDir, pMonitor->buffer, sizeof(pMonitor->buffer), TRUE, pMonitor->notifyFilter, NULL, &pMonitor->ol, MonitorCallback); } /* * Stops monitoring a directory. */ void StopMonitoring(HDIR_MONITOR pMonitor) { if (pMonitor) { pMonitor->fStop = TRUE; CancelIo(pMonitor->hDir); while (!HasOverlappedIoCompleted(&pMonitor->ol)) { //SleepEx(5, TRUE); Sleep(5); } CloseHandle(pMonitor->ol.hEvent); CloseHandle(pMonitor->hDir); HeapFree(GetProcessHeap(), 0, pMonitor); } } /* * Starts monitoring a directory. */ HDIR_MONITOR StartMonitoring(LPCTSTR szDirectory, DWORD notifyFilter, FileChangeCallback callback,void *pScene) { HDIR_MONITOR pMonitor = (HDIR_MONITOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pMonitor)); pMonitor->hDir = CreateFile(szDirectory, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL); strcpy(pMonitor->szTrackedDir,szDirectory); pMonitor->psCene = pScene; if (pMonitor->hDir != INVALID_HANDLE_VALUE) { pMonitor->ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); pMonitor->notifyFilter = notifyFilter; pMonitor->callback = callback; if (RefreshMonitoring(pMonitor)) { return pMonitor; } else { CloseHandle(pMonitor->ol.hEvent); CloseHandle(pMonitor->hDir); } } HeapFree(GetProcessHeap(), 0, pMonitor); return NULL; } void DW_WatchDirectoryCheck() { while (WAIT_IO_COMPLETION == MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, MWMO_ALERTABLE)) ; } int MyStrCompare(char *S1,char *S2) { while (*S1 && *S2) { if (((*S1 == '\\') || (*S1 == '/')) && ((*S2 == '\\') || (*S2 == '/'))) { // OK } else if (ToUpper(*S1) == ToUpper(*S2)) { // OK } else return 0; S2++; S1++; } if ((*S1 == 0) && (*S1 == *S2)) return 1; return 0; } void CALLBACK FileCallback(LPTSTR szFile, void*M,DWORD action) { //return; HDIR_MONITOR Monitor; Monitor =(HDIR_MONITOR)M; WORLD *pScene; u32 Counter; char szFileComplete[MAX_PATH]; sprintf(szFileComplete,"%s%s",(char *)Monitor->szTrackedDir,szFile); FILE *F; F = fopen(szFileComplete,"rb"); if (!F) return; // <= File is destroyed. Return; char Buf[32]; if (fread(Buf,1,16,F) < 4) { fclose(F); return; } fclose(F); F = fopen(szFileComplete,"ab"); if (!F) return; // <= File is open. Return; fclose(F); if (action == FILE_ACTION_MODIFIED)// && */(Dico.mpst_Dico[ID].AssociatedValue > 1)) { pScene = (WORLD *)Monitor->psCene; switch (GetFileNameExtend((char *)szFile)) { case '.CCM': #ifndef USER_MODE #ifndef ONLINE_MODE { pScene->LoadIniFile((char *)szFile); }; #endif #endif break; case '.LUA': #ifndef USER_MODE if ((pScene->WFlags & LUA_AUTO_RELOAD) && GetFileNameExtend(pScene->ScriptNameStack[pScene->currentScript]) == '.LUA') pScene->LoadLua(pScene->ScriptNameStack[pScene->currentScript], 2); #endif break; case '.SVG': #ifdef USE_SVG { return; //TO FINISH if(strncmp(szFile, "SVG", 3) != 0) return; //asking for reconvert SVG file extern HWND hWnd; char Text[2048]; sprintf(Text,"SVG file %s has been modified outside camcam\nDo you want to reconvert it to a MAD file ?",szFile); if(MessageBox(GetDesktopWindow(),Text,"Camcam message",MB_YESNO|MB_SYSTEMMODAL) == IDYES) { char svgCompleteFilename[260]; strcpy(svgCompleteFilename, szFile); char madCompleteFilename[260]; sprintf(madCompleteFilename, "Mads\\%s.mad", szFile+4); extern bool svg2mad(char* svgFilename, char* destMadFilename); svg2mad(svgCompleteFilename, madCompleteFilename); } }; #endif break; case '.MAD': { //reentrance support static bool firstEntry = true; static time_t lastTime; if(!firstEntry) { time_t diffOfTime = time(NULL)-lastTime; if(diffOfTime<2) { lastTime = time(NULL); return; } } firstEntry = false; //asking for reimport MAD file char Text[2048]; sprintf(Text,"MAD file %s has been modified outside camcam\nDo you want to reimport it ?",szFile); if ((pScene->WFlags & MAD_AUTO_RELOAD) || (MessageBox(GetDesktopWindow(),Text,"Camcam message",MB_YESNO|MB_SYSTEMMODAL) == IDYES)) { extern u32 MAD_2_CAMCAM(char *FileName); MAD_2_CAMCAM(szFileComplete); } //reentrance support lastTime = time(NULL); }; break; case '.MMT': case '.MAT': case '.MSH': case '.OBJ': case '.SSC': case '.IKM': case '.LGH': /* a small scene must be update */ if (pScene->WFlags & LUA_AUTO_RELOAD) pScene->TouchSmallScene(szFileComplete); break; case '.JPG': case '.PNG': case '.TGA': case '.PSD': case '.BMP': case 'TEXT': case '.TXT': /* maybe a media must be update */ pScene->TouchMedia(szFileComplete); if ((szFileComplete[0] == '.') && (szFileComplete[1] == '\\')) pScene->TouchMedia(szFileComplete+2); break; case '.PGR': pScene->TouchPGenerator(szFileComplete); break; case '.FUR': pScene->TouchFur(szFileComplete); break; }; } } int DW_WatchDirectory(char *DirectoryToWatch,void (*fn)(void *,char *),void *pS) { if (h) StopMonitoring(h); h = NULL; h = StartMonitoring(TEXT(DirectoryToWatch), FILE_NOTIFY_CHANGE_LAST_WRITE|FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME, FileCallback,pS); return TRUE; } int DW_UnWatchDirectory() { if (h) StopMonitoring(h); h= NULL; return 1; } // ************** LUA DIR WATCH ************************** void CALLBACK LuaCallback(LPTSTR szFile, void*M,DWORD action) { HDIR_MONITOR Monitor =(HDIR_MONITOR)M; WORLD *pScene = (WORLD *)Monitor->psCene; ObjectEventDatas datas; datas.type = EVENT_TYPE_STRING; sprintf(datas.data,"%s/%s",(char *)Monitor->szTrackedDir,szFile); //sprintf(datas.data,"%s",szFile); pScene->LuaProcessEventDatas(EVT_onDirWatch, &datas); } int DWLua_WatchDirectory(char *DirectoryToWatch, void *pS) { if (hLua) StopMonitoring(hLua); hLua = NULL; hLua = StartMonitoring(TEXT(DirectoryToWatch), FILE_NOTIFY_CHANGE_LAST_WRITE|FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME, LuaCallback,pS); return TRUE; } int DWLua_UnWatchDirectory() { if (hLua) StopMonitoring(hLua); hLua = NULL; return 1; }