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 pure nothrow @safe 117 private immutable (C)[][] create_variable_identifiers(C)(const C[][] input) 118 119 do 120 { 121 immutable (C)[][] output = new immutable (C)[][input.length]; 122 123 for (size_t i = 0; i < input.length; i++) { 124 output[i] = ('%' ~ input[i] ~ '%').idup; 125 } 126 127 return output; 128 } 129 130 enum wstring[] windows_variable_names = 131 [ 132 `ALLUSERSPROFILE`w, 133 `APPDATA`w, 134 `CommonProgramFiles`w, 135 `CommonProgramFiles(x86)`w, 136 `CommonProgramW6432`w, 137 `COMPUTERNAME`w, 138 `ComSpec`w, 139 `DriverData`w, 140 `HOMEDRIVE`w, 141 `HOMEPATH`w, 142 `LOCALAPPDATA`w, 143 `LOGONSERVER`w, 144 `NUMBER_OF_PROCESSORS`w, 145 `OneDrive`w, 146 `OS`w, 147 `Path`w, 148 `PATHEXT`w, 149 `PROCESSOR_ARCHITECTURE`w, 150 `PROCESSOR_ARCHITEW6432`w, 151 `PROCESSOR_IDENTIFIER`w, 152 `PROCESSOR_LEVEL`w, 153 `PROCESSOR_REVISION`w, 154 `ProgramData`w, 155 `ProgramFiles`w, 156 `ProgramFiles(x86)`w, 157 `ProgramW6432`w, 158 `PROMPT`w, 159 `PSModulePath`w, 160 `PUBLIC`w, 161 `SESSIONNAME`w, 162 `SystemDrive`w, 163 `SystemRoot`w, 164 `TEMP`w, 165 `TMP`w, 166 `USERDOMAIN`w, 167 `USERDOMAIN_ROAMINGPROFILE`w, 168 `USERNAME`w, 169 `USERPROFILE`w, 170 `windir`w, 171 ]; 172 173 enum wstring[] windows_variable_wnames = c_names!(wchar)(windows_variable_names); 174 enum wstring[] windows_variables = create_variable_identifiers!(wchar)(windows_variable_names); 175 176 pure nothrow @safe @nogc 177 private size_t max_length(wstring[] list) 178 179 do 180 { 181 size_t max_length = 0; 182 183 for (size_t i = 0; i < list.length; i++) { 184 if (list[i].length > max_length) { 185 max_length = list[i].length; 186 } 187 } 188 189 return max_length; 190 } 191 192 nothrow 193 wstring echo_variables(wstring name) 194 195 do 196 { 197 static import core.sys.windows.winbase; 198 static import std.algorithm; 199 static import std.array; 200 static import npp_api.pluginfunc.string; 201 202 enum buf_length = max_length(windows_variable_names) + 1; 203 204 core.sys.windows.winnt.WCHAR[buf_length] name_buf = '\0'; 205 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] buf = '\0'; 206 207 if (name.length > buf_length) { 208 return null; 209 } 210 211 npp_api.pluginfunc..string.copy_string(name_buf, name); 212 213 core.sys.windows.windef.DWORD Environment_length = core.sys.windows.winbase.GetEnvironmentVariableW(&(name_buf[0]), &(buf[0]), buf.length); 214 215 if (Environment_length == 0) { 216 return null; 217 } 218 219 return buf[0 .. Environment_length].idup; 220 } 221 222 nothrow 223 wstring repalce_variables(wstring path) 224 225 do 226 { 227 static import core.sys.windows.winbase; 228 static import std.algorithm; 229 static import std.array; 230 static import npp_api.pluginfunc.string; 231 232 if (path == null) { 233 return path; 234 } 235 236 try { 237 if (!std.algorithm.canFind(path, '%')) { 238 return path; 239 } 240 } catch (Exception e) { 241 //ToDo: 242 return path; 243 } 244 245 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] buf = '\0'; 246 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] output_buf = '\0'; 247 248 for (size_t i = 0; i < windows_variable_wnames.length; i++) { 249 try { 250 if (!std.algorithm.canFind(path, windows_variables[i])) { 251 continue; 252 } 253 } catch (Exception e) { 254 //ToDo: 255 continue; 256 } 257 258 core.sys.windows.windef.DWORD Environment_length = core.sys.windows.winbase.GetEnvironmentVariableW(&(windows_variable_wnames[i][0]), &(buf[0]), buf.length); 259 260 if (Environment_length == 0) { 261 continue; 262 } 263 264 path = std.array.replace(path, windows_variables[i], buf[0 .. Environment_length]).idup; 265 } 266 267 return path; 268 } 269 270 /** 271 * search exe file from "PATH" 272 */ 273 nothrow 274 wstring search_exe(const wchar[] exe_name, wstring default_name = null) 275 276 in 277 { 278 assert(exe_name.length != 0); 279 280 for (size_t i = 0; i < exe_name.length; i++) { 281 assert(exe_name[i] != '\\'); 282 } 283 } 284 285 do 286 { 287 static import core.sys.windows.winnt; 288 static import core.sys.windows.winbase; 289 static import std.array; 290 static import std.file; 291 static import std.string; 292 static import std.path; 293 static import npp_api.pluginfunc.string; 294 295 //dlang GC Bug? 296 version (none) { 297 //ToDo: インストールされたものの中から検索 298 try { 299 core.sys.windows.winnt.WCHAR[.OS_MAX_PATH] buf = '\0'; 300 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); 301 302 if (Environment_length == 0) { 303 return (default_name != null) ? (default_name) : (exe_name.idup); 304 } 305 306 wstring[] PATH_directory = std.array.split(buf[0 .. Environment_length].idup, ';'); 307 308 foreach (PATH; PATH_directory) { 309 if ((!std.file.exists(PATH)) || (!std.file.isDir(PATH))) { 310 continue; 311 } 312 313 wstring file_exe = std.path.buildPath(PATH, exe_name); 314 315 if ((!std.file.exists(file_exe)) || (!std.file.isFile(file_exe))) { 316 continue; 317 } 318 319 return file_exe.idup; 320 } 321 } catch (Exception e) { 322 //ToDo: 323 } 324 325 return (default_name != null) ? (default_name) : (exe_name.idup); 326 } else { 327 return (default_name != null) ? (default_name) : (exe_name.idup); 328 } 329 } 330 331 //ToDo: dlang GC bug? 332 @disable 333 nothrow 334 string search_exe(const char[] exe_name, string default_name = null) 335 336 in 337 { 338 assert(exe_name.length != 0); 339 340 for (size_t i = 0; i < exe_name.length; i++) { 341 assert(exe_name[i] != '\\'); 342 } 343 } 344 345 do 346 { 347 static import std.array; 348 static import std.file; 349 static import std.string; 350 static import std.path; 351 static import std.process; 352 353 try { 354 string[] PATH_directory = std.array.split(std.process.environment[`PATH`], ';'); 355 356 foreach (PATH; PATH_directory) { 357 if ((!std.file.exists(PATH)) || (!std.file.isDir(PATH))) { 358 continue; 359 } 360 361 string file_exe = std.path.buildPath(PATH, exe_name); 362 363 if ((!std.file.exists(file_exe)) || (!std.file.isFile(file_exe))) { 364 continue; 365 } 366 367 return file_exe.idup; 368 } 369 } catch (Exception e) { 370 } 371 372 return (default_name != null) ? (default_name) : (exe_name.idup); 373 }