1 module unde.file_manager.find_path; 2 3 import unde.global_state; 4 import unde.lib; 5 import unde.lsblk; 6 import unde.path_mnt; 7 import unde.slash; 8 9 import berkeleydb.all; 10 11 import std.stdio; 12 import std..string; 13 14 import std.file; 15 16 version (Windows) 17 { 18 import unde.scan; 19 } 20 21 enum unDE_Path_Finder_Flags { 22 Go_Up, 23 Go_Down, 24 Out, 25 Try_Other_Directory 26 } 27 28 private unDE_Path_Finder_Flags 29 what_to_do_with_path_by_rectangle(GlobalState gs, 30 in ref DRect surf_rect, in ref RectSize rectsize, 31 in PathMnt path, DRect apply_rect, in SortType sort, 32 in int level = 0) 33 { 34 if (level == 0) 35 { 36 if (rectsize.rect(sort).In(surf_rect)) 37 { 38 if (path > gs.main_path) 39 { 40 if (gs.path != SL) 41 { 42 return unDE_Path_Finder_Flags.Go_Up; 43 } 44 else 45 { 46 return unDE_Path_Finder_Flags.Try_Other_Directory; 47 } 48 } 49 } 50 } 51 52 /*writefln("!%s", path); 53 writefln("R %s, %s, %s, %s", rectsize.rect(sort).x, 54 rectsize.rect(sort).x+rectsize.rect(sort).w, 55 rectsize.rect(sort).y, 56 rectsize.rect(sort).y+rectsize.rect(sort).h); 57 writefln("S %s, %s, %s, %s", surf_rect.x, surf_rect.x+surf_rect.w, 58 surf_rect.y, surf_rect.y+surf_rect.h);*/ 59 60 if (surf_rect.In(rectsize.rect(sort))) 61 { 62 gs.path = path; 63 gs.apply_rect = apply_rect; 64 gs.sort = sort; 65 //writefln("path=%s, apply_rect=%s, sort=%s", 66 // gs.path, gs.apply_rect, gs.sort); 67 } 68 69 //writefln("rectsize=%s, surf_rect=%s", rectsize.rect(sort), surf_rect); 70 if (rectsize.rect(sort).In(surf_rect)) 71 return unDE_Path_Finder_Flags.Out; 72 73 if (rectsize.rect(sort).NotIntersect(surf_rect)) 74 return unDE_Path_Finder_Flags.Try_Other_Directory; 75 76 return unDE_Path_Finder_Flags.Go_Down; 77 } 78 79 version(Windows) 80 { 81 public DRect 82 get_drect_of_drives(GlobalState gs, string drive) 83 { 84 DRect full_rect = DRect(0, 0, 1024*1024, 1024*1024); 85 RectSize rectsize = RectSize(full_rect, full_rect, full_rect); 86 87 int ret = 0; 88 89 string[] paths; 90 91 foreach(char c; 'A'..'Z'+1) 92 { 93 string disk = c ~ ":"; 94 if ( disk in gs.lsblk ) 95 { 96 paths ~= disk; 97 } 98 } 99 100 int levels = 0; 101 long l = paths.length; 102 /*if (l > 0) 103 { 104 l--; 105 }*/ 106 for (long i=12; i < l; i=i*2+12) 107 { 108 l -= i; 109 levels++; 110 } 111 if (l > 0) levels++; 112 113 immutable long entries_on_last_level = l; 114 115 //RectSize[string] rect_sizes; 116 117 //writefln("levels = %s", levels); 118 long[] coords = new long[levels+1]; 119 long i = 0; 120 size_t lev = 1; 121 bool first = true; 122 foreach (string name; paths) 123 { 124 DRect rect; 125 calculate_rect(full_rect, rect, coords, lev); 126 127 if (name == drive) return rect; 128 129 calculate_coords(coords, lev, i, levels, entries_on_last_level); 130 first = false; 131 } 132 133 return full_rect; 134 } 135 } 136 137 /* EN: This function make selection of directory by surface rectangle 138 So gs.path must specify the most deep directory which still 139 include surface rectangle. 140 141 RU: Эта функция выбирает директорию в соответствии с прямоугольником, 142 который занимает surface. После выполнения этой функции gs.path 143 должен указывать на самую глубокую директорию которая ещё включает 144 прямоугольник surface. 145 */ 146 unDE_Path_Finder_Flags 147 find_path(GlobalState gs, DbTxn txn, CoordinatesPlusScale surf, PathMnt path, 148 DRect apply_rect, SortType sort = SortType.ByName, 149 in int level = 0) 150 { 151 DRect surf_rect = surf.getRect(); 152 153 go_up: 154 bool up = false; 155 Dbt key, data; 156 157 DirEntry de; 158 try 159 { 160 de = DirEntry(path); 161 } 162 catch (FileException e) 163 { 164 return unDE_Path_Finder_Flags.Try_Other_Directory; 165 } 166 167 if (path in gs.lsblk) 168 { 169 string path0 = path.get_key(gs.lsblk); 170 key = path0; 171 auto res = gs.db_map.get(txn, &key, &data); 172 if (res == 0) 173 { 174 RectSize rectsize; 175 rectsize = data.to!(RectSize); 176 apply_rect = rectsize.rect(sort).apply(apply_rect); 177 } 178 else 179 { 180 version(Windows) 181 { 182 if (path.length == 2) 183 { 184 DRect rect = get_drect_of_drives(gs, path); 185 apply_rect = rect.apply(apply_rect); 186 } 187 } 188 189 { 190 // TODO: Created mount point, rescan up path 191 } 192 } 193 } 194 195 try 196 { 197 path.update(gs.lsblk); 198 } 199 catch (Exception e) 200 { 201 return unDE_Path_Finder_Flags.Out; 202 } 203 204 string path0 = path.get_key(gs.lsblk); 205 key = path0; 206 auto res = gs.db_map.get(txn, &key, &data); 207 version(Windows) 208 { 209 if (path == SL) res = 0; 210 } 211 212 if (res == 0) 213 { 214 up = false; 215 RectSize rectsize; 216 version(Windows) 217 { 218 if (path == SL) 219 { 220 DRect full_rect = DRect(0, 0, 1024*1024, 1024*1024); 221 rectsize = RectSize(full_rect, full_rect, full_rect); 222 } 223 else 224 rectsize = data.to!(RectSize); 225 } 226 else 227 { 228 rectsize = data.to!(RectSize); 229 } 230 rectsize.rect(sort) = rectsize.rect(sort).apply(apply_rect); 231 auto wtdwpbr = what_to_do_with_path_by_rectangle(gs, surf_rect, 232 rectsize, path, apply_rect, sort, level); 233 //writefln("%s - %s", path, wtdwpbr); 234 final switch (wtdwpbr) 235 { 236 case unDE_Path_Finder_Flags.Go_Up: 237 path = gs.path = PathMnt(SL); 238 apply_rect = gs.apply_rect = DRect(0, 0, 1024*1024, 1024*1024); 239 gs.sort = SortType.ByName; 240 goto go_up; 241 242 case unDE_Path_Finder_Flags.Go_Down: 243 if (!de.isSymlink && de.isDir) 244 { 245 string[] paths; 246 247 try 248 { 249 //writefln("Go Down?"); 250 bool done = false; 251 version(Windows) 252 { 253 if (path == SL) 254 { 255 //writefln("This way?"); 256 foreach(char c; 'A'..'Z'+1) 257 { 258 string name = c ~ ":"; 259 if ( name in gs.lsblk ) 260 { 261 auto r = find_path(gs, txn, surf, path.next(name), 262 rectsize.rect(sort), rectsize.sort, level+1); 263 if (r == unDE_Path_Finder_Flags.Out) return r; 264 } 265 } 266 done = true; 267 } 268 } 269 270 if (!done) 271 { 272 //writefln("This way!"); 273 foreach (string name; 274 dirEntries(path, SpanMode.shallow)) 275 { 276 auto r = find_path(gs, txn, surf, path.next(name), 277 rectsize.rect(sort), rectsize.sort, level+1); 278 if (r == unDE_Path_Finder_Flags.Out) return r; 279 } 280 } 281 } catch (FileException e) 282 { 283 } 284 } 285 break; 286 287 case unDE_Path_Finder_Flags.Out: 288 if (level == 0 && path != SL) 289 goto case unDE_Path_Finder_Flags.Go_Up; 290 return unDE_Path_Finder_Flags.Out; 291 292 case unDE_Path_Finder_Flags.Try_Other_Directory: 293 if (level == 0 && path != SL) 294 goto case unDE_Path_Finder_Flags.Go_Up; 295 return unDE_Path_Finder_Flags.Try_Other_Directory; 296 } 297 } 298 else 299 { 300 //throw new Exception("No " ~ path ~ " entry"); 301 } 302 303 return unDE_Path_Finder_Flags.Try_Other_Directory; 304 }