Menu

[r2]: / NppWLangLexer_Plugin / src / NppExtLexerInterface.cpp  Maximize  Restore  History

Download this file

422 lines (307 with data), 13.1 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
// NppExtLexerInterface.cpp
// This file is part of the Notepad++ External Lexers Plugin.
// Copyright 2008 - 2009 Thell Fowler (thell@almostautomated.com)
//
// This program is free software; you can redistribute it and/or modify it under the terms of
// the GNU General Public License as published by the Free Software Foundation; either version
// 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program;
// if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
///////////////////////////////////////////////////////////////////////////////////////////////
// Public Plugin Interface Extension Functions
// for use with Notepad++ External Lexer Plugins
///////////////////////////////////////////////////////////////////////////////////////////////
/***
*
* This file implements the extension to NppPluginInterface for using Scintilla's
* external lexer capabilities in a Notepad++ plugin.
*
* The commenting in this code may seem excessive, yet it is there for people who would
* like to better understand how the plugin system works and how it can be used.
*
***/
///////////////////////////////////////////////////////////////////////////////////////////////
// Include Directives
#include "NppExtLexerInterface.h"
//#include "NppExtLexer_Common.h" // Included for access to lexer object creation.
#define MININT (-1)
///////////////////////////////////////////////////////////////////////////////////////////////
// External Lexer Interface Implementation
namespace Npp_ExtLexer_Interface {
namespace { // <--- Unnamed namespace for private variables --->
//*********************************************************************************************
// Private Interface Implementation
//---------------------------------------------------------------------------------------------
// Parameter constants
// <--- From Npp's Parameters.h
const int NB_MAX_EXTERNAL_LANG = 30;
const int MAX_EXTERNAL_LEXER_NAME_LEN = 16;
const int MAX_EXTERNAL_LEXER_DESC_LEN = 32;
// <--- Just for a little clarity in the function calls --->
const bool FOLD = true;
const bool LEX = false;
// <--- Containers --->
std::vector<FuncItem> _LexerFuncVector; // Container for lexer function commands.
std::vector<FuncItem> ReturnVector; // Container for the ordered function commands.
std::vector<Lexer> _LexerDetailVector; // Container for lexer details.
//*********************************************************************************************
// Exported Lexer Functions.
//---------------------------------------------------------------------------------------------
// Plugin Lexer Details - for Notepad++'s PluginsManager and Scintilla's LexerManager
/*
* Both managers need to know the details of lexers included in this plugin.
*
* Notepad++ fills in the language menu and the style preferences dialog, as
* well as handles style properties control with Scintilla.
*
* Scintilla does all of the accessing of the document, application of styles,
* folding, and so on using the information provided by Notepad++ and this
* plugin's messaging.
*
*/
int __stdcall GetLexerCount()
{
return _LexerDetailVector.size();
}
int getLexerFuncCount ()
{
return _LexerFuncVector.size();
}
void __stdcall GetLexerName(unsigned int Index, char *name, int buflength)
{
// Both Notepad++ and Scintilla use this. Scintilla expects char and Notepad++ will
// convert it itself.
std::string currLangName = _LexerDetailVector.at(Index)._name;
if (buflength > 0 ) {
buflength--;
int n = currLangName.length();
if (n > buflength) n = buflength;
memcpy(name, currLangName.c_str(), n), name[n] = '\0';
}
}
void __stdcall GetLexerStatusText(unsigned int Index, TCHAR *desc, int buflength)
{
// Notepad++ uses this, but Scintilla does not. Which allows use of TCHAR vs char.
tstring currLangDesc = _LexerDetailVector.at(Index)._description;;
if (buflength > 0) {
buflength--;
int n = currLangDesc.length();
if (n > buflength) n = buflength;
TMEMCPY(desc, currLangDesc.c_str(), n), desc[n] = '\0';
}
}
//---------------------------------------------------------------------------------------------
// Scintilla Lexer Functions
/*
* The Fold and Lex functions are simple call relayers to a particular lexer
* in this plugin.
*
*/
void __stdcall ExtLex(unsigned int langID, unsigned int startPos, int length, int initStyle,
char *words[], WindowID window, char *props)
{
/*
* This is just a forwarding function that forwards Scintilla's fold command to
* the correct exteneral lexer.
*
*/
namespace pIface = Npp_Plugin_Interface;
Lexer* currLexer = &_LexerDetailVector.at(langID);
if (! ( currLexer->SCI_LEXERID >= SCLEX_AUTOMATIC ) || ( pIface::isNppReady() ) ) {
// Each lexer has a LEXERID that Scintilla assigns. For external lexers this ID isn't
// known until Scintilla's first call for a lexer to lex a document.
// When that happens the ID is stored and used for filtering notification messages.
int lexerID = ::SendMessage(pIface::hCurrView(), SCI_GETLEXER, 0, 0);
currLexer->SCI_LEXERID = lexerID;
}
else if ( currLexer->SCI_LEXERID < SCLEX_AUTOMATIC ) {
::MessageBox(pIface::hNpp(), TEXT(" SCI_LEXERID is less than SCLEX_AUTOMATIC and Npp reports ready! " ),
TEXT(" Npp External Lexer Problem "), MB_OK | MB_ICONEXCLAMATION );
return; // This shouldn't happen!
}
currLexer->_pLexOrFold(0, startPos, length, initStyle, words, window, props);
}
void __stdcall ExtFold(int langID, unsigned int startPos, int length, int initStyle,
char *words[], WindowID window, char *props)
{
/*
* This is just a forwarding function that forwards Scintilla's fold command to
* the correct exteneral lexer.
*
*/
Lexer* currLexer = &_LexerDetailVector.at(langID);
currLexer->_pLexOrFold(1, startPos, length, initStyle, words, window, props);
}
} // End:: Unnamed namespace for private implementation.
//*********************************************************************************************
// Publicly defined functions.
void init(std::string Name, tstring statusText, NppExtLexerFunction pLexOrFold,
PFUNCPLUGINCMD pMenuDlg) // Setup a lexer definition.
{
/*
* This function initializes the lexer values that will get passed to both the Scintilla
* External Lexer Library and Notepad++'s Plugin Manager.
*
*/
// Notify if length is too long.
if ( Name.length() > MAX_EXTERNAL_LEXER_NAME_LEN )
::MessageBox(Npp_Plugin_Interface::hNpp(),
TEXT("Lexer name is too long and will be truncated."),
TEXT("Lexer Name Alert"),
MB_ICONINFORMATION);
if ( statusText.length() > MAX_EXTERNAL_LEXER_DESC_LEN )
::MessageBox(Npp_Plugin_Interface::hNpp(),
TEXT("Lexer description is too long and will be truncated."),
TEXT("Lexer Description Alert"),
MB_ICONINFORMATION);
// The lexer details vector is used to store the SCI lexerID and the pointer to the
// lexers entry point function ( usually LexOrFold() ).
Lexer thisLexer;
thisLexer._name.assign(Name);
thisLexer._description.assign(statusText);
thisLexer._pLexOrFold = pLexOrFold;
thisLexer.SCI_LEXERID = NULL;
_LexerDetailVector.push_back(thisLexer);
/*
* This plugin extension uses the lexer's name for the menu. Since the lexer name is also
* used by Notepad++ and Scintilla as a char* value and the FuncItem expects a TCHAR*
* value we need to convert it prior to registering the FuncItem.
*
*/
// Create a tstring and copy the standard character string into it. Should work for both
// unicode and ansi.
int len = Name.length();
tstring itemName = tstring(len, '\0');
std::copy(Name.begin(), Name.end(), itemName.begin());
setLexerFuncItem(itemName, pMenuDlg);
}
void setLexerFuncItem(tstring Name, PFUNCPLUGINCMD pFunction,
int cmdID, bool init2Check, ShortcutKey* pShKey)
{
/*
* This function stores Function Items to the FuncItem vector.
*
* If three basic entries 'separator', 'help', and 'about' are stored as PluginFuncItems
* and an extension to this namespace provides another FuncItems vector, the two can
* be merged while at the same time ensuring the main plugins menu functions are at
* the bottom (or top) of the plugin's menu in Npp.
*
*/
// Notify if length is too long.
if ( !( Name.length() < nbChar ) )
::MessageBox(Npp_Plugin_Interface::hNpp(),
TEXT("Function name is too long and will be truncated."),
TEXT("Function Item Name Alert"),
MB_ICONINFORMATION);
FuncItem thisFunction;
Name.copy(thisFunction._itemName, Name.length());
thisFunction._itemName[ Name.length() ] = '\0';
thisFunction._cmdID = cmdID;
thisFunction._pFunc = pFunction;
thisFunction._init2Check = init2Check;
thisFunction._pShKey = pShKey;
_LexerFuncVector.push_back(thisFunction);
}
int getSCILexerIDByIndex(int index)
{
/*
* Returns the SCI_LEXERID at vector index. Useful when dealing with notifications and
* messaging.
*
*/
return ( _LexerDetailVector.at(index).SCI_LEXERID );
}
int getSCILexerIDByName( std::string name )
{
/*
* Returns the SCI_LEXERID from the vector index item with the matching name. Useful
* when dealing with notifications and messaging.
*
*/
std::vector<Lexer>::iterator currLexer = _LexerDetailVector.begin();
for (currLexer; currLexer < _LexerDetailVector.end(); currLexer++ ) {
if ( currLexer->_name.compare( name ) == 0 ) return currLexer->SCI_LEXERID;
}
return ( MININT );
}
std::vector<FuncItem> getLexerFuncVector()
{
/*
*
* Provides a response for a namespace's extension to retrieve and work with the
* plugin's function item vector.
*
* Useful to merge additional function items together before responding to the
* Npp plugin manager's getFuncArray() call.
*
*/
return ( _LexerFuncVector );
}
std::vector<Lexer> getLexerDetailVector()
{
/*
*
* Provides a response for a namespace's extension to retrieve and work with the
* plugin's function item vector.
*
* Useful to merge additional function items together before responding to the
* Npp plugin manager's getFuncArray() call.
*
*/
return ( _LexerDetailVector );
}
//---------------------------------------------------------------------------------------------
// 'Virtualized' base plugin FuncItem functions.
/*
* These functions will be used instead of the base plugin functions to allow for the
* inclusion of a sorted lexer FuncItem list in the menu above the base plugins.
*
*/
FuncItem * getPluginFuncArray() // Return this plugin's sorted FuncItem array.
{
/*
* In order to have the function items show up in the Notepad++ plugins menu with
* the base plugins' function items at the bottom a new vector is created and the existing
* vectors are copied into it with the lexer functions first.
*
*/
namespace pIface = Npp_Plugin_Interface;
// <--- Local function for sorting criteria predicate. --->
struct sortByName
{
bool operator()(FuncItem& f1, FuncItem& f2)
{
return ( _tcscmp(f1._itemName, f2._itemName) < 0 );
}
};
if ( _LexerFuncVector.empty() ) {
// Doesn't look like there are any lexer function items so just send the plugin's.
ReturnVector = pIface::getPluginFuncVector();
}
else {
// Sort the lexer function items vector.
std::sort(_LexerFuncVector.begin(), _LexerFuncVector.end(), sortByName());
// Copy it to the vector that will be returned to Notepad++'s PluginsManager.
ReturnVector = _LexerFuncVector;
// Append the base plugin's function items (ie 'Help', 'About', etc...
std::vector<FuncItem> tmpVector = pIface::getPluginFuncVector();
std::copy(tmpVector.begin(), tmpVector.end(), std::back_inserter(ReturnVector));
}
return ( &ReturnVector[0] );
}
int getPluginFuncCount()
{
/*
*
* Provides a response to PluginsManager's getFuncArray call and allows for extensions
* to work with generating an array to send back that includes their own FuncItems.
*
*/
return ( Npp_Plugin_Interface::getPluginFuncCount() + getLexerFuncCount() );
}
} // End namespace: Npp_ExtLexer_Interface.
MongoDB Logo MongoDB