wxWidgets / wxWidgets

Cross-Platform C++ GUI Library
https://www.wxwidgets.org/
5.93k stars 1.73k forks source link

Patch to demonstrate an external lexer in the STC sample #17484

Open wxtrac opened 8 years ago

wxtrac commented 8 years ago

Issue migrated from trac ticket # 17484

component: wxStyledText | priority: normal | keywords: wxStyledText sample

2016-04-06 18:40:50: @NewPagodi created the issue


This ticket includes a patch and file LexLambdaCalc.cpp to demonstrate the new features added in tickets 17480 and 17481 (loading external lexers and the GetDirectXXX methods).

The file LexLambdaCalc.cpp is a heavily commented example of an external lexer. For the sample to work effectively this file will need to be compiled as a shared library (LexLambdaCalc.dll/so) that is placed in the sample applications working directory. To compile, the following folders will need to be on the INCLUDE path $(WXWIN)\src\stc\scintilla\include $(WXWIN)\src\stc\scintilla\lexlib In addition, wxscintilla.lib/.a or wxscintillad.lib/.a, as appropriate, will need to be added as a link lib.

The patch modifies the stc sample to add a menu item (menu->Window->External lexer) that when called simply creates a new frame. This is similar to how another window (a minimal editor) is created in that sample.

Upon the frame's creation, if the shared library can not be found, a message box stating that it can not be found pops up and the resulting frame does almost nothing. If the shared library can be found, the STC loads the external lexer and uses it to color some sample text.

As mentioned in the comments for ticket 17480, the make files for the sample should be modified to build the shared library along with the sample. Unfortunately, this is currently beyond my abilities, and I hope someone else can do this. Or at least provide some tips on what needs to be done to accomplish this.

wxtrac commented 8 years ago

2016-04-06 18:41:51: @NewPagodi uploaded file stc_ext_lex_example.patch (6.7 KiB)

Modifications for the STC sample

wxtrac commented 8 years ago

2016-04-11 08:23:03: @NewPagodi commented


I've looked at the bakefiles this weekend and I think I've figured out all but 1 line. Something like the following should be added to /samples/stc/stctest.bkl

    <module id="LexLambdaCalc"  template="wx" template_append="wx_append">
        <sources>LexLambdaCalc.cpp</sources>

        <if cond="OUT_OF_TREE_MAKEFILES=='0'">
            <include>$(TOP_SRCDIR)src/stc/scintilla/include</include>
            <include>$(TOP_SRCDIR)src/stc/scintilla/lexlib</include>
            <sys-lib>$(LIB_SCINTILLA)</sys-lib>
        </if>
        <if cond="OUT_OF_TREE_MAKEFILES=='1'">
            <include>$(SRCDIR)/$(WXTOPDIR)src/stc/scintilla/include</include>
            <include>$(SRCDIR)/$(WXTOPDIR)src/stc/scintilla/lexlib</include>
            <sys-lib>wxscintilla</sys-lib>
        </if>
    </module>

So far, I've verified that this works with visual c on windows.

The problematic line is 'wxscintilla' which is, I think, used for the makefile.unx. This line will just simply add 'wxscintilla' to the link libs, but that's not correct. The name should be "decorated" to match the debug status and other things added to the name when the wxWidgets libraries were built.

I've tried using '$(LIB_SCINTILLA)' and 'wxscintilla' instead, but both of those give an error with bakefile.

wxtrac commented 8 years ago

2016-04-11 08:24:32: @NewPagodi uploaded file LexLambdaCalc.cpp (13.7 KiB)

Updated external lexer sample

wxtrac commented 8 years ago

2016-04-11 08:52:02: @NewPagodi commented


I've also updated the sample lexer to include some comments about the calling convention that should be used with some of helper functions the lexer file contains.

The problem is that the in the scintilla source file /src/stc/scintilla/src/ExternalLexer.h, the prototypes for these functions the scintilla library expects to find in the dll are given as

#if PLAT_WIN
#define EXT_LEXER_DECL __stdcall
#else
#define EXT_LEXER_DECL
#endif

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

typedef void*(EXT_LEXER_DECL *GetLexerFunction)(unsigned int Index);
typedef int (EXT_LEXER_DECL *GetLexerCountFn)();
typedef void (EXT_LEXER_DECL *GetLexerNameFn)(unsigned int Index, char *name, int buflength);
typedef LexerFactoryFunction(EXT_LEXER_DECL *GetLexerFactoryFunction)(unsigned int Index);

However, a typical sample found online will begin its declarations for these functions with lines like:

#ifdef _WIN32
#define EXT_LEXER_DECL __declspec( dllexport ) __stdcall
#else
#define EXT_LEXER_DECL
#endif

static const char *lexerName = "lexername";

extern "C" {

int EXT_LEXER_DECL GetLexerCount() {
        return 1;
}

See for example http://www.scintilla.org/LexPython.cxx.html

Notice that in the example the first line is changed to '#ifdef _WIN32' instead of '#if PLAT_WIN'. For scintilla versions on windows that have their own platform implementations (PLAT_WX and PLAT_GTK_WIN32) this example won't work. The '__stdcall' part needs to be removed.

This is certainly an unfortunate situation, but I don't see anything that can be done other than note this in the example.