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