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 * npp menu 19 * 20 * Author: dokutoku, https://twitter.com/dokutoku3 21 * License: GPL-2.0 or later 22 */ 23 module npp_api.pluginfunc.path; 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 std.algorithm; 33 private static import std.array; 34 private static import std.file; 35 private static import std.string; 36 private static import std.path; 37 private static import std.process; 38 private static import npp_api.powereditor.misc.pluginsmanager.plugininterface; 39 private static import npp_api.pluginfunc.npp_msgs; 40 private static import npp_api.pluginfunc.string; 41 private static import std.process; 42 43 enum OS_MAX_PATH = 32768; 44 45 /** 46 * get file path 47 */ 48 nothrow @nogc 49 bool get_full_current_path(core.sys.windows.windef.HWND _nppHandle, ref core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] path_temp) 50 51 do 52 { 53 static import core.sys.windows.windef; 54 static import npp_api.powereditor.misc.pluginsmanager.plugininterface; 55 static import npp_api.pluginfunc.npp_msgs; 56 57 path_temp[] = '\0'; 58 59 if (npp_api.pluginfunc.npp_msgs.send_NPPM_GETFULLCURRENTPATH(_nppHandle, .OS_MAX_PATH, &(path_temp[0])) == core.sys.windows.windef.TRUE) { 60 return true; 61 } else { 62 return false; 63 } 64 } 65 66 nothrow 67 wstring get_file_path(core.sys.windows.windef.HWND _nppHandle) 68 69 do 70 { 71 static import core.sys.windows.winnt; 72 static import npp_api.pluginfunc.string; 73 74 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] path_temp; 75 76 if (.get_full_current_path(_nppHandle, path_temp)) { 77 return npp_api.pluginfunc..string.from_stringz(path_temp); 78 } else { 79 return null; 80 } 81 } 82 83 nothrow 84 wstring get_directory_path(core.sys.windows.windef.HWND _nppHandle) 85 86 do 87 { 88 static import core.sys.windows.windef; 89 static import core.sys.windows.winnt; 90 static import npp_api.pluginfunc.string; 91 static import npp_api.pluginfunc.npp_msgs; 92 93 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] path_temp; 94 95 if (npp_api.pluginfunc.npp_msgs.send_NPPM_GETCURRENTDIRECTORY(_nppHandle, .OS_MAX_PATH, &(path_temp[0])) == core.sys.windows.windef.TRUE) { 96 return npp_api.pluginfunc..string.from_stringz(path_temp); 97 } else { 98 return null; 99 } 100 } 101 102 pure nothrow @safe 103 private immutable (C)[][] c_names(C)(const C[][] input) 104 105 do 106 { 107 immutable (C)[][] output = new immutable (C)[][input.length]; 108 109 for (size_t i = 0; i < input.length; i++) { 110 output[i] = (input[i] ~ '\0').idup; 111 } 112 113 return output; 114 } 115 116 deprecated 117 alias create_variable_identifiers = .create_variable_ids; 118 119 pure nothrow @safe 120 private immutable (C)[][] create_variable_ids(C)(const C[][] input) 121 122 do 123 { 124 immutable (C)[][] output = new immutable (C)[][input.length]; 125 126 for (size_t i = 0; i < input.length; i++) { 127 output[i] = ('%' ~ input[i] ~ '%').idup; 128 } 129 130 return output; 131 } 132 133 enum wstring[] windows_variable_names = 134 [ 135 `ALLUSERSPROFILE`w, 136 `APPDATA`w, 137 `CommonProgramFiles`w, 138 `CommonProgramFiles(x86)`w, 139 `CommonProgramW6432`w, 140 `COMPUTERNAME`w, 141 `ComSpec`w, 142 `DriverData`w, 143 `HOMEDRIVE`w, 144 `HOMEPATH`w, 145 `LOCALAPPDATA`w, 146 `LOGONSERVER`w, 147 `NUMBER_OF_PROCESSORS`w, 148 `OneDrive`w, 149 `OS`w, 150 `Path`w, 151 `PATHEXT`w, 152 `PROCESSOR_ARCHITECTURE`w, 153 `PROCESSOR_ARCHITEW6432`w, 154 `PROCESSOR_IDENTIFIER`w, 155 `PROCESSOR_LEVEL`w, 156 `PROCESSOR_REVISION`w, 157 `ProgramData`w, 158 `ProgramFiles`w, 159 `ProgramFiles(x86)`w, 160 `ProgramW6432`w, 161 `PROMPT`w, 162 `PSModulePath`w, 163 `PUBLIC`w, 164 `SESSIONNAME`w, 165 `SystemDrive`w, 166 `SystemRoot`w, 167 `TEMP`w, 168 `TMP`w, 169 `USERDOMAIN`w, 170 `USERDOMAIN_ROAMINGPROFILE`w, 171 `USERNAME`w, 172 `USERPROFILE`w, 173 `windir`w, 174 ]; 175 176 enum wstring[] windows_variable_wnames = c_names!(wchar)(windows_variable_names); 177 enum wstring[] windows_variables = create_variable_ids!(wchar)(windows_variable_names); 178 179 pure nothrow @safe @nogc 180 private size_t max_length(wstring[] list) 181 182 do 183 { 184 size_t max_length = 0; 185 186 for (size_t i = 0; i < list.length; i++) { 187 if (list[i].length > max_length) { 188 max_length = list[i].length; 189 } 190 } 191 192 return max_length; 193 } 194 195 nothrow 196 wstring echo_variables(wstring name) 197 198 do 199 { 200 static import core.sys.windows.winbase; 201 static import std.algorithm; 202 static import std.array; 203 static import npp_api.pluginfunc.string; 204 205 enum buf_length = max_length(windows_variable_names) + 1; 206 207 core.sys.windows.winnt.WCHAR[buf_length] name_buf = '\0'; 208 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] buf = '\0'; 209 210 if (name.length > buf_length) { 211 return null; 212 } 213 214 npp_api.pluginfunc..string.copy_string(name_buf, name); 215 216 core.sys.windows.windef.DWORD Environment_length = core.sys.windows.winbase.GetEnvironmentVariableW(&(name_buf[0]), &(buf[0]), buf.length); 217 218 if (Environment_length == 0) { 219 return null; 220 } 221 222 return buf[0 .. Environment_length].idup; 223 } 224 225 nothrow 226 wstring repalce_variables(wstring path) 227 228 do 229 { 230 static import core.sys.windows.winbase; 231 static import std.algorithm; 232 static import std.array; 233 static import npp_api.pluginfunc.string; 234 235 if (path == null) { 236 return path; 237 } 238 239 try { 240 if (!std.algorithm.canFind(path, '%')) { 241 return path; 242 } 243 } catch (Exception e) { 244 //ToDo: 245 return path; 246 } 247 248 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] buf = '\0'; 249 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] output_buf = '\0'; 250 251 for (size_t i = 0; i < windows_variable_wnames.length; i++) { 252 try { 253 if (!std.algorithm.canFind(path, windows_variables[i])) { 254 continue; 255 } 256 } catch (Exception e) { 257 //ToDo: 258 continue; 259 } 260 261 core.sys.windows.windef.DWORD Environment_length = core.sys.windows.winbase.GetEnvironmentVariableW(&(windows_variable_wnames[i][0]), &(buf[0]), buf.length); 262 263 if (Environment_length == 0) { 264 continue; 265 } 266 267 path = std.array.replace(path, windows_variables[i], buf[0 .. Environment_length]).idup; 268 } 269 270 return path; 271 } 272 273 /** 274 * search exe file from "PATH" 275 */ 276 nothrow 277 wstring search_exe(const wchar[] exe_name, wstring default_name = null) 278 279 in 280 { 281 assert(exe_name.length != 0); 282 283 for (size_t i = 0; i < exe_name.length; i++) { 284 assert(exe_name[i] != '\\'); 285 } 286 } 287 288 do 289 { 290 static import core.sys.windows.winnt; 291 static import core.sys.windows.winbase; 292 static import std.array; 293 static import std.file; 294 static import std.string; 295 static import std.path; 296 static import npp_api.pluginfunc.string; 297 298 //dlang GC Bug? 299 version (none) { 300 //ToDo: インストールされたものの中から検索 301 try { 302 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] buf = '\0'; 303 core.sys.windows.windef.DWORD Environment_length = core.sys.windows.winbase.GetEnvironmentVariableW(&(npp_api.pluginfunc..string.c_wstring!(`PATH`w)[0]), &(buf[0]), buf.length); 304 305 if (Environment_length == 0) { 306 return (default_name != null) ? (default_name) : (exe_name.idup); 307 } 308 309 wstring[] PATH_directory = std.array.split(buf[0 .. Environment_length].idup, ';'); 310 311 foreach (PATH; PATH_directory) { 312 if ((!std.file.exists(PATH)) || (!std.file.isDir(PATH))) { 313 continue; 314 } 315 316 wstring file_exe = std.path.buildPath(PATH, exe_name); 317 318 if ((!std.file.exists(file_exe)) || (!std.file.isFile(file_exe))) { 319 continue; 320 } 321 322 return file_exe.idup; 323 } 324 } catch (Exception e) { 325 //ToDo: 326 } 327 328 return (default_name != null) ? (default_name) : (exe_name.idup); 329 } else { 330 return (default_name != null) ? (default_name) : (exe_name.idup); 331 } 332 } 333 334 //ToDo: dlang GC bug? 335 @disable 336 nothrow 337 string search_exe(const char[] exe_name, string default_name = null) 338 339 in 340 { 341 assert(exe_name.length != 0); 342 343 for (size_t i = 0; i < exe_name.length; i++) { 344 assert(exe_name[i] != '\\'); 345 } 346 } 347 348 do 349 { 350 static import std.array; 351 static import std.file; 352 static import std.string; 353 static import std.path; 354 static import std.process; 355 356 try { 357 string[] PATH_directory = std.array.split(std.process.environment[`PATH`], ';'); 358 359 foreach (PATH; PATH_directory) { 360 if ((!std.file.exists(PATH)) || (!std.file.isDir(PATH))) { 361 continue; 362 } 363 364 string file_exe = std.path.buildPath(PATH, exe_name); 365 366 if ((!std.file.exists(file_exe)) || (!std.file.isFile(file_exe))) { 367 continue; 368 } 369 370 return file_exe.idup; 371 } 372 } catch (Exception e) { 373 } 374 375 return (default_name != null) ? (default_name) : (exe_name.idup); 376 }