X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?p=ede;a=blobdiff_plain;f=libede%2Fsrc%2FFileSystemBox.ec;h=8842cf1b965abf9a75025b71589d19e5445b0ccd;hp=f7bb89b7e9cdf19cc31696afcb43e31f7f7ea78c;hb=HEAD;hpb=869508b5dd2f1151768de7a389edb4a32a5d11ce diff --git a/libede/src/FileSystemBox.ec b/libede/src/FileSystemBox.ec index f7bb89b..8842cf1 100644 --- a/libede/src/FileSystemBox.ec +++ b/libede/src/FileSystemBox.ec @@ -1,17 +1,24 @@ public import "ecere" +import "FileSystemCache" #ifdef __WIN32__ static char * rootName = "Entire Computer"; -static char * msNetwork = "Microsoft Windows Network"; +static const char * msNetwork = "Microsoft Windows Network"; #else -static char * rootName = "File System"; +static const char * rootName = "File System"; #endif private: -define guiApp = ((GuiApplication)__thisModule); // how to do this in a dll? +define guiApp = (GuiApplication)((__thisModule).application); define selectionColor = guiApp.currentSkin.selectionColor; //Color { 10, 36, 106 }; -static char * fileIconNames[] = +void MessageBoxTodo(const char * message) +{ + PrintLn("MessageBoxTodo(char * message) -- ", message); + MessageBox { type = ok, text = "MessageBoxTodo(char * message)", contents = message }.Modal(); +} + +static const char * fileIconNames[] = { "<:ecere>mimeTypes/file.png", /* none */ @@ -46,26 +53,45 @@ static char * fileIconNames[] = "<:ecere>mimeTypes/package.png", /* treeLoader */ "<:ecere>places/startHere.png", /* lineNumbers */ - + + "" +}; + +define countOfCompIconNames = 6; +static const char * compIconNames[] = +{ +/* + "<:ede>a.png", + "<:ede>b.png", + "<:ede>c.png", + "<:ede>d.png", + "<:ede>not.png", +*/ + "<:ede>devices/media-optical.png", + "<:ede>devices/media-flash.png", + "<:ede>places/network-server.png", + "<:ede>places/folder-saved-search.png", + "<:ede>places/user-home.png", + "<:ede>emblem-not.png", "" }; public enum _FileType { none, - + normalFile, ewsFile, epjFile, ecFile, ehFile, cFile, hFile, cppFile, hppFile, textFile, webFile, pictureFile, soundFile, archiveFile, packageFile, opticalMediaImageFile, /* these (all previous) are sort equal */ - + folder, folderOpen, computer, drive, netDrive, cdrom, removable, floppy, network, server, share, // these are sort equal - + // utilities treeLoader, lineNumbers; - /*property char * + /*property char * { set { @@ -137,15 +163,28 @@ public enum _FileType } }; +public enum FileSystemBoxMode { directory, list }; + class FileSystemBoxBits { - bool foldersOnly:1, filesOnly:1, details:1, treeBranches:1, previewPictures:1, navigateFolders:1; + bool foldersOnly:1, filesOnly:1, details:1, pathColumn:1, treeBranches:1, previewPictures:1, navigateFolders:1, autoLoad:1; + bool preview:1; + bool columnsCompareStyle:1; //bool header:1, freeSelect:1, fullRowSelect:1, multiSelect:1, autoScroll:1, alwaysHL : 1, moveRows:1, resizable:1; //bool moveFields:1, clearHeader:1, alwaysEdit:1, collapse:1, treeBranch:1, rootCollapse:1, heightSet:1; //bool sortable:1, noDragging:1, fillLastField:1, expandOnAdd:1; -}; + bool textFileLinesStyle:1; + + FileSystemBoxMode mode:2; +} public class FileSystemBox : Window // should we not derive from ListBox instead? + // I say we should, but we can't right now... + // because ListBox (inside ecere library) is + // not exposing enough internal machinery... + // could we not have a different private and + // public mechanism when deriving a class than + // we do when simply instanciating a class? /* this stuff from the listbox would be nicely exposed... fullRowSelect = false; @@ -163,12 +202,18 @@ public class FileSystemBox : Window // should we not derive from ListBox instead public: FileSystemNode root; - FileSystemNode selection; + FileSystemBoxSelection selection { }; - virtual bool Window::NotifyNodeSelect(FileSystemBox box, FileSystemNode node); - virtual bool Window::NotifyNodeOpen(FileSystemBox box, FileSystemNode node); - - property char * path + subclass(InterfaceFileSystemIterator) iteratorClass; + FileSystemCache cache; + + virtual bool Window::NotifyNodeSelect(FileSystemBox box, FileSystemBoxSelection selection); + //virtual bool Window::NotifyNodeNavigate(FileSystemBox box, FileSystemNode node); + virtual bool Window::NotifyNodeOpen(FileSystemBox box, FileSystemBoxSelection selection); + virtual bool Window::NotifyNodeMenu(FileSystemBox box, Menu menu, FileSystemBoxSelection selection); + virtual bool Window::NotifyIteratorInit(FileSystemBox box, FileSystemIterator fileSystemIterator); + + property const char * path { set { @@ -180,16 +225,37 @@ public: if(created) Load(); } - get { return path; } //isset { return path && path[0]; } } + property Array comparedPaths + { + set + { + if(comparedPaths) + { + comparedPaths.Free(); + delete comparedPaths; + } + if(value && value.count) + comparedPaths = value; + if(locationBox) + locationBox.path = value[0]; + if(created) + Load(); + } + get { return comparedPaths; } + //isset { return comparedPaths && comparedPaths.count; } + } + + property FileSystemBoxMode mode { set { bits.mode = value; } get { return bits.mode; } }; property bool foldersOnly { set { bits.foldersOnly = value; bits.filesOnly = !value; } get { return bits.foldersOnly; } }; property bool filesOnly { set { bits.filesOnly = value; bits.foldersOnly = !value; } get { return bits.filesOnly; } }; property bool previewPictures { set { bits.previewPictures = value; } get { return bits.previewPictures; } }; property char * extensions { set { delete extensions; if(value && value[0]) extensions = CopyString(value); } get { return extensions; } } - property bool details { set { bits.details = value; } get { return bits.details; } }; + property bool details { set { bits.details = value; ChangeViewType(); } get { return bits.details; } }; + property bool pathColumn { set { bits.pathColumn = value; ChangeViewType(); } get { return bits.pathColumn; } }; property bool treeBranches { set @@ -201,8 +267,31 @@ public: } get { return bits.treeBranches; } }; + property Color selectionColor { set { list.selectionColor = value; } get { return list.selectionColor; }/* isset { return selectionColor ? true : false; }*/ }; + property Color selectionText { set { list.selectionText = value; } get { return list.selectionText; }/* isset { return selectionText ? true : false; }*/ }; property bool navigateFolders { set { bits.navigateFolders = value; bits.filesOnly = !value; } get { return bits.navigateFolders; } }; - + property bool multiSelect { set { list.multiSelect = value; } get { return list.multiSelect; } }; + property bool autoLoad { set { bits.autoLoad = value; } get { return bits.autoLoad; } }; + property bool hasHeader { set { list.hasHeader = value; } get { return list.hasHeader; } }; + property bool preview + { + set + { + bits.preview = value; + split.leftPane = value ? list : null; + split.visible = value; + show.visible = value; + if(!value) + { + list.parent = this; + list.anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; + } + } + get { return bits.preview; } + }; + property bool columnsCompareStyle { set { bits.columnsCompareStyle = value; } get { return bits.columnsCompareStyle; } }; + property bool textFileLinesStyle { set { bits.textFileLinesStyle = value; } get { return bits.textFileLinesStyle; } }; + property FileSystemNode node { get @@ -228,16 +317,106 @@ public: } } + void SelectMultipleByPath(Array paths) + { + DataRow row; + bool firstRow = false; + Map map { }; + for(path : paths) + map[path] = true; + for(row = list.firstRow; row; row = row.next) + { + FileSystemNode node = (FileSystemNode)row.tag; + if(map[node.path]) + { + if(!firstRow) + { + list.SelectRow(row); + firstRow = true; + } + else + row.selected = true; + } + else + row.selected = false; + } + delete map; + } + + FileSystemNode SelectLocation(const char * location) + { + int c; + char * temp; + char step[MAX_LOCATION]; + + //StringArray steps { growingFactor = 4 }; + Array steps { }; + FileSystemNode result = null; + FileSystemNode node = null; + + temp = CopyString(location); + while(temp[0]) + { + GetLastDirectory(temp, step); + StripLastDirectory(temp, temp); + steps.Add(CopyString(step)); + } + + for(c = steps.count - 1; c >= 0; c--) + { + //char * t = steps[c]; + node = Find(steps[c], node); + if(!node) + break; + //Select(node); + } + if(node) + { + result = node; + Select(result); + } + + steps.Free(); + delete temp; + delete steps; + + return result; + } + FileSystemNode Find(const char * name, FileSystemNode parent) { - FileSystemNode node; - FileSystemNode start = parent ? parent : root; - if(!start.loaded || !start.childrenLoaded) - LoadTreeNode(start); - for(node = start.children.first; node; node = node.next) - if(node.name && !strcmpi(node.name, name)) - return node; - return null; + FileSystemNode node = null; + FileSystemNode result = null; + if(!parent/* && !strcmp(name, "/")*/) + { + DataRow row; + for(row = list.firstRow; row; row = row.next) + { + node = (FileSystemNode)row.tag; + if(node.name && !fstrcmp(node.name, name)) + break; + } + if(node) + result = node; + //result = root; + } + else + { + FileSystemNode start = parent ? parent : root; + if(!start.bits.loaded || !start.bits.childrenLoaded) + LoadTreeNode(start); + for(node = start.children.first; node; node = node.next) + if(node.name && !fstrcmp(node.name, name)) + break; + if(node) + result = node; + } + return result; + } + + void Clear() + { + list.Clear(); } void Refresh() @@ -245,28 +424,88 @@ public: Load(); } + bool MenuOpen(MenuItem selection, Modifiers mods) + { + OpenNode(); + return true; + } + + bool MenuReplaceListItemByContainingDir(MenuItem selection, Modifiers mods) + { + bool result = true; + //FileSystemBoxSelection selection = this.selection.Copy(); // TOFIX compiler bug -- FileSystemBox.c -- ../libede/src/FileSystemBox.ec:420:49: error: ‘selection’ redeclared as different kind of symbol + FileSystemBoxSelection sel = this.selection.Copy(); + FileSystemNode node = sel.node; + char newPath[MAX_LOCATION]; + StripLastDirectory(node.path, newPath); + //node.path = newPath; + //node. + //if(node && node.type.isFolder && bits.navigateFolders) + // property::path = node.path; + delete sel; + return result; + } + + bool MenuReplaceListItemByChild(MenuItem selection, Modifiers mods) + { + bool result = true; + //FileSystemBoxSelection selection = this.selection.Copy(); // TOFIX compiler bug -- FileSystemBox.c -- ../libede/src/FileSystemBox.ec:420:49: error: ‘selection’ redeclared as different kind of symbol + FileSystemBoxSelection sel = this.selection.Copy(); + FileSystemNode node = sel.node; + char newPath[MAX_LOCATION]; + StripLastDirectory(node.path, newPath); + //node.path = newPath; + //node. + //if(node && node.type.isFolder && bits.navigateFolders) + // property::path = node.path; + delete sel; + return result; + } + private: FileSystemBoxBits bits; char * path; char * extensions; + Array comparedPaths; BitmapResource fileIcons[_FileType]; + BitmapResource compIcons[countOfCompIconNames]; // todo: fix this limitation + + Bitmap bitmap; + //BitmapArray bitmaps { growingFactor = 16 }; FileSystemBox() { char wd[MAX_LOCATION]; GetWorkingDir(wd, sizeof(wd)); property::path = wd; - + InitFileIcons(); + InitCompIcons(); // todo: these icons should not be initialize, they should be set + // or at least initalized when the comparison listing is requested + // and we know how many paths are being compared. list.AddField(nameField); + bits.autoLoad = true; + //iteratorClass = class(FileSystemIterator); } + ~FileSystemBox() { + if(comparedPaths) + { + comparedPaths.Free(); + delete comparedPaths; + } delete extensions; delete path; } + + watch(background) + { + list.background = background; + }; + void InitFileIcons() { _FileType c; @@ -277,13 +516,34 @@ private: } } - DataField nameField { dataType = "FileSystemNode", width = 240, userData = this, freeData = false }; + void InitCompIcons() + { + _FileType c; + for(c = 0; c < countOfCompIconNames; c++) + { + compIcons[c] = BitmapResource { compIconNames[c], alphaBlend = true }; + AddResource(compIcons[c]); + } + } + + DataField nameField { header = "Name", dataType = "FileSystemNode", width = 240, userData = this, freeData = false/*, editable = true*/; }; + DataField pathField { header = "Location", dataType = /*"String"*/ "char *", width = 300, freeData = true }; DataField typeField { header = "Type", dataType = /*"String"*/ "char *", width = 40, freeData = false }; DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right, freeData = false }; + DataField modifiedField { header = "Modified", dataType = "SecSince1970", width = 96, alignment = right, freeData = false }; bool OnPostCreate() { - Load(); + if(bits.autoLoad) + { + if(!path) + { + char wd[MAX_LOCATION]; + GetWorkingDir(wd, sizeof(wd)); + property::path = wd; + } + Load(); + } return true; } @@ -296,6 +556,7 @@ private: hasVertScroll = true; fullRowSelect = false; sortable = true; + alwaysHighLight = true; anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; @@ -328,7 +589,7 @@ private: } else { - if(!node.loaded || !node.childrenLoaded) + if(!node.bits.loaded || !node.bits.childrenLoaded) { LoadTreeNode(node); //list.Sort(nameField, 1); @@ -341,7 +602,7 @@ private: } return true; } - + bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods) { DataRow row = listBox.currentRow; @@ -353,17 +614,38 @@ private: PopupMenu popup; Menu menu { }; - MenuItem { menu, "Cut\tCtrl+X", t, NotifySelect = null, disabled = false }; - MenuItem { menu, "Copy\tCtrl+C", c, NotifySelect = null, disabled = false }; - MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /*!clipboard*/ }; - MenuItem { menu, "Delete\tDel", d, NotifySelect = null, disabled = false }; - //MenuDivider { menu }; + if(NotifyNodeMenu) + NotifyNodeMenu(master, this, menu, selection); + else + { + char * text; + + text = PrintString("Open ", node.name); + MenuItem { menu, text, o, NotifySelect = MenuOpen, disabled = false }; //delete text; + + if(node.bits.isListItem/* && TODO: unless node is at root location*/) + { + MenuDivider { menu }; + MenuItem { menu, "Replace by Parent\tCtrl+R", r, NotifySelect = MenuReplaceListItemByContainingDir, disabled = false }; + } + else if(bits.mode == list) + { + MenuDivider { menu }; + MenuItem { menu, "Replace List Item\tCtrl+R", r, NotifySelect = MenuReplaceListItemByChild, disabled = false }; + } + MenuDivider { menu }; + MenuItem { menu, "Cut\tCtrl+X", t, NotifySelect = null, disabled = false }; + MenuItem { menu, "Copy\tCtrl+C", c, NotifySelect = null, disabled = false }; + MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /*!clipboard*/ }; + MenuItem { menu, "Delete\tDel", d, NotifySelect = null, disabled = false }; + //MenuDivider { menu }; + } popup = PopupMenu { master = this, menu = menu, - position = { - x + clientStart.x + absPosition.x - guiApp.desktop.position.x, + position = { + x + clientStart.x + absPosition.x - guiApp.desktop.position.x, y + clientStart.y + absPosition.y - guiApp.desktop.position.y } }; popup.Create(); @@ -374,12 +656,57 @@ private: bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods) { - if(row) + OldList rows; + OldLink item; + + selection.nodes.Free(); + list.GetMultiSelection(rows); + for(item = rows.first; item; item = item.next) { + DataRow row = item.data; FileSystemNode node = (FileSystemNode)row.tag; - NotifyNodeSelect(listBox.parent.master, this, node); - selection = node; + selection.nodes.Add(node); + incref node; } + rows.Free(null); + if(row) + selection.node = (FileSystemNode)row.tag; + else + selection.node = null; + + if(selection.node && bits.preview) + { + //int pos; + FileSystemNode node = selection.node; + /*if(bitmap) + bitmap.Free();*/ + delete bitmap; + if(node && node.type == pictureFile) + { + bitmap = Bitmap { }; + bitmap.Load(node.path, null, displaySystem); + } + + /*bitmaps.Clear(); + bitmaps = BitmapArray { }; + for(pos = 0; pos < selectedItems.count; pos++) + { + Bitmap bitmap { }; + selItem = (ExplorerFileItem)selectedItems._[pos]; + bitmap.Load(selItem.path, null, displaySystem); + //bitmaps.Add(bitmap); + } + if(node && node.type == pictureFile) + { + bitmap = Bitmap { }; + bitmap.Load(node.path, null, displaySystem); + }*/ + + show.Update(null); + //NotifyItemSelect(master, view, item, selectedItems); + } + + NotifyNodeSelect(listBox.parent.master, this, selection); return true; } @@ -387,7 +714,7 @@ private: { if(row) { - FileSystemNode node = (FileSystemNode)row.tag; + //FileSystemNode node = (FileSystemNode)row.tag; } return true; } @@ -396,7 +723,7 @@ private: { if(row) { - FileSystemNode node = (FileSystemNode)row.tag; + //FileSystemNode node = (FileSystemNode)row.tag; } return true; } @@ -405,39 +732,126 @@ private: { if(row) { - FileSystemNode node = (FileSystemNode)row.tag; + //FileSystemNode node = (FileSystemNode)row.tag; } return true; } bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods) { - return OpenNode(); + bool result = !(selection.node && selection.node.type.isFolder && bits.navigateFolders); + OpenNode(); + return result; } bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch) { - bool result; + //bool result = false; if((SmartKey)key == enter) - result = OpenNode(); - else - result = true; + /*result = */OpenNode(); + #if 0 + else if((SmartKey)key == f2) + /*result = */RenameNode(); + #endif + else if((SmartKey)key == f2) + { + FileSystemNode node = selection.node; + node.row.Edit(nameField); + } + //else + //result = true; return true; } }; + PaneSplitter split + { + this; + //leftPane = list; + rightPane = show; + //split = 200; + scaleSplit = 0.5f; + tabCycle = true; + visible = false; + }; + + Window show + { + this; + visible = false; + borderStyle = none; + anchor = Anchor { top = 0, right = 0, bottom = 0 }; + + void OnRedraw(Surface surface) + { + FileSystemBox fsb = (FileSystemBox)parent; + if(fsb.bitmap) + { + int wBmp = fsb.bitmap.width; + int hBmp = fsb.bitmap.height; + int wWnd = fsb.show.clientSize.w; + int hWnd = fsb.show.clientSize.h; + + //int wList = 0;//fsb.list.size.w + fsb.split.size.w; + + //float scale = Min((float)(wWnd - 10) / wBmp, (float)(hWnd - 10) / hBmp); + + //int wDraw = (int)(wBmp * scale); + //int hDraw = (int)(hBmp * scale); + + #ifndef __linux__ + surface.Filter(fsb.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw, wBmp, hBmp); + #else + // Until Filter / Stretch works with X + surface.Blit(fsb.bitmap, (wWnd - wBmp) / 2, (hWnd - hBmp) / 2, 0, 0, wBmp, hBmp); + #endif + } + else + { + surface.SetForeground(white); + surface.Area(0, 0, fsb.clientSize.w - 1, fsb.clientSize.h - 1); + } + } + }; + bool OpenNode() { - bool result; - if(selection && selection.type.isFolder && bits.navigateFolders) + bool result = false; + FileSystemBoxSelection sel = this.selection.Copy(); + //FileSystemNode node = selection.node; + for(node : sel.nodes) { - property::path = selection.path; - result = true; + sel.node = node; + if(node && node.type.isFolder && bits.navigateFolders) + property::path = node.path; + if(NotifyNodeOpen(this.master, this, sel) && !result) + result = true; } - else - result = NotifyNodeOpen(this.master, this, selection); + delete sel; + return result; + } + + #if 0 + bool RenameNode() + { + bool result; + //FileSystemBoxSelection selection = this.selection.Copy(); + FileSystemNode node = selection.node; + //if(node && node.type.isFolder && bits.navigateFolders) + // property::path = node.path; + // ------------------------------------------- working here --------------------------- + //node.row.Edit(); + /*result = NotifyNodeRename(this.master, this, node); + if(result) + { + if(RenameFile(oldn, newn)) + { + node.name = newn; + } + }*/ return result; } + #endif // Edit Menu Menu editMenu { menu, "Edit", e }; @@ -464,7 +878,7 @@ private: MenuItem itemEditPaste { editMenu, "Paste\tCtrl+V", p; - + bool NotifySelect(MenuItem selection, Modifiers mods) { //EditPaste(); @@ -482,13 +896,31 @@ private: } }; - // WHY is this crashing ? + // WHY is this crashing ? /*void OnResize(int width, int height) { if(this && nameField) nameField.width = width - 80; }*/ + void ChangeViewType() + { + list.Clear(); + list.ClearFields(); + list.resizable = bits.details || bits.pathColumn; + list.moveFields = bits.details || bits.pathColumn; + list.hasHeader = bits.details || bits.pathColumn; + list.AddField(nameField); + if(bits.pathColumn) + list.AddField(pathField); + if(bits.details) + { + list.AddField(typeField); + list.AddField(sizeField); + list.AddField(modifiedField); + } + } + void Load() { // TODO: fix this! @@ -503,58 +935,76 @@ private: list.AddField(sizeField); } }*/ - if(bits.treeBranches) - LoadTree(); - else - LoadList(); - } - - void LoadList() - { - FileListing listing { path, extensions = extensions }; - list.Clear(); - while(listing.Find()) + if(comparedPaths && !bits.treeBranches) + LoadComparedList(); + else { - if((!bits.foldersOnly && !bits.filesOnly) || - (bits.foldersOnly && listing.stats.attribs.isDirectory) || - (bits.filesOnly && !listing.stats.attribs.isDirectory/*listing.stats.attribs.isFile*/)) // TOCHECK: isFile broken? + FileAttribs pathAttribs = FileExists(path); + if(pathAttribs) { - FileSystemNode node = MakeFileSystemNode(listing.stats, listing.name, listing.path, bits.previewPictures, displaySystem); - DataRow row = list.AddRow(); - row.tag = (int)node; - row.SetData(nameField, node); - if(bits.details) + if(pathAttribs.isDirectory) { - row.SetData(typeField, node.extension); - row.SetData(sizeField, (void *)node.stats.size); + if(bits.treeBranches) + LoadTreeDirectory(); + else + { + if(iteratorClass) + LoadListIterator(); + else + LoadListDirectory(); + } } + else if(pathAttribs.isFile) // we assume this is a file list + { + File f = FileOpen(path, read); + if(f) + { + if(bits.treeBranches) + LoadTreeFileList(f); + else + LoadListFileList(f); + delete f; + } + else + MessageBoxTodo($"unable to open file list"); + } + else + MessageBoxTodo($"path is not a directory nor is it a file"); } + else + MessageBoxTodo($"path does not exist"); } list.Sort(nameField, 1); } - void LoadTree() + void LoadTreeDirectory() { bool isRoot = !strcmp(path, "/"); - //char startPath[MAX_LOCATION]; - FileSystemNode parent; - FileSystemNode node; - FileListing listing { path, extensions = extensions }; - + char name[MAX_LOCATION]; + //FileSystemNode parent; + //FileSystemNode node; + //FileListing listing { path, extensions = extensions }; + + if(!isRoot) + GetLastDirectory(path, name); + else + name[0] = '\0'; + /*if(!path) GetWorkingDir(startPath, sizeof(startPath)); else strcpy(path, startPath);*/ - + bits.mode = directory; + list.Clear(); delete root; - #ifdef __WIN32__ +#ifdef __WIN32__ if(isRoot) { - root = FileSystemNode { loaded = true, childrenLoaded = true }; - AddTreeNode(root, true, false, null); + root = FileSystemNode { bits.loaded = true, bits.childrenLoaded = true }; + AddTreeNode(root, true, false, false, null); while(listing.Find()) { int len = strlen(listing.name); @@ -574,107 +1024,518 @@ private: info[0] = 0; } - parent = MakeFileSystemNode(listing.stats, name, listing.path, bits.previewPictures, displaySystem); + parent = + MakeFileSystemNode( + listing.stats, + name, + listing.path, + false, bits.previewPictures, false, + displaySystem); if(info[0]) - parent.info = CopyString(info); - parent.loaded = true; - AddTreeNode(parent, !listing.stats.attribs.isDirectory, listing.stats.attribs.isDirectory, root); + parent.info = info; //CopyString(info); + parent.bits.loaded = true; + AddTreeNode( + parent, + !listing.stats.attribs.isDirectory, + false, + listing.stats.attribs.isDirectory, + root); if(!listing.stats.attribs.isDirectory) - parent.childrenLoaded = true; + parent.bits.childrenLoaded = true; } node = FileSystemNode { name = msNetwork, type = network }; - AddTreeNode(node, false, true, null); + AddTreeNode(node, false, false, true, null); node.row.collapsed = true; } else - #endif +#endif { - root = MakeFileSystemNode(FileStats { attribs = FileExists(path)}, path, path, bits.previewPictures, displaySystem); - AddTreeNode(root, false, true, null); + FileStats stats; + FileGetStats(path, stats); + root = MakeFileSystemNode(stats, name, path, false, bits.previewPictures, false, displaySystem); + AddTreeNode(root, false, false, true, null); LoadTreeNode(root); } - if(isRoot) + if(isRoot) + { + root.type = computer; + root.label = rootName; + } + + list.Sort(nameField, 1); + list.SelectRow(root.row); + } + + void LoadListDirectory() + { + FileListing listing { path, extensions = extensions }; + + bits.mode = directory; + while(listing.Find()) + ProcessListItem(listing.name, listing.path, listing.stats, false); + } + + void LoadListFileList(File f) + { + char line[65536]; + bits.mode = list; + while(f.GetLine(line, 65536)) + { + FileStats stats {}; + char name[MAX_FILENAME]; + FileGetStats(line, stats); + GetLastDirectory(line, name); + ProcessListItem(name, line, stats, true); + } + } + + void LoadTreeFileList(File f) + { + char line[65536]; + bits.mode = list; + while(f.GetLine(line, 65536)) + { + FileStats stats {}; + char name[MAX_FILENAME]; + FileSystemNode node; + FileGetStats(line, stats); + GetLastDirectory(line, name); + node = ProcessTreeItem(name, line, stats, node); + } + } + + void LoadListIterator() + { + FileSystemIterator iterator = eInstance_New(iteratorClass); + if(iterator) + { + iterator.owner = this; + iterator.OnObject = ListIterator_OnObject; + //iterator.OnLeavingDirectory = ListIterator_OnLeavingDirectory; + NotifyIteratorInit(master, this, iterator); + iterator.Iterate(path, true); + delete iterator; + } + } + + bool ListIterator_OnObject(const char * name, const char * path, FileStats stats, bool isRootObject) + { + ProcessListItem(name, path, stats, false); + return false; + } + + //void ListIterator_OnLeavingDirectory(char * path) { } + + void ProcessListItem(const char * name, const char * path, FileStats stats, bool isListItem) + { + if((!bits.foldersOnly && !bits.filesOnly) || (bits.foldersOnly && stats.attribs.isDirectory) || (bits.filesOnly && stats.attribs.isFile)) + { + FileSystemNode node = MakeFileSystemNode(stats, name, path, false, bits.previewPictures, isListItem, displaySystem); + AddNode(node); + } + } + + FileSystemNode ProcessTreeItem(char * name, char * path, FileStats stats, FileSystemNode parent) + { + FileSystemNode node = MakeFileSystemNode(stats, name, path, false, bits.previewPictures, true, displaySystem); + AddTreeNode(parent, false, false, true, null); + //LoadTreeNode(node); + return node; + } + + void LoadTreeNode(FileSystemNode node) + { + if(!node.bits.loaded) + { + char path[MAX_LOCATION]; + node.GetPath(path); + { + FileListing listing { path, extensions = extensions }; + if(node.children.count == 1) + DeleteNode(node.children.first); + + while(listing.Find()) + { + char * test; + FileSystemNode child = null; + if(!listing.stats.attribs.isRemovable && ((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && listing.stats.attribs.isDirectory) || + (bits.filesOnly && listing.stats.attribs.isFile))) + child = MakeAndAddToTreeFileSystemNodeFromFileListing(listing, node); + if(child) + NodeChildLoad(child, node); + test = child.name; + if(!test) + PrintLn("error"); + } + } + node.bits.childrenLoaded = true; + node.bits.loaded = true; + node.row.SortSubRows(false); + } + else if(!node.bits.childrenLoaded) + { + FileSystemNode child; + if(node.children.first) + { + for(child = node.children.first; child; child = child.next) + { + if(!child.bits.loaded) + LoadTreeNode(child); + else if(!child.bits.childrenLoaded) + NodeChildLoad(child, node); + } + node.bits.childrenLoaded = true; + node.row.SortSubRows(false); + } + } + } + + void NodeChildLoad(FileSystemNode parent, FileSystemNode node) + { + char path[MAX_LOCATION]; + parent.GetPath(path); + if(bits.textFileLinesStyle && FileExists(path).isFile) + { + PrintLn("Test"); + } + else + { + bool added = false; + FileListing listing { path, extensions = extensions }; + while(listing.Find()) + { + //char * test; + FileSystemNode child = null; + if((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && listing.stats.attribs.isDirectory) || + (bits.filesOnly && listing.stats.attribs.isFile)) + child = MakeAndAddToTreeFileSystemNodeFromFileListing(listing, parent); + if(child) + { + added = true; + /* + test = child.name; + if(!test) + PrintLn("error"); + */ + } + } + if(!added) + added = true; + } + parent.bits.childrenLoaded = true; + } + + void LoadComparedList() + { + int c/*, cmp*/ /*, smallest*/, icon;//, equalCount; + int count = comparedPaths ? comparedPaths.count : 0; + //bool allDone = false; + bool not; + FileStats stats; + char path[MAX_LOCATION]; + //Array states { }; + //Array listings { }; + //Array equals { }; + //Array> mapNodes { }; + + //Array> lists { }; + //Map equals{ }; + + + MapNode> na; + //MapNode nb; + Map> names { }; + //Map> names { }; + //Map names { }; // does not seem to be working + //Map names { }; + { + for(c = 0; c < comparedPaths.count; c++) + { + FileListing listing { comparedPaths[c], extensions = extensions }; + while(listing.Find()) + { + /*Map*/Array m = names[listing.name]; + if(!m) + m = { }; + names[listing.name] = m; + /*/m[c] = */m.Add(c); + } + } + /* // compiles and should work but better solution? + for(c = 0; c < comparedPaths.count; c++) + { + FileListing listing { comparedPaths[c], extensions = extensions }; + while(listing.Find()) + { + Array a = names[listing.name]; + if(!a) + a = { }; + names[listing.name] = a; + a[c] = true; + } + } + */ + /* // does not seem to be working + for(c = 0; c < comparedPaths.count; c++) + { + FileListing listing { comparedPaths[c], extensions = extensions }; + while(listing.Find()) + { + names[listing.name][c] = true; + } + } + */ + /* + if(comparedPaths.count > 0) + { + FileListing listing { comparedPaths[0], extensions = extensions }; + while(listing.Find()) + { + // should be able to just do names[listing.name]._0 = true; + BoolArrayInt bai = names[listing.name]; + bai._0 = true; + names[listing.name] = bai; + } + } + if(comparedPaths.count > 1) + { + FileListing listing { comparedPaths[1], extensions = extensions }; + while(listing.Find()) + { + // should be able to just do names[listing.name]._1 = true; + BoolArrayInt bai = names[listing.name]; + bai._1 = true; + names[listing.name] = bai; + } + } + */ + // and so on.... + } + + /* + for(dirPath : comparedPaths) { - root.type = computer; - root.name = rootName; - } + char * p = dirPath; + if(FileExists(dirPath).isDirectory) + { + FileListing listing { dirPath, extensions = extensions }; + //MapNode mn; + Map list { }; + //states.Add(listing.Find() == true ? matching : endOfListing); + while(listing.Find()) + list[listing.name] = 0; + //for(mn = ; mn; mn = mn.next) + //mn = list.root.minimum; + mapNodes.Add(/-*mn*-/list.root.minimum); + lists.Add(list); + //PrintLn(dirPath, " -- .Find() -- ", states[states.count-1] == matching ? listing.name : "endOfListing*"); + //listings.Add(listing); - list.Sort(nameField, 1); - list.SelectRow(root.row); - } + { + MapNode mn; + PrintLn("------------- DIR LISTING FOR ", dirPath); + for(mn = list.root.minimum; mn; mn = mn.next) + { + PrintLn(mn.key); + } + } + } + } + */ - void LoadTreeNode(FileSystemNode node) - { - if(!node.loaded) + for(na = names.root.minimum; na; na = na.next) { - char path[MAX_LOCATION]; - node.GetPath(path); + /*Map equals = na.value; + //MapNode nb; + /* + while(!allDone) + { + smallest = 0; + equals.Add(0); + for(c = 1; c < count; c++) { - FileListing listing { path, extensions = extensions }; - if(node.children.count == 1) - DeleteNode(node.children.first); + //if(states[c] == endOfListing) continue; + if(!mapNodes[c]) continue; + // todo: use better comparison method + // it should compare file type (dir/file) before + // comparing file name. + // should also provide alternative methods + // of comparison including ones that consider + // date changes as differences of some kind. + // pethaps a OnCompare(a, b) to allow implementation + // of custom methods of comparison. + // note: this (or these) method(s) depend on files + // being listed in sorted order by FileListing. + // different comparison methods should have + // appropriatly different sorting in FileListing. + // + //cmp = strcmp(listings[smallest].name, listings[c].name); + cmp = fstrcmp(mapNodes[smallest].key, mapNodes[c].key); + PrintLn("COMPARING - ", mapNodes[smallest].key, " and ", mapNodes[c].key); + if(cmp == 0) + equals.Add(c); + //equals[c] = true; + else if(cmp > 0) + { + smallest = c; + equals.size = 0; + equals.Add(c); + } + } - while(listing.Find()) + */ + if(equals.count == count) // all are equal, no diff icon + { + icon = 0; + not = false; + } + else if(equals.count == count-1) // all are equal but one, not-sign icon for singled out missing + { + int i; + /* + for(nb = equals.root.minimum, i = 0; nb; nb = nb.next, i++) { - if((!bits.foldersOnly && !bits.filesOnly) || - (bits.foldersOnly && listing.stats.attribs.isDirectory) || - (bits.filesOnly && !listing.stats.attribs.isDirectory/*listing.stats.attribs.isFile*/)) // TOCHECK: isFile broken? + if(i != nb.key) + */ + for(i = 0; i < equals.count; i++) + { + if(i != equals[i]) { - FileSystemNode child = MakeFileSystemNode(listing.stats, listing.name, listing.path, bits.previewPictures, displaySystem); - AddTreeNode(child, true, false, node); - NodeChildLoad(child, node); + icon = i+1; + break; } } + //if(!nb) + if(i == equals.count) + icon = count; + not = true; } - node.childrenLoaded = true; - node.loaded = true; - node.row.SortSubRows(false); + else if(equals.count == 1) // only one is present, all others missing, present-sign for singled out present + { + //icon = equals.root.minimum.key+1; + icon = equals[0]+1; + not = false; + } + else // mixed + { + icon = 0; // todo + not = true; + } +#if 0 + // or + if(equals.count == count) // all are equal, no diff icon + ; + else if(count/2 - equals.count < 0) // more than half are equal, use not-sign icons for all missing + ; + else // less than half are equal, use present-sign icons for all present + ; +#endif + + /*if((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && listings[smallest].stats.attribs.isDirectory) || + (bits.filesOnly && listings[smallest].stats.attribs.isFile))*/ + strcpy(path, comparedPaths[/*smallest*/equals[0]]); + PathCat(path, /*mapNodes[smallest].key*/na.key); + FileGetStats(path, stats); + if((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && stats.attribs.isDirectory) || + (bits.filesOnly && stats.attribs.isFile)) + { + FileSystemNode node = + MakeComparedFileSystemNode( + stats, + /*mapNodes[smallest].key*/na.key, + path, + false, bits.previewPictures, + icon, not, equals, + displaySystem); + AddNode(node); + } + /* + for(equal : equals) + { + mapNodes[equal] = mapNodes[equal].next; + //states[equal] = listings[equal].Find() == true ? matching : endOfListing; + //PrintLn(comparedPaths[equal], " -- .Find() -- ", states[equal] == matching ? listings[equal].name : "endOfListing*"); + } + equals.size = 0; + //for(c = 0; c < count && states[c] == endOfListing; c++); + for(c = 0; c < count && !mapNodes[c]; c++); + if(c == count) + allDone = true; + */ + } + list.Sort(nameField, 1); + } + + void AddNode(FileSystemNode node) + { + DataRow row = list.AddRow(); + row.tag = (intptr)node; + node.row = row; + incref node; + row.SetData(nameField, node); + if(bits.pathColumn) + { + char path[MAX_LOCATION]; + StripLastDirectory(node.path, path); + row.SetData(pathField, CopyString(path)); } - else if(!node.childrenLoaded) + if(bits.details) { - FileSystemNode child; - if(node.children.first) + if(node.type.isFile) { - for(child = node.children.first; child; child = child.next) - { - if(!child.loaded) - LoadTreeNode(child); - else if(!child.childrenLoaded) - NodeChildLoad(child, node); - } - node.childrenLoaded = true; - node.row.SortSubRows(false); + row.SetData(typeField, node.extension); + row.SetData(sizeField, /*(void *)*/node.stats.size); } + row.SetData(modifiedField, node.stats.modified); } } - void NodeChildLoad(FileSystemNode parent, FileSystemNode node) + FileSystemNode MakeAndAddToTreeFileSystemNodeFromFileListing(FileListing listing, FileSystemNode parent) { - char path[MAX_LOCATION]; - parent.GetPath(path); + FileSystemNode result = null; + /*if((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && listing.stats.attribs.isDirectory) || + (bits.filesOnly && listing.stats.attribs.isFile))*/ + /*if(!listing.stats.attribs.isRemovable && ((!bits.foldersOnly && !bits.filesOnly) || + (bits.foldersOnly && listing.stats.attribs.isDirectory) || + (bits.filesOnly && listing.stats.attribs.isFile)))*/ { - bool added = false; - FileListing listing { path, extensions = extensions }; - while(listing.Find()) + bool textFileLinesStyle = false; + const char * test = listing.name; + if(!test) + PrintLn("error"); + result = MakeFileSystemNode(listing.stats, listing.name, listing.path, false, bits.previewPictures, false, displaySystem); + test = result.name; + if(!test) + PrintLn("error"); + if(bits.textFileLinesStyle) { - if((!bits.foldersOnly && !bits.filesOnly) || - (bits.foldersOnly && listing.stats.attribs.isDirectory) || - (bits.filesOnly && !listing.stats.attribs.isDirectory/*listing.stats.attribs.isFile*/)) // TOCHECK: isFile broken? - { - FileSystemNode child = MakeFileSystemNode(listing.stats, listing.name, listing.path, bits.previewPictures, displaySystem); - AddTreeNode(child, true, false, parent); - added = true; - } + char ext[MAX_LOCATION]; + GetExtension(listing.name, ext); + if(!strcmpi(ext, "txt") || !strcmpi(ext, "text")) + textFileLinesStyle = true; } - if(!added) - added = true; + //AddTreeNode(result, true, false, textFileLinesStyle, parent); + AddTreeNode(result, !textFileLinesStyle && listing.stats.attribs.isFile, false, !listing.stats.attribs.isFile || textFileLinesStyle, parent); + test = result.name; + if(!test) + PrintLn("error"); } - //parent.childrenLoaded = true; + return result; } - void AddTreeNode(FileSystemNode node, bool loaded, bool addLoader, FileSystemNode addTo) + void AddTreeNode( + FileSystemNode node, + bool loaded, + bool childrenLoaded, + bool addLoader, + FileSystemNode addTo) { DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : list.AddRow(); if(addTo) @@ -683,16 +1544,32 @@ private: node.indent = addTo.indent + 1; addTo.children.Add(node); } - row.tag = (int)node; + row.tag = (intptr)node; node.row = row; row.SetData(null, node); + if(bits.pathColumn) + { + char path[MAX_LOCATION]; + StripLastDirectory(node.path, path); + row.SetData(pathField, CopyString(path)); + } + if(bits.details) + { + if(node.type.isFile) + { + row.SetData(typeField, node.extension); + row.SetData(sizeField, /*(void *)*/node.stats.size); + } + row.SetData(modifiedField, node.stats.modified); + } - node.loaded = loaded; + node.bits.loaded = loaded; + node.bits.childrenLoaded = childrenLoaded; if(addLoader) //AddTreeNode(FileSystemNode { }, false, false, node); // why would this create a compile error? - AddTreeNode(FileSystemNode { type = none }, false, false, node); + AddTreeNode(FileSystemNode { type = none, name = "Loader" }, false, false, false, node); - if(node.indent > 0) + if(node.indent > 0 || bits.mode == list) row.collapsed = true; else if(node.type == folder) node.type = folderOpen; @@ -701,13 +1578,20 @@ private: void DeleteNode(FileSystemNode node) { FileSystemNode child; - for(; (child = node.children.first); ) - DeleteNode(child); + if(treeBranches) + { + for(; (child = node.children.first); ) + DeleteNode(child); + } list.DeleteRow(node.row); node.Delete(); + //delete node; + //Update(null); } } +enum ComparisonState { endOfListing, matching }; + /* #if 0 class ExplorerView : FileSystemBox @@ -808,7 +1692,7 @@ public: location.GetPath(path); { FileListing listing { path }; - + ExplorerFileItem item; DataRow row; @@ -863,7 +1747,7 @@ public: location.GetPath(path); { FileListing listing { path }; - + ExplorerFileItem item; DataRow row; @@ -912,7 +1796,7 @@ public: location.GetPath(path); { FileListing listing { path }; - + ExplorerFileItem item; DataRow row; @@ -959,7 +1843,7 @@ public: location.GetPath(path); { FileListing listing { path }; - + ExplorerFileItem item; DataRow row; @@ -1005,7 +1889,7 @@ public: { _[c].Free(); delete _[c]; - } + } count = 0; size = 0; } @@ -1044,9 +1928,9 @@ public: int hWnd = clientSize.h; int wList = view.list.size.w + view.split.size.w; - + float scale = Min((float)(wWnd - 10) / wBmp, (float)(hWnd - 10) / hBmp); - + int wDraw = (int)(wBmp * scale); int hDraw = (int)(hBmp * scale); @@ -1097,10 +1981,10 @@ public: for(pos = 0; pos < selectedItems.count; pos++) { Bitmap bitmap { }; - selItem = (ExplorerFileItem)selectedItems._[pos]; + selItem = (ExplorerFileItem)selectedItems._[pos]; bitmap.Load(selItem.path, null, displaySystem); //view.bitmaps.Add(bitmap); - } + } if(item && item.type == pictureFile) { view.bitmap = Bitmap { }; @@ -1123,7 +2007,7 @@ public: location.GetPath(path); { FileListing listing { path }; - + ExplorerFileItem item; DataRow row; @@ -1159,7 +2043,7 @@ public: FileSystemNode selection; virtual bool Window::NotifyNodeSelect(ExplorerTree tree, FileSystemNode node); - + property FileSystemNode node { get @@ -1247,7 +2131,7 @@ public: } return true; } - + bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods) { DataRow row = listBox.currentRow; @@ -1268,8 +2152,8 @@ public: popup = PopupMenu { master = this, menu = menu, - position = { - x + clientStart.x + absPosition.x - guiApp.desktop.position.x, + position = { + x + clientStart.x + absPosition.x - guiApp.desktop.position.x, y + clientStart.y + absPosition.y - guiApp.desktop.position.y } }; popup.Create(); @@ -1342,7 +2226,7 @@ public: MenuItem itemEditPaste { editMenu, "Paste\tCtrl+V", p; - + bool NotifySelect(MenuItem selection, Modifiers mods) { //EditPaste(); @@ -1360,7 +2244,7 @@ public: } }; - // WHY is this crashing ? + // WHY is this crashing ? /-*void OnResize(int width, int height) { if(this && nameField) @@ -1386,16 +2270,16 @@ public: #else root.name = "/"; #endif - AddTreeNode(root, true, false, null, tree); + AddTreeNode(root, true, false, false, null, tree); - // How can this make sense for linux? + // How can this make sense for linux? #ifdef __WIN32__ while(listing.Find()) { int len = strlen(listing.name); char info[MAX_LOCATION]; char name[MAX_LOCATION]; - if(listing.stats.attribs.isDrive && + if(listing.stats.attribs.isDrive && len > 3 && !strncmp(&listing.name[1], ": [", 3)) { strncpy(name, listing.name, 2); @@ -1413,13 +2297,13 @@ public: if(info[0]) parent.info = CopyString(info); parent.loaded = true; - AddTreeNode(parent, !listing.stats.attribs.isDirectory, listing.stats.attribs.isDirectory, root, tree); + AddTreeNode(parent, !listing.stats.attribs.isDirectory, false, listing.stats.attribs.isDirectory, root, tree); if(!listing.stats.attribs.isDirectory) parent.childrenLoaded = true; } #endif node = FileSystemNode { name = msNetwork, type = network }; - AddTreeNode(node, false, true, null, tree); + AddTreeNode(node, false, false, true, null, tree); node.row.collapsed = true; tree.Sort(nameField, 1); tree.SelectRow(root.row); @@ -1448,7 +2332,7 @@ public: ClipBoard clipBoard { }; if(clipBoard.Allocate(size+1)) { - GetSel(clipBoard.memory, true); + GetSel(clipBoard.memory, true); // Save clipboard clipBoard.Save(); } @@ -1497,11 +2381,11 @@ hGlobal = GlobalAlloc(GHND, Len(DF) + Len(strFiles)) 'put all files to a exclusi If hGlobal Then 'if the globalalloc worked lpGlobal = GlobalLock(hGlobal) 'lock the hGlobal DF.pFiles = Len(DF) 'set the size of the files - + Call CopyMem(ByVal lpGlobal, DF, Len(DF)) 'copy df to the lpglobal Call CopyMem(ByVal (lpGlobal + Len(DF)), ByVal strFiles, Len(strFiles)) 'copy strfiles to lpglobal Call GlobalUnlock(hGlobal) 'unlock hglobal again - + SetClipboardData CF_HDROP, hGlobal 'put files to the clipboard End If *-/ @@ -1528,7 +2412,7 @@ public: } BSloc Remove(FileSystemNode item) { - + } } #endif @@ -1577,7 +2461,7 @@ public class ExplorerFileItem : struct //float scale = Min((float)clientSize.w / (float)bitmap.width, (float)clientSize.h / (float)bitmap.height); int w = 16; //(int)(bitmap.width * scale); int h = 16; //(int)(bitmap.height * scale); - + Bitmap icon; icon = control.fileIcons[type].bitmap; @@ -1588,7 +2472,7 @@ public class ExplorerFileItem : struct indentSize = 8; } textOffset = indent * indentSize + (icon ? (icon.width + 6) : 0); - + if(info) sprintf(label, "%s [%s]", name, info); else @@ -1689,7 +2573,7 @@ public: { //_[c].Free() delete _[c]; - } + } count = 0; size = 0; } @@ -1701,10 +2585,10 @@ ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, char info[MAX_LOCATION]; char name[MAX_LOCATION]; char extension[MAX_EXTENSION]; - + ExplorerFileItem item { }; - //if(attribs.isFile) // TODO fix this in ecere + //if(stats.attribs.isFile) // -- should work now if(attribs.isDirectory) { extension[0] = 0; @@ -1718,7 +2602,7 @@ ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, item.type = cdrom; if(attribs.isRemote) item.type = netDrive; - if(attribs.isRemovable) + if(attribs.isRemovable) { if(fileName[0] == 'A' || fileName[0] == 'B') item.type = floppy; @@ -1731,11 +2615,11 @@ ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, GetExtension(fileName, extension); //strupr(extension); strlwr(extension); - + item.type = _FileType::SelectByExtension(extension); } - if(attribs.isDrive && + if(attribs.isDrive && len > 3 && !strncmp(&fileName[1], ": [", 3)) { strncpy(name, fileName, 2); @@ -1766,10 +2650,53 @@ ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, #endif */ -public class FileSystemNode : struct +public class FileSystemBoxSelection +{ +public: + FileSystemNode node; + Array nodes { }; + +private: + FileSystemBoxSelection Copy() + { + FileSystemBoxSelection copy { node = node }; + for(node : nodes) + { + copy.nodes.Add(node); + incref node; + } + return copy; + } + + ~FileSystemBoxSelection() + { + nodes.Free(); + } +} + +class FileSystemNodeBits +{ + bool loaded:1, childrenLoaded:1, isListItem:1; +}; + +public class FileSystemNode { + +private: + FileSystemNodeBits bits; + char * path; + char * name; + char * extension; + char * label; + char * info; + + ~FileSystemNode() + { + Free(); + } + public: - /*//LinkElement link; + /* LinkElement link; FileSystemNode parent; FileSystemNodeType type; @@ -1778,12 +2705,36 @@ public: FileSystemNode prev, next; - bool loaded, childrenLoaded; int indent; - char * path; - char * name; - char * extension; - char * info; + + property bool isListItem { set { bits.isListItem = value; } get { return bits.isListItem; } }; + + property const char * path + { + set { delete path; if(value && value[0]) path = CopyString(value); } + get { return path; } isset { return path && path[0]; } + } + property const char * name + { + set { delete name; if(value && value[0]) name = CopyString(value); } + get { return name; } isset { return name && name[0]; } + } + property char * extension + { + set { delete extension; if(value && value[0]) extension = CopyString(value); } + get { return extension; } isset { return extension && extension[0]; } + } + property const char * label + { + set { delete label; if(value && value[0]) label = CopyString(value); } + get { return label; } isset { return label && label[0]; } + } + property const char * info + { + set { delete info; if(value && value[0]) info = CopyString(value); } + get { return info; } isset { return info && info[0]; } + } + DataRow row; OldList children; _FileType type; @@ -1793,12 +2744,19 @@ public: Bitmap bitmap; + int cmpIcon; + bool cmpNot; + Array exists; // would use (see) BoolArrayInt to pack this into an int if could be accessed as an array + void GetPath(String outputPath) - { - FileSystemNode up; - if(parent) + { + if(path) + strcpy(outputPath, path); + else if(parent) { - strcpy(outputPath, name); + FileSystemNode up; + if(name) + strcpy(outputPath, name); for(up = parent; up; up = up.parent) { char temp[MAX_LOCATION]; @@ -1808,12 +2766,7 @@ public: } } else -/*#ifdef __WIN32__ - strcpy(outputPath, "/"); -#else*/ - strcpy(outputPath, name); -//#endif - + strcpy(outputPath, name ? name : ""); } bool IsChildOf(FileSystemNode node) @@ -1830,13 +2783,13 @@ public: if(children.first) { FileSystemNode child; - + for(child = children.first; child; child = child.next) { FileSystemNode copy { }; - copy.name = CopyString(child.name); + copy.name = child.name; //CopyString(child.name); copy.type = child.type; - fsb.AddTreeNode(copy, child.loaded, false, addTo); + fsb.AddTreeNode(copy, child.bits.loaded, false, false, addTo); if(forceExpanded) copy.row.collapsed = false; if(recursive) @@ -1844,7 +2797,7 @@ public: } } } - + void EnsureVisible(bool expand) { if(parent) @@ -1868,7 +2821,10 @@ public: children.Delete(child); } //if(name) + delete path; delete name; + delete extension; + delete label; delete info; } @@ -1882,31 +2838,53 @@ public: void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox fsb, Alignment alignment, DataDisplayFlags displayFlags) { //int indentSize = (displayFlags.dropBox) ? 0 : 10; - int indent = 16; + //int indent = 16; int xStart; int len; int w, h; //int textOffset; - char label[MAX_FILENAME]; + char * alt; + char text[MAX_LOCATION]; + bool comp; Bitmap icon; + Bitmap diffIcon; + Bitmap notIcon; if(!this) return; - + + comp = fsb.comparedPaths && fsb.comparedPaths.count > 1; + icon = fsb.fileIcons[type].bitmap; + alt = bits.isListItem ? path : name; + if(comp && !fsb.bits.columnsCompareStyle && cmpIcon) + { + /* + diffIcon = Bitmap { }; + diffIcon.AllocateDD( + surface.display.displaySystem, + fsb.compIcons[cmpIcon].bitmap.width, + fsb.compIcons[cmpIcon].bitmap.height); + if(fsb.compIcons[cmpIcon].bitmap) + diffIcon.Copy(fsb.compIcons[cmpIcon].bitmap); + */ + diffIcon = fsb.compIcons[cmpIcon-1].bitmap; + notIcon = fsb.compIcons[countOfCompIconNames-1].bitmap; + } //xStart = indent * indent + x + (icon ? (icon.width + 5) : 0); - xStart = x + (icon ? (icon.width + 5) : 0); + xStart = x + (icon ? (icon.width + 5) : 0) + (comp ? 18*(fsb.bits.columnsCompareStyle ? fsb.comparedPaths.count : 1) : 0); - if(!name) + if(!alt) return; if(info) - sprintf(label, "%s [%s]", name, info); + sprintf(text, "%s [%s]", label ? label : alt, info); else - strcpy(label, name); - len = strlen(label); - + strcpy(text, label ? label : alt); //"%d-%d/%s", stats.inode, stats.nlink + //sprintf(text, "%d-%d/%s", stats.inode, stats.nlink, label ? label : alt); + len = strlen(text); + if(!icon) { if(type == folder || type == folderOpen) @@ -1915,21 +2893,21 @@ public: indent = 8; } //textOffset = indent * indentSize + (icon ? (icon.width + 4) : 0); - + + surface.SetForeground(displayFlags.selected ? fsb.selectionText : fsb.foreground); surface.TextOpacity(false); - surface.TextExtent(label, len, &w, &h); + surface.TextExtent(text, len, &w, &h); h = Max(h, 16); - + // Draw the current row stipple if(displayFlags.selected) //surface.Area(xStart - 1, y, xStart - 1, y + h - 1); //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1); surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1); - - //surface.WriteTextDots(alignment, x + textOffset, y + 2, width - textOffset, name, strlen(name)); - surface.WriteTextDots(alignment, xStart, y + 2, width, label, len); + //surface.WriteTextDots(alignment, x + textOffset, y + 2, width - textOffset, alt, strlen(alt)); + surface.WriteTextDots(alignment, xStart, y + 2, width, text, len); - //if(!guiApp.textMode) -- how to do this in a dll? + if(!guiApp.textMode) { if(displayFlags.current) { @@ -1949,6 +2927,80 @@ public: surface.LineStipple(0); } + if(comp) + { + if(!fsb.bits.columnsCompareStyle && diffIcon) + { + w = diffIcon.width; + h = diffIcon.height; + /*if(cmpNot && notIcon) + { + Surface s = diffIcon.GetSurface(0,0, {w,h}); + s.SetForeground(white); + s.Blit(notIcon, x,y, 0,0, w,h); + delete s; + }*/ + surface.SetForeground(white); + surface.Blit(diffIcon, x,y, 0,0, w,h); + if(cmpNot && notIcon) + surface.Blit(notIcon, x,y, 0,0, w,h); + x+=18; + //delete diffIcon; + } + else if(fsb.bits.columnsCompareStyle && exists && exists.count) + { + int c, d; + for(c = d = 0; c < fsb.comparedPaths.count; c++) + { + if(d == exists.count || exists[d] != c) + x+=18; + else + { + diffIcon = fsb.compIcons[c].bitmap; + if(diffIcon) + { + w = diffIcon.width; + h = diffIcon.height; + surface.SetForeground(white); + surface.Blit(diffIcon, x,y, 0,0, w,h); + } + x+=18; + d++; + } + } + /* + for(c = d = 0; c < exists.count; c++) + { + if(exists[c] != d) + { + d = exists[c]+1; + x+=18*(exists[c]-d); + } + else + { + diffIcon = fsb.compIcons[exists[c]].bitmap; + if(diffIcon) + { + w = diffIcon.width; + h = diffIcon.height; + surface.SetForeground(white); + surface.Blit(diffIcon, x,y, 0,0, w,h); + } + d++; + x+=18; + } + } + if(exists.count < fsb.comparedPaths.count && exists[exists.count-1] != d) + { + x+=18*(exists[exists.count-1]-d); + } + */ + } + else if(fsb.bits.columnsCompareStyle) + { + x+=18*fsb.comparedPaths.count; + } + } if(icon) { w = icon.width; @@ -1978,17 +3030,70 @@ public: //surface.alphaWrite = blend; surface.SetForeground(white); //surface.Blit(icon, x + indent * indentSize, y,0,0, icon.width, icon.height); - surface.Blit(icon, x,y,0,0, icon.width, icon.height); + surface.Blit(icon, x,y, 0,0, w,h); } } } + Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData) + { + EditBox editBox + { + dataBox, anchor = { 0, 0, 0, 0 }; + borderStyle = none; + //borderStyle = contour; + opacity = 1.0f; + //background = white; + //autoSize = true; + contents = name; + }; + //dataBox.borderStyle = none; + dataBox.borderStyle = contour; + dataBox.background = white; + //dataBox.opacity = 0.0f; + editBox.Create(); + return editBox; + } + + bool OnSaveEdit(EditBox editBox, void * object) + { + bool changed = false; + if(editBox.modifiedDocument) + { +#if 0 + // how the heck did this work for PathBox? :S + //String::OnFree(); + //changed = _class._vTbl[__ecereVMethodID_class_OnGetDataFromString](_class, &this, editBox.contents); + PrintLn(name); + //if(strcmp(editBox.contents, this.name)) + ; + /*{ + //changed = NotifyNodeRename(this.master, this, node); + changed = true; + if(changed && RenameFile(name, editBox.contents)) + { + name = editBox.contents; + } + else + { + changed = false; + } + }*/ +#endif + } + return changed; + } + int OnCompare(FileSystemNode b) { int result; FileSystemNode a = this; if(a.type == b.type || (a.type < folder && b.type < folder) || (a.type >= drive)) + { + if(!a.name || !b.name) + PrintLn("error: FileSystemNode::OnCompare -- null-named node"); result = strcmpi(a.name, b.name); + } else { if(a.type == folder && b.type < folder) result = -1; @@ -1998,18 +3103,34 @@ public: return result; } - /*int OnCompare(FileSystemNode b) +#if 0 + //int OnCompare(FileSystemNode b) + //{ + //int result; + //FileSystemNode a = this; + //if(a.parent < b.parent) result = -1; + //else if(a.parent > b.parent) result = 1; + //else + //result = fstrcmp(a.name, b.name); + //return result; + //} +#endif + + bool OnGetDataFromString(const char * string) { - int result; - FileSystemNode a = this; - if(a.parent < b.parent) result = -1; - else if(a.parent > b.parent) result = 1; - else - result = fstrcmp(a.name, b.name); - return result; - }*/ +#if 0 + if(string && *string) + { + int len = strlen(string) + 1; + name = new char[len]; + CopyBytes(name, string, len); + return true; + } +#endif + return false; + } - char * OnGetString(char * tempString, FileSystemToolWindow fileSysToolWnd, bool * needClass) + const char * OnGetString(char * tempString, void * unused /*FileSystemToolWindow fileSysToolWnd*/, bool * needClass) { return name ? name : ""; } @@ -2028,7 +3149,7 @@ public: if(stats.attribs.isShare) node.type = share; if(stats.attribs.isCDROM) node.type = cdrom; if(stats.attribs.isRemote) node.type = netDrive; - if(stats.attribs.isRemovable) + if(stats.attribs.isRemovable) { if(name[0] == 'A' || name[0] == 'B') node.type = floppy; @@ -2044,18 +3165,34 @@ public: } return node; }*/ -static FileSystemNode MakeFileSystemNode(const FileStats stats, - const char * fileName, const char * filePath, - const bool previewPicture, const DisplaySystem displaySystem) + +FileSystemNode MakeFileSystemNode( + const FileStats stats, + const char * name, + const char * path, + const bool pathAddName, + const bool previewPicture, + const bool isListItem, + /*const */DisplaySystem displaySystem) { - int len = strlen(fileName); + int len = strlen(name); char info[MAX_LOCATION]; - char name[MAX_LOCATION]; + char name2[MAX_LOCATION]; char extension[MAX_EXTENSION]; - + FileSystemNode node { stats = stats }; - //if(stats.attribs.isFile) // TODO fix this in ecere + /*if(!pathAddName) + { + char o[MAX_LOCATION]; + //char r[MAX_LOCATION]; + //StripLastDirectory(path, o); + GetLastDirectory(path, o); + if(fstrcmp(name, o)) + //if(!FileExists(path)) + PrintLn("Stop!"); + }*/ + //if(stats.attribs.isFile) // TODO fix this in ecere -- WTH -- this has been fixed :/ if(stats.attribs.isDirectory) { extension[0] = '\0'; @@ -2065,9 +3202,9 @@ static FileSystemNode MakeFileSystemNode(const FileStats stats, if(stats.attribs.isShare) node.type = share; if(stats.attribs.isCDROM) node.type = cdrom; if(stats.attribs.isRemote) node.type = netDrive; - if(stats.attribs.isRemovable) + if(stats.attribs.isRemovable) { - if(fileName[0] == 'A' || fileName[0] == 'B') + if(name[0] == 'A' || name[0] == 'B') node.type = floppy; else node.type = removable; @@ -2075,37 +3212,109 @@ static FileSystemNode MakeFileSystemNode(const FileStats stats, } else { - GetExtension(fileName, extension); + GetExtension(name, extension); strlwr(extension); - + node.type = _FileType::SelectByExtension(extension); } - if(stats.attribs.isDrive && - len > 3 && !strncmp(&fileName[1], ": [", 3)) + if(stats.attribs.isDrive && + len > 3 && !strncmp(&name[1], ": [", 3)) { - strncpy(name, fileName, 2); - name[2] = 0; - strncpy(info, &fileName[4], len - 5); + strncpy(name2, name, 2); + name2[2] = 0; + strncpy(info, &name[4], len - 5); info[len - 5] = 0; } else { - strcpy(name, fileName); + strcpy(name2, name); info[0] = 0; } - node.path = CopyString(filePath); - node.name = CopyString(name); + if(pathAddName) + { + //bool isFile = stats.attribs.isFile; + //bool isFolder = stats.attribs.isDirectory; + char full[MAX_LOCATION]; + strcpy(full, path); + PathCat(full, name); + node.path = full; //CopyString(full); + } + else + node.path = path; //CopyString(path); + node.name = name2; //CopyString(name2); if(info[0]) - node.info = CopyString(info); - node.extension = CopyString(extension); + node.info = info; //CopyString(info); + node.extension = extension; //CopyString(extension); if(node.type == pictureFile && previewPicture) { node.bitmap = Bitmap { alphaBlend = true }; - node.bitmap.Load(filePath, null, displaySystem); + node.bitmap.Load(path, null, displaySystem); } + if(isListItem) + node.bits.isListItem = true; + + return node; +} + +FileSystemNode MakeComparedFileSystemNode( + const FileStats stats, + const char * name, + const char * path, + const bool pathAddName, + const bool previewPicture, + const int cmpIcon, + const bool cmpNot, + /*const */Array exists, + /*const */DisplaySystem displaySystem) +{ + FileSystemNode node = MakeFileSystemNode(stats, name, path, pathAddName, previewPicture, false, displaySystem); + if(node) + { + node.cmpIcon = cmpIcon; + node.cmpNot = cmpNot; + node.exists = exists; + } return node; } + +#if 0 // could we do this? +class BoolArrayInt : int +{ + // packing 32 bools in one int exposing them as an array + bool [32]:1; // the :1 specifies the size of each element + // byte [4]:8; // packing 4 bytes in an int exposing them as an arrat +} +// allowing you to access each 32 bits with the following notation: +static void Dummy() +{ + int c; + BoolArrayInt a; + a[0] = true; + a[31] = false; + for(c = 0; c < 32; c++) + a[c] = SomFunction(...); +} +#endif +class BoolArrayInt : int +{ + bool _0:1; + bool _1:1; + bool _2:1; + bool _3:1; + bool _4:1; + bool _5:1; + bool _6:1; + bool _7:1; + bool _8:1; + bool _9:1; + bool _10:1; + bool _11:1; + bool _12:1; + bool _13:1; + bool _14:1; + bool _15:1; +}