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