Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Notepad++ plugin development in C++: Cannot jump to specified line right after opening File

I'm new to Notepad++ plugin development and I wrote a little command to navigate between files, much like the "jump to definition" function you have for many programming tools.

I'm using this template: https://github.com/npp-plugins/plugintemplate

I have managed to write a command that analyses the word under the cursor and subsequently opens another file, setting the cursor there to a position corresponding to the word found.

I open the file using NPPM_DOOPEN and I set the cursor using SCI_GOTOLINE. This works fine. What does not work, is scrolling to make this line visible and topmost with SCI_SETFIRSTVISIBLELINE.

How do I do that?


Without avail, I've tried a lot of other functions (like SCI_SCROLLCARET, SCI_SETSEL) and I have tried to react to NPPN_BUFFERACTIVATED. While I do get the event (NPPN_BUFFERACTIVATED), it still seems too early. When I send SCI_SETFIRSTVISIBLELINE on a file already open, then Notepad++ jumps correctly.


How to reproduce:

Download the plugin template from above, open PluginDefinition.cpp, there you will find two commands. Empty the body of one them and add:

std::wstring filepath = L"PATH TO A LONG TEXT FILE";
::SendMessage(nppData._nppHandle, NPPM_DOOPEN, 0, (LPARAM)filepath.c_str()); // works

int which = -1;
::SendMessage(nppData._nppHandle, NPPM_GETCURRENTSCINTILLA, 0, (LPARAM)&which);
HWND curScintilla = (which == 0) ? nppData._scintillaMainHandle : ppData._scintillaSecondHandle;
int line = 300; // go to line 300
::SendMessage(curScintilla, SCI_GOTOLINE, line - 1, 0); // works
::SendMessage(curScintilla, SCI_SETFIRSTVISIBLELINE, line - 1, 0); // does NOT work
//::SendMessage(curScintilla, SCI_SCROLLCARET, 0, 0); // works sometimes
like image 452
mahanako Avatar asked Dec 21 '25 13:12

mahanako


1 Answers

I believe NPPM_DOOPEN is asynchronous. When it returns, the Scintilla editor isn't loaded at that time. So, SCI_SETFIRSTVISIBLELINE does work, but only if the file was already open.

You need to wait until Notepad++ finishes loading before triggering scroll & jump messages.

#include <windows.h>
#include <string>
#include "PluginDefinition.h"

extern NppData nppData;

static std::wstring g_filepath;
static int g_targetLine = 0;
static UINT_PTR g_timerId = 0;

VOID CALLBACK ScrollToLineProc(HWND, UINT, UINT_PTR, DWORD) {
    KillTimer(NULL, g_timerId);
    int wh = -1;
    ::SendMessage(nppData._nppHandle, NPPM_GETCURRENTSCINTILLA, 0, (LPARAM)&wh);
    if (wh == -1) return;
    HWND curScintilla = (wh == 0) ? nppData._scintillaMainHandle : nppData._scintillaSecondHandle;
    wchar_t currentFile[MAX_PATH];
    ::SendMessage(nppData._nppHandle, NPPM_GETFULLCURRENTPATH, MAX_PATH, (LPARAM)currentFile);
    if (_wcsicmp(currentFile, g_filepath.c_str()) != 0) return;
    ::SendMessage(curScintilla, SCI_GOTOLINE, g_targetLine - 1, 0);
    ::SendMessage(curScintilla, SCI_SETFIRSTVISIBLELINE, g_targetLine - 1, 0);
    ::SendMessage(curScintilla, SCI_SCROLLCARET, 0, 0);
}

void jumpToFile() {
    g_filepath = L"PATH TO A LONG TEXT FILE";
    g_targetLine = 300;
    if (::SendMessage(nppData._nppHandle, NPPM_DOOPEN, 0, (LPARAM)g_filepath.c_str())) {
        g_timerId = SetTimer(NULL, 0, 150, ScrollToLineProc);
    }
}

void commandMenuInit() {
    setCommand(0, TEXT("Jump to File"), jumpToFile, NULL, false);
}
like image 79
0ro2 Avatar answered Dec 24 '25 03:12

0ro2



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!