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 * プラグインの定義から自動的にインターフェイスをミックスインするためのもの 19 * 20 * Author: dokutoku, https://twitter.com/dokutoku3 21 * License: GPL-2.0 or later 22 */ 23 module npp_api.pluginfunc.extra_interfece; 24 25 26 version (Windows): 27 version (Not_betterC): 28 29 private static import core.sys.windows.windef; 30 private static import std.traits; 31 private static import npp_api.powereditor.misc.pluginsmanager.plugininterface; 32 private static import npp_api.pluginfunc.config_file; 33 private static import npp_api.pluginfunc.menu; 34 35 enum current_mixin_version = 0.001; 36 37 /** 38 * ToDo: 39 */ 40 struct npp_plugin_definition 41 { 42 static import npp_api.powereditor.misc.pluginsmanager.plugininterface; 43 static import npp_api.pluginfunc.config_file; 44 static import npp_api.pluginfunc.menu; 45 static import npp_api.pluginfunc.config_file; 46 47 //immutable string released = null; 48 49 float mixin_version = current_mixin_version; 50 51 npp_api.pluginfunc.config_file.config_type_t config_type = npp_api.pluginfunc.config_file.config_type_t.none; 52 53 /** 54 * Plugin name 55 */ 56 string name = null; 57 58 /** 59 * Plugin version 60 */ 61 float version_number = 0.001; 62 63 /** 64 * version version string 65 */ 66 string version_string = null; 67 68 /** 69 * Author name 70 */ 71 string author = null; 72 73 /** 74 * plugin config file info 75 */ 76 npp_api.pluginfunc.config_file.plugin_config_info config_info; 77 78 /** 79 * menu list 80 */ 81 npp_api.pluginfunc.menu.menu_item_t[] menu_items = null; 82 83 //ToDo: export? 84 85 invariant 86 { 87 } 88 } 89 90 mixin template npp_main_menu(npp_api.pluginfunc.menu.menu_item_t[] main_menu_items) 91 { 92 private static import npp_api.pluginfunc.menu; 93 94 static if (!__traits(compiles, .main_menu_def)) { 95 /* 96 * main menu 97 */ 98 enum npp_api.powereditor.misc.pluginsmanager.plugininterface.FuncItem[main_menu_items.length] main_menu_def = npp_api.pluginfunc.menu.create_main_menu!(main_menu_items.length)(main_menu_items); 99 npp_api.powereditor.misc.pluginsmanager.plugininterface.FuncItem[main_menu_items.length] main_menu = main_menu_def; 100 } 101 } 102 103 mixin template npp_menu_actions(npp_api.pluginfunc.menu.menu_item_t[] menu_container) 104 { 105 private static import npp_api.pluginfunc.menu; 106 107 static if (!__traits(compiles, .sub_menu_actions_def)) { 108 /* 109 * sub menu actions 110 */ 111 enum sub_menu_actions_def = npp_api.pluginfunc.menu.create_sub_menu_actions(menu_container); 112 static assert(sub_menu_actions_def.length == npp_api.pluginfunc.menu.count_sub_menu_ids(menu_container)); 113 npp_api.pluginfunc.menu.menu_action[sub_menu_actions_def.length] sub_menu_actions = .sub_menu_actions_def; 114 } 115 } 116 117 mixin template npp_menu_index(npp_api.pluginfunc.menu.menu_item_t[] menu_container) 118 { 119 private static import npp_api.pluginfunc.menu; 120 121 static if (!__traits(compiles, .menu_index_def)) { 122 /* 123 * 124 */ 125 enum menu_index_length = npp_api.pluginfunc.menu.count_all_menu_items(menu_container); 126 enum npp_api.pluginfunc.menu.sub_menu_index[menu_index_length] menu_index_def = npp_api.pluginfunc.menu.create_menu_index!(menu_index_length)(menu_container); 127 npp_api.pluginfunc.menu.sub_menu_index[menu_index_length] menu_index = .menu_index_def; 128 129 /* 130 * メニュー部分のインデックスを返す 131 */ 132 template search_menu_index(string id) 133 { 134 enum size_t search_menu_index = npp_api.pluginfunc.menu.search_menu_index(.menu_index_def, id); 135 } 136 137 template search_index(string id) 138 { 139 enum size_t search_index = npp_api.pluginfunc.menu.search_index(.menu_index_def, id); 140 static assert(menu_index_length >= search_index); 141 } 142 } 143 144 static assert(.menu_index_def.length == npp_api.pluginfunc.menu.count_all_menu_items(menu_container)); 145 } 146 147 mixin template npp_autoload(npp_api.pluginfunc.config_file.config_type_t config_type, npp_api.pluginfunc.config_file.setting_item[] settings) 148 { 149 private static import std.algorithm; 150 private static import npp_api.pluginfunc.config_file; 151 private static import npp_api.pluginfunc.ini_setting; 152 153 static if ((!__traits(compiles, .auto_settings)) && (settings.length != 0)) { 154 static if (config_type == npp_api.pluginfunc.config_file.config_type_t.ini) { 155 enum auto_settings_def = npp_api.pluginfunc.ini_setting.convert_setting!(settings.length)(settings); 156 npp_api.pluginfunc.ini_setting.ini_setting_item[settings.length] auto_settings = auto_settings_def; 157 enum wstring[] setting_ids = npp_api.pluginfunc.ini_setting.create_setting_idetifiers(auto_settings_def); 158 159 deprecated 160 alias setting_identifiers = .setting_ids; 161 162 deprecated 163 alias search_setting_identifier_index = .search_setting_id_index; 164 165 size_t search_setting_id_index(wstring[] id_list, wstring id) 166 167 do 168 { 169 for (size_t i = 0; i < id_list.length; i++) { 170 if (std.algorithm.cmp(id_list[i], id) == 0) { 171 return i; 172 } 173 } 174 175 assert(0); 176 } 177 178 deprecated 179 alias search_setting_identifier = .search_setting_id; 180 181 template search_setting_id(wstring id) 182 { 183 enum search_setting_id = search_setting_id_index(.setting_ids, id); 184 static assert(auto_settings_def.length > search_setting_id); 185 } 186 } else static if (config_type == npp_api.pluginfunc.config_file.config_type_t.none) { 187 } else { 188 static assert(false); 189 } 190 } 191 } 192 193 mixin template menu_checked_list(size_t main_menu_length, npp_api.pluginfunc.menu.sub_menu_index[] menu_index) 194 { 195 private static import npp_api.pluginfunc.menu; 196 197 static if (!__traits(compiles, .menu_index_checked_def)) { 198 deprecated 199 alias menu_index_checked_identifiers = .menu_index_checked_ids; 200 201 deprecated 202 alias main_menu_checked_identifiers = .main_menu_checked_ids; 203 204 enum wstring[] menu_index_checked_ids = npp_api.pluginfunc.menu.create_menu_index_checked_id(menu_index); 205 enum wstring[] main_menu_checked_ids = npp_api.pluginfunc.menu.create_main_menu_checked_id(menu_index); 206 } 207 } 208 209 /** 210 * menu_index_checkedからmain_menu_checkedへコピーする 211 */ 212 pure nothrow @safe @nogc 213 void update_main_menu_checked(size_t main_menu_length, size_t menu_index_length)(ref npp_api.powereditor.misc.pluginsmanager.plugininterface.FuncItem[main_menu_length] main_menu, const ref npp_api.pluginfunc.menu.sub_menu_index[menu_index_length] menu_index) 214 215 in 216 { 217 } 218 219 do 220 { 221 for (size_t i = 0, j = 0; i < menu_index.length; i++) { 222 if (menu_index[i].depth == 1) { 223 main_menu[j]._init2Check = menu_index[i].func_item._init2Check; 224 j++; 225 } 226 } 227 } 228 229 mixin template npp_plugin_config(npp_api.pluginfunc.config_file.config_type_t type) 230 { 231 static if (!__traits(compiles, .plugin_config_file)) { 232 static if (type == npp_api.pluginfunc.config_file.config_type_t.ini) { 233 npp_api.pluginfunc.ini_setting.npp_ini_session plugin_config_file; 234 } else static if (type == npp_api.pluginfunc.config_file.config_type_t.none) { 235 } else { 236 static assert(false); 237 } 238 } 239 } 240 241 mixin template npp_DLLMain(npp_api.pluginfunc.config_file.config_type_t type, wstring[] menu_index_checked_ids, alias menu_index) 242 { 243 private static import core.sys.windows.basetsd; 244 private static import core.sys.windows.dll; 245 private static import core.sys.windows.windef; 246 private static import core.sys.windows.winnt; 247 private static import npp_api.pluginfunc.config_file; 248 249 static if (!__traits(compiles, .DllMain)) { 250 pragma(mangle, "DllMain") 251 extern (Windows) 252 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) 253 254 do 255 { 256 static import core.sys.windows.dll; 257 static import core.sys.windows.windef; 258 static import core.sys.windows.winnt; 259 260 switch (reasonForCall) { 261 case core.sys.windows.winnt.DLL_PROCESS_ATTACH: 262 core.sys.windows.dll.dll_process_attach(hModule); 263 264 static if (__traits(compiles, .pluginInit)) { 265 .pluginInit(hModule); 266 } 267 268 break; 269 270 case core.sys.windows.winnt.DLL_PROCESS_DETACH: 271 static if ((type != npp_api.pluginfunc.config_file.config_type_t.none) && (menu_index_checked_ids.length != 0)) { 272 plugin_config_file.write_menu_checked(menu_index); 273 } 274 275 static if (__traits(compiles, .pluginCleanUp)) { 276 .pluginCleanUp(); 277 } 278 279 core.sys.windows.dll.dll_process_detach(hModule); 280 281 break; 282 283 case core.sys.windows.winnt.DLL_THREAD_ATTACH: 284 core.sys.windows.dll.dll_thread_attach(true, true); 285 286 break; 287 288 case core.sys.windows.winnt.DLL_THREAD_DETACH: 289 core.sys.windows.dll.dll_thread_detach(true, true); 290 291 break; 292 293 default: 294 break; 295 } 296 297 return core.sys.windows.windef.TRUE; 298 } 299 } 300 } 301 302 mixin template npp_setInfo(alias nppData, npp_api.pluginfunc.config_file.plugin_config_info config_info, alias plugin_config_file, alias auto_settings, alias main_menu, alias menu_index) 303 if (is(typeof(nppData) == npp_api.powereditor.misc.pluginsmanager.plugininterface.NppData) && std.traits.isStaticArray!(typeof(main_menu)) && std.traits.isStaticArray!(typeof(menu_index))) 304 { 305 private static import npp_api.powereditor.misc.pluginsmanager.plugininterface; 306 private static import npp_api.pluginfunc.extra_interfece; 307 private static import npp_api.pluginfunc.config_file; 308 309 static if (!__traits(compiles, .setInfo)) { 310 pragma(mangle, "setInfo") 311 extern (C) 312 nothrow 313 export void setInfo(npp_api.powereditor.misc.pluginsmanager.plugininterface.NppData notpadPlusData) 314 315 do 316 { 317 static import std.utf; 318 static import npp_api.pluginfunc.extra_interfece; 319 320 nppData = notpadPlusData; 321 322 static if (__traits(compiles, .gshared_nppData)) { 323 .gshared_nppData = notpadPlusData; 324 } 325 326 try { 327 static if (config_info.type != npp_api.pluginfunc.config_file.config_type_t.none) { 328 enum directory_name = std.utf.toUTF16(config_info.directory_name); 329 enum file_name = std.utf.toUTF16(config_info.file_name); 330 enum section_name = std.utf.toUTF16(config_info.ini_section_name); 331 plugin_config_file = npp_api.pluginfunc.ini_setting.npp_ini_session(nppData._nppHandle, directory_name, file_name, section_name); 332 333 static if (main_menu.length != 0) { 334 plugin_config_file.auto_load(auto_settings, menu_index); 335 } else { 336 plugin_config_file.auto_load(auto_settings); 337 } 338 } 339 340 static if (main_menu.length != 0) { 341 npp_api.pluginfunc.extra_interfece.update_main_menu_checked(main_menu, menu_index); 342 } 343 } catch (Exception e) { 344 //ToDo: 345 } 346 347 static if (__traits(compiles, .pluginSetInfo)) { 348 .pluginSetInfo(notpadPlusData); 349 } 350 } 351 } 352 } 353 354 mixin template npp_beNotified(alias nppData, alias main_menu, alias menu_index, alias menu_index_def, alias sub_menu_actions) 355 { 356 private static import std.traits; 357 private static import npp_api.scintilla.scintilla; 358 private static import npp_api.powereditor.misc.pluginsmanager.notepad_plus_msgs; 359 private static import npp_api.pluginfunc.menu; 360 361 static if (!__traits(compiles, .beNotified) && (npp_api.pluginfunc.menu.allocate_sub_menu_length(menu_index_def) != 0)) { 362 static if (__traits(compiles, .pluginBeNotified) && !std.traits.hasFunctionAttributes!(.pluginBeNotified, "@nogc")) { 363 pragma(mangle, "beNotified") 364 extern (C) 365 nothrow 366 export void beNotified(npp_api.scintilla.scintilla.SCNotification* notifyCode) 367 368 do 369 { 370 static import npp_api.powereditor.misc.pluginsmanager.notepad_plus_msgs; 371 static import npp_api.pluginfunc.menu; 372 373 /+ 374 if (notifyCode == null) { 375 return; 376 } 377 +/ 378 379 switch ((*notifyCode).nmhdr.code) { 380 case npp_api.powereditor.misc.pluginsmanager.notepad_plus_msgs.NPPN_TBMODIFICATION: 381 //init submenu 382 enum required = npp_api.pluginfunc.menu.allocate_sub_menu_length(menu_index_def); 383 npp_api.pluginfunc.menu.init_submenu(nppData._nppHandle, main_menu, menu_index, sub_menu_actions, required); 384 385 break; 386 387 default: 388 break; 389 } 390 391 .pluginBeNotified(*notifyCode); 392 } 393 } else { 394 pragma(mangle, "beNotified") 395 extern (C) 396 nothrow @nogc 397 export void beNotified(npp_api.scintilla.scintilla.SCNotification* notifyCode) 398 399 do 400 { 401 static import npp_api.powereditor.misc.pluginsmanager.notepad_plus_msgs; 402 static import npp_api.pluginfunc.menu; 403 404 /+ 405 if (notifyCode == null) { 406 return; 407 } 408 +/ 409 410 switch ((*notifyCode).nmhdr.code) { 411 case npp_api.powereditor.misc.pluginsmanager.notepad_plus_msgs.NPPN_TBMODIFICATION: 412 //init submenu 413 enum required = npp_api.pluginfunc.menu.allocate_sub_menu_length(menu_index_def); 414 npp_api.pluginfunc.menu.init_submenu(nppData._nppHandle, main_menu, menu_index, sub_menu_actions, required); 415 416 break; 417 418 default: 419 break; 420 } 421 422 static if (__traits(compiles, .pluginBeNotified)) { 423 .pluginBeNotified(*notifyCode); 424 } 425 } 426 } 427 } 428 } 429 430 mixin template npp_messageProc(alias sub_menu_actions_def) 431 if (std.traits.isArray!(typeof(sub_menu_actions_def))) 432 { 433 private static import core.sys.windows.windef; 434 private static import core.sys.windows.winuser; 435 private static import npp_api.pluginfunc.menu; 436 private static import npp_api.pluginfunc.basic_interface; 437 438 static if ((!__traits(compiles, .messageProc)) && (sub_menu_actions_def.length != 0)) { 439 pragma(mangle, "messageProc") 440 extern (C) 441 nothrow 442 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) 443 444 do 445 { 446 static import core.sys.windows.windef; 447 static import core.sys.windows.winuser; 448 static import npp_api.pluginfunc.menu; 449 static import npp_api.pluginfunc.basic_interface; 450 451 if (Message == core.sys.windows.winuser.WM_COMMAND) { 452 int id = core.sys.windows.windef.LOWORD(wParam); 453 454 if (npp_api.pluginfunc.menu.sub_menu_action(id, .sub_menu_actions)) { 455 return core.sys.windows.windef.TRUE; 456 } 457 } 458 459 static if (__traits(compiles, .pluginMessageProc)) { 460 if (pluginMessageProc(Message, wParam, lParam)) { 461 return core.sys.windows.windef.TRUE; 462 } else { 463 return core.sys.windows.windef.FALSE; 464 } 465 } else { 466 return core.sys.windows.windef.TRUE; 467 } 468 } 469 } 470 } 471 472 mixin template npp_plugin_interface(.npp_plugin_definition plugin_def) 473 { 474 private static import std.utf; 475 private static import npp_api.pluginfunc.basic; 476 private static import npp_api.pluginfunc.string; 477 private static import npp_api.pluginfunc.basic_interface; 478 private static import npp_api.pluginfunc.extra_interfece; 479 480 static assert(npp_api.pluginfunc.extra_interfece.current_mixin_version >= plugin_def.mixin_version); 481 enum plugin_name = npp_api.pluginfunc..string.c_wstring!(std.utf.toUTF16(plugin_def.name)).idup; 482 483 mixin npp_api.pluginfunc.basic_interface.npp_nppData!(); 484 mixin npp_api.pluginfunc.basic.plugin_messageBox!(plugin_name); 485 mixin npp_api.pluginfunc.extra_interfece.npp_menu_actions!(plugin_def.menu_items); 486 mixin npp_api.pluginfunc.extra_interfece.npp_main_menu!(plugin_def.menu_items); 487 mixin npp_api.pluginfunc.extra_interfece.npp_messageProc!(sub_menu_actions_def); 488 mixin npp_api.pluginfunc.extra_interfece.npp_menu_index!(plugin_def.menu_items); 489 mixin npp_api.pluginfunc.extra_interfece.npp_autoload!(plugin_def.config_info.type, plugin_def.config_info.settings); 490 mixin npp_api.pluginfunc.extra_interfece.menu_checked_list!(.main_menu.length, .menu_index_def); 491 mixin npp_api.pluginfunc.extra_interfece.npp_plugin_config!(plugin_def.config_info.type); 492 mixin npp_api.pluginfunc.extra_interfece.npp_DLLMain!(plugin_def.config_info.type, .menu_index_checked_ids, .menu_index); 493 494 //ToDo: 495 static if (__traits(compiles, .plugin_config_file) && __traits(compiles, .auto_settings)) { 496 mixin npp_api.pluginfunc.extra_interfece.npp_setInfo!(.nppData, plugin_def.config_info, .plugin_config_file, .auto_settings, .main_menu, .menu_index); 497 } 498 499 mixin npp_api.pluginfunc.extra_interfece.npp_beNotified!(.nppData, .main_menu, .menu_index, .menu_index_def, .sub_menu_actions); 500 mixin npp_api.pluginfunc.basic_interface.npp_plugin_interface!(plugin_name, main_menu_def); 501 mixin npp_api.pluginfunc.basic_interface.npp_plugin_interface!(); 502 }