Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions NppPlugin/include/Notepad_plus_msgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -990,6 +990,34 @@ enum Platform { PF_UNKNOWN, PF_X86, PF_X64, PF_IA64, PF_ARM64 };
// lParam[out]: language file name string receives all copied native language file name string
// Return the number of char copied/to copy

#define NPPM_ADDSCNMODIFIEDFLAGS (NPPMSG + 117)
// BOOL NPPM_ADDSCNMODIFIEDFLAGS(0, unsigned long scnMotifiedFlags2Add)
// Add the necessary SCN_MODIFIED flags so that your plugin will receive the SCN_MODIFIED notification for these events, enabling your specific treatments.
// By default, Notepad++ only forwards SCN_MODIFIED with the following 5 flags/events:
// SC_MOD_DELETETEXT | SC_MOD_INSERTTEXT | SC_PERFORMED_UNDO | SC_PERFORMED_REDO | SC_MOD_CHANGEINDICATOR to plugins.
// If your plugin needs to process other SCN_MODIFIED events, you should add the required flags by sending this message to Notepad++. You can send it immediately after receiving NPPN_READY,
// or only when your plugin needs to listen to specific events (to avoid penalizing Notepad++'s performance). Just ensure that the message is sent only once.
// wParam: 0 (not used)
// lParam[in]: scnMotifiedFlags2Add - Scintilla SCN_MODIFIED flags to add.
// Return TRUE
//
// Example:
//
// extern "C" __declspec(dllexport) void beNotified(SCNotification* notifyCode)
// {
// switch (notifyCode->nmhdr.code)
// {
// case NPPN_READY:
// {
// // Add SC_MOD_BEFOREDELETE and SC_MOD_BEFOREINSERT to listen to the 2 events of SCN_MODIFIED
// ::SendMessage(nppData._nppHandle, NPPM_ADDSCNMODIFIEDFLAGS, 0, SC_MOD_BEFOREDELETE | SC_MOD_BEFOREINSERT);
// }
// break;
// ...
// }
// ...
// }

// For RUNCOMMAND_USER
#define VAR_NOT_RECOGNIZED 0
#define FULL_CURRENT_PATH 1
Expand Down
26 changes: 25 additions & 1 deletion PythonScript/python_tests/tests/test_NotepadCallbackTestCase.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import time
import tempfile
import os
from Npp import notepad, editor, NOTIFICATION, LANGTYPE, SCINTILLANOTIFICATION
from Npp import notepad, editor, NOTIFICATION, LANGTYPE, SCINTILLANOTIFICATION, MODIFICATIONFLAGS

globalCallbackCalled = False

Expand Down Expand Up @@ -188,5 +188,29 @@ def callback_with_disallowed_sync_method(self, args):
notepad.activateBufferID(self.oldBufferID)
self.callbackCalled = True

def callback_editor_before_modified(self, args):
flags = args["modificationType"]
self.assertTrue((flags & MODIFICATIONFLAGS.BEFOREDELETE != 0) or (flags & MODIFICATIONFLAGS.BEFOREINSERT != 0))
self.callbackCalled = True

def test_add_modification_flags(self):
original_mask = editor.getModEventMask()
self.assertTrue(notepad.addModificationFlags(MODIFICATIONFLAGS.BEFOREDELETE | MODIFICATIONFLAGS.BEFOREINSERT))
editor.setModEventMask(MODIFICATIONFLAGS.BEFOREDELETE | MODIFICATIONFLAGS.BEFOREINSERT)
editor.callback(lambda a: self.callback_editor_before_modified(a), [SCINTILLANOTIFICATION.MODIFIED])
editor.write('A')
self.poll_for_callback()
self.assertTrue(self.callbackCalled, "BEFOREINSERT test failed, callback not called")
self.callbackCalled = False
editor.undo()
self.poll_for_callback()
self.assertTrue(self.callbackCalled, "BEFOREDELETE test failed, callback not called")
editor.setModEventMask(original_mask)

def test_add_modification_flags_invalid(self):
with self.assertRaises(RuntimeError):
notepad.addModificationFlags(0x800000)



suite = unittest.TestLoader().loadTestsFromTestCase(NotepadCallbackTestCase)
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ def callback_scintillawrapper_int_int_stringresult_getCurLine(self, args):
self.callbackCalled = True

def test_scintillawrapper_int_int_stringresult_in_callback_getCurLine(self):
editor.callback(lambda args: self.callback_scintillawrapper_int_int_stringresult_getLine(args), [SCINTILLANOTIFICATION.MODIFIED])
editor.callback(lambda args: self.callback_scintillawrapper_int_int_stringresult_getCurLine(args), [SCINTILLANOTIFICATION.MODIFIED])
editor.write("One\r\nTwo\r\nThree")
self.poll_for_callback()
self.assertEqual(self.callbackCalled, True)
Expand Down
8 changes: 8 additions & 0 deletions PythonScript/src/NotepadPlusWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "MainThread.h"
#include "ScintillaCallbackCounter.h"
#include "InvalidValueProvidedException.h"
#include "Enums.h"

namespace NppPythonScript
{
Expand Down Expand Up @@ -1124,6 +1125,13 @@ bool NotepadPlusWrapper::isAutoIndention() {
return static_cast<bool>(callNotepad(NPPM_ISAUTOINDENTON));
}

bool NotepadPlusWrapper::addModificationFlags(uint32_t flags) {
if ((flags & ~PYSCR_SC_MODEVENTMASKALL) != 0) {
throw InvalidValueProvidedException("Provided flags value is not a valid MODIFICATION enum value.");
}
return static_cast<bool>(callNotepad(NPPM_ADDSCNMODIFIEDFLAGS, 0, static_cast<LPARAM>(flags)));
}

bool NotepadPlusWrapper::isSingleView() const
{
HWND splitter_hwnd = FindWindowEx(m_nppHandle, NULL, L"splitterContainer", NULL);
Expand Down
2 changes: 2 additions & 0 deletions PythonScript/src/NotepadPlusWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,8 @@ class NotepadPlusWrapper
boost::python::object NotepadPlusWrapper::getExternalLexerAutoIndentMode(const char* externalLexerName);
bool NotepadPlusWrapper::setExternalLexerAutoIndentMode(const char* externalLexerName, AutoIndentMode indentMode);
bool NotepadPlusWrapper::isAutoIndention();

bool NotepadPlusWrapper::addModificationFlags(uint32_t flags);

bool isSingleView() const;
void flashWindow(UINT count, DWORD timeout) const;
Expand Down
1 change: 1 addition & 0 deletions PythonScript/src/NotepadPython.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ void export_notepad()
.def("getExternalLexerAutoIndentMode", &NotepadPlusWrapper::getExternalLexerAutoIndentMode, boost::python::args("externalLexerName"), "Get ExternalLexerAutoIndentMode for an installed external programming language.")
.def("setExternalLexerAutoIndentMode", &NotepadPlusWrapper::setExternalLexerAutoIndentMode, boost::python::args("externalLexerName", "indentMode"), "Set ExternalLexerAutoIndentMode for an installed external programming language.")
.def("isAutoIndention", &NotepadPlusWrapper::isAutoIndention, "Returns True if autoindention is enabled else False")
.def("addModificationFlags", &NotepadPlusWrapper::addModificationFlags, boost::python::args("flags"), "Returns True if successful, else False")

.def("isSingleView", &NotepadPlusWrapper::isSingleView, "True if only one view is used, False otherwise")
.def("flashWindow", &NotepadPlusWrapper::flashWindow, boost::python::args("count", "milliseconds"), "Flashes notepad++ for the given count and timeout");
Expand Down
6 changes: 6 additions & 0 deletions docs/source/notepad.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ Notepad++ Object
*view* is 0 or 1.


.. method:: notepad.addModificationFlags(flags)

A bitwise OR combination of values from the :class:`MODIFICATIONFLAGS` enum.



.. method:: notepad.allocateCmdID(numberRequested) -> int

Allocates a range of Command ID for use in WM_COMMAND. Mainly used internally by plugins.
Expand Down