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  * ini file setting
19  *
20  * Author: dokutoku, https://twitter.com/dokutoku3
21  * License: GPL-2.0 or later
22  */
23 module npp_api.pluginfunc.ini_setting;
24 
25 
26 version (Windows):
27 version (Not_betterC):
28 
29 private static import core.sys.windows.winbase;
30 private static import core.sys.windows.windef;
31 private static import core.sys.windows.winnt;
32 private static import core.sys.windows.winuser;
33 private static import npp_api.PowerEditor.MISC.PluginsManager.Notepad_plus_msgs;
34 private static import npp_api.PowerEditor.MISC.PluginsManager.PluginInterface;
35 private static import npp_api.pluginfunc.config_file;
36 private static import npp_api.pluginfunc.menu;
37 private static import npp_api.pluginfunc.npp_msgs;
38 private static import npp_api.pluginfunc.path;
39 private static import npp_api.pluginfunc.string;
40 private static import std.conv;
41 private static import std.file;
42 private static import std.path;
43 private static import std.stdio;
44 private static import std.string;
45 private static import std.traits;
46 private static import std.utf;
47 
48 struct ini_setting_item
49 {
50 	mixin npp_api.pluginfunc.config_file.setting_item_internal!(wchar);
51 }
52 
53 ini_setting_item[output_length] convert_setting(size_t output_length)(npp_api.pluginfunc.config_file.setting_item[] input_setting)
54 
55 	do
56 	{
57 		ini_setting_item[output_length] output;
58 
59 		for (size_t i = 0; i < input_setting.length; i++) {
60 			output[i].name = std.utf.toUTF16(input_setting[i].name[0 .. $]);
61 			output[i].name = npp_api.pluginfunc..string.copy_string(output[i].name);
62 			output[i].type = input_setting[i].type;
63 
64 			switch (input_setting[i].type) {
65 				case npp_api.pluginfunc.config_file.value_type.string_type:
66 				case npp_api.pluginfunc.config_file.value_type.path_type:
67 					if (input_setting[i].value.string_value != null) {
68 						output[i].value.wstring_value = std.utf.toUTF16(input_setting[i].value.string_value[0 .. $]);
69 					}
70 
71 					break;
72 
73 				default:
74 					output[i].value = input_setting[i].value;
75 
76 					break;
77 			}
78 
79 			output[i].extra_filter = input_setting[i].extra_filter;
80 		}
81 
82 		return output;
83 	}
84 
85 pure nothrow @safe
86 wstring[] create_setting_idetifiers(size_t setting_length)(ini_setting_item[setting_length] setting_items)
87 
88 	do
89 	{
90 		wstring[] output = new wstring[setting_length];
91 
92 		for (size_t i = 0; i < setting_items.length; i++) {
93 			output[i] = npp_api.pluginfunc..string.from_stringz(setting_items[i].name);
94 		}
95 
96 		return output;
97 	}
98 
99 struct npp_ini_session
100 {
101 private:
102 	wstring npp_config_path = null;
103 	wstring plugin_config_path = null;
104 	wstring config_file = null;
105 	core.sys.windows.winnt.WCHAR[] section_name = null;
106 	bool is_valid = false;
107 	wchar[npp_api.pluginfunc.config_file.setting_name_length] setting_name_buf;
108 	//path_buf;
109 
110 public:
111 	this(core.sys.windows.windef.HWND _nppHandle, const wchar[] plugin_directry, const wchar[] config_filename, const wchar[] section_name)
112 
113 		in
114 		{
115 			assert(section_name.length != 0);
116 
117 			if (plugin_directry.length != 0) {
118 				assert(std.path.isValidPath(plugin_directry));
119 			}
120 		}
121 
122 		do
123 		{
124 			this.section_name = section_name.dup;
125 			this.section_name ~= "\0"w;
126 			core.sys.windows.winnt.WCHAR[npp_api.pluginfunc.path.OS_MAX_PATH] input_buf = '\0';
127 			npp_api.pluginfunc.npp_msgs.send_NPPM_GETPLUGINSCONFIGDIR(_nppHandle, input_buf.length, &(input_buf[0]));
128 			this.npp_config_path = npp_api.pluginfunc..string.from_stringz(input_buf);
129 
130 			if (std.file.exists(this.npp_config_path) && std.file.isDir(this.npp_config_path)) {
131 				if (plugin_directry.length != 0) {
132 					this.plugin_config_path = std.path.buildPath(this.npp_config_path, plugin_directry).idup;
133 
134 					if (!std.file.exists(this.plugin_config_path) || !std.file.isDir(this.plugin_config_path)) {
135 						std.file.mkdir(this.plugin_config_path);
136 					}
137 				} else {
138 					this.plugin_config_path = this.npp_config_path.idup;
139 				}
140 
141 				this.config_file = std.path.buildPath(this.plugin_config_path, std.path.setExtension(config_filename, `.ini`w)).idup;
142 
143 				if (!std.file.exists(this.config_file) || !std.file.isFile(this.config_file)) {
144 					try {
145 						std.stdio.File new_file = std.stdio.File(this.config_file, `w`w);
146 						new_file.close();
147 						this.is_valid = true;
148 					} catch (Exception e) {
149 						//ToDo:
150 					}
151 				} else {
152 					this.is_valid = true;
153 				}
154 
155 				this.config_file ~= "\0"w;
156 			} else {
157 				throw new Exception(`Unknown Notepad++ config path`);
158 			}
159 		}
160 
161 	pragma(inline, true)
162 	pure nothrow @safe @nogc
163 	bool is_valid_setting() const
164 
165 		do
166 		{
167 			return this.is_valid;
168 		}
169 
170 	/**
171 	 * メニューにチェックをつけるかどうか
172 	 *
173 	 * Params:
174 	 *      key_name = 設定名
175 	 *      default_value = 設定の読み込みに失敗した場合のデフォルト値
176 	 *
177 	 * Returns: メニューにチェックをつけるかどうか
178 	 */
179 	nothrow @nogc
180 	bool is_mfs_checked(const wchar[] key_name, bool default_value = false)
181 
182 		in
183 		{
184 			assert(key_name.length != 0);
185 		}
186 
187 		do
188 		{
189 			npp_api.pluginfunc..string.copy_string(this.setting_name_buf, key_name);
190 			core.sys.windows.windef.UINT result = core.sys.windows.winbase.GetPrivateProfileIntW(&(this.section_name[0]), &(this.setting_name_buf[0]), int.max, &(this.config_file[0]));
191 
192 			if (result == int.max) {
193 				return default_value;
194 			}
195 
196 			return (result == 1) ? (true) : (false);
197 		}
198 
199 	nothrow @nogc
200 	void load_menu_checked(size_t menu_index_length)(ref npp_api.pluginfunc.menu.sub_menu_index[menu_index_length] menu_index)
201 
202 		do
203 		{
204 			for (size_t i = 0; i < menu_index.length; i++) {
205 				if (menu_index[i].menu_checked_id.length != 0) {
206 					menu_index[i].func_item._init2Check = this.is_mfs_checked(menu_index[i].menu_checked_id, menu_index[i].func_item._init2Check);
207 				}
208 			}
209 		}
210 
211 	nothrow
212 	void auto_load(size_t setting_length)(ref .ini_setting_item[setting_length] settings) const
213 
214 		do
215 		{
216 			npp_api.pluginfunc.config_file.value_buf value_buf;
217 
218 			bool result_temp;
219 
220 			foreach (ref setting; settings) {
221 				result_temp = false;
222 
223 				switch (setting.type) {
224 					case npp_api.pluginfunc.config_file.value_type.bool_type:
225 						result_temp = this.load_config(setting.name, value_buf.bool_value);
226 
227 						if ((result_temp) && (setting.extra_filter != null)) {
228 							result_temp = setting.extra_filter(value_buf);
229 						}
230 
231 						if (result_temp) {
232 							setting.value.bool_value = value_buf.bool_value;
233 						}
234 
235 						break;
236 
237 					case npp_api.pluginfunc.config_file.value_type.int_type:
238 						result_temp = this.load_config(setting.name, int.max, value_buf.int_value);
239 
240 						if ((result_temp) && (setting.extra_filter != null)) {
241 							result_temp = setting.extra_filter(value_buf);
242 						}
243 
244 						if (result_temp) {
245 							setting.value.int_value = value_buf.int_value;
246 						}
247 
248 						break;
249 
250 					case npp_api.pluginfunc.config_file.value_type.uint_type:
251 						result_temp = this.load_config(setting.name, uint.max, value_buf.uint_value);
252 
253 						if ((result_temp) && (setting.extra_filter != null)) {
254 							result_temp = setting.extra_filter(value_buf);
255 						}
256 
257 						if (result_temp) {
258 							setting.value.uint_value = value_buf.uint_value;
259 						}
260 
261 						break;
262 
263 					case npp_api.pluginfunc.config_file.value_type.string_type:
264 						value_buf.wstring_value[] = '\0';
265 						result_temp = this.load_config(setting.name, value_buf.wstring_value);
266 
267 						if ((result_temp) && (setting.extra_filter != null)) {
268 							result_temp = setting.extra_filter(value_buf);
269 						}
270 
271 						if (result_temp) {
272 							setting.value.wstring_value = npp_api.pluginfunc..string.from_stringz(value_buf.wstring_value);
273 						}
274 
275 						break;
276 
277 					case npp_api.pluginfunc.config_file.value_type.path_type:
278 						value_buf.wstring_value[] = '\0';
279 						result_temp = this.load_config(setting.name, value_buf.wstring_value);
280 
281 						if ((result_temp) && (setting.extra_filter != null)) {
282 							result_temp = setting.extra_filter(value_buf);
283 						}
284 
285 						if (result_temp) {
286 							setting.value.wstring_value = npp_api.pluginfunc..string.from_stringz(value_buf.path_value);
287 						}
288 
289 						break;
290 
291 					default:
292 						break;
293 				}
294 			}
295 		}
296 
297 	pragma(inline, true)
298 	nothrow
299 	void auto_load(size_t setting_length, size_t menu_index_length)(ref .ini_setting_item[setting_length] settings, ref npp_api.pluginfunc.menu.sub_menu_index[menu_index_length] menu_index)
300 
301 		do
302 		{
303 			this.auto_load(settings);
304 			this.load_menu_checked(menu_index);
305 		}
306 
307 	pragma(inline, true)
308 	nothrow @nogc
309 	void write_menu_checked(const wchar[] key_name, bool value)
310 
311 		in
312 		{
313 			assert(key_name.length != 0);
314 		}
315 
316 		do
317 		{
318 			npp_api.pluginfunc..string.copy_string(this.setting_name_buf, key_name);
319 			core.sys.windows.winbase.WritePrivateProfileStringW(&(this.section_name[0]), &(this.setting_name_buf[0]), &(((value) ? (npp_api.pluginfunc..string.c_wstring!(`1`w)) : (npp_api.pluginfunc..string.c_wstring!(`0`w)))[0]), &(this.config_file[0]));
320 		}
321 
322 	pragma(inline, true)
323 	nothrow @nogc
324 	void write_menu_checked(size_t menu_index_length)(ref npp_api.pluginfunc.menu.sub_menu_index[menu_index_length] menu_index)
325 
326 		do
327 		{
328 			for (size_t i = 0; i < menu_index.length; i++) {
329 				if (menu_index[i].menu_checked_id.length != 0) {
330 					this.write_menu_checked(menu_index[i].menu_checked_id, menu_index[i].func_item._init2Check);
331 				}
332 			}
333 		}
334 
335 	pragma(inline, true)
336 	nothrow
337 	bool auto_write(size_t setting_length)(const ref .ini_setting_item[setting_length] settings)
338 
339 		do
340 		{
341 			foreach (setting; settings) {
342 				switch (setting.type) {
343 					case npp_api.pluginfunc.config_file.value_type.bool_type:
344 						this.write_config(setting.name, setting.value.bool_value);
345 
346 						break;
347 
348 					case npp_api.pluginfunc.config_file.value_type.int_type:
349 						this.write_config(setting.name, setting.value.int_value);
350 
351 						break;
352 
353 					case npp_api.pluginfunc.config_file.value_type.uint_type:
354 						this.write_config(setting.name, setting.value.uint_value);
355 
356 						break;
357 
358 					case npp_api.pluginfunc.config_file.value_type.string_type:
359 						this.write_config(setting.name, setting.value.wstring_value);
360 
361 						break;
362 
363 					case npp_api.pluginfunc.config_file.value_type.path_type:
364 						this.write_config(setting.name, setting.value.wstring_value);
365 
366 						break;
367 
368 					default:
369 						break;
370 				}
371 			}
372 		}
373 
374 	pragma(inline, true)
375 	nothrow
376 	void auto_write(size_t setting_length, size_t menu_index_length)(ref .ini_setting_item[setting_length] settings, ref npp_api.pluginfunc.menu.sub_menu_index[menu_index_length] menu_index)
377 
378 		do
379 		{
380 			this.auto_write(settings);
381 			this.load_menu_checked(menu_index);
382 		}
383 
384 	/**
385 	 * ???
386 	 *
387 	 * Params:
388 	 *      key_name = ???
389 	 *      result_value = オプションの格納場所
390 	 *
391 	 * Returns: 正常にloadできたかどうか
392 	 */
393 	nothrow @nogc
394 	bool load_config(const ref wchar[npp_api.pluginfunc.config_file.setting_name_length] key_name, ref bool result_value) const
395 
396 		in
397 		{
398 			assert(key_name[$ - 1] == '\0');
399 		}
400 
401 		do
402 		{
403 			core.sys.windows.windef.UINT temp_value = core.sys.windows.winbase.GetPrivateProfileIntW(&(this.section_name[0]), &(key_name[0]), int.max, &(this.config_file[0]));
404 
405 			switch (temp_value) {
406 				case 0:
407 					result_value = false;
408 
409 					return true;
410 
411 				case 1:
412 					result_value = true;
413 
414 					return true;
415 
416 				default:
417 					return false;
418 			}
419 		}
420 
421 	/**
422 	 * ???
423 	 *
424 	 * Params:
425 	 *      key_name = ???
426 	 *      invaild_value = ???
427 	 *      result_value = オプションの格納場所
428 	 *
429 	 * Returns: 正常にloadできたかどうか
430 	 */
431 	nothrow @nogc
432 	bool load_config(const ref wchar[npp_api.pluginfunc.config_file.setting_name_length] key_name, core.sys.windows.windef.INT invaild_value, ref core.sys.windows.windef.UINT result_value) const
433 
434 		in
435 		{
436 			assert(key_name[$ - 1] == '\0');
437 		}
438 
439 		do
440 		{
441 			core.sys.windows.windef.UINT temp_value = core.sys.windows.winbase.GetPrivateProfileIntW(&(this.section_name[0]), &(key_name[0]), invaild_value, &(this.config_file[0]));
442 
443 			if (temp_value == invaild_value) {
444 				return false;
445 			}
446 
447 			result_value = temp_value;
448 
449 			return true;
450 		}
451 
452 	/**
453 	 * ???
454 	 *
455 	 * Params:
456 	 *      key_name = ???
457 	 *      invaild_value = ???
458 	 *      result_value = オプションの格納場所
459 	 *
460 	 * Returns: 正常にloadできたかどうか
461 	 */
462 	nothrow @nogc
463 	bool load_config(const ref wchar[npp_api.pluginfunc.config_file.setting_name_length] key_name, core.sys.windows.windef.INT invaild_value, ref int result_value) const
464 
465 		in
466 		{
467 			assert(key_name[$ - 1] == '\0');
468 		}
469 
470 		do
471 		{
472 			core.sys.windows.windef.UINT temp_value = core.sys.windows.winbase.GetPrivateProfileIntW(&(this.section_name[0]), &(key_name[0]), invaild_value, &(this.config_file[0]));
473 
474 			if (temp_value == invaild_value) {
475 				return false;
476 			}
477 
478 			result_value = cast(int)(temp_value);
479 
480 			return true;
481 		}
482 
483 	/**
484 	 * ???
485 	 *
486 	 * Params:
487 	 *      key_name = ???
488 	 *      invaild_value = ???
489 	 *      result_value = オプションの格納場所
490 	 *
491 	 * Returns: 正常にloadできたかどうか
492 	 */
493 	pragma(inline, true)
494 	nothrow @nogc
495 	bool load_config(size_t value_length)(const ref wchar[npp_api.pluginfunc.config_file.setting_name_length] key_name, ref wchar[value_length] result_value) const
496 
497 		in
498 		{
499 			assert(key_name[$ - 1] == '\0');
500 		}
501 
502 		do
503 		{
504 			core.sys.windows.windef.DWORD result_temp = core.sys.windows.winbase.GetPrivateProfileStringW(&(this.section_name[0]), &(key_name[0]), &("\0"w[0]), &(result_value[0]), result_value.length, &(this.config_file[0]));
505 
506 			if ((result_temp == 0) || (result_value[0] == '\0')) {
507 				return false;
508 			}
509 
510 			return true;
511 		}
512 
513 	/**
514 	 * ???
515 	 *
516 	 * Params:
517 	 *      key_name = ???
518 	 *      result_value = オプションの格納場所
519 	 *
520 	 * Returns: 正常にloadできたかどうか
521 	 */
522 	pragma(inline, true)
523 	bool load_config(C)(const (C)[] key_name, ref bool result_value) const
524 		if (std.traits.isSomeChar!(C))
525 
526 		in
527 		{
528 		}
529 
530 		do
531 		{
532 			core.sys.windows.windef.UINT temp_value = core.sys.windows.winbase.GetPrivateProfileIntW(&(this.section_name[0]), std.utf.toUTF16z(key_name), int.max, &(this.config_file[0]));
533 
534 			switch (temp_value) {
535 				case 0:
536 					result_value = false;
537 
538 					return true;
539 
540 				case 1:
541 					result_value = true;
542 
543 					return true;
544 
545 				default:
546 					return false;
547 			}
548 		}
549 
550 	/**
551 	 * ???
552 	 *
553 	 * Params:
554 	 *      key_name = ???
555 	 *      invaild_value = ???
556 	 *      result_value = オプションの格納場所
557 	 *
558 	 * Returns: 正常にloadできたかどうか
559 	 */
560 	pragma(inline, true)
561 	bool load_config(C)(const (C)[] key_name, core.sys.windows.windef.INT invaild_value, ref core.sys.windows.windef.UINT result_value) const
562 		if (std.traits.isSomeChar!(C))
563 
564 		in
565 		{
566 		}
567 
568 		do
569 		{
570 			core.sys.windows.windef.UINT temp_value = core.sys.windows.winbase.GetPrivateProfileIntW(&(this.section_name[0]), std.utf.toUTF16z(key_name), invaild_value, &(this.config_file[0]));
571 
572 			if (temp_value == invaild_value) {
573 				return false;
574 			}
575 
576 			result_value = temp_value;
577 
578 			return true;
579 		}
580 
581 	/**
582 	 * ???
583 	 *
584 	 * Params:
585 	 *      key_name = ???
586 	 *      value = ???
587 	 *
588 	 * Returns: WritePrivateProfileStringWの結果
589 	 */
590 	pragma(inline, true)
591 	nothrow @nogc
592 	bool write_config(size_t value_length)(const ref wchar[npp_api.pluginfunc.config_file.setting_name_length] key_name, bool value) const
593 
594 		in
595 		{
596 			assert(key_name[$ - 1] == '\0');
597 		}
598 
599 		do
600 		{
601 			return (core.sys.windows.winbase.WritePrivateProfileStringW(&(this.section_name[0]), &(key_name[0]), &(((value) ? (npp_api.pluginfunc..string.c_wstring!(`1`w)) : (npp_api.pluginfunc..string.c_wstring!(`0`w)))[0]), &(this.config_file[0])) != 0) ? (true) : (false);
602 		}
603 
604 	/**
605 	 * ???
606 	 *
607 	 * Params:
608 	 *      key_name = ???
609 	 *      value = ???
610 	 *
611 	 * Returns: 正常にwriteできたかどうか
612 	 */
613 	pragma(inline, true)
614 	nothrow
615 	bool write_config(size_t value_length, D)(const ref wchar[npp_api.pluginfunc.config_file.setting_name_length] key_name, const D value) const
616 		if (std.traits.isNumeric!(D))
617 
618 		in
619 		{
620 			assert(key_name[$ - 1] == '\0');
621 		}
622 
623 		do
624 		{
625 			return (core.sys.windows.winbase.WritePrivateProfileStringW(&(this.section_name[0]), &(key_name[0]), std.utf.toUTF16z(std.conv.to!(wstring)(value)), &(this.config_file[0])) != 0) ? (true) : (false);
626 		}
627 
628 	/**
629 	 * ???
630 	 *
631 	 * Params:
632 	 *      key_name = ???
633 	 *      value = ???
634 	 *
635 	 * Returns: 正常にwriteできたかどうか
636 	 */
637 	pragma(inline, true)
638 	nothrow
639 	bool write_config(size_t value_length)(const ref wchar[npp_api.pluginfunc.config_file.setting_name_length] key_name, const wchar[] value) const
640 
641 		in
642 		{
643 			assert(key_name[$ - 1] == '\0');
644 		}
645 
646 		do
647 		{
648 
649 			return (core.sys.windows.winbase.WritePrivateProfileStringW(&(this.section_name[0]), &(key_name[0]), (value.length != 0) ? (std.utf.toUTF16z(value)) : (core.sys.windows.windef.NULL), &(this.config_file[0])) != 0) ? (true) : (false);
650 		}
651 
652 	/**
653 	 * ???
654 	 *
655 	 * Params:
656 	 *      key_name = ???
657 	 *      value = ???
658 	 *
659 	 * Returns: WritePrivateProfileStringWの結果
660 	 */
661 	pragma(inline, true)
662 	bool write_config(C)(const (C)[] key_name, bool value) const
663 		if (std.traits.isSomeChar!(C))
664 
665 		in
666 		{
667 			assert(key_name.length != 0);
668 		}
669 
670 		do
671 		{
672 			return (core.sys.windows.winbase.WritePrivateProfileStringW(&(this.section_name[0]), std.utf.toUTF16z(key_name), &(((value) ? (npp_api.pluginfunc..string.c_wstring!(`1`w)) : (npp_api.pluginfunc..string.c_wstring!(`0`w)))[0]), &(this.config_file[0])) != 0) ? (true) : (false);
673 		}
674 
675 	/**
676 	 * ???
677 	 *
678 	 * Params:
679 	 *      key_name = ???
680 	 *      value = ???
681 	 *
682 	 * Returns: 正常にwriteできたかどうか
683 	 */
684 	pragma(inline, true)
685 	bool write_config(C, D)(const (C)[] key_name, const D value) const
686 		if (std.traits.isSomeChar!(C) && std.traits.isNumeric!(D))
687 
688 		in
689 		{
690 		}
691 
692 		do
693 		{
694 			return (core.sys.windows.winbase.WritePrivateProfileStringW(&(this.section_name[0]), std.utf.toUTF16z(key_name), std.utf.toUTF16z(std.conv.to!(wstring)(value)), &(this.config_file[0])) != 0) ? (true) : (false);
695 		}
696 
697 	/**
698 	 * ???
699 	 *
700 	 * Params:
701 	 *      key_name = ???
702 	 *      value = ???
703 	 *
704 	 * Returns: 正常にwriteできたかどうか
705 	 */
706 	bool write_config(C)(const (C)[] key_name, const (C)[] value) const
707 		if (std.traits.isSomeChar!(C))
708 
709 		in
710 		{
711 		}
712 
713 		do
714 		{
715 			if (value.length == 0) {
716 				return (core.sys.windows.winbase.WritePrivateProfileStringW(&(this.section_name[0]), std.utf.toUTF16z(key_name), core.sys.windows.windef.NULL, &(this.config_file[0])) != 0) ? (true) : (false);
717 			} else {
718 				return (core.sys.windows.winbase.WritePrivateProfileStringW(&(this.section_name[0]), std.utf.toUTF16z(key_name), std.utf.toUTF16z(value), &(this.config_file[0])) != 0) ? (true) : (false);
719 			}
720 		}
721 
722 	/**
723 	 * ???
724 	 *
725 	 * Params:
726 	 *      ??? = ???
727 	 */
728 	void write_config(C)(const (C)[] key_name, const npp_api.PowerEditor.MISC.PluginsManager.PluginInterface.FuncItem func_item) const
729 		if (std.traits.isSomeChar!(C))
730 
731 		do
732 		{
733 			this.write_config(key_name, func_item._init2Check);
734 		}
735 
736 	pragma(inline, true)
737 	pure nothrow @safe
738 	wstring get_config_file_path() const
739 
740 		do
741 		{
742 			return this.config_file.idup;
743 		}
744 
745 	pragma(inline, true)
746 	pure nothrow @safe
747 	wstring get_config_folder_path() const
748 
749 		do
750 		{
751 			return this.plugin_config_path.idup;
752 		}
753 
754 	/**
755 	 * 
756 	 */
757 	void mkdir(const wchar[] sub_directry = ``w)
758 
759 		in
760 		{
761 			if (sub_directry.length != 0) {
762 				assert(std.path.isValidPath(sub_directry));
763 			}
764 		}
765 
766 		do
767 		{
768 			wstring path = std.path.buildPath(this.plugin_config_path, sub_directry);
769 
770 			if (!std.file.exists(path) && !std.file.isDir(path)) {
771 				std.file.mkdir(path);
772 			}
773 		}
774 
775 	invariant
776 	{
777 		assert((this.section_name.length != 0) && (this.section_name[$ - 1] == '\0'));
778 		assert((this.config_file.length != 0));
779 	}
780 }