1 //this file is part of notepad++
2 //Copyright (C)2003 Don HO <donho@altern.org>
3 //
4 //This program is free software; you can redistribute it and/or
5 //modify it under the terms of the GNU General Public License
6 //as published by the Free Software Foundation; either
7 //version 2 of the License, or (at your option) any later version.
8 //
9 //This program is distributed in the hope that it will be useful,
10 //but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //GNU General Public License for more details.
13 //
14 //You should have received a copy of the GNU General Public License
15 //along with this program; if not, write to the Free Software
16 //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 /**
18  * Notepad++ plugin basic interface
19  *
20  * Author: dokutoku, https://twitter.com/dokutoku3
21  * License: GPL-2.0 or later
22  */
23 module npp_api.pluginfunc.basic_interface;
24 
25 
26 version (Windows):
27 
28 private static import core.sys.windows.winnt;
29 private static import npp_api.pluginfunc.string;
30 private static import npp_api.PowerEditor.MISC.PluginsManager.PluginInterface;
31 private static import std.traits;
32 
33 struct plugin_DLL_info
34 {
35 	string CompanyName = null;
36 	string FileDescription = null;
37 	string FileVersion = null;
38 	string InternalName = null;
39 	string LegalCopyright = null;
40 	string OriginalFilename = null;
41 	string ProductName = null;
42 	string ProductVersion = null;
43 }
44 
45 /**
46  * Notepad++ callable
47  */
48 template is_npp_func(alias func_name)
49 {
50 	enum bool is_npp_func = (std.traits.isFunction!(func_name)) && (__traits(getLinkage, func_name) == `C`);
51 }
52 
53 /**
54  * Notepad++ plugin interface function
55  */
56 template is_plugin_func(alias func_name)
57 {
58 	enum bool is_plugin_func = (is_npp_func!(func_name)) && (__traits(getProtection, func_name) == `export`);
59 }
60 
61 template is_DllMain(alias func_name)
62 {
63 	enum bool is_DllMain = (std.traits.isFunction!(func_name)) && (__traits(getLinkage, func_name) == `Windows`) && (__traits(getProtection, func_name) == `export`);
64 }
65 
66 mixin template npp_nppData()
67 {
68 	private static import npp_api.PowerEditor.MISC.PluginsManager.PluginInterface;
69 
70 	//ToDo: Compilation error
71 	static if (!__traits(compiles, .nppData)) {
72 		pragma(mangle, "nppData")
73 		extern (C)
74 		npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData nppData;
75 	}
76 }
77 
78 /**
79  * main_menu変数の宣言
80  */
81 mixin template npp_main_menu(alias main_menu_items)
82 	if (std.traits.isArray!(typeof(main_menu_items)))
83 {
84 	private static import npp_api.PowerEditor.MISC.PluginsManager.PluginInterface;
85 	private static import npp_api.pluginfunc.basic_interface;
86 
87 	static if (!__traits(compiles, .main_menu_def)) {
88 		enum npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[main_menu_items.length] main_menu_def = npp_api.pluginfunc.basic_interface.npp_init_main_menu!(main_menu_items.length, typeof(main_menu_items))(main_menu_items);
89 		npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[main_menu_items.length] main_menu = main_menu_def;
90 	}
91 }
92 
93 mixin template npp_DLLMain()
94 {
95 	version (D_BetterC) {
96 		private static import core.sys.windows.basetsd;
97 		private static import core.sys.windows.windef;
98 		private static import core.sys.windows.winnt;
99 
100 		static if (!__traits(compiles, .DllMain)) {
101 			static if (!__traits(compiles, .pluginInit) && !__traits(compiles, .pluginCleanUp)) {
102 				pragma(mangle, "DllMain")
103 				extern (Windows)
104 				pure nothrow @safe @nogc
105 				export core.sys.windows.windef.BOOL DllMain(core.sys.windows.basetsd.HANDLE hModule, core.sys.windows.windef.DWORD reasonForCall, core.sys.windows.winnt.LPVOID lpReserved)
106 
107 					do
108 					{
109 						return core.sys.windows.windef.TRUE;
110 					}
111 			} else {
112 				pragma(mangle, "DllMain")
113 				extern (Windows)
114 				nothrow @nogc
115 				export core.sys.windows.windef.BOOL DllMain(core.sys.windows.basetsd.HANDLE hModule, core.sys.windows.windef.DWORD reasonForCall, core.sys.windows.winnt.LPVOID lpReserved)
116 
117 					do
118 					{
119 						switch (reasonForCall) {
120 							case core.sys.windows.winnt.DLL_PROCESS_ATTACH:
121 								static if (__traits(compiles, .pluginInit)) {
122 									.pluginInit(hModule);
123 								}
124 
125 								break;
126 
127 							case core.sys.windows.winnt.DLL_PROCESS_DETACH:
128 								static if (__traits(compiles, .pluginCleanUp)) {
129 									.pluginCleanUp();
130 								}
131 
132 								break;
133 
134 							default:
135 								break;
136 						}
137 
138 						return core.sys.windows.windef.TRUE;
139 					}
140 			}
141 		}
142 	} else {
143 		private static import core.sys.windows.basetsd;
144 		private static import core.sys.windows.dll;
145 		private static import core.sys.windows.windef;
146 		private static import core.sys.windows.winnt;
147 
148 		static if (!__traits(compiles, .DllMain)) {
149 			pragma(mangle, "DllMain")
150 			extern (Windows)
151 			export core.sys.windows.windef.BOOL DllMain(core.sys.windows.basetsd.HANDLE hModule, core.sys.windows.windef.DWORD reasonForCall, core.sys.windows.winnt.LPVOID lpReserved)
152 
153 				do
154 				{
155 					switch (reasonForCall) {
156 						case core.sys.windows.winnt.DLL_PROCESS_ATTACH:
157 							core.sys.windows.dll.dll_process_attach(hModule);
158 
159 							static if (__traits(compiles, .pluginInit)) {
160 								.pluginInit(hModule);
161 							}
162 
163 							break;
164 
165 						case core.sys.windows.winnt.DLL_PROCESS_DETACH:
166 							static if (__traits(compiles, .pluginCleanUp)) {
167 								.pluginCleanUp();
168 							}
169 
170 							core.sys.windows.dll.dll_process_detach(hModule);
171 
172 							break;
173 
174 						case core.sys.windows.winnt.DLL_THREAD_ATTACH:
175 							core.sys.windows.dll.dll_thread_attach(true, true);
176 
177 							break;
178 
179 						case core.sys.windows.winnt.DLL_THREAD_DETACH:
180 							core.sys.windows.dll.dll_thread_detach(true, true);
181 
182 							break;
183 
184 						default:
185 							break;
186 					}
187 
188 					return core.sys.windows.windef.TRUE;
189 				}
190 		}
191 	}
192 }
193 
194 mixin template npp_getName()
195 {
196 	private static import core.sys.windows.windef;
197 	private static import core.sys.windows.winnt;
198 
199 	static if (!__traits(compiles, .getName)) {
200 		pragma(mangle, "getName")
201 		extern (C)
202 		pure nothrow @safe @nogc
203 		export const (core.sys.windows.winnt.WCHAR)* getName()
204 
205 			do
206 			{
207 				return core.sys.windows.windef.NULL;
208 			}
209 	}
210 }
211 
212 mixin template npp_getName(wstring plugin_name)
213 {
214 	private static import std.traits;
215 	private static import core.sys.windows.windef;
216 	private static import core.sys.windows.winnt;
217 	private static import npp_api.pluginfunc.string;
218 
219 	static if (!__traits(compiles, .getName)) {
220 		pragma(mangle, "getName")
221 		extern (C)
222 		pure nothrow @safe @nogc
223 		export const (core.sys.windows.winnt.WCHAR)* getName()
224 
225 			do
226 			{
227 				static if (plugin_name.length != 0) {
228 					static assert(plugin_name[$ - 1] == '\0');
229 
230 					return &(plugin_name[0]);
231 				} else {
232 					return core.sys.windows.windef.NULL;
233 				}
234 			}
235 	}
236 }
237 
238 pragma(inline, true)
239 pure nothrow @safe @nogc
240 npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[main_menu_length] npp_init_main_menu(size_t main_menu_length, main_menu_type)(main_menu_type menu_def)
241 	if (std.traits.isArray!(main_menu_type))
242 
243 	in
244 	{
245 		static if (std.traits.isStaticArray!(main_menu_type)) {
246 			static assert(is(main_menu_type : npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[main_menu_length]));
247 		} else static if (std.traits.isDynamicArray!(main_menu_type)) {
248 			static assert(is(main_menu_type : npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[]));
249 		}
250 
251 		assert(main_menu_length == menu_def.length);
252 	}
253 
254 	do
255 	{
256 		npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[main_menu_length] output;
257 
258 		for (size_t i = 0; i < main_menu_length; i++) {
259 			output[i]._itemName = npp_api.pluginfunc..string.copy_string(menu_def[i]._itemName);
260 			output[i]._pFunc = menu_def[i]._pFunc;
261 			output[i]._cmdID = menu_def[i]._cmdID;
262 			output[i]._init2Check = menu_def[i]._init2Check;
263 			output[i]._pShKey = menu_def[i]._pShKey;
264 		}
265 
266 		return output;
267 	}
268 
269 mixin template npp_getFuncsArray()
270 {
271 	private static import npp_api.PowerEditor.MISC.PluginsManager.PluginInterface;
272 
273 	static if (!__traits(compiles, .getFuncsArray)) {
274 		pragma(mangle, "getFuncsArray")
275 		extern (C)
276 		pure nothrow @nogc
277 		export const (npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem)* getFuncsArray(int* nbF)
278 
279 			do
280 			{
281 				/+
282 				if (nbF == null) {
283 					return null;
284 				}
285 				+/
286 
287 				*nbF = 0;
288 
289 				return null;
290 			}
291 	}
292 }
293 
294 mixin template npp_getFuncsArray(alias func_list)
295 	if (std.traits.isArray!(typeof(func_list)))
296 {
297 	private static import std.traits;
298 	private static import npp_api.PowerEditor.MISC.PluginsManager.PluginInterface;
299 	private static import npp_api.pluginfunc.basic_interface;
300 
301 	version (D_BetterC) {
302 		static assert(std.traits.isStaticArray!(typeof(func_list)));
303 	}
304 
305 	static if (std.traits.isStaticArray!(typeof(func_list))) {
306 		static assert(is(typeof(func_list) : const npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[func_list.length]));
307 		static assert(func_list.length != 0);
308 		static assert(int.max >= func_list.length);
309 	} else {
310 		static assert(is(typeof(func_list) : const npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[]));
311 	}
312 
313 	static if (!__traits(compiles, .getFuncsArray)) {
314 		pragma(mangle, "getFuncsArray")
315 		extern (C)
316 		nothrow @nogc
317 		export const (npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem)* getFuncsArray(int* nbF)
318 
319 			in
320 			{
321 				assert(int.max >= func_list.length);
322 			}
323 
324 			do
325 			{
326 				/+
327 				if (nbF == null) {
328 					return null;
329 				}
330 				+/
331 
332 				*nbF = cast(int)(func_list.length);
333 
334 				static if (std.traits.isStaticArray!(typeof(func_list))) {
335 					return &(func_list[0]);
336 				} else {
337 					if (func_list.length != 0) {
338 						return &(func_list[0]);
339 					} else {
340 						return null;
341 					}
342 				}
343 			}
344 	}
345 }
346 
347 mixin template npp_isUnicode()
348 {
349 	private static import core.sys.windows.windef;
350 
351 	/**
352 	 * This API return always true now, since Notepad++ isn't compiled in ANSI mode anymore
353 	 */
354 	static if (!__traits(compiles, .isUnicode)) {
355 		pragma(mangle, "isUnicode")
356 		extern (C)
357 		pure nothrow @safe @nogc
358 		export core.sys.windows.windef.BOOL isUnicode()
359 
360 			do
361 			{
362 				return core.sys.windows.windef.TRUE;
363 			}
364 	}
365 }
366 
367 mixin template npp_setInfo()
368 {
369 	private static import std.traits;
370 	private static import npp_api.PowerEditor.MISC.PluginsManager.PluginInterface;
371 
372 	static if (!__traits(compiles, .setInfo)) {
373 		static if (!__traits(compiles, .pluginSetInfo) && !__traits(compiles, .nppData) && !__traits(compiles, .gshared_nppData)) {
374 			pragma(mangle, "setInfo")
375 			extern (C)
376 			pure nothrow @safe @nogc
377 			export void setInfo(npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData notpadPlusData)
378 
379 				do
380 				{
381 				}
382 		} else static if (std.traits.hasFunctionAttributes!(.pluginSetInfo, "@nogc")) {
383 			pragma(mangle, "setInfo")
384 			extern (C)
385 			nothrow @nogc
386 			export void setInfo(npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData notpadPlusData)
387 
388 				do
389 				{
390 					static if (__traits(compiles, .nppData)) {
391 						.nppData = notpadPlusData;
392 					}
393 
394 					static if (__traits(compiles, .gshared_nppData)) {
395 						.gshared_nppData = notpadPlusData;
396 					}
397 
398 					.pluginSetInfo(notpadPlusData);
399 				}
400 		} else {
401 			pragma(mangle, "setInfo")
402 			extern (C)
403 			nothrow
404 			export void setInfo(npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData notpadPlusData)
405 
406 				do
407 				{
408 					static if (__traits(compiles, .nppData)) {
409 						.nppData = notpadPlusData;
410 					}
411 
412 					static if (__traits(compiles, .gshared_nppData)) {
413 						.gshared_nppData = notpadPlusData;
414 					}
415 
416 					.pluginSetInfo(notpadPlusData);
417 				}
418 		}
419 	}
420 }
421 
422 mixin template npp_setInfo(alias nppData)
423 	if (is(typeof(nppData) == npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData))
424 {
425 	private static import std.traits;
426 	private static import npp_api.PowerEditor.MISC.PluginsManager.PluginInterface;
427 
428 	static if (!__traits(compiles, .setInfo)) {
429 		static if (!__traits(compiles, .pluginSetInfo) || (__traits(compiles, .pluginSetInfo) && (std.traits.hasFunctionAttributes!(.pluginSetInfo, "@nogc")))) {
430 			pragma(mangle, "setInfo")
431 			extern (C)
432 			nothrow @nogc
433 			export void setInfo(npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData notpadPlusData)
434 
435 				do
436 				{
437 					nppData = notpadPlusData;
438 
439 					static if (__traits(compiles, .gshared_nppData)) {
440 						.gshared_nppData = notpadPlusData;
441 					}
442 
443 					static if (__traits(compiles, .pluginSetInfo)) {
444 						.pluginSetInfo(notpadPlusData);
445 					}
446 				}
447 		} else {
448 			pragma(mangle, "setInfo")
449 			extern (C)
450 			nothrow
451 			export void setInfo(npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData notpadPlusData)
452 
453 				do
454 				{
455 					nppData = notpadPlusData;
456 
457 					static if (__traits(compiles, .gshared_nppData)) {
458 						.gshared_nppData = notpadPlusData;
459 					}
460 
461 					static if (__traits(compiles, .pluginSetInfo)) {
462 						.pluginSetInfo(notpadPlusData);
463 					}
464 				}
465 		}
466 	}
467 }
468 
469 mixin template npp_setInfo(alias nppData, alias main_menu, alias menu_def)
470 	if (is(typeof(nppData) == npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData) && std.traits.isArray!(typeof(main_menu)) && std.traits.isArray!(typeof(menu_def)))
471 {
472 	private static import std.traits;
473 	private static import npp_api.PowerEditor.MISC.PluginsManager.PluginInterface;
474 	private static import npp_api.pluginfunc.basic_interface;
475 
476 	version (D_BetterC) {
477 		static assert(std.traits.isStaticArray!(typeof(main_menu)));
478 		static assert(std.traits.isStaticArray!(typeof(menu_def)));
479 	}
480 
481 	static if (std.traits.isStaticArray!(typeof(main_menu))) {
482 		static assert(is(typeof(main_menu) : npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[main_menu.length]));
483 		static assert(main_menu.length != 0);
484 	} else {
485 		static assert(is(typeof(main_menu) : npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[]));
486 	}
487 
488 	static if (std.traits.isStaticArray!(typeof(menu_def))) {
489 		static assert(is(typeof(menu_def) : npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[menu_def.length]));
490 		static assert(menu_def.length != 0);
491 
492 		static if (std.traits.isStaticArray!(typeof(main_menu))) {
493 			static assert(menu_def.length >= main_menu.length);
494 		}
495 	} else {
496 		static assert(is(typeof(menu_def) : npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem[]));
497 	}
498 
499 	static if (!__traits(compiles, .setInfo)) {
500 		static if (!__traits(compiles, .pluginSetInfo) || (__traits(compiles, .pluginSetInfo) && (std.traits.hasFunctionAttributes!(.pluginSetInfo, "@nogc")))) {
501 			pragma(mangle, "setInfo")
502 			extern (C)
503 			nothrow @nogc
504 			export void setInfo(npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData notpadPlusData)
505 
506 				in
507 				{
508 					assert(menu_def.length >= main_menu.length);
509 				}
510 
511 				do
512 				{
513 					nppData = notpadPlusData;
514 
515 					static if (__traits(compiles, .gshared_nppData)) {
516 						.gshared_nppData = notpadPlusData;
517 					}
518 
519 					static if (__traits(compiles, .pluginSetInfo)) {
520 						.pluginSetInfo(notpadPlusData);
521 					}
522 				}
523 		} else {
524 			pragma(mangle, "setInfo")
525 			extern (C)
526 			nothrow
527 			export void setInfo(npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.NppData notpadPlusData)
528 
529 				in
530 				{
531 					assert(menu_def.length >= main_menu.length);
532 				}
533 
534 				do
535 				{
536 					nppData = notpadPlusData;
537 
538 					static if (__traits(compiles, .gshared_nppData)) {
539 						.gshared_nppData = notpadPlusData;
540 					}
541 
542 					static if (__traits(compiles, .pluginSetInfo)) {
543 						.pluginSetInfo(notpadPlusData);
544 					}
545 				}
546 		}
547 	}
548 }
549 
550 mixin template npp_beNotified()
551 {
552 	private static import npp_api.pluginfunc.basic_interface;
553 	private static import npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs;
554 	private static import npp_api.scintilla.Scintilla;
555 	private static import std.traits;
556 
557 	static if (!__traits(compiles, .beNotified)) {
558 		static if (!__traits(compiles, .pluginBeNotified)) {
559 			pragma(mangle, "beNotified")
560 			extern (C)
561 			pure nothrow @safe @nogc
562 			export void beNotified(npp_api.scintilla.Scintilla.SCNotification* notifyCode)
563 
564 				do
565 				{
566 					/+
567 					/+
568 					if (notifyCode == null) {
569 						return;
570 					}
571 					+/
572 
573 					switch ((*notifyCode).nmhdr.code) {
574 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_READY:
575 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_TBMODIFICATION:
576 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILEBEFORECLOSE:
577 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILEOPENED:
578 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILECLOSED:
579 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILEBEFOREOPEN:
580 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILEBEFORESAVE:
581 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILESAVED:
582 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_SHUTDOWN:
583 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_BUFFERACTIVATED:
584 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_LANGCHANGED:
585 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_WORDSTYLESUPDATED:
586 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_SHORTCUTREMAPPED:
587 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILEBEFORELOAD:
588 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILELOADFAILED:
589 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_READONLYCHANGED:
590 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_DOCORDERCHANGED:
591 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_SNAPSHOTDIRTYFILELOADED:
592 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_BEFORESHUTDOWN:
593 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_CANCELSHUTDOWN:
594 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILEBEFORERENAME:
595 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILERENAMECANCEL:
596 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILERENAMED:
597 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILEBEFOREDELETE:
598 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILEDELETEFAILED:
599 						case npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs.NPPN_FILEDELETED:
600 							break;
601 
602 						default:
603 							break;
604 					}
605 					+/
606 				}
607 		} else static if (std.traits.hasFunctionAttributes!(.pluginBeNotified, "@nogc")) {
608 			pragma(mangle, "beNotified")
609 			extern (C)
610 			nothrow @nogc
611 			export void beNotified(npp_api.scintilla.Scintilla.SCNotification* notifyCode)
612 
613 				do
614 				{
615 					/+
616 					if (notifyCode == null) {
617 						return;
618 					}
619 					+/
620 
621 					.pluginBeNotified(*notifyCode);
622 				}
623 		} else {
624 			pragma(mangle, "beNotified")
625 			extern (C)
626 			nothrow
627 			export void beNotified(npp_api.scintilla.Scintilla.SCNotification* notifyCode)
628 
629 				do
630 				{
631 					/+
632 					if (notifyCode == null) {
633 						return;
634 					}
635 					+/
636 
637 					.pluginBeNotified(*notifyCode);
638 				}
639 		}
640 	}
641 }
642 
643 mixin template npp_messageProc()
644 {
645 	private static import std.traits;
646 	private static import core.sys.windows.windef;
647 	private static import npp_api.pluginfunc.basic_interface;
648 
649 	static if (!__traits(compiles, .messageProc)) {
650 		static if (!__traits(compiles, .pluginMessageProc)) {
651 			pragma(mangle, "messageProc")
652 			extern (C)
653 			pure nothrow @safe @nogc
654 			export core.sys.windows.windef.LRESULT messageProc(core.sys.windows.windef.UINT Message, core.sys.windows.windef.WPARAM wParam, core.sys.windows.windef.LPARAM lParam)
655 
656 				do
657 				{
658 					/*
659 					switwch (Message) {
660 						case core.sys.windows.winuser.WM_MOVE:
661 						case core.sys.windows.winuser.WM_SIZE:
662 						case core.sys.windows.winuser.WM_COMMAND:
663 							break;
664 
665 						default:
666 							break;
667 					}
668 					*/
669 
670 					return core.sys.windows.windef.TRUE;
671 				}
672 		} else static if (std.traits.hasFunctionAttributes!(.pluginMessageProc, "@nogc")) {
673 			pragma(mangle, "messageProc")
674 			extern (C)
675 			nothrow @nogc
676 			export core.sys.windows.windef.LRESULT messageProc(core.sys.windows.windef.UINT Message, core.sys.windows.windef.WPARAM wParam, core.sys.windows.windef.LPARAM lParam)
677 
678 				do
679 				{
680 					if (.pluginMessageProc(Message, wParam, lParam)) {
681 						return core.sys.windows.windef.TRUE;
682 					} else {
683 						return core.sys.windows.windef.FALSE;
684 					}
685 				}
686 		} else {
687 			pragma(mangle, "messageProc")
688 			extern (C)
689 			nothrow
690 			export core.sys.windows.windef.LRESULT messageProc(core.sys.windows.windef.UINT Message, core.sys.windows.windef.WPARAM wParam, core.sys.windows.windef.LPARAM lParam)
691 
692 				do
693 				{
694 					if (.pluginMessageProc(Message, wParam, lParam)) {
695 						return core.sys.windows.windef.TRUE;
696 					} else {
697 						return core.sys.windows.windef.FALSE;
698 					}
699 				}
700 		}
701 	}
702 }
703 
704 mixin template npp_plugin_interface()
705 {
706 	private static import npp_api.pluginfunc.basic_interface;
707 
708 	mixin npp_api.pluginfunc.basic_interface.npp_nppData!();
709 	mixin npp_api.pluginfunc.basic_interface.npp_DLLMain!();
710 	mixin npp_api.pluginfunc.basic_interface.npp_getName!();
711 	mixin npp_api.pluginfunc.basic_interface.npp_getFuncsArray!();
712 	mixin npp_api.pluginfunc.basic_interface.npp_isUnicode!();
713 	mixin npp_api.pluginfunc.basic_interface.npp_setInfo!(nppData);
714 	mixin npp_api.pluginfunc.basic_interface.npp_beNotified!();
715 	mixin npp_api.pluginfunc.basic_interface.npp_messageProc!();
716 
717 	static assert(npp_api.pluginfunc.basic_interface.is_DllMain!(.DllMain));
718 	static assert(npp_api.pluginfunc.basic_interface.is_plugin_func!(.getName));
719 	static assert(npp_api.pluginfunc.basic_interface.is_plugin_func!(.getFuncsArray));
720 	static assert(npp_api.pluginfunc.basic_interface.is_plugin_func!(.isUnicode));
721 	static assert(npp_api.pluginfunc.basic_interface.is_plugin_func!(.setInfo));
722 	static assert(npp_api.pluginfunc.basic_interface.is_plugin_func!(.beNotified));
723 	static assert(npp_api.pluginfunc.basic_interface.is_plugin_func!(.messageProc));
724 }
725 
726 mixin template npp_plugin_interface(wstring plugin_name, alias main_menu_items)
727 	if (std.traits.isArray!(typeof(main_menu_items)))
728 {
729 	private static import npp_api.pluginfunc.basic_interface;
730 
731 	private enum plugin_name_internal = plugin_name ~ "\0";
732 
733 	mixin npp_api.pluginfunc.basic_interface.npp_nppData!();
734 	mixin npp_api.pluginfunc.basic_interface.npp_main_menu!(main_menu_items);
735 	mixin npp_api.pluginfunc.basic_interface.npp_getName!(plugin_name_internal);
736 	mixin npp_api.pluginfunc.basic_interface.npp_getFuncsArray!(main_menu);
737 	mixin npp_api.pluginfunc.basic_interface.npp_setInfo!(nppData, main_menu, main_menu_def);
738 	mixin npp_api.pluginfunc.basic_interface.npp_plugin_interface!();
739 }