New feature: Log Mornitoring (tail -f)
This feature allows users to monitor log files' writing, as Unix "tail -f" command. Here are the conditions of monitoring: 1. file to monitor should exist. 2. file will be set as readonly during monitoring. 3. each update will scroll to the last line.
This commit is contained in:
parent
50c7e228ff
commit
2ff03fe250
|
@ -58,7 +58,7 @@ enum tb_stat {tb_saved, tb_unsaved, tb_ro};
|
|||
|
||||
#define NPP_INTERNAL_FUCTION_STR TEXT("Notepad++::InternalFunction")
|
||||
|
||||
int docTabIconIDs[] = {IDI_SAVED_ICON, IDI_UNSAVED_ICON, IDI_READONLY_ICON};
|
||||
int docTabIconIDs[] = {IDI_SAVED_ICON, IDI_UNSAVED_ICON, IDI_READONLY_ICON, IDI_MONITORING_ICON};
|
||||
|
||||
ToolBarButtonUnit toolBarIcons[] = {
|
||||
{IDM_FILE_NEW, IDI_NEW_OFF_ICON, IDI_NEW_ON_ICON, IDI_NEW_OFF_ICON, IDR_FILENEW},
|
||||
|
@ -112,6 +112,7 @@ ToolBarButtonUnit toolBarIcons[] = {
|
|||
{IDM_VIEW_DOC_MAP, IDI_VIEW_UD_DLG_OFF_ICON, IDI_VIEW_UD_DLG_ON_ICON, IDI_VIEW_UD_DLG_OFF_ICON, IDR_DOCMAP},
|
||||
{IDM_VIEW_FUNC_LIST, IDI_VIEW_UD_DLG_OFF_ICON, IDI_VIEW_UD_DLG_ON_ICON, IDI_VIEW_UD_DLG_OFF_ICON, IDR_FUNC_LIST},
|
||||
{IDM_VIEW_FILEBROWSER, IDI_VIEW_UD_DLG_OFF_ICON, IDI_VIEW_UD_DLG_ON_ICON, IDI_VIEW_UD_DLG_OFF_ICON, IDR_FILEBROWSER},
|
||||
{IDM_VIEW_MONITORING, IDI_VIEW_UD_DLG_OFF_ICON, IDI_VIEW_UD_DLG_ON_ICON, IDI_VIEW_UD_DLG_OFF_ICON, IDR_FILEMONITORING},
|
||||
|
||||
//-------------------------------------------------------------------------------------//
|
||||
{0, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON, IDI_SEPARATOR_ICON},
|
||||
|
@ -1923,6 +1924,11 @@ void Notepad_plus::checkDocState()
|
|||
|
||||
if (_pAnsiCharPanel)
|
||||
_pAnsiCharPanel->switchEncoding();
|
||||
|
||||
enableCommand(IDM_VIEW_MONITORING, not curBuf->isUntitled(), MENU | TOOLBAR);
|
||||
enableCommand(IDM_EDIT_SETREADONLY, not curBuf->isMonitoringOn(), MENU);
|
||||
checkMenuItem(IDM_VIEW_MONITORING, curBuf->isMonitoringOn());
|
||||
_toolBar.setCheck(IDM_VIEW_MONITORING, curBuf->isMonitoringOn());
|
||||
}
|
||||
|
||||
void Notepad_plus::checkUndoState()
|
||||
|
@ -3521,19 +3527,25 @@ void Notepad_plus::docGotoAnotherEditView(FileTransferMode mode)
|
|||
showView(viewToGo);
|
||||
}
|
||||
|
||||
bool monitoringWasOn = false;
|
||||
|
||||
//Close the document if we transfered the document instead of cloning it
|
||||
if (mode == TransferMove)
|
||||
{
|
||||
Buffer *buf = MainFileManager->getBufferByID(current);
|
||||
monitoringWasOn = buf->isMonitoringOn();
|
||||
|
||||
//just close the activate document, since thats the one we moved (no search)
|
||||
doClose(_pEditView->getCurrentBufferID(), currentView());
|
||||
/*
|
||||
if (noOpenedDoc())
|
||||
::SendMessage(_pPublicInterface->getHSelf(), WM_CLOSE, 0, 0);
|
||||
*/
|
||||
} // else it was cone, so leave it
|
||||
|
||||
//Activate the other view since thats where the document went
|
||||
switchEditViewTo(viewToGo);
|
||||
|
||||
if (monitoringWasOn)
|
||||
{
|
||||
command(IDM_VIEW_MONITORING);
|
||||
}
|
||||
}
|
||||
|
||||
bool Notepad_plus::activateBuffer(BufferID id, int whichOne)
|
||||
|
|
|
@ -186,7 +186,6 @@ struct VisibleGUIConf final
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
class FileDialog;
|
||||
class Notepad_plus_Window;
|
||||
class AnsiCharPanel;
|
||||
|
@ -643,8 +642,15 @@ private:
|
|||
}
|
||||
|
||||
static DWORD WINAPI backupDocument(void *params);
|
||||
//static DWORD WINAPI monitorFileOnChange(void * params);
|
||||
//static DWORD WINAPI monitorDirectoryOnChange(void * params);
|
||||
|
||||
static DWORD WINAPI monitorFileOnChange(void * params);
|
||||
struct MonitorInfo final {
|
||||
MonitorInfo(Buffer *buf, ScintillaEditView *mainEditorView, ScintillaEditView *subEditorView) :
|
||||
_buffer(buf), _mainEditorView(mainEditorView), _subEditorView(subEditorView) {};
|
||||
Buffer *_buffer = nullptr;
|
||||
ScintillaEditView *_mainEditorView = nullptr;
|
||||
ScintillaEditView *_subEditorView = nullptr;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1754,6 +1754,48 @@ void Notepad_plus::command(int id)
|
|||
}
|
||||
break;
|
||||
|
||||
case IDM_VIEW_MONITORING:
|
||||
{
|
||||
static HANDLE hThread = nullptr;
|
||||
Buffer * curBuf = _pEditView->getCurrentBuffer();
|
||||
if (curBuf->isMonitoringOn())
|
||||
{
|
||||
curBuf->stopMonitoring();
|
||||
::CloseHandle(hThread);
|
||||
hThread = nullptr;
|
||||
checkMenuItem(IDM_VIEW_MONITORING, false);
|
||||
_toolBar.setCheck(IDM_VIEW_MONITORING, false);
|
||||
curBuf->setUserReadOnly(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
const TCHAR *longFileName = curBuf->getFullPathName();
|
||||
if (::PathFileExists(longFileName))
|
||||
{
|
||||
if (curBuf->isDirty())
|
||||
{
|
||||
::MessageBox(_pPublicInterface->getHSelf(), TEXT("The document is dirty. Please save the modification before monitoring it."), TEXT("Monitoring problem"), MB_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
curBuf->startMonitoring(); // monitoring firstly for making monitoring icon
|
||||
curBuf->setUserReadOnly(true);
|
||||
|
||||
MonitorInfo *monitorInfo = new MonitorInfo(curBuf, &_mainEditView, &_subEditView);
|
||||
hThread = ::CreateThread(NULL, 0, monitorFileOnChange, (void *)monitorInfo, 0, NULL); // will be deallocated while quitting thread
|
||||
checkMenuItem(IDM_VIEW_MONITORING, true);
|
||||
_toolBar.setCheck(IDM_VIEW_MONITORING, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
::MessageBox(_pPublicInterface->getHSelf(), TEXT("The file should exist to be monitored."), TEXT("Monitoring problem"), MB_OK);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case IDM_EXECUTE:
|
||||
{
|
||||
bool isFirstTime = !_runDlg.isCreated();
|
||||
|
|
|
@ -33,121 +33,97 @@
|
|||
#include "EncodingMapper.h"
|
||||
#include "VerticalFileSwitcher.h"
|
||||
#include "functionListPanel.h"
|
||||
#include "ReadDirectoryChanges.h"
|
||||
#include <tchar.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
struct monitorFileParams {
|
||||
WCHAR _fullFilePath[MAX_PATH];
|
||||
};
|
||||
|
||||
DWORD WINAPI Notepad_plus::monitorFileOnChange(void * params)
|
||||
{
|
||||
monitorFileParams *mfp = (monitorFileParams *)params;
|
||||
MonitorInfo *monitorInfo = (MonitorInfo *)params;
|
||||
Buffer *buf = monitorInfo->_buffer;
|
||||
ScintillaEditView *mainEditorView = monitorInfo->_mainEditorView;
|
||||
ScintillaEditView *subEditorView = monitorInfo->_subEditorView;
|
||||
|
||||
//Le répertoire à surveiller :
|
||||
const TCHAR *fullFileName = (const TCHAR *)buf->getFullPathName();
|
||||
|
||||
//The folder to watch :
|
||||
WCHAR folderToMonitor[MAX_PATH];
|
||||
//::MessageBoxW(NULL, mfp->_fullFilePath, TEXT("PATH AFTER thread"), MB_OK);
|
||||
lstrcpy(folderToMonitor, mfp->_fullFilePath);
|
||||
lstrcpy(folderToMonitor, fullFileName);
|
||||
//MessageBox(NULL, fullFileName, TEXT("fullFileName"), MB_OK);
|
||||
|
||||
::PathRemoveFileSpecW(folderToMonitor);
|
||||
|
||||
//::PathRemoveFileSpecW(folderToMonitor);
|
||||
//MessageBox(NULL, folderToMonitor, TEXT("folderToMonitor"), MB_OK);
|
||||
|
||||
HANDLE hDirectory = ::CreateFile(folderToMonitor,
|
||||
FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
const DWORD dwNotificationFlags = FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||
|
||||
// buffer qui va récuppérer les informations de mise à jour
|
||||
const int MAX_BUFFER = 1024;
|
||||
BYTE buffer[MAX_BUFFER];
|
||||
DWORD nombreDeByteRetournes = 0;
|
||||
// Create the monitor and add directory to watch.
|
||||
CReadDirectoryChanges changes;
|
||||
changes.AddDirectory(folderToMonitor, true, dwNotificationFlags);
|
||||
|
||||
bool cond = true;
|
||||
while (cond)
|
||||
HANDLE changeHandles[] = { buf->getMonitoringEvent(), changes.GetWaitHandle() };
|
||||
|
||||
bool toBeContinued = true;
|
||||
|
||||
while (toBeContinued)
|
||||
{
|
||||
::Sleep(1000);
|
||||
// surveille un changement dans le répertoire : il attend tant que rien ne se passe : c’est synchrone.
|
||||
BOOL res = ReadDirectoryChangesW(hDirectory, buffer, MAX_BUFFER,
|
||||
TRUE, FILE_NOTIFY_CHANGE_LAST_WRITE, &nombreDeByteRetournes, NULL, NULL);
|
||||
|
||||
if (res == FALSE)
|
||||
continue;
|
||||
|
||||
// puis on transforme le buffer pour être lisible.
|
||||
FILE_NOTIFY_INFORMATION *notifyInfo = (FILE_NOTIFY_INFORMATION *)buffer;
|
||||
|
||||
wchar_t fn[MAX_PATH];
|
||||
memset(fn, 0, MAX_PATH*sizeof(wchar_t));
|
||||
if (notifyInfo->Action != FILE_ACTION_MODIFIED)
|
||||
continue;
|
||||
|
||||
// affiche le fichier qui a été modifié.
|
||||
if (notifyInfo->FileNameLength <= 0)
|
||||
continue;
|
||||
|
||||
TCHAR str2Display[512];
|
||||
generic_strncpy(fn, notifyInfo->FileName, notifyInfo->FileNameLength / sizeof(wchar_t));
|
||||
generic_sprintf(str2Display, TEXT("offset : %d\raction : %d\rfn len : %d\rfn : %s"), notifyInfo->NextEntryOffset, notifyInfo->Action, notifyInfo->FileNameLength, notifyInfo->FileName);
|
||||
// on peut vérifier avec ceci :
|
||||
//printInt(notifyInfo->NextEntryOffset);
|
||||
//printInt(notifyInfo->FileNameLength);
|
||||
MessageBox(NULL, str2Display, TEXT("name"), MB_OK);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD WINAPI Notepad_plus::monitorDirectoryOnChange(void * params)
|
||||
DWORD waitStatus = ::WaitForMultipleObjects(_countof(changeHandles), changeHandles, FALSE, INFINITE);
|
||||
switch (waitStatus)
|
||||
{
|
||||
monitorFileParams *mfp = (monitorFileParams *)params;
|
||||
case WAIT_OBJECT_0 + 0:
|
||||
// Mutex was signaled. User removes this folder or file browser is closed
|
||||
toBeContinued = false;
|
||||
break;
|
||||
|
||||
//Le répertoire à surveiller :
|
||||
WCHAR folderToMonitor[MAX_PATH];
|
||||
//::MessageBoxW(NULL, mfp->_fullFilePath, TEXT("PATH AFTER thread"), MB_OK);
|
||||
lstrcpy(folderToMonitor, mfp->_fullFilePath);
|
||||
|
||||
|
||||
//::PathRemoveFileSpecW(folderToMonitor);
|
||||
|
||||
HANDLE hDirectory = ::CreateFile(folderToMonitor,
|
||||
FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, NULL);
|
||||
|
||||
// buffer qui va récuppérer les informations de mise à jour
|
||||
const int MAX_BUFFER = 1024;
|
||||
BYTE buffer[MAX_BUFFER];
|
||||
DWORD nombreDeByteRetournes = 0;
|
||||
|
||||
bool cond = true;
|
||||
while (cond)
|
||||
case WAIT_OBJECT_0 + 1:
|
||||
// We've received a notification in the queue.
|
||||
{
|
||||
::Sleep(1000);
|
||||
// surveille un changement dans le répertoire : il attend tant que rien ne se passe : c’est synchrone.
|
||||
ReadDirectoryChangesW(hDirectory, buffer, MAX_BUFFER,
|
||||
TRUE, FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_FILE_NAME, &nombreDeByteRetournes, NULL, NULL);
|
||||
// puis on transforme le buffer pour être lisible.
|
||||
FILE_NOTIFY_INFORMATION *notifyInfo = (FILE_NOTIFY_INFORMATION *)buffer;
|
||||
DWORD dwAction;
|
||||
CStringW wstrFilename;
|
||||
if (changes.CheckOverflow())
|
||||
printStr(L"Queue overflowed.");
|
||||
else
|
||||
{
|
||||
changes.Pop(dwAction, wstrFilename);
|
||||
|
||||
wchar_t fn[MAX_PATH];
|
||||
memset(fn, 0, MAX_PATH*sizeof(wchar_t));
|
||||
if (dwAction == FILE_ACTION_MODIFIED && lstrcmp(fullFileName, wstrFilename.GetString()) == 0)
|
||||
{
|
||||
MainFileManager->reloadBuffer(buf->getID());
|
||||
buf->updateTimeStamp();
|
||||
|
||||
//if (notifyInfo->Action != FILE_ACTION_MODIFIED)
|
||||
if (notifyInfo->Action != FILE_ACTION_ADDED && notifyInfo->Action != FILE_ACTION_REMOVED && notifyInfo->Action != FILE_ACTION_RENAMED_OLD_NAME && notifyInfo->Action != FILE_ACTION_RENAMED_NEW_NAME)
|
||||
continue;
|
||||
|
||||
// affiche le fichier qui a été modifié.
|
||||
//if (notifyInfo->FileNameLength <= 0)
|
||||
//continue;
|
||||
|
||||
generic_strncpy(fn, notifyInfo->FileName, notifyInfo->FileNameLength / sizeof(wchar_t));
|
||||
|
||||
// on peut vérifier avec ceci :
|
||||
//printInt(notifyInfo->FileNameLength);
|
||||
MessageBox(NULL, fn, TEXT("name"), MB_OK);
|
||||
// not only test main view
|
||||
if (buf == mainEditorView->getCurrentBuffer())
|
||||
{
|
||||
int lastLineToShow = mainEditorView->execute(SCI_GETLINECOUNT);
|
||||
mainEditorView->scroll(0, lastLineToShow);
|
||||
}
|
||||
return TRUE;
|
||||
// but also test sub-view, because the buffer could be clonned
|
||||
if (buf == subEditorView->getCurrentBuffer())
|
||||
{
|
||||
int lastLineToShow = subEditorView->execute(SCI_GETLINECOUNT);
|
||||
subEditorView->scroll(0, lastLineToShow);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WAIT_IO_COMPLETION:
|
||||
// Nothing to do.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Just for sample purposes. The destructor will
|
||||
// call Terminate() automatically.
|
||||
changes.Terminate();
|
||||
//MessageBox(NULL, TEXT("FREEDOM !!!"), TEXT("out"), MB_OK);
|
||||
delete monitorInfo;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
*/
|
||||
|
||||
BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive, bool isReadOnly, int encoding, const TCHAR *backupFileName, time_t fileNameTimestamp)
|
||||
{
|
||||
|
@ -368,20 +344,6 @@ BufferID Notepad_plus::doOpen(const generic_string& fileName, bool isRecursive,
|
|||
_pluginsManager.notify(&scnN);
|
||||
if (_pFileSwitcherPanel)
|
||||
_pFileSwitcherPanel->newItem(buf, currentView());
|
||||
|
||||
/*
|
||||
if (::PathFileExists(longFileName))
|
||||
{
|
||||
// Thread to
|
||||
monitorFileParams *params = new monitorFileParams;
|
||||
lstrcpy(params->_fullFilePath, longFileName);
|
||||
//::MessageBoxW(NULL, params._fullFilePath, TEXT("PATH b4 thread"), MB_OK);
|
||||
//HANDLE hThread = ::CreateThread(NULL, 0, monitorFileOnChange, params, 0, NULL);
|
||||
HANDLE hThread = ::CreateThread(NULL, 0, monitorFileOnChange, params, 0, NULL);
|
||||
::CloseHandle(hThread);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -671,6 +633,12 @@ void Notepad_plus::doClose(BufferID id, int whichOne, bool doDeleteBackup)
|
|||
|
||||
int nrDocs = whichOne==MAIN_VIEW?(_mainDocTab.nbItem()):(_subDocTab.nbItem());
|
||||
|
||||
if (buf->isMonitoringOn())
|
||||
{
|
||||
// turn off monitoring
|
||||
command(IDM_VIEW_MONITORING);
|
||||
}
|
||||
|
||||
//Do all the works
|
||||
bool isBufRemoved = removeBufferFromView(id, whichOne);
|
||||
BufferID hiddenBufferID = BUFFER_INVALID;
|
||||
|
|
|
@ -454,7 +454,7 @@ BOOL Notepad_plus::notify(SCNotification *notification)
|
|||
_tabPopupMenu.checkItem(IDM_EDIT_SETREADONLY, isUserReadOnly);
|
||||
|
||||
bool isSysReadOnly = buf->getFileReadOnly();
|
||||
_tabPopupMenu.enableItem(IDM_EDIT_SETREADONLY, !isSysReadOnly);
|
||||
_tabPopupMenu.enableItem(IDM_EDIT_SETREADONLY, not isSysReadOnly && not buf->isMonitoringOn());
|
||||
_tabPopupMenu.enableItem(IDM_EDIT_CLEARREADONLY, isSysReadOnly);
|
||||
|
||||
bool isFileExisting = PathFileExists(buf->getFullPathName()) != FALSE;
|
||||
|
|
|
@ -337,10 +337,25 @@ public:
|
|||
_isLoadedDirty = val;
|
||||
}
|
||||
|
||||
void startMonitoring() {
|
||||
_isMonitoringOn = true;
|
||||
_eventHandle = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
};
|
||||
|
||||
private:
|
||||
HANDLE getMonitoringEvent() const {
|
||||
return _eventHandle;
|
||||
};
|
||||
|
||||
void stopMonitoring() {
|
||||
_isMonitoringOn = false;
|
||||
::SetEvent(_eventHandle);
|
||||
::CloseHandle(_eventHandle);
|
||||
};
|
||||
|
||||
bool isMonitoringOn() const { return _isMonitoringOn; };
|
||||
void updateTimeStamp();
|
||||
|
||||
private:
|
||||
int indexOfReference(const ScintillaEditView * identifier) const;
|
||||
|
||||
void setStatus(DocFileStatus status)
|
||||
|
@ -395,4 +410,8 @@ private:
|
|||
generic_string _backupFileName;
|
||||
bool _isModified = false;
|
||||
bool _isLoadedDirty = false; // it's the indicator for finding buffer's initial state
|
||||
|
||||
// For the monitoring
|
||||
HANDLE _eventHandle = nullptr;
|
||||
bool _isMonitoringOn = false;
|
||||
};
|
|
@ -145,7 +145,11 @@ void DocTabView::bufferUpdated(Buffer * buffer, int mask)
|
|||
{
|
||||
tie.mask |= TCIF_IMAGE;
|
||||
tie.iImage = buffer->isDirty()?UNSAVED_IMG_INDEX:SAVED_IMG_INDEX;
|
||||
if (buffer->isReadOnly())
|
||||
if (buffer->isMonitoringOn())
|
||||
{
|
||||
tie.iImage = MONITORING_IMG_INDEX;
|
||||
}
|
||||
else if (buffer->isReadOnly())
|
||||
{
|
||||
tie.iImage = REDONLY_IMG_INDEX;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
const int SAVED_IMG_INDEX = 0;
|
||||
const int UNSAVED_IMG_INDEX = 1;
|
||||
const int REDONLY_IMG_INDEX = 2;
|
||||
const int MONITORING_IMG_INDEX = 3;
|
||||
|
||||
class DocTabView : public TabBarPlus
|
||||
{
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 822 B |
|
@ -333,6 +333,7 @@
|
|||
#define IDM_VIEW_TAB9 (IDM_VIEW + 94)
|
||||
#define IDM_VIEW_TAB_NEXT (IDM_VIEW + 95)
|
||||
#define IDM_VIEW_TAB_PREV (IDM_VIEW + 96)
|
||||
#define IDM_VIEW_MONITORING (IDM_VIEW + 97)
|
||||
|
||||
#define IDM_VIEW_GOTO_ANOTHER_VIEW 10001
|
||||
#define IDM_VIEW_CLONE_TO_ANOTHER_VIEW 10002
|
||||
|
|
|
@ -131,6 +131,7 @@
|
|||
#define IDI_UNSAVED_ICON 502
|
||||
#define IDI_READONLY_ICON 503
|
||||
#define IDI_FIND_RESULT_ICON 504
|
||||
#define IDI_MONITORING_ICON 505
|
||||
|
||||
#define IDI_PROJECT_WORKSPACE 601
|
||||
#define IDI_PROJECT_WORKSPACEDIRTY 602
|
||||
|
@ -192,7 +193,6 @@
|
|||
#define IDR_CLOSETAB_INACT 1531
|
||||
#define IDR_CLOSETAB_HOVER 1532
|
||||
#define IDR_CLOSETAB_PUSH 1533
|
||||
|
||||
#define IDR_FUNC_LIST_ICO 1534
|
||||
#define IDR_DOCMAP_ICO 1535
|
||||
#define IDR_PROJECTPANEL_ICO 1536
|
||||
|
@ -200,6 +200,8 @@
|
|||
#define IDR_ASCIIPANEL_ICO 1538
|
||||
#define IDR_DOCSWITCHER_ICO 1539
|
||||
#define IDR_FILEBROWSER_ICO 1540
|
||||
#define IDR_FILEMONITORING 1541
|
||||
|
||||
#define ID_MACRO 20000
|
||||
#define ID_MACRO_LIMIT 20200
|
||||
|
||||
|
|
Loading…
Reference in New Issue