public import "ecere" import "FileSystemCache" #ifdef __WIN32__ static char * rootName = "Entire Computer"; static char * msNetwork = "Microsoft Windows Network"; #else static char * rootName = "File System"; #endif private: define guiApp = (GuiApplication)((__thisModule).application); define selectionColor = guiApp.currentSkin.selectionColor; //Color { 10, 36, 106 }; void MessageBoxTodo(char * message) { PrintLn("MessageBoxTodo(char * message) -- ", message); MessageBox { type = ok, text = "MessageBoxTodo(char * message)", contents = message }.Modal(); } static char * fileIconNames[] = { "<:ecere>mimeTypes/file.png", /* none */ "<:ecere>mimeTypes/file.png", /* normalFile */ "<:ecere>mimeTypes/textEcereWorkspace.png", /* ewsFile */ "<:ecere>mimeTypes/textEcereProject.png", /* epjFile */ "<:ecere>mimeTypes/textEcereSource.png", /* ecFile */ "<:ecere>mimeTypes/textEcereHeader.png", /* ehFile */ "<:ecere>mimeTypes/textCSource.png", /* cFile */ "<:ecere>mimeTypes/textCHeader.png", /* hFile */ "<:ecere>mimeTypes/textC++Source.png", /* cppFile */ "<:ecere>mimeTypes/textC++Header.png", /* hppFile */ "<:ecere>mimeTypes/text.png", /* textFile */ "<:ecere>mimeTypes/textHyperTextMarkup.png", /* webFile */ "<:ecere>mimeTypes/image.png", /* pictureFile */ "<:ecere>status/audioVolumeHigh.png", /* soundFile */ "<:ecere>mimeTypes/package.png", /* archiveFile */ "<:ecere>mimeTypes/packageSoftware.png", /* packageFile */ "<:ecere>mimeTypes/packageOpticalDisc.png", /* opticalMediaImageFile */ "<:ecere>places/folder.png", /* folder */ "<:ecere>status/folderOpen.png", /* folderOpen */ "<:ecere>devices/computer.png", /* computer */ "<:ecere>devices/driveHardDisk.png", /* drive */ "<:ecere>places/driveRemote.png", /* netDrive */ "<:ecere>devices/mediaOptical.png", /* cdrom */ "<:ecere>devices/driveRemovableMedia.png", /* removable */ "<:ecere>devices/mediaFloppy.png", /* floppy */ "<:ecere>places/networkWorkgroup.png", /* network */ "<:ecere>places/networkServer.png", /* server */ "<:ecere>places/folderRemote.png", /* share */ "<:ecere>mimeTypes/package.png", /* treeLoader */ "<:ecere>places/startHere.png", /* lineNumbers */ "" }; define countOfCompIconNames = 6; static 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 * { set { this = SelectByExtension(value); } }*/ public property bool isFolder { get { return this >= folder && this <= share; } } public property bool isFile { get { return this >= normalFile && this <= opticalMediaImageFile; } } _FileType ::SelectByExtension(char * extension) { if(!strcmpi(extension, "ews")) return ewsFile; else if(!strcmpi(extension, "epj")) return epjFile; else if(!strcmpi(extension, "ec")) return ecFile; else if(!strcmpi(extension, "eh")) return ehFile; else if(!strcmpi(extension, "cpp") || !strcmpi(extension, "cc") || !strcmpi(extension, "cxx")) return cppFile; else if(!strcmpi(extension, "hpp") || !strcmpi(extension, "hh") || !strcmpi(extension, "hxx")) return hppFile; else if(!strcmpi(extension, "c")) return cFile; else if(!strcmpi(extension, "h")) return hFile; else if(!strcmpi(extension, "txt") || !strcmpi(extension, "text") || !strcmpi(extension, "nfo") || !strcmpi(extension, "info")) return textFile; else if(!strcmpi(extension, "htm") || !strcmpi(extension, "html") || !strcmpi(extension, "css") || !strcmpi(extension, "php") || !strcmpi(extension, "js")) return webFile; else if(!strcmpi(extension, "bmp") || !strcmpi(extension, "pcx") || !strcmpi(extension, "jpg") || !strcmpi(extension, "jpeg") || !strcmpi(extension, "gif") || !strcmpi(extension, "png") || !strcmpi(extension, "ico")) return pictureFile; else if(!strcmpi(extension, "wav") || !strcmpi(extension, "mp3") || !strcmpi(extension, "ogg") || !strcmpi(extension, "snd")) return soundFile; else if(!strcmpi(extension, "ear") || !strcmpi(extension, "7z") || !strcmpi(extension, "rar") || !strcmpi(extension, "zip") || !strcmpi(extension, "gz") || !strcmpi(extension, "bz2") || !strcmpi(extension, "tar") || !strcmpi(extension, "arj") || !strcmpi(extension, "lza") || !strcmpi(extension, "lzh") || !strcmpi(extension, "cpio") || !strcmpi(extension, "z")) return archiveFile; else if(!strcmpi(extension, "cab") || !strcmpi(extension, "deb") || !strcmpi(extension, "rpm")) return packageFile; else if(!strcmpi(extension, "iso") || !strcmpi(extension, "mds") || !strcmpi(extension, "cue") || !strcmpi(extension, "bin") || !strcmpi(extension, "ccd") || !strcmpi(extension, "bwt") || !strcmpi(extension, "cdi") || !strcmpi(extension, "nrg")) return opticalMediaImageFile; return normalFile; } }; public enum FileSystemBoxMode { directory, list }; class FileSystemBoxBits { 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; treeBranches = true; collapseControl = true; rootCollapseButton = true; sortable = true; */ { borderStyle = deep; hasHorzScroll = false; hasVertScroll = false; menu = Menu { }; public: FileSystemNode root; FileSystemBoxSelection selection { }; 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 char * path { set { delete path; if(value && value[0]) path = CopyString(value); if(locationBox) locationBox.path = value; if(created) Load(); } get { return path; } //isset { return path && path[0]; } } property Array comparedPaths { set { 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; ChangeViewType(); } get { return bits.details; } }; property bool pathColumn { set { bits.pathColumn = value; ChangeViewType(); } get { return bits.pathColumn; } }; property bool treeBranches { set { bits.treeBranches = value; list.treeBranches = value; list.collapseControl = value; list.rootCollapseButton = value; } 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; } 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 { if(!list) return null; if(!list.currentRow) return null; if(!list.currentRow.tag) return null; return (FileSystemNode)list.currentRow.tag; } } PathBox locationBox; void Select(FileSystemNode node) { if(node.row) { node.EnsureVisible(false); list.SelectRow(node.row); } } 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(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 = 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() { Load(); } bool MenuOpen(MenuItem selection, Modifiers mods) { OpenNode(); } 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() { delete extensions; delete path; } watch(background) { list.background = background; }; void InitFileIcons() { _FileType c; for(c = 0; c < _FileType::enumSize; c++) { fileIcons[c] = BitmapResource { fileIconNames[c], alphaBlend = true }; AddResource(fileIcons[c]); } } 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() { if(bits.autoLoad) { if(!path) { char wd[MAX_LOCATION]; GetWorkingDir(wd, sizeof(wd)); property::path = wd; } Load(); } return true; } ListBox list { this; borderStyle = none; hasHorzScroll = true; hasVertScroll = true; fullRowSelect = false; sortable = true; alwaysHighLight = true; anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; // WHY is this not working ? /*void OnResize(int width, int height) { if(vertScroll.visible) nameField.width = width - vertScroll.size.w; else nameField.width = width; }*/ bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed) { if(row) { FileSystemNode node = (FileSystemNode)row.tag; FileSystemNode child; if(collapsed) { /* for(child = node.children.last; child; child = node.children.last) { listBox.DeleteRow(child.row); child.Free(); delete child; } node.childrenLoaded = false; */ } else { if(!node.bits.loaded || !node.bits.childrenLoaded) { LoadTreeNode(node); //list.Sort(nameField, 1); //node. } for(child = node.children.first; child && child.next; child = child.next); if(child) child.EnsureVisible(false); } } return true; } bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods) { DataRow row = listBox.currentRow; if(row) { FileSystemNode node = (FileSystemNode)row.tag; if(node) { PopupMenu popup; Menu 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, y + clientStart.y + absPosition.y - guiApp.desktop.position.y } }; popup.Create(); } } return true; } bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods) { 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; 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; } bool NotifyEditing(ListBox listBox, DataRow row) { if(row) { FileSystemNode node = (FileSystemNode)row.tag; } return true; } bool NotifyEdited(ListBox listBox, DataRow row) { if(row) { FileSystemNode node = (FileSystemNode)row.tag; } return true; } bool NotifyEditDone(ListBox listBox, DataRow row) { if(row) { FileSystemNode node = (FileSystemNode)row.tag; } return true; } bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods) { 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; if((SmartKey)key == enter) 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 = false; FileSystemBoxSelection sel = this.selection.Copy(); //FileSystemNode node = selection.node; for(node : sel.nodes) { sel.node = node; if(node && node.type.isFolder && bits.navigateFolders) property::path = node.path; if(NotifyNodeOpen(this.master, this, sel) && !result) result = true; } 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 }; MenuItem itemEditCut { editMenu, "Cut\tCtrl+X", t, disabled = true; bool NotifySelect(MenuItem selection, Modifiers mods) { //EditCut(); return true; } }; MenuItem itemEditCopy { editMenu, "Copy\tCtrl+C", c, disabled = true; bool NotifySelect(MenuItem selection, Modifiers mods) { //EditCopy(); return true; } }; MenuItem itemEditPaste { editMenu, "Paste\tCtrl+V", p; bool NotifySelect(MenuItem selection, Modifiers mods) { //EditPaste(); return true; } }; MenuItem itemEditDelete { editMenu, "Delete\tDel", d, disabled = true; bool NotifySelect(MenuItem selection, Modifiers mods) { //EditDelete(); return true; } }; // 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! // this is crashing in for designer when details = true // can't save the file, always yields a crash /*if(list && created) { list.ClearFields(); list.AddField(nameField); if(bits.details) { list.AddField(typeField); list.AddField(sizeField); } }*/ list.Clear(); if(comparedPaths && !bits.treeBranches) LoadComparedList(); else { FileAttribs pathAttribs = FileExists(path); if(pathAttribs) { if(pathAttribs.isDirectory) { 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 LoadTreeDirectory() { bool isRoot = !strcmp(path, "/"); 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__ if(isRoot) { root = FileSystemNode { bits.loaded = true, bits.childrenLoaded = true }; AddTreeNode(root, true, false, false, null); while(listing.Find()) { int len = strlen(listing.name); char info[MAX_LOCATION]; char name[MAX_LOCATION]; if(listing.stats.attribs.isDrive && len > 3 && !strncmp(&listing.name[1], ": [", 3)) { strncpy(name, listing.name, 2); name[2] = 0; strncpy(info, &listing.name[4], len - 5); info[len - 5] = 0; } else { strcpy(name, listing.name); info[0] = 0; } parent = MakeFileSystemNode( listing.stats, name, listing.path, false, bits.previewPictures, false, displaySystem); if(info[0]) 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.bits.childrenLoaded = true; } node = FileSystemNode { name = msNetwork, type = network }; AddTreeNode(node, false, false, true, null); node.row.collapsed = true; } else #endif { 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) { 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(char * name, char * path, FileStats stats, bool isRootObject) { ProcessListItem(name, path, stats, false); return false; } //void ListIterator_OnLeavingDirectory(char * path) { } void ProcessListItem(char * name, 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) { 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); { MapNode mn; PrintLn("------------- DIR LISTING FOR ", dirPath); for(mn = list.root.minimum; mn; mn = mn.next) { PrintLn(mn.key); } } } } */ for(na = names.root.minimum; na; na = na.next) { /*Map equals = na.value; //MapNode nb; /* while(!allDone) { smallest = 0; equals.Add(0); for(c = 1; c < count; c++) { //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); } } */ 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(i != nb.key) */ for(i = 0; i < equals.count; i++) { if(i != equals[i]) { icon = i+1; break; } } //if(!nb) if(i == equals.count) icon = count; not = true; } 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 = (int)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)); } 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); } } FileSystemNode MakeAndAddToTreeFileSystemNodeFromFileListing(FileListing listing, FileSystemNode parent) { 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 textFileLinesStyle = false; 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) { char ext[MAX_LOCATION]; GetExtension(listing.name, ext); if(!strcmpi(ext, "txt") || !strcmpi(ext, "text")) textFileLinesStyle = 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"); } return result; } void AddTreeNode( FileSystemNode node, bool loaded, bool childrenLoaded, bool addLoader, FileSystemNode addTo) { DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : list.AddRow(); if(addTo) { node.parent = addTo; node.indent = addTo.indent + 1; addTo.children.Add(node); } row.tag = (int)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.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, name = "Loader" }, false, false, false, node); if(node.indent > 0 || bits.mode == list) row.collapsed = true; else if(node.type == folder) node.type = folderOpen; } void DeleteNode(FileSystemNode node) { FileSystemNode 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 { borderStyle = none; hasHorzScroll = false; hasVertScroll = false; virtual void Load(FileSystemNode parent); virtual void Refresh(); virtual void LaunchNotifyItemSelect(Window master, ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems) { view.NotifyItemSelect(master, view, item, selectedItems); } virtual bool Window::NotifyItemSelect(ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems); virtual bool Window::NotifyItemOpen(ExplorerView view, ExplorerFileItem item); ListBox list { master = master, parent = this; //this, master; borderStyle = none; hasHorzScroll = true; hasVertScroll = true; resizable = true; sortable = true; fullRowSelect = false; multiSelect = true; anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods) { ExplorerView view = (ExplorerView)listBox.parent; if(listBox.currentRow) { DataRow listRow; ExplorerFileItemArray selectedItems { growingFactor = 16 }; for(listRow = listBox.firstRow; listRow; listRow = listRow.next) if(listRow.selected) selectedItems.Add((ExplorerFileItem)listRow.tag); //view.NotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag); view.LaunchNotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag, selectedItems); } return true; } bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods) { ExplorerView view = (ExplorerView)listBox.parent; view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag); return false; } bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch) { if((SmartKey)key == enter) { ExplorerView view = (ExplorerView)listBox.parent; view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag); } return true; } }; ExplorerView() { } } #endif #if 0 class ExplorerViewList : ExplorerView { FileSystemNode location; public: DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this }; ExplorerViewDetails() { list.AddField(nameField); } void Refresh() { Load(location); } void Load(FileSystemNode location) { char path[MAX_LOCATION]; this.location = location; location.GetPath(path); { FileListing listing { path }; ExplorerFileItem item; DataRow row; list.Clear(); while(listing.Find()) { item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); row = list.AddRow(); row.tag = (int)item; row.SetData(nameField, item); } list.Sort(nameField, 1); } } } #endif #if 0 class ExplorerViewDetails : ExplorerView { list.hasHeader = true; list.moveFields = true; list.resizable = true; list.sortable = true; FileSystemNode location; public: DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this }; DataField typeField { header = "Type", dataType = /-*"String"*-/ "char *", width = 40 }; DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right }; ExplorerViewDetails() { list.AddField(nameField); list.AddField(typeField); list.AddField(sizeField); } void Refresh() { Load(location); } void Load(FileSystemNode location) { char path[MAX_LOCATION]; this.location = location; location.GetPath(path); { FileListing listing { path }; ExplorerFileItem item; DataRow row; list.Clear(); while(listing.Find()) { item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); row = list.AddRow(); row.tag = (int)item; row.SetData(nameField, item); row.SetData(typeField, CopyString(item.extension)); row.SetData(sizeField, (uint)listing.stats.size); } list.Sort(nameField, 1); } } } #endif #if 0 class ExplorerViewIcons : ExplorerView { FileSystemNode location; public: DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this }; ExplorerViewDetails() { list.AddField(nameField); } void Refresh() { Load(location); } void Load(FileSystemNode location) { char path[MAX_LOCATION]; this.location = location; location.GetPath(path); { FileListing listing { path }; ExplorerFileItem item; DataRow row; list.Clear(); while(listing.Find()) { item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); row = list.AddRow(); row.tag = (int)item; row.SetData(nameField, item); } list.Sort(nameField, 1); } } } #endif #if 0 class ExplorerViewCards : ExplorerView { FileSystemNode location; public: DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this }; ExplorerViewDetails() { list.AddField(nameField); } void Refresh() { Load(location); } void Load(FileSystemNode location) { char path[MAX_LOCATION]; this.location = location; location.GetPath(path); { FileListing listing { path }; ExplorerFileItem item; DataRow row; list.Clear(); while(listing.Find()) { item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); row = list.AddRow(); row.tag = (int)item; row.SetData(nameField, item); } list.Sort(nameField, 1); } } } #endif #if 0 public class BitmapArray : RedjArray { type = class(Bitmap); public: Bitmap * const _; Bitmap * Add(Bitmap bitmap) { uint pos = _count; Append(1); _[pos] = bitmap; return &_[pos]; } Bitmap * AddBefore(uint position, Bitmap bitmap) { Insert(position, 1); _[position] = bitmap; return &_[position]; } void Clear() { int c; for(c = 0; c < _count; c++) { _[c].Free(); delete _[c]; } count = 0; size = 0; } } #endif #if 0 class ExplorerViewShowcase : ExplorerView { list.anchor = Anchor { left = 0, top = 0, bottom = 0 }; list.size = Size { w = 200 }; FileSystemNode location; public: DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 180, editable = true, userData = this }; Bitmap bitmap; BitmapArray bitmaps { growingFactor = 16 }; Window show { this; borderStyle = none; anchor = Anchor { top = 0, right = 0, bottom = 0 }; void OnRedraw(Surface surface) { ExplorerViewShowcase view = (ExplorerViewShowcase)parent; if(view.bitmap) { int wBmp = view.bitmap.width; int hBmp = view.bitmap.height; int wWnd = clientSize.w; 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); #ifndef __linux__ surface.Filter(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw, wBmp, hBmp); #else // Until Filter / Stretch works with X surface.Blit(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw); #endif } else { surface.SetForeground(white); surface.Area(0, 0, view.clientSize.w - 1, view.clientSize.h - 1); } } } SplitWindow split { this; leftPane = list; rightPane = show; split = 200; tabCycle = true; }; ExplorerViewDetails() { list.AddField(nameField); } void LaunchNotifyItemSelect(Window master, ExplorerViewShowcase view, ExplorerFileItem item, ExplorerFileItemArray selectedItems) { int pos; ExplorerFileItem selItem; if(view.bitmap) view.bitmap.Free(); delete view.bitmap; if(item && item.type == pictureFile) { view.bitmap = Bitmap { }; view.bitmap.Load(item.path, null, displaySystem); } view.bitmaps.Clear(); view.bitmaps = BitmapArray { }; for(pos = 0; pos < selectedItems.count; pos++) { Bitmap bitmap { }; selItem = (ExplorerFileItem)selectedItems._[pos]; bitmap.Load(selItem.path, null, displaySystem); //view.bitmaps.Add(bitmap); } if(item && item.type == pictureFile) { view.bitmap = Bitmap { }; view.bitmap.Load(item.path, null, displaySystem); } view.show.Update(null); view.NotifyItemSelect(master, view, item, selectedItems); } void Refresh() { Load(location); } void Load(FileSystemNode location) { char path[MAX_LOCATION]; this.location = location; location.GetPath(path); { FileListing listing { path }; ExplorerFileItem item; DataRow row; list.Clear(); while(listing.Find()) { item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem); row = list.AddRow(); row.tag = (int)item; row.SetData(nameField, item); } list.Sort(nameField, 1); } } } #endif #if 0 class ExplorerTree : FileSystemBox { hasHorzScroll = false; hasVertScroll = false; menu = Menu { }; public: DataField nameField { dataType = "FileSystemNode", width = 240, userData = this }; FileSystemNode root; FileSystemNode selection; virtual bool Window::NotifyNodeSelect(ExplorerTree tree, FileSystemNode node); property FileSystemNode node { get { if(!tree) return null; if(!tree.currentRow) return null; if(!tree.currentRow.tag) return null; return (FileSystemNode)tree.currentRow.tag; } } void Select(FileSystemNode node) { if(node.row) { node.EnsureVisible(false); tree.SelectRow(node.row); } } FileSystemNode Find(const char * name, FileSystemNode parent) { FileSystemNode node; FileSystemNode start = parent ? parent : root; if(!start.loaded || !start.childrenLoaded) LoadTreeNode(start, tree); for(node = start.children.first; node; node = node.next) if(node.name && !strcmpi(node.name, name)) return node; return null; } ListBox tree { master = master, parent = this; //this, master; borderStyle = none; hasHorzScroll = true; hasVertScroll = true; fullRowSelect = false; treeNodees = true; collapseControl = true; rootCollapseButton = true; anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 }; // WHY is this not working ? /-*void OnResize(int width, int height) { if(vertScroll.visible) nameField.width = width - vertScroll.size.w; else nameField.width = width; }*-/ bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed) { if(row) { FileSystemNode node = (FileSystemNode)row.tag; FileSystemNode child; if(collapsed) { /-* for(child = node.children.last; child; child = node.children.last) { listBox.DeleteRow(child.row); child.Free(); delete child; } node.childrenLoaded = false; *-/ } else { if(!node.loaded || !node.childrenLoaded) LoadTreeNode(node, tree); for(child = node.children.first; child && child.next; child = child.next); if(child) child.EnsureVisible(false); } } return true; } bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods) { DataRow row = listBox.currentRow; if(row) { FileSystemNode node = (FileSystemNode)row.tag; if(node) { 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 }; popup = PopupMenu { master = this, menu = menu, position = { x + clientStart.x + absPosition.x - guiApp.desktop.position.x, y + clientStart.y + absPosition.y - guiApp.desktop.position.y } }; popup.Create(); } } return true; } bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods) { if(row) { FileSystemNode node = (FileSystemNode)row.tag; NotifyNodeSelect(listBox.parent.master, this, node); selection = node; } return true; } bool NotifyEditing(ListBox listBox, DataRow row) { if(row) { FileSystemNode node = (FileSystemNode)row.tag; } return true; } bool NotifyEdited(ListBox listBox, DataRow row) { if(row) { FileSystemNode node = (FileSystemNode)row.tag; } return true; } bool NotifyEditDone(ListBox listBox, DataRow row) { if(row) { FileSystemNode node = (FileSystemNode)row.tag; } return true; } }; // Edit Menu Menu editMenu { menu, "Edit", e }; MenuItem itemEditCut { editMenu, "Cut\tCtrl+X", t, disabled = true; bool NotifySelect(MenuItem selection, Modifiers mods) { //EditCut(); return true; } }; MenuItem itemEditCopy { editMenu, "Copy\tCtrl+C", c, disabled = true; bool NotifySelect(MenuItem selection, Modifiers mods) { //EditCopy(); return true; } }; MenuItem itemEditPaste { editMenu, "Paste\tCtrl+V", p; bool NotifySelect(MenuItem selection, Modifiers mods) { //EditPaste(); return true; } }; MenuItem itemEditDelete { editMenu, "Delete\tDel", d, disabled = true; bool NotifySelect(MenuItem selection, Modifiers mods) { //EditDelete(); return true; } }; // WHY is this crashing ? /-*void OnResize(int width, int height) { if(this && nameField) nameField.width = width - 80; }*-/ ExplorerTree() { tree.AddField(nameField); } void Load() { FileSystemNode parent; FileSystemNode node; FileListing listing { "/" }; tree.Clear(); root = FileSystemNode { type = computer, loaded = true, childrenLoaded = true }; #ifdef __WIN32__ root.name = rootName; #else root.name = "/"; #endif AddTreeNode(root, true, false, false, null, tree); // 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 && len > 3 && !strncmp(&listing.name[1], ": [", 3)) { strncpy(name, listing.name, 2); name[2] = 0; strncpy(info, &listing.name[4], len - 5); info[len - 5] = 0; } else { strcpy(name, listing.name); info[0] = 0; } parent = MakeFileSystemNode(listing.stats, name); if(info[0]) parent.info = CopyString(info); parent.loaded = true; 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, false, true, null, tree); node.row.collapsed = true; tree.Sort(nameField, 1); tree.SelectRow(root.row); } } #if 0 public class ClipBoardFiles { public: property } // CLIPBOARD void Copy() { if(this) { int size = SelSize(); if(size) { // Try to allocate memory ClipBoard clipBoard { }; if(clipBoard.Allocate(size+1)) { GetSel(clipBoard.memory, true); // Save clipboard clipBoard.Save(); } delete clipBoard; } } } void Paste() { if(this) { ClipBoard clipBoard { }; if(clipBoard.Load()) PutS(clipBoard.memory); delete clipBoard; } } void Cut() { if(this) { Copy(); DelSel(); SetViewToCursor(true); Modified(); } } /-* Private Type DROPFILES pFiles As Long pt As POINTAPI fNC As Long fWide As Long End Type For iCounter = 0 To filelist.ListCount - 1 If filelist.Selected(iCounter) = True Then strFiles = strFiles & FixPath(filelist.Path) & filelist.List(iCounter) & vbNullChar End If Next 'all selected items are now put in strFiles hGlobal = GlobalAlloc(GHND, Len(DF) + Len(strFiles)) 'put all files to a exclusive number 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 *-/ bool SaveFile(const char * filePath) { } #endif #if 0 public class FileTreeNodeBSArray : ArrayBinarySorted { type = class(FileSystemNode); public: FileSystemNode * const _; BSloc Add(FileSystemNode item) { BSloc result = Find(item); if(!result.valid) { Insert(result.pos, 1); _[result.pos] = item; } return result; } BSloc Remove(FileSystemNode item) { } } #endif #if 0 public class FileTreeNodeArray : RedjArray { type = class(FileSystemNode); public: FileSystemNode * const _; FileSystemNode * Add(FileSystemNode item) { uint pos = _count; Append(1); _[pos] = item; return &_[pos]; } FileSystemNode * AddBefore(uint position, FileSystemNode item) { Insert(position, 1); _[position] = item; return &_[position]; } } #endif #if 0 public class ExplorerFileItem : struct { char * path; char * name; char * info; char * extension; _FileType type; int indent; Bitmap bitmap; void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox control, Alignment alignment, DataDisplayFlags displayFlags) { int indentSize = (displayFlags.dropBox) ? 0 : 10; int textOffset; int len; char label[MAX_FILENAME]; //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; if(!icon) { if(type == folder || type == folderOpen) surface.SetForeground(red); //Color { 170, 170, 0 } // REDJ What is that color? indentSize = 8; } textOffset = indent * indentSize + (icon ? (icon.width + 6) : 0); if(info) sprintf(label, "%s [%s]", name, info); else strcpy(label, name); len = strlen(label); surface.WriteTextDots (alignment, x + textOffset, y + 2, width - textOffset, label, len); if(type == pictureFile && control.previewPictures && bitmap) { #ifndef __linux__ //surface.Filter(bitmap, (clientSize.w - w) / 2,(clientSize.h - h) / 2, 0,0, w, h, bitmap.width, bitmap.height); surface.Filter(bitmap, x + indent * indentSize + 2, y, 0, 0, w, h, bitmap.width, bitmap.height); #else // Until Filter / Stretch works with X //surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2,(clientSize.h - bitmap.height) / 2, 0,0, bitmap.width, bitmap.height); surface.blend = true; surface.Blit(bitmap, x + indent * indentSize + 2, y,0,0, w, h); #endif //bitmap.Free(); //delete bitmap; } else if(icon) surface.Blit(icon, x + indent * indentSize + 2, y,0,0, icon.width, icon.height); } int OnCompare(ExplorerFileItem b) { int result; if(type == b.type || (type < folder && b.type < folder) || (type >= drive)) result = strcmpi(name, b.name); else { if(type == folder && b.type < folder) result = -1; else if(type < folder && b.type == folder) result = 1; } return result; } void OnCopy(ExplorerFileItem newData) { type = newData.type; indent = newData.indent; if(newData.name) { int len = strlen(newData.name) + 1; name = new char[len]; CopyBytes(name, newData.name, len); } } bool OnGetDataFromString(char * string) { int len = strlen(string) + 1; name = new char[len]; CopyBytes(name, string, len); return true; } void OnFree() { delete path; delete name; delete info; delete extension; if(bitmap) bitmap.Free(); } char * OnGetString(char * string, void * fieldData, bool * needClass) { return name; } }; public class ExplorerFileItemArray : RedjArray { type = class(ExplorerFileItem); public: ExplorerFileItem * const _; ExplorerFileItem * Add(ExplorerFileItem item) { uint pos = _count; Append(1); _[pos] = item; return &_[pos]; } ExplorerFileItem * AddBefore(uint position, ExplorerFileItem item) { Insert(position, 1); _[position] = item; return &_[position]; } void Clear() { int c; for(c = 0; c < _count; c++) { //_[c].Free() delete _[c]; } count = 0; size = 0; } } ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, const char * filePath, const bool previewPicture, const DisplaySystem displaySystem) { int len = strlen(fileName); char info[MAX_LOCATION]; char name[MAX_LOCATION]; char extension[MAX_EXTENSION]; ExplorerFileItem item { }; //if(stats.attribs.isFile) // -- should work now if(attribs.isDirectory) { extension[0] = 0; item.type = (attribs.isDrive) ? drive : folder; if(attribs.isServer) item.type = server; if(attribs.isShare) item.type = share; if(attribs.isCDROM) item.type = cdrom; if(attribs.isRemote) item.type = netDrive; if(attribs.isRemovable) { if(fileName[0] == 'A' || fileName[0] == 'B') item.type = floppy; else item.type = removable; } } else { GetExtension(fileName, extension); //strupr(extension); strlwr(extension); item.type = _FileType::SelectByExtension(extension); } if(attribs.isDrive && len > 3 && !strncmp(&fileName[1], ": [", 3)) { strncpy(name, fileName, 2); name[2] = 0; strncpy(info, &fileName[4], len - 5); info[len - 5] = 0; } else { strcpy(name, fileName); info[0] = 0; } item.path = CopyString(filePath); item.name = CopyString(name); if(info[0]) item.info = CopyString(info); item.extension = CopyString(extension); if(item.type == pictureFile && previewPicture) { item.bitmap = Bitmap { }; item.bitmap.Load(filePath, null, displaySystem); } return item; } #endif */ 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; FileSystemNode parent; FileSystemNodeType type; char * name;*/ FileSystemNode prev, next; int indent; property bool isListItem { set { bits.isListItem = value; } get { return bits.isListItem; } }; property char * path { set { delete path; if(value && value[0]) path = CopyString(value); } get { return path; } isset { return path && path[0]; } } property 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 char * label { set { delete label; if(value && value[0]) label = CopyString(value); } get { return label; } isset { return label && label[0]; } } property 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; FileSystemNode parent; FileStats stats; 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) { if(path) strcpy(outputPath, path); else if(parent) { FileSystemNode up; if(name) strcpy(outputPath, name); for(up = parent; up; up = up.parent) { char temp[MAX_LOCATION]; strcpy(temp, up.name); PathCat(temp, outputPath); strcpy(outputPath, temp); } } else strcpy(outputPath, name ? name : ""); } bool IsChildOf(FileSystemNode node) { FileSystemNode test; for(test = parent; test; test = test.parent) if(test == node) return true; return false; } void DuplicateChildren(bool recursive, bool forceExpanded, FileSystemNode addTo, FileSystemBox fsb) { if(children.first) { FileSystemNode child; for(child = children.first; child; child = child.next) { FileSystemNode copy { }; copy.name = child.name; //CopyString(child.name); copy.type = child.type; fsb.AddTreeNode(copy, child.bits.loaded, false, false, addTo); if(forceExpanded) copy.row.collapsed = false; if(recursive) child.DuplicateChildren(recursive, forceExpanded, copy, fsb); } } } void EnsureVisible(bool expand) { if(parent) parent.EnsureVisible(true); if(expand) row.collapsed = false; // TODO: row.EnsureVisible(); // making the row visible by scrolling } void OnFree() { //delete name; } void Free() { FileSystemNode child; for(; (child = children.first); ) { child.Free(); children.Delete(child); } //if(name) delete path; delete name; delete extension; delete label; delete info; } void Delete() { Free(); if(parent) parent.children.Delete(this); } 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 xStart; int len; int w, h; //int textOffset; 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) + (comp ? 18*(fsb.bits.columnsCompareStyle ? fsb.comparedPaths.count : 1) : 0); if(!alt) return; if(info) sprintf(text, "%s [%s]", label ? label : alt, info); else 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) surface.SetForeground(yellow); //indentSize = 8; indent = 8; } //textOffset = indent * indentSize + (icon ? (icon.width + 4) : 0); surface.SetForeground(displayFlags.selected ? fsb.selectionText : fsb.foreground); surface.TextOpacity(false); 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, alt, strlen(alt)); surface.WriteTextDots(alignment, xStart, y + 2, width, text, len); if(!guiApp.textMode) { if(displayFlags.current) { if(displayFlags.active) { surface.LineStipple(0x5555); if(displayFlags.selected) surface.SetForeground(0xFFFFFF80); else surface.SetForeground(black); } else { surface.SetForeground(selectionColor); } surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1); 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; h = icon.height; } if(type == pictureFile && fsb.previewPictures && bitmap) { surface.SetForeground(white); surface.blend = true; //#ifndef __linux__ //surface.Filter(bitmap, (clientSize.w - w) / 2,(clientSize.h - h) / 2, 0,0, w, h, bitmap.width, bitmap.height); //surface.Filter(bitmap, x + indent/* * indentSize*/ + 2, y, 0, 0, w, h, bitmap.width, bitmap.height); surface.Filter(bitmap, x,y,0,0, w, h, bitmap.width, bitmap.height); //#else // Until Filter / Stretch works with X //surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2,(clientSize.h - bitmap.height) / 2, 0,0, bitmap.width, bitmap.height); // surface.blend = true; //surface.Blit(bitmap, x + indent/* * indentSize*/ + 2, y,0,0, w, h); //surface.Blit(bitmap, x,y,0,0, bitmap.width, bitmap.height); //#endif //bitmap.Free(); //delete bitmap; } else if(icon) { //surface.blend = true; //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, 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; else if(a.type < folder && b.type == folder) result = 1; else result = 0; } return result; } #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(char * string) { #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) { return name ? name : ""; } } /*FileSystemNode MakeFileSystemNode(const FileStats stats, const char * name) { FileSystemNode node { stats = stats }; node.name = CopyString(name); if(!node.name) node.name = null; if(stats.attribs.isDirectory) { node.type = (stats.attribs.isDrive) ? drive : folder; if(stats.attribs.isServer) node.type = server; 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(name[0] == 'A' || name[0] == 'B') node.type = floppy; else node.type = removable; } } else { char extension[MAX_EXTENSION]; GetExtension(node.name, extension); node.type = _FileType::SelectByExtension(extension); } return node; }*/ 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(name); char info[MAX_LOCATION]; char name2[MAX_LOCATION]; char extension[MAX_EXTENSION]; FileSystemNode node { stats = stats }; /*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'; node.type = (stats.attribs.isDrive) ? drive : folder; if(stats.attribs.isServer) node.type = server; 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(name[0] == 'A' || name[0] == 'B') node.type = floppy; else node.type = removable; } } else { GetExtension(name, extension); strlwr(extension); node.type = _FileType::SelectByExtension(extension); } if(stats.attribs.isDrive && len > 3 && !strncmp(&name[1], ": [", 3)) { strncpy(name2, name, 2); name2[2] = 0; strncpy(info, &name[4], len - 5); info[len - 5] = 0; } else { strcpy(name2, name); info[0] = 0; } 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 = info; //CopyString(info); node.extension = extension; //CopyString(extension); if(node.type == pictureFile && previewPicture) { node.bitmap = Bitmap { alphaBlend = true }; 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; }