2 import "FileSystemCache"
5 static char * rootName = "Entire Computer";
6 static char * msNetwork = "Microsoft Windows Network";
8 static char * rootName = "File System";
12 define guiApp = (GuiApplication)((__thisModule).application);
13 define selectionColor = guiApp.currentSkin.selectionColor; //Color { 10, 36, 106 };
15 void MessageBoxTodo(char * message)
17 PrintLn("MessageBoxTodo(char * message) -- ", message);
18 MessageBox { type = ok, text = "MessageBoxTodo(char * message)", contents = message }.Modal();
21 static char * fileIconNames[] =
23 "<:ecere>mimeTypes/file.png", /* none */
25 "<:ecere>mimeTypes/file.png", /* normalFile */
26 "<:ecere>mimeTypes/textEcereWorkspace.png", /* ewsFile */
27 "<:ecere>mimeTypes/textEcereProject.png", /* epjFile */
28 "<:ecere>mimeTypes/textEcereSource.png", /* ecFile */
29 "<:ecere>mimeTypes/textEcereHeader.png", /* ehFile */
30 "<:ecere>mimeTypes/textCSource.png", /* cFile */
31 "<:ecere>mimeTypes/textCHeader.png", /* hFile */
32 "<:ecere>mimeTypes/textC++Source.png", /* cppFile */
33 "<:ecere>mimeTypes/textC++Header.png", /* hppFile */
34 "<:ecere>mimeTypes/text.png", /* textFile */
35 "<:ecere>mimeTypes/textHyperTextMarkup.png", /* webFile */
36 "<:ecere>mimeTypes/image.png", /* pictureFile */
37 "<:ecere>status/audioVolumeHigh.png", /* soundFile */
38 "<:ecere>mimeTypes/package.png", /* archiveFile */
39 "<:ecere>mimeTypes/packageSoftware.png", /* packageFile */
40 "<:ecere>mimeTypes/packageOpticalDisc.png", /* opticalMediaImageFile */
42 "<:ecere>places/folder.png", /* folder */
43 "<:ecere>status/folderOpen.png", /* folderOpen */
44 "<:ecere>devices/computer.png", /* computer */
45 "<:ecere>devices/driveHardDisk.png", /* drive */
46 "<:ecere>places/driveRemote.png", /* netDrive */
47 "<:ecere>devices/mediaOptical.png", /* cdrom */
48 "<:ecere>devices/driveRemovableMedia.png", /* removable */
49 "<:ecere>devices/mediaFloppy.png", /* floppy */
50 "<:ecere>places/networkWorkgroup.png", /* network */
51 "<:ecere>places/networkServer.png", /* server */
52 "<:ecere>places/folderRemote.png", /* share */
54 "<:ecere>mimeTypes/package.png", /* treeLoader */
55 "<:ecere>places/startHere.png", /* lineNumbers */
60 define countOfCompIconNames = 6;
61 static char * compIconNames[] =
70 "<:ede>devices/media-optical.png",
71 "<:ede>devices/media-flash.png",
72 "<:ede>places/network-server.png",
73 "<:ede>places/folder-saved-search.png",
74 "<:ede>places/user-home.png",
75 "<:ede>emblem-not.png",
83 normalFile, ewsFile, epjFile, ecFile, ehFile, cFile, hFile, cppFile, hppFile,
84 textFile, webFile, pictureFile, soundFile,
85 archiveFile, packageFile, opticalMediaImageFile, /* these (all previous) are sort equal */
87 folder, folderOpen, computer,
88 drive, netDrive, cdrom, removable, floppy, network, server, share, // these are sort equal
98 this = SelectByExtension(value);
102 public property bool isFolder
104 get { return this >= folder && this <= share; }
107 public property bool isFile
109 get { return this >= normalFile && this <= opticalMediaImageFile; }
112 _FileType ::SelectByExtension(char * extension)
114 if(!strcmpi(extension, "ews"))
116 else if(!strcmpi(extension, "epj"))
118 else if(!strcmpi(extension, "ec"))
120 else if(!strcmpi(extension, "eh"))
122 else if(!strcmpi(extension, "cpp") ||
123 !strcmpi(extension, "cc") || !strcmpi(extension, "cxx"))
125 else if(!strcmpi(extension, "hpp") ||
126 !strcmpi(extension, "hh") || !strcmpi(extension, "hxx"))
128 else if(!strcmpi(extension, "c"))
130 else if(!strcmpi(extension, "h"))
132 else if(!strcmpi(extension, "txt") || !strcmpi(extension, "text") ||
133 !strcmpi(extension, "nfo") || !strcmpi(extension, "info"))
135 else if(!strcmpi(extension, "htm") || !strcmpi(extension, "html") ||
136 !strcmpi(extension, "css") || !strcmpi(extension, "php") ||
137 !strcmpi(extension, "js"))
139 else if(!strcmpi(extension, "bmp") || !strcmpi(extension, "pcx") ||
140 !strcmpi(extension, "jpg") || !strcmpi(extension, "jpeg") ||
141 !strcmpi(extension, "gif") || !strcmpi(extension, "png") ||
142 !strcmpi(extension, "ico"))
144 else if(!strcmpi(extension, "wav") || !strcmpi(extension, "mp3") ||
145 !strcmpi(extension, "ogg") || !strcmpi(extension, "snd"))
147 else if(!strcmpi(extension, "ear") || !strcmpi(extension, "7z") ||
148 !strcmpi(extension, "rar") || !strcmpi(extension, "zip") ||
149 !strcmpi(extension, "gz") || !strcmpi(extension, "bz2") ||
150 !strcmpi(extension, "tar") || !strcmpi(extension, "arj") ||
151 !strcmpi(extension, "lza") || !strcmpi(extension, "lzh") ||
152 !strcmpi(extension, "cpio") || !strcmpi(extension, "z"))
154 else if(!strcmpi(extension, "cab") || !strcmpi(extension, "deb") ||
155 !strcmpi(extension, "rpm"))
157 else if(!strcmpi(extension, "iso") || !strcmpi(extension, "mds") ||
158 !strcmpi(extension, "cue") || !strcmpi(extension, "bin") ||
159 !strcmpi(extension, "ccd") || !strcmpi(extension, "bwt") ||
160 !strcmpi(extension, "cdi") || !strcmpi(extension, "nrg"))
161 return opticalMediaImageFile;
166 public enum FileSystemBoxMode { directory, list };
168 class FileSystemBoxBits
170 bool foldersOnly:1, filesOnly:1, details:1, pathColumn:1, treeBranches:1, previewPictures:1, navigateFolders:1, autoLoad:1;
172 bool columnsCompareStyle:1;
173 //bool header:1, freeSelect:1, fullRowSelect:1, multiSelect:1, autoScroll:1, alwaysHL : 1, moveRows:1, resizable:1;
174 //bool moveFields:1, clearHeader:1, alwaysEdit:1, collapse:1, treeBranch:1, rootCollapse:1, heightSet:1;
175 //bool sortable:1, noDragging:1, fillLastField:1, expandOnAdd:1;
176 bool textFileLinesStyle:1;
178 FileSystemBoxMode mode:2;
181 public class FileSystemBox : Window // should we not derive from ListBox instead?
182 // I say we should, but we can't right now...
183 // because ListBox (inside ecere library) is
184 // not exposing enough internal machinery...
185 // could we not have a different private and
186 // public mechanism when deriving a class than
187 // we do when simply instanciating a class?
189 this stuff from the listbox would be nicely exposed...
190 fullRowSelect = false;
192 collapseControl = true;
193 rootCollapseButton = true;
198 hasHorzScroll = false;
199 hasVertScroll = false;
205 FileSystemBoxSelection selection { };
207 subclass(InterfaceFileSystemIterator) iteratorClass;
208 FileSystemCache cache;
210 virtual bool Window::NotifyNodeSelect(FileSystemBox box, FileSystemBoxSelection selection);
211 //virtual bool Window::NotifyNodeNavigate(FileSystemBox box, FileSystemNode node);
212 virtual bool Window::NotifyNodeOpen(FileSystemBox box, FileSystemBoxSelection selection);
213 virtual bool Window::NotifyNodeMenu(FileSystemBox box, Menu menu, FileSystemBoxSelection selection);
214 virtual bool Window::NotifyIteratorInit(FileSystemBox box, FileSystemIterator fileSystemIterator);
221 if(value && value[0])
222 path = CopyString(value);
224 locationBox.path = value;
229 //isset { return path && path[0]; }
232 property Array<String> comparedPaths
236 delete comparedPaths;
237 if(value && value.count)
238 comparedPaths = value;
240 locationBox.path = value[0];
244 get { return comparedPaths; }
245 //isset { return comparedPaths && comparedPaths.count; }
248 property FileSystemBoxMode mode { set { bits.mode = value; } get { return bits.mode; } };
249 property bool foldersOnly { set { bits.foldersOnly = value; bits.filesOnly = !value; } get { return bits.foldersOnly; } };
250 property bool filesOnly { set { bits.filesOnly = value; bits.foldersOnly = !value; } get { return bits.filesOnly; } };
251 property bool previewPictures { set { bits.previewPictures = value; } get { return bits.previewPictures; } };
252 property char * extensions { set { delete extensions; if(value && value[0]) extensions = CopyString(value); } get { return extensions; } }
253 property bool details { set { bits.details = value; ChangeViewType(); } get { return bits.details; } };
254 property bool pathColumn { set { bits.pathColumn = value; ChangeViewType(); } get { return bits.pathColumn; } };
255 property bool treeBranches
259 bits.treeBranches = value;
260 list.treeBranches = value;
261 list.collapseControl = value;
262 list.rootCollapseButton = value;
264 get { return bits.treeBranches; }
266 property Color selectionColor { set { list.selectionColor = value; } get { return list.selectionColor; }/* isset { return selectionColor ? true : false; }*/ };
267 property Color selectionText { set { list.selectionText = value; } get { return list.selectionText; }/* isset { return selectionText ? true : false; }*/ };
268 property bool navigateFolders { set { bits.navigateFolders = value; bits.filesOnly = !value; } get { return bits.navigateFolders; } };
269 property bool multiSelect { set { list.multiSelect = value; } get { return list.multiSelect; } };
270 property bool autoLoad { set { bits.autoLoad = value; } get { return bits.autoLoad; } };
271 property bool hasHeader { set { list.hasHeader = value; } get { return list.hasHeader; } };
272 property bool preview
276 bits.preview = value;
277 split.leftPane = value ? list : null;
278 split.visible = value;
279 show.visible = value;
281 get { return bits.preview; }
283 property bool columnsCompareStyle { set { bits.columnsCompareStyle = value; } get { return bits.columnsCompareStyle; } };
284 property bool textFileLinesStyle { set { bits.textFileLinesStyle = value; } get { return bits.textFileLinesStyle; } };
286 property FileSystemNode node
294 if(!list.currentRow.tag)
296 return (FileSystemNode)list.currentRow.tag;
302 void Select(FileSystemNode node)
306 node.EnsureVisible(false);
307 list.SelectRow(node.row);
311 void SelectMultipleByPath(Array<String> paths)
314 bool firstRow = false;
315 Map<String, bool> map { };
318 for(row = list.firstRow; row; row = row.next)
320 FileSystemNode node = (FileSystemNode)row.tag;
332 row.selected = false;
337 FileSystemNode SelectLocation(char * location)
341 char step[MAX_LOCATION];
343 //StringArray steps { growingFactor = 4 };
344 Array<String> steps { };
345 FileSystemNode result = null;
346 FileSystemNode node = null;
348 temp = CopyString(location);
351 GetLastDirectory(temp, step);
352 StripLastDirectory(temp, temp);
353 steps.Add(CopyString(step));
356 for(c = steps.count - 1; c >= 0; c--)
359 node = Find(steps[c], node);
377 FileSystemNode Find(const char * name, FileSystemNode parent)
379 FileSystemNode node = null;
380 FileSystemNode result = null;
381 if(!parent/* && !strcmp(name, "/")*/)
384 for(row = list.firstRow; row; row = row.next)
386 node = (FileSystemNode)row.tag;
387 if(node.name && !fstrcmp(node.name, name))
396 FileSystemNode start = parent ? parent : root;
397 if(!start.bits.loaded || !start.bits.childrenLoaded)
399 for(node = start.children.first; node; node = node.next)
400 if(node.name && !fstrcmp(node.name, name))
418 bool MenuOpen(MenuItem selection, Modifiers mods)
423 bool MenuReplaceListItemByContainingDir(MenuItem selection, Modifiers mods)
426 //FileSystemBoxSelection selection = this.selection.Copy(); // TOFIX compiler bug -- FileSystemBox.c -- ../libede/src/FileSystemBox.ec:420:49: error: ‘selection’ redeclared as different kind of symbol
427 FileSystemBoxSelection sel = this.selection.Copy();
428 FileSystemNode node = sel.node;
429 char newPath[MAX_LOCATION];
430 StripLastDirectory(node.path, newPath);
431 //node.path = newPath;
433 //if(node && node.type.isFolder && bits.navigateFolders)
434 // property::path = node.path;
439 bool MenuReplaceListItemByChild(MenuItem selection, Modifiers mods)
442 //FileSystemBoxSelection selection = this.selection.Copy(); // TOFIX compiler bug -- FileSystemBox.c -- ../libede/src/FileSystemBox.ec:420:49: error: ‘selection’ redeclared as different kind of symbol
443 FileSystemBoxSelection sel = this.selection.Copy();
444 FileSystemNode node = sel.node;
445 char newPath[MAX_LOCATION];
446 StripLastDirectory(node.path, newPath);
447 //node.path = newPath;
449 //if(node && node.type.isFolder && bits.navigateFolders)
450 // property::path = node.path;
456 FileSystemBoxBits bits;
460 Array<String> comparedPaths;
462 BitmapResource fileIcons[_FileType];
463 BitmapResource compIcons[countOfCompIconNames]; // todo: fix this limitation
466 //BitmapArray bitmaps { growingFactor = 16 };
470 char wd[MAX_LOCATION];
471 GetWorkingDir(wd, sizeof(wd));
475 InitCompIcons(); // todo: these icons should not be initialize, they should be set
476 // or at least initalized when the comparison listing is requested
477 // and we know how many paths are being compared.
478 list.AddField(nameField);
479 bits.autoLoad = true;
480 //iteratorClass = class(FileSystemIterator);
491 list.background = background;
497 for(c = 0; c < _FileType::enumSize; c++)
499 fileIcons[c] = BitmapResource { fileIconNames[c], alphaBlend = true };
500 AddResource(fileIcons[c]);
507 for(c = 0; c < countOfCompIconNames; c++)
509 compIcons[c] = BitmapResource { compIconNames[c], alphaBlend = true };
510 AddResource(compIcons[c]);
514 DataField nameField { header = "Name", dataType = "FileSystemNode", width = 240, userData = this, freeData = false/*, editable = true*/; };
515 DataField pathField { header = "Location", dataType = /*"String"*/ "char *", width = 300, freeData = true };
516 DataField typeField { header = "Type", dataType = /*"String"*/ "char *", width = 40, freeData = false };
517 DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right, freeData = false };
518 DataField modifiedField { header = "Modified", dataType = "SecSince1970", width = 96, alignment = right, freeData = false };
526 char wd[MAX_LOCATION];
527 GetWorkingDir(wd, sizeof(wd));
540 hasHorzScroll = true;
541 hasVertScroll = true;
542 fullRowSelect = false;
544 alwaysHighLight = true;
546 anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
548 // WHY is this not working ?
549 /*void OnResize(int width, int height)
551 if(vertScroll.visible)
552 nameField.width = width - vertScroll.size.w;
554 nameField.width = width;
557 bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed)
561 FileSystemNode node = (FileSystemNode)row.tag;
562 FileSystemNode child;
566 for(child = node.children.last; child; child = node.children.last)
568 listBox.DeleteRow(child.row);
572 node.childrenLoaded = false;
577 if(!node.bits.loaded || !node.bits.childrenLoaded)
580 //list.Sort(nameField, 1);
583 for(child = node.children.first; child && child.next; child = child.next);
585 child.EnsureVisible(false);
591 bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods)
593 DataRow row = listBox.currentRow;
596 FileSystemNode node = (FileSystemNode)row.tag;
603 NotifyNodeMenu(master, this, menu, selection);
608 text = PrintString("Open ", node.name);
609 MenuItem { menu, text, o, NotifySelect = MenuOpen, disabled = false }; //delete text;
611 if(node.bits.isListItem/* && TODO: unless node is at root location*/)
613 MenuDivider { menu };
614 MenuItem { menu, "Replace by Parent\tCtrl+R", r, NotifySelect = MenuReplaceListItemByContainingDir, disabled = false };
616 else if(bits.mode == list)
618 MenuDivider { menu };
619 MenuItem { menu, "Replace List Item\tCtrl+R", r, NotifySelect = MenuReplaceListItemByChild, disabled = false };
621 MenuDivider { menu };
622 MenuItem { menu, "Cut\tCtrl+X", t, NotifySelect = null, disabled = false };
623 MenuItem { menu, "Copy\tCtrl+C", c, NotifySelect = null, disabled = false };
624 MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /*!clipboard*/ };
625 MenuItem { menu, "Delete\tDel", d, NotifySelect = null, disabled = false };
626 //MenuDivider { menu };
631 master = this, menu = menu,
633 x + clientStart.x + absPosition.x - guiApp.desktop.position.x,
634 y + clientStart.y + absPosition.y - guiApp.desktop.position.y }
642 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
647 selection.nodes.Free();
648 list.GetMultiSelection(rows);
649 for(item = rows.first; item; item = item.next)
651 DataRow row = item.data;
652 FileSystemNode node = (FileSystemNode)row.tag;
653 selection.nodes.Add(node);
658 selection.node = (FileSystemNode)row.tag;
660 selection.node = null;
662 if(selection.node && bits.preview)
665 FileSystemNode node = selection.node;
669 if(node && node.type == pictureFile)
672 bitmap.Load(node.path, null, displaySystem);
676 bitmaps = BitmapArray { };
677 for(pos = 0; pos < selectedItems.count; pos++)
680 selItem = (ExplorerFileItem)selectedItems._[pos];
681 bitmap.Load(selItem.path, null, displaySystem);
682 //bitmaps.Add(bitmap);
684 if(node && node.type == pictureFile)
687 bitmap.Load(node.path, null, displaySystem);
691 //NotifyItemSelect(master, view, item, selectedItems);
694 NotifyNodeSelect(listBox.parent.master, this, selection);
698 bool NotifyEditing(ListBox listBox, DataRow row)
702 FileSystemNode node = (FileSystemNode)row.tag;
707 bool NotifyEdited(ListBox listBox, DataRow row)
711 FileSystemNode node = (FileSystemNode)row.tag;
716 bool NotifyEditDone(ListBox listBox, DataRow row)
720 FileSystemNode node = (FileSystemNode)row.tag;
725 bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods)
727 bool result = !(selection.node && selection.node.type.isFolder && bits.navigateFolders);
732 bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
735 if((SmartKey)key == enter)
738 else if((SmartKey)key == f2)
739 result = RenameNode();
741 else if((SmartKey)key == f2)
743 FileSystemNode node = selection.node;
744 node.row.Edit(nameField);
768 anchor = Anchor { top = 0, right = 0, bottom = 0 };
770 void OnRedraw(Surface surface)
772 FileSystemBox fsb = (FileSystemBox)parent;
775 int wBmp = fsb.bitmap.width;
776 int hBmp = fsb.bitmap.height;
777 int wWnd = fsb.show.clientSize.w;
778 int hWnd = fsb.show.clientSize.h;
780 int wList = 0;//fsb.list.size.w + fsb.split.size.w;
782 float scale = Min((float)(wWnd - 10) / wBmp, (float)(hWnd - 10) / hBmp);
784 int wDraw = (int)(wBmp * scale);
785 int hDraw = (int)(hBmp * scale);
788 surface.Filter(fsb.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw, wBmp, hBmp);
790 // Until Filter / Stretch works with X
791 surface.Blit(fsb.bitmap, (wWnd - wBmp) / 2, (hWnd - hBmp) / 2, 0, 0, wBmp, hBmp);
796 surface.SetForeground(white);
797 surface.Area(0, 0, fsb.clientSize.w - 1, fsb.clientSize.h - 1);
805 FileSystemBoxSelection sel = this.selection.Copy();
806 //FileSystemNode node = selection.node;
807 for(node : sel.nodes)
810 if(node && node.type.isFolder && bits.navigateFolders)
811 property::path = node.path;
812 if(NotifyNodeOpen(this.master, this, sel) && !result)
823 //FileSystemBoxSelection selection = this.selection.Copy();
824 FileSystemNode node = selection.node;
825 //if(node && node.type.isFolder && bits.navigateFolders)
826 // property::path = node.path;
827 // ------------------------------------------- working here ---------------------------
829 /*result = NotifyNodeRename(this.master, this, node);
832 if(RenameFile(oldn, newn))
842 Menu editMenu { menu, "Edit", e };
845 editMenu, "Cut\tCtrl+X", t, disabled = true;
847 bool NotifySelect(MenuItem selection, Modifiers mods)
853 MenuItem itemEditCopy
855 editMenu, "Copy\tCtrl+C", c, disabled = true;
857 bool NotifySelect(MenuItem selection, Modifiers mods)
863 MenuItem itemEditPaste
865 editMenu, "Paste\tCtrl+V", p;
867 bool NotifySelect(MenuItem selection, Modifiers mods)
873 MenuItem itemEditDelete
875 editMenu, "Delete\tDel", d, disabled = true;
877 bool NotifySelect(MenuItem selection, Modifiers mods)
884 // WHY is this crashing ?
885 /*void OnResize(int width, int height)
887 if(this && nameField)
888 nameField.width = width - 80;
891 void ChangeViewType()
895 list.resizable = bits.details || bits.pathColumn;
896 list.moveFields = bits.details || bits.pathColumn;
897 list.hasHeader = bits.details || bits.pathColumn;
898 list.AddField(nameField);
900 list.AddField(pathField);
903 list.AddField(typeField);
904 list.AddField(sizeField);
905 list.AddField(modifiedField);
912 // this is crashing in for designer when details = true // can't save the file, always yields a crash
913 /*if(list && created)
916 list.AddField(nameField);
919 list.AddField(typeField);
920 list.AddField(sizeField);
924 if(comparedPaths && !bits.treeBranches)
928 FileAttribs pathAttribs = FileExists(path);
931 if(pathAttribs.isDirectory)
933 if(bits.treeBranches)
943 else if(pathAttribs.isFile) // we assume this is a file list
945 File f = FileOpen(path, read);
948 if(bits.treeBranches)
955 MessageBoxTodo($"unable to open file list");
958 MessageBoxTodo($"path is not a directory nor is it a file");
961 MessageBoxTodo($"path does not exist");
963 list.Sort(nameField, 1);
966 void LoadTreeDirectory()
968 bool isRoot = !strcmp(path, "/");
969 char name[MAX_LOCATION];
970 FileSystemNode parent;
972 FileListing listing { path, extensions = extensions };
975 GetLastDirectory(path, name);
980 GetWorkingDir(startPath, sizeof(startPath));
982 strcpy(path, startPath);*/
983 bits.mode = directory;
991 root = FileSystemNode { bits.loaded = true, bits.childrenLoaded = true };
992 AddTreeNode(root, true, false, false, null);
993 while(listing.Find())
995 int len = strlen(listing.name);
996 char info[MAX_LOCATION];
997 char name[MAX_LOCATION];
998 if(listing.stats.attribs.isDrive &&
999 len > 3 && !strncmp(&listing.name[1], ": [", 3))
1001 strncpy(name, listing.name, 2);
1003 strncpy(info, &listing.name[4], len - 5);
1008 strcpy(name, listing.name);
1017 false, bits.previewPictures, false,
1020 parent.info = info; //CopyString(info);
1021 parent.bits.loaded = true;
1024 !listing.stats.attribs.isDirectory,
1026 listing.stats.attribs.isDirectory,
1028 if(!listing.stats.attribs.isDirectory)
1029 parent.bits.childrenLoaded = true;
1032 node = FileSystemNode { name = msNetwork, type = network };
1033 AddTreeNode(node, false, false, true, null);
1034 node.row.collapsed = true;
1040 FileGetStats(path, stats);
1041 root = MakeFileSystemNode(stats, name, path, false, bits.previewPictures, false, displaySystem);
1042 AddTreeNode(root, false, false, true, null);
1048 root.type = computer;
1049 root.label = rootName;
1052 list.Sort(nameField, 1);
1053 list.SelectRow(root.row);
1056 void LoadListDirectory()
1058 FileListing listing { path, extensions = extensions };
1060 bits.mode = directory;
1061 while(listing.Find())
1062 ProcessListItem(listing.name, listing.path, listing.stats, false);
1065 void LoadListFileList(File f)
1069 while(f.GetLine(line, 65536))
1072 char name[MAX_FILENAME];
1073 FileGetStats(line, stats);
1074 GetLastDirectory(line, name);
1075 ProcessListItem(name, line, stats, true);
1079 void LoadTreeFileList(File f)
1083 while(f.GetLine(line, 65536))
1086 char name[MAX_FILENAME];
1087 FileSystemNode node;
1088 FileGetStats(line, stats);
1089 GetLastDirectory(line, name);
1090 node = ProcessTreeItem(name, line, stats, node);
1094 void LoadListIterator()
1096 FileSystemIterator iterator = eInstance_New(iteratorClass);
1099 iterator.owner = this;
1100 iterator.OnObject = ListIterator_OnObject;
1101 //iterator.OnLeavingDirectory = ListIterator_OnLeavingDirectory;
1102 NotifyIteratorInit(master, this, iterator);
1103 iterator.Iterate(path, true);
1108 bool ListIterator_OnObject(char * name, char * path, FileStats stats, bool isRootObject)
1110 ProcessListItem(name, path, stats, false);
1114 //void ListIterator_OnLeavingDirectory(char * path) { }
1116 void ProcessListItem(char * name, char * path, FileStats stats, bool isListItem)
1118 if((!bits.foldersOnly && !bits.filesOnly) || (bits.foldersOnly && stats.attribs.isDirectory) || (bits.filesOnly && stats.attribs.isFile))
1120 FileSystemNode node = MakeFileSystemNode(stats, name, path, false, bits.previewPictures, isListItem, displaySystem);
1125 FileSystemNode ProcessTreeItem(char * name, char * path, FileStats stats, FileSystemNode parent)
1127 FileSystemNode node = MakeFileSystemNode(stats, name, path, false, bits.previewPictures, true, displaySystem);
1128 AddTreeNode(parent, false, false, true, null);
1129 //LoadTreeNode(node);
1133 void LoadTreeNode(FileSystemNode node)
1135 if(!node.bits.loaded)
1137 char path[MAX_LOCATION];
1140 FileListing listing { path, extensions = extensions };
1141 if(node.children.count == 1)
1142 DeleteNode(node.children.first);
1144 while(listing.Find())
1147 FileSystemNode child = null;
1148 if(!listing.stats.attribs.isRemovable && ((!bits.foldersOnly && !bits.filesOnly) ||
1149 (bits.foldersOnly && listing.stats.attribs.isDirectory) ||
1150 (bits.filesOnly && listing.stats.attribs.isFile)))
1151 child = MakeAndAddToTreeFileSystemNodeFromFileListing(listing, node);
1153 NodeChildLoad(child, node);
1159 node.bits.childrenLoaded = true;
1160 node.bits.loaded = true;
1161 node.row.SortSubRows(false);
1163 else if(!node.bits.childrenLoaded)
1165 FileSystemNode child;
1166 if(node.children.first)
1168 for(child = node.children.first; child; child = child.next)
1170 if(!child.bits.loaded)
1171 LoadTreeNode(child);
1172 else if(!child.bits.childrenLoaded)
1173 NodeChildLoad(child, node);
1175 node.bits.childrenLoaded = true;
1176 node.row.SortSubRows(false);
1181 void NodeChildLoad(FileSystemNode parent, FileSystemNode node)
1183 char path[MAX_LOCATION];
1184 parent.GetPath(path);
1185 if(bits.textFileLinesStyle && FileExists(path).isFile)
1192 FileListing listing { path, extensions = extensions };
1193 while(listing.Find())
1196 FileSystemNode child = null;
1197 if((!bits.foldersOnly && !bits.filesOnly) ||
1198 (bits.foldersOnly && listing.stats.attribs.isDirectory) ||
1199 (bits.filesOnly && listing.stats.attribs.isFile))
1200 child = MakeAndAddToTreeFileSystemNodeFromFileListing(listing, parent);
1210 parent.bits.childrenLoaded = true;
1213 void LoadComparedList()
1215 int c, cmp/*, smallest*/, icon;//, equalCount;
1216 int count = comparedPaths ? comparedPaths.count : 0;
1217 //bool allDone = false;
1220 char path[MAX_LOCATION];
1221 //Array<ComparisonState> states { };
1222 //Array<FileListing> listings { };
1223 //Array<int> equals { };
1224 //Array<MapNode<String, int>> mapNodes { };
1226 //Array<Map<String, int>> lists { };
1227 //Map<int, bool> equals{ };
1230 MapNode<String, /*Map<int, */Array<int>> na;
1231 //MapNode<int, int> nb;
1232 Map<String, /*Map<int, */Array<int>> names { };
1233 //Map<String, Array<bool>> names { };
1234 //Map<String, bool[16]> names { }; // does not seem to be working
1235 //Map<String, BoolArrayInt> names { };
1237 for(c = 0; c < comparedPaths.count; c++)
1239 FileListing listing { comparedPaths[c], extensions = extensions };
1240 while(listing.Find())
1242 /*Map<int, int>*/Array<int> m = names[listing.name];
1245 names[listing.name] = m;
1246 /*/m[c] = */m.Add(c);
1249 /* // compiles and should work but better solution?
1250 for(c = 0; c < comparedPaths.count; c++)
1252 FileListing listing { comparedPaths[c], extensions = extensions };
1253 while(listing.Find())
1255 Array<bool> a = names[listing.name];
1258 names[listing.name] = a;
1263 /* // does not seem to be working
1264 for(c = 0; c < comparedPaths.count; c++)
1266 FileListing listing { comparedPaths[c], extensions = extensions };
1267 while(listing.Find())
1269 names[listing.name][c] = true;
1274 if(comparedPaths.count > 0)
1276 FileListing listing { comparedPaths[0], extensions = extensions };
1277 while(listing.Find())
1279 // should be able to just do names[listing.name]._0 = true;
1280 BoolArrayInt bai = names[listing.name];
1282 names[listing.name] = bai;
1285 if(comparedPaths.count > 1)
1287 FileListing listing { comparedPaths[1], extensions = extensions };
1288 while(listing.Find())
1290 // should be able to just do names[listing.name]._1 = true;
1291 BoolArrayInt bai = names[listing.name];
1293 names[listing.name] = bai;
1301 for(dirPath : comparedPaths)
1304 if(FileExists(dirPath).isDirectory)
1306 FileListing listing { dirPath, extensions = extensions };
1307 //MapNode<String, int> mn;
1308 Map<String, int> list { };
1309 //states.Add(listing.Find() == true ? matching : endOfListing);
1310 while(listing.Find())
1311 list[listing.name] = 0;
1312 //for(mn = ; mn; mn = mn.next)
1313 //mn = list.root.minimum;
1314 mapNodes.Add(/-*mn*-/list.root.minimum);
1316 //PrintLn(dirPath, " -- .Find() -- ", states[states.count-1] == matching ? listing.name : "endOfListing*");
1317 //listings.Add(listing);
1320 MapNode<String, int> mn;
1321 PrintLn("------------- DIR LISTING FOR ", dirPath);
1322 for(mn = list.root.minimum; mn; mn = mn.next)
1331 for(na = names.root.minimum; na; na = na.next)
1333 /*Map<int, */Array<int> equals = na.value;
1334 //MapNode<int, int> nb;
1340 for(c = 1; c < count; c++)
1342 //if(states[c] == endOfListing) continue;
1343 if(!mapNodes[c]) continue;
1344 // todo: use better comparison method
1345 // it should compare file type (dir/file) before
1346 // comparing file name.
1347 // should also provide alternative methods
1348 // of comparison including ones that consider
1349 // date changes as differences of some kind.
1350 // pethaps a OnCompare(a, b) to allow implementation
1351 // of custom methods of comparison.
1352 // note: this (or these) method(s) depend on files
1353 // being listed in sorted order by FileListing.
1354 // different comparison methods should have
1355 // appropriatly different sorting in FileListing.
1357 //cmp = strcmp(listings[smallest].name, listings[c].name);
1358 cmp = fstrcmp(mapNodes[smallest].key, mapNodes[c].key);
1359 PrintLn("COMPARING - ", mapNodes[smallest].key, " and ", mapNodes[c].key);
1372 if(equals.count == count) // all are equal, no diff icon
1377 else if(equals.count == count-1) // all are equal but one, not-sign icon for singled out missing
1381 for(nb = equals.root.minimum, i = 0; nb; nb = nb.next, i++)
1385 for(i = 0; i < equals.count; i++)
1394 if(i == equals.count)
1398 else if(equals.count == 1) // only one is present, all others missing, present-sign for singled out present
1400 //icon = equals.root.minimum.key+1;
1411 if(equals.count == count) // all are equal, no diff icon
1413 else if(count/2 - equals.count < 0) // more than half are equal, use not-sign icons for all missing
1415 else // less than half are equal, use present-sign icons for all present
1419 /*if((!bits.foldersOnly && !bits.filesOnly) ||
1420 (bits.foldersOnly && listings[smallest].stats.attribs.isDirectory) ||
1421 (bits.filesOnly && listings[smallest].stats.attribs.isFile))*/
1422 strcpy(path, comparedPaths[/*smallest*/equals[0]]);
1423 PathCat(path, /*mapNodes[smallest].key*/na.key);
1424 FileGetStats(path, stats);
1425 if((!bits.foldersOnly && !bits.filesOnly) ||
1426 (bits.foldersOnly && stats.attribs.isDirectory) ||
1427 (bits.filesOnly && stats.attribs.isFile))
1429 FileSystemNode node =
1430 MakeComparedFileSystemNode(
1432 /*mapNodes[smallest].key*/na.key,
1434 false, bits.previewPictures,
1442 mapNodes[equal] = mapNodes[equal].next;
1443 //states[equal] = listings[equal].Find() == true ? matching : endOfListing;
1444 //PrintLn(comparedPaths[equal], " -- .Find() -- ", states[equal] == matching ? listings[equal].name : "endOfListing*");
1447 //for(c = 0; c < count && states[c] == endOfListing; c++);
1448 for(c = 0; c < count && !mapNodes[c]; c++);
1453 list.Sort(nameField, 1);
1456 void AddNode(FileSystemNode node)
1458 DataRow row = list.AddRow();
1459 row.tag = (int)node;
1462 row.SetData(nameField, node);
1465 char path[MAX_LOCATION];
1466 StripLastDirectory(node.path, path);
1467 row.SetData(pathField, CopyString(path));
1471 if(node.type.isFile)
1473 row.SetData(typeField, node.extension);
1474 row.SetData(sizeField, /*(void *)*/node.stats.size);
1476 row.SetData(modifiedField, node.stats.modified);
1480 FileSystemNode MakeAndAddToTreeFileSystemNodeFromFileListing(FileListing listing, FileSystemNode parent)
1482 FileSystemNode result = null;
1483 /*if((!bits.foldersOnly && !bits.filesOnly) ||
1484 (bits.foldersOnly && listing.stats.attribs.isDirectory) ||
1485 (bits.filesOnly && listing.stats.attribs.isFile))*/
1486 /*if(!listing.stats.attribs.isRemovable && ((!bits.foldersOnly && !bits.filesOnly) ||
1487 (bits.foldersOnly && listing.stats.attribs.isDirectory) ||
1488 (bits.filesOnly && listing.stats.attribs.isFile)))*/
1490 bool textFileLinesStyle = false;
1491 char * test = listing.name;
1494 result = MakeFileSystemNode(listing.stats, listing.name, listing.path, false, bits.previewPictures, false, displaySystem);
1498 if(bits.textFileLinesStyle)
1500 char ext[MAX_LOCATION];
1501 GetExtension(listing.name, ext);
1502 if(!strcmpi(ext, "txt") || !strcmpi(ext, "text"))
1503 textFileLinesStyle = true;
1505 //AddTreeNode(result, true, false, textFileLinesStyle, parent);
1506 AddTreeNode(result, !textFileLinesStyle && listing.stats.attribs.isFile, false, !listing.stats.attribs.isFile || textFileLinesStyle, parent);
1515 FileSystemNode node,
1517 bool childrenLoaded,
1519 FileSystemNode addTo)
1521 DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : list.AddRow();
1524 node.parent = addTo;
1525 node.indent = addTo.indent + 1;
1526 addTo.children.Add(node);
1528 row.tag = (int)node;
1530 row.SetData(null, node);
1533 char path[MAX_LOCATION];
1534 StripLastDirectory(node.path, path);
1535 row.SetData(pathField, CopyString(path));
1539 if(node.type.isFile)
1541 row.SetData(typeField, node.extension);
1542 row.SetData(sizeField, /*(void *)*/node.stats.size);
1544 row.SetData(modifiedField, node.stats.modified);
1547 node.bits.loaded = loaded;
1548 node.bits.childrenLoaded = childrenLoaded;
1550 //AddTreeNode(FileSystemNode { }, false, false, node); // why would this create a compile error?
1551 AddTreeNode(FileSystemNode { type = none, name = "Loader" }, false, false, false, node);
1553 if(node.indent > 0 || bits.mode == list)
1554 row.collapsed = true;
1555 else if(node.type == folder)
1556 node.type = folderOpen;
1559 void DeleteNode(FileSystemNode node)
1561 FileSystemNode child;
1564 for(; (child = node.children.first); )
1567 list.DeleteRow(node.row);
1574 enum ComparisonState { endOfListing, matching };
1578 class ExplorerView : FileSystemBox
1581 hasHorzScroll = false;
1582 hasVertScroll = false;
1584 virtual void Load(FileSystemNode parent);
1585 virtual void Refresh();
1587 virtual void LaunchNotifyItemSelect(Window master, ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems)
1589 view.NotifyItemSelect(master, view, item, selectedItems);
1592 virtual bool Window::NotifyItemSelect(ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems);
1593 virtual bool Window::NotifyItemOpen(ExplorerView view, ExplorerFileItem item);
1597 master = master, parent = this;
1600 hasHorzScroll = true;
1601 hasVertScroll = true;
1604 fullRowSelect = false;
1607 anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
1609 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
1611 ExplorerView view = (ExplorerView)listBox.parent;
1612 if(listBox.currentRow)
1615 ExplorerFileItemArray selectedItems { growingFactor = 16 };
1616 for(listRow = listBox.firstRow; listRow; listRow = listRow.next)
1617 if(listRow.selected)
1618 selectedItems.Add((ExplorerFileItem)listRow.tag);
1619 //view.NotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag);
1620 view.LaunchNotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag, selectedItems);
1625 bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods)
1627 ExplorerView view = (ExplorerView)listBox.parent;
1628 view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag);
1632 bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
1634 if((SmartKey)key == enter)
1636 ExplorerView view = (ExplorerView)listBox.parent;
1637 view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag);
1650 class ExplorerViewList : ExplorerView
1653 FileSystemNode location;
1657 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
1659 ExplorerViewDetails()
1661 list.AddField(nameField);
1669 void Load(FileSystemNode location)
1671 char path[MAX_LOCATION];
1672 this.location = location;
1673 location.GetPath(path);
1675 FileListing listing { path };
1677 ExplorerFileItem item;
1682 while(listing.Find())
1684 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
1686 row = list.AddRow();
1687 row.tag = (int)item;
1688 row.SetData(nameField, item);
1690 list.Sort(nameField, 1);
1697 class ExplorerViewDetails : ExplorerView
1699 list.hasHeader = true;
1700 list.moveFields = true;
1701 list.resizable = true;
1702 list.sortable = true;
1704 FileSystemNode location;
1708 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
1709 DataField typeField { header = "Type", dataType = /-*"String"*-/ "char *", width = 40 };
1710 DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right };
1712 ExplorerViewDetails()
1714 list.AddField(nameField);
1715 list.AddField(typeField);
1716 list.AddField(sizeField);
1724 void Load(FileSystemNode location)
1726 char path[MAX_LOCATION];
1727 this.location = location;
1728 location.GetPath(path);
1730 FileListing listing { path };
1732 ExplorerFileItem item;
1737 while(listing.Find())
1739 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
1741 row = list.AddRow();
1742 row.tag = (int)item;
1743 row.SetData(nameField, item);
1744 row.SetData(typeField, CopyString(item.extension));
1745 row.SetData(sizeField, (uint)listing.stats.size);
1747 list.Sort(nameField, 1);
1754 class ExplorerViewIcons : ExplorerView
1757 FileSystemNode location;
1761 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
1763 ExplorerViewDetails()
1765 list.AddField(nameField);
1773 void Load(FileSystemNode location)
1775 char path[MAX_LOCATION];
1776 this.location = location;
1777 location.GetPath(path);
1779 FileListing listing { path };
1781 ExplorerFileItem item;
1786 while(listing.Find())
1788 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
1790 row = list.AddRow();
1791 row.tag = (int)item;
1792 row.SetData(nameField, item);
1794 list.Sort(nameField, 1);
1801 class ExplorerViewCards : ExplorerView
1804 FileSystemNode location;
1808 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
1810 ExplorerViewDetails()
1812 list.AddField(nameField);
1820 void Load(FileSystemNode location)
1822 char path[MAX_LOCATION];
1823 this.location = location;
1824 location.GetPath(path);
1826 FileListing listing { path };
1828 ExplorerFileItem item;
1833 while(listing.Find())
1835 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
1837 row = list.AddRow();
1838 row.tag = (int)item;
1839 row.SetData(nameField, item);
1841 list.Sort(nameField, 1);
1848 public class BitmapArray : RedjArray
1850 type = class(Bitmap);
1853 Bitmap * Add(Bitmap bitmap)
1860 Bitmap * AddBefore(uint position, Bitmap bitmap)
1862 Insert(position, 1);
1863 _[position] = bitmap;
1864 return &_[position];
1869 for(c = 0; c < _count; c++)
1881 class ExplorerViewShowcase : ExplorerView
1883 list.anchor = Anchor { left = 0, top = 0, bottom = 0 };
1884 list.size = Size { w = 200 };
1886 FileSystemNode location;
1890 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 180, editable = true, userData = this };
1893 BitmapArray bitmaps { growingFactor = 16 };
1899 anchor = Anchor { top = 0, right = 0, bottom = 0 };
1901 void OnRedraw(Surface surface)
1903 ExplorerViewShowcase view = (ExplorerViewShowcase)parent;
1906 int wBmp = view.bitmap.width;
1907 int hBmp = view.bitmap.height;
1908 int wWnd = clientSize.w;
1909 int hWnd = clientSize.h;
1911 int wList = view.list.size.w + view.split.size.w;
1913 float scale = Min((float)(wWnd - 10) / wBmp, (float)(hWnd - 10) / hBmp);
1915 int wDraw = (int)(wBmp * scale);
1916 int hDraw = (int)(hBmp * scale);
1919 surface.Filter(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw, wBmp, hBmp);
1921 // Until Filter / Stretch works with X
1922 surface.Blit(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw);
1927 surface.SetForeground(white);
1928 surface.Area(0, 0, view.clientSize.w - 1, view.clientSize.h - 1);
1942 ExplorerViewDetails()
1944 list.AddField(nameField);
1947 void LaunchNotifyItemSelect(Window master, ExplorerViewShowcase view, ExplorerFileItem item, ExplorerFileItemArray selectedItems)
1950 ExplorerFileItem selItem;
1954 if(item && item.type == pictureFile)
1956 view.bitmap = Bitmap { };
1957 view.bitmap.Load(item.path, null, displaySystem);
1960 view.bitmaps.Clear();
1961 view.bitmaps = BitmapArray { };
1962 for(pos = 0; pos < selectedItems.count; pos++)
1965 selItem = (ExplorerFileItem)selectedItems._[pos];
1966 bitmap.Load(selItem.path, null, displaySystem);
1967 //view.bitmaps.Add(bitmap);
1969 if(item && item.type == pictureFile)
1971 view.bitmap = Bitmap { };
1972 view.bitmap.Load(item.path, null, displaySystem);
1975 view.show.Update(null);
1976 view.NotifyItemSelect(master, view, item, selectedItems);
1984 void Load(FileSystemNode location)
1986 char path[MAX_LOCATION];
1987 this.location = location;
1988 location.GetPath(path);
1990 FileListing listing { path };
1992 ExplorerFileItem item;
1997 while(listing.Find())
1999 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
2001 row = list.AddRow();
2002 row.tag = (int)item;
2003 row.SetData(nameField, item);
2005 list.Sort(nameField, 1);
2012 class ExplorerTree : FileSystemBox
2014 hasHorzScroll = false;
2015 hasVertScroll = false;
2021 DataField nameField { dataType = "FileSystemNode", width = 240, userData = this };
2023 FileSystemNode root;
2024 FileSystemNode selection;
2026 virtual bool Window::NotifyNodeSelect(ExplorerTree tree, FileSystemNode node);
2028 property FileSystemNode node
2034 if(!tree.currentRow)
2036 if(!tree.currentRow.tag)
2038 return (FileSystemNode)tree.currentRow.tag;
2042 void Select(FileSystemNode node)
2046 node.EnsureVisible(false);
2047 tree.SelectRow(node.row);
2051 FileSystemNode Find(const char * name, FileSystemNode parent)
2053 FileSystemNode node;
2054 FileSystemNode start = parent ? parent : root;
2055 if(!start.loaded || !start.childrenLoaded)
2056 LoadTreeNode(start, tree);
2057 for(node = start.children.first; node; node = node.next)
2058 if(node.name && !strcmpi(node.name, name))
2065 master = master, parent = this;
2068 hasHorzScroll = true;
2069 hasVertScroll = true;
2070 fullRowSelect = false;
2072 collapseControl = true;
2073 rootCollapseButton = true;
2075 anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
2077 // WHY is this not working ?
2078 /-*void OnResize(int width, int height)
2080 if(vertScroll.visible)
2081 nameField.width = width - vertScroll.size.w;
2083 nameField.width = width;
2086 bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed)
2090 FileSystemNode node = (FileSystemNode)row.tag;
2091 FileSystemNode child;
2095 for(child = node.children.last; child; child = node.children.last)
2097 listBox.DeleteRow(child.row);
2101 node.childrenLoaded = false;
2106 if(!node.loaded || !node.childrenLoaded)
2107 LoadTreeNode(node, tree);
2108 for(child = node.children.first; child && child.next; child = child.next);
2110 child.EnsureVisible(false);
2116 bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods)
2118 DataRow row = listBox.currentRow;
2121 FileSystemNode node = (FileSystemNode)row.tag;
2127 MenuItem { menu, "Cut\tCtrl+X", t, NotifySelect = null, disabled = false };
2128 MenuItem { menu, "Copy\tCtrl+C", c, NotifySelect = null, disabled = false };
2129 MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /-*!clipboard*-/ };
2130 MenuItem { menu, "Delete\tDel", d, NotifySelect = null, disabled = false };
2131 //MenuDivider { menu };
2135 master = this, menu = menu,
2137 x + clientStart.x + absPosition.x - guiApp.desktop.position.x,
2138 y + clientStart.y + absPosition.y - guiApp.desktop.position.y }
2146 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2150 FileSystemNode node = (FileSystemNode)row.tag;
2151 NotifyNodeSelect(listBox.parent.master, this, node);
2157 bool NotifyEditing(ListBox listBox, DataRow row)
2161 FileSystemNode node = (FileSystemNode)row.tag;
2166 bool NotifyEdited(ListBox listBox, DataRow row)
2170 FileSystemNode node = (FileSystemNode)row.tag;
2175 bool NotifyEditDone(ListBox listBox, DataRow row)
2179 FileSystemNode node = (FileSystemNode)row.tag;
2186 Menu editMenu { menu, "Edit", e };
2187 MenuItem itemEditCut
2189 editMenu, "Cut\tCtrl+X", t, disabled = true;
2191 bool NotifySelect(MenuItem selection, Modifiers mods)
2197 MenuItem itemEditCopy
2199 editMenu, "Copy\tCtrl+C", c, disabled = true;
2201 bool NotifySelect(MenuItem selection, Modifiers mods)
2207 MenuItem itemEditPaste
2209 editMenu, "Paste\tCtrl+V", p;
2211 bool NotifySelect(MenuItem selection, Modifiers mods)
2217 MenuItem itemEditDelete
2219 editMenu, "Delete\tDel", d, disabled = true;
2221 bool NotifySelect(MenuItem selection, Modifiers mods)
2228 // WHY is this crashing ?
2229 /-*void OnResize(int width, int height)
2231 if(this && nameField)
2232 nameField.width = width - 80;
2237 tree.AddField(nameField);
2242 FileSystemNode parent;
2243 FileSystemNode node;
2244 FileListing listing { "/" };
2248 root = FileSystemNode { type = computer, loaded = true, childrenLoaded = true };
2250 root.name = rootName;
2254 AddTreeNode(root, true, false, false, null, tree);
2256 // How can this make sense for linux?
2258 while(listing.Find())
2260 int len = strlen(listing.name);
2261 char info[MAX_LOCATION];
2262 char name[MAX_LOCATION];
2263 if(listing.stats.attribs.isDrive &&
2264 len > 3 && !strncmp(&listing.name[1], ": [", 3))
2266 strncpy(name, listing.name, 2);
2268 strncpy(info, &listing.name[4], len - 5);
2273 strcpy(name, listing.name);
2277 parent = MakeFileSystemNode(listing.stats, name);
2279 parent.info = CopyString(info);
2280 parent.loaded = true;
2281 AddTreeNode(parent, !listing.stats.attribs.isDirectory, false, listing.stats.attribs.isDirectory, root, tree);
2282 if(!listing.stats.attribs.isDirectory)
2283 parent.childrenLoaded = true;
2286 node = FileSystemNode { name = msNetwork, type = network };
2287 AddTreeNode(node, false, false, true, null, tree);
2288 node.row.collapsed = true;
2289 tree.Sort(nameField, 1);
2290 tree.SelectRow(root.row);
2295 public class ClipBoardFiles
2309 int size = SelSize();
2312 // Try to allocate memory
2313 ClipBoard clipBoard { };
2314 if(clipBoard.Allocate(size+1))
2316 GetSel(clipBoard.memory, true);
2329 ClipBoard clipBoard { };
2330 if(clipBoard.Load())
2331 PutS(clipBoard.memory);
2342 SetViewToCursor(true);
2348 Private Type DROPFILES
2354 For iCounter = 0 To filelist.ListCount - 1
2355 If filelist.Selected(iCounter) = True Then
2356 strFiles = strFiles & FixPath(filelist.Path) & filelist.List(iCounter) & vbNullChar
2359 'all selected items are now put in strFiles
2361 hGlobal = GlobalAlloc(GHND, Len(DF) + Len(strFiles)) 'put all files to a exclusive number
2362 If hGlobal Then 'if the globalalloc worked
2363 lpGlobal = GlobalLock(hGlobal) 'lock the hGlobal
2364 DF.pFiles = Len(DF) 'set the size of the files
2366 Call CopyMem(ByVal lpGlobal, DF, Len(DF)) 'copy df to the lpglobal
2367 Call CopyMem(ByVal (lpGlobal + Len(DF)), ByVal strFiles, Len(strFiles)) 'copy strfiles to lpglobal
2368 Call GlobalUnlock(hGlobal) 'unlock hglobal again
2370 SetClipboardData CF_HDROP, hGlobal 'put files to the clipboard
2373 bool SaveFile(const char * filePath)
2379 public class FileTreeNodeBSArray : ArrayBinarySorted
2381 type = class(FileSystemNode);
2383 FileSystemNode * const _;
2384 BSloc Add(FileSystemNode item)
2386 BSloc result = Find(item);
2389 Insert(result.pos, 1);
2390 _[result.pos] = item;
2394 BSloc Remove(FileSystemNode item)
2402 public class FileTreeNodeArray : RedjArray
2404 type = class(FileSystemNode);
2406 FileSystemNode * const _;
2407 FileSystemNode * Add(FileSystemNode item)
2414 FileSystemNode * AddBefore(uint position, FileSystemNode item)
2416 Insert(position, 1);
2418 return &_[position];
2424 public class ExplorerFileItem : struct
2435 void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox control, Alignment alignment, DataDisplayFlags displayFlags)
2437 int indentSize = (displayFlags.dropBox) ? 0 : 10;
2440 char label[MAX_FILENAME];
2442 //float scale = Min((float)clientSize.w / (float)bitmap.width, (float)clientSize.h / (float)bitmap.height);
2443 int w = 16; //(int)(bitmap.width * scale);
2444 int h = 16; //(int)(bitmap.height * scale);
2448 icon = control.fileIcons[type].bitmap;
2451 if(type == folder || type == folderOpen)
2452 surface.SetForeground(red); //Color { 170, 170, 0 } // REDJ What is that color?
2455 textOffset = indent * indentSize + (icon ? (icon.width + 6) : 0);
2458 sprintf(label, "%s [%s]", name, info);
2460 strcpy(label, name);
2461 len = strlen(label);
2463 surface.WriteTextDots
2464 (alignment, x + textOffset, y + 2, width - textOffset, label, len);
2465 if(type == pictureFile && control.previewPictures && bitmap)
2468 //surface.Filter(bitmap, (clientSize.w - w) / 2,(clientSize.h - h) / 2, 0,0, w, h, bitmap.width, bitmap.height);
2469 surface.Filter(bitmap, x + indent * indentSize + 2, y, 0, 0, w, h, bitmap.width, bitmap.height);
2471 // Until Filter / Stretch works with X
2472 //surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2,(clientSize.h - bitmap.height) / 2, 0,0, bitmap.width, bitmap.height);
2473 surface.blend = true;
2474 surface.Blit(bitmap, x + indent * indentSize + 2, y,0,0, w, h);
2480 surface.Blit(icon, x + indent * indentSize + 2, y,0,0, icon.width, icon.height);
2483 int OnCompare(ExplorerFileItem b)
2486 if(type == b.type || (type < folder && b.type < folder) || (type >= drive))
2487 result = strcmpi(name, b.name);
2490 if(type == folder && b.type < folder) result = -1;
2491 else if(type < folder && b.type == folder) result = 1;
2496 void OnCopy(ExplorerFileItem newData)
2498 type = newData.type;
2499 indent = newData.indent;
2502 int len = strlen(newData.name) + 1;
2503 name = new char[len];
2504 CopyBytes(name, newData.name, len);
2508 bool OnGetDataFromString(char * string)
2510 int len = strlen(string) + 1;
2511 name = new char[len];
2512 CopyBytes(name, string, len);
2526 char * OnGetString(char * string, void * fieldData, bool * needClass)
2532 public class ExplorerFileItemArray : RedjArray
2534 type = class(ExplorerFileItem);
2536 ExplorerFileItem * const _;
2537 ExplorerFileItem * Add(ExplorerFileItem item)
2544 ExplorerFileItem * AddBefore(uint position, ExplorerFileItem item)
2546 Insert(position, 1);
2548 return &_[position];
2553 for(c = 0; c < _count; c++)
2563 ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, const char * filePath, const bool previewPicture, const DisplaySystem displaySystem)
2565 int len = strlen(fileName);
2566 char info[MAX_LOCATION];
2567 char name[MAX_LOCATION];
2568 char extension[MAX_EXTENSION];
2570 ExplorerFileItem item { };
2572 //if(stats.attribs.isFile) // -- should work now
2573 if(attribs.isDirectory)
2577 item.type = (attribs.isDrive) ? drive : folder;
2578 if(attribs.isServer)
2584 if(attribs.isRemote)
2585 item.type = netDrive;
2586 if(attribs.isRemovable)
2588 if(fileName[0] == 'A' || fileName[0] == 'B')
2591 item.type = removable;
2596 GetExtension(fileName, extension);
2597 //strupr(extension);
2600 item.type = _FileType::SelectByExtension(extension);
2603 if(attribs.isDrive &&
2604 len > 3 && !strncmp(&fileName[1], ": [", 3))
2606 strncpy(name, fileName, 2);
2608 strncpy(info, &fileName[4], len - 5);
2613 strcpy(name, fileName);
2617 item.path = CopyString(filePath);
2618 item.name = CopyString(name);
2620 item.info = CopyString(info);
2621 item.extension = CopyString(extension);
2623 if(item.type == pictureFile && previewPicture)
2625 item.bitmap = Bitmap { };
2626 item.bitmap.Load(filePath, null, displaySystem);
2634 public class FileSystemBoxSelection
2637 FileSystemNode node;
2638 Array<FileSystemNode> nodes { };
2641 FileSystemBoxSelection Copy()
2643 FileSystemBoxSelection copy { node = node };
2646 copy.nodes.Add(node);
2652 ~FileSystemBoxSelection()
2658 class FileSystemNodeBits
2660 bool loaded:1, childrenLoaded:1, isListItem:1;
2663 public class FileSystemNode
2667 FileSystemNodeBits bits;
2680 /*//LinkElement<FileSystemNode> link;
2681 FileSystemNode parent;
2683 FileSystemNodeType type;
2687 FileSystemNode prev, next;
2691 property bool isListItem { set { bits.isListItem = value; } get { return bits.isListItem; } };
2693 property char * path
2695 set { delete path; if(value && value[0]) path = CopyString(value); }
2696 get { return path; } isset { return path && path[0]; }
2698 property char * name
2700 set { delete name; if(value && value[0]) name = CopyString(value); }
2701 get { return name; } isset { return name && name[0]; }
2703 property char * extension
2705 set { delete extension; if(value && value[0]) extension = CopyString(value); }
2706 get { return extension; } isset { return extension && extension[0]; }
2708 property char * label
2710 set { delete label; if(value && value[0]) label = CopyString(value); }
2711 get { return label; } isset { return label && label[0]; }
2713 property char * info
2715 set { delete info; if(value && value[0]) info = CopyString(value); }
2716 get { return info; } isset { return info && info[0]; }
2722 FileSystemNode parent;
2730 Array<int> exists; // would use (see) BoolArrayInt to pack this into an int if could be accessed as an array
2732 void GetPath(String outputPath)
2735 strcpy(outputPath, path);
2740 strcpy(outputPath, name);
2741 for(up = parent; up; up = up.parent)
2743 char temp[MAX_LOCATION];
2744 strcpy(temp, up.name);
2745 PathCat(temp, outputPath);
2746 strcpy(outputPath, temp);
2750 strcpy(outputPath, name ? name : "");
2753 bool IsChildOf(FileSystemNode node)
2755 FileSystemNode test;
2756 for(test = parent; test; test = test.parent)
2762 void DuplicateChildren(bool recursive, bool forceExpanded, FileSystemNode addTo, FileSystemBox fsb)
2766 FileSystemNode child;
2768 for(child = children.first; child; child = child.next)
2770 FileSystemNode copy { };
2771 copy.name = child.name; //CopyString(child.name);
2772 copy.type = child.type;
2773 fsb.AddTreeNode(copy, child.bits.loaded, false, false, addTo);
2775 copy.row.collapsed = false;
2777 child.DuplicateChildren(recursive, forceExpanded, copy, fsb);
2782 void EnsureVisible(bool expand)
2785 parent.EnsureVisible(true);
2787 row.collapsed = false;
2788 // TODO: row.EnsureVisible(); // making the row visible by scrolling
2798 FileSystemNode child;
2799 for(; (child = children.first); )
2802 children.Delete(child);
2816 parent.children.Delete(this);
2819 void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox fsb, Alignment alignment, DataDisplayFlags displayFlags)
2821 //int indentSize = (displayFlags.dropBox) ? 0 : 10;
2828 char text[MAX_LOCATION];
2838 comp = fsb.comparedPaths && fsb.comparedPaths.count > 1;
2840 icon = fsb.fileIcons[type].bitmap;
2841 alt = bits.isListItem ? path : name;
2842 if(comp && !fsb.bits.columnsCompareStyle && cmpIcon)
2845 diffIcon = Bitmap { };
2846 diffIcon.AllocateDD(
2847 surface.display.displaySystem,
2848 fsb.compIcons[cmpIcon].bitmap.width,
2849 fsb.compIcons[cmpIcon].bitmap.height);
2850 if(fsb.compIcons[cmpIcon].bitmap)
2851 diffIcon.Copy(fsb.compIcons[cmpIcon].bitmap);
2853 diffIcon = fsb.compIcons[cmpIcon-1].bitmap;
2854 notIcon = fsb.compIcons[countOfCompIconNames-1].bitmap;
2856 //xStart = indent * indent + x + (icon ? (icon.width + 5) : 0);
2857 xStart = x + (icon ? (icon.width + 5) : 0) + (comp ? 18*(fsb.bits.columnsCompareStyle ? fsb.comparedPaths.count : 1) : 0);
2863 sprintf(text, "%s [%s]", label ? label : alt, info);
2865 strcpy(text, label ? label : alt); //"%d-%d/%s", stats.inode, stats.nlink
2866 //sprintf(text, "%d-%d/%s", stats.inode, stats.nlink, label ? label : alt);
2871 if(type == folder || type == folderOpen)
2872 surface.SetForeground(yellow);
2876 //textOffset = indent * indentSize + (icon ? (icon.width + 4) : 0);
2878 surface.SetForeground(displayFlags.selected ? fsb.selectionText : fsb.foreground);
2879 surface.TextOpacity(false);
2880 surface.TextExtent(text, len, &w, &h);
2883 // Draw the current row stipple
2884 if(displayFlags.selected)
2885 //surface.Area(xStart - 1, y, xStart - 1, y + h - 1);
2886 //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1);
2887 surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1);
2888 //surface.WriteTextDots(alignment, x + textOffset, y + 2, width - textOffset, alt, strlen(alt));
2889 surface.WriteTextDots(alignment, xStart, y + 2, width, text, len);
2891 if(!guiApp.textMode)
2893 if(displayFlags.current)
2895 if(displayFlags.active)
2897 surface.LineStipple(0x5555);
2898 if(displayFlags.selected)
2899 surface.SetForeground(0xFFFFFF80);
2901 surface.SetForeground(black);
2905 surface.SetForeground(selectionColor);
2907 surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1);
2908 surface.LineStipple(0);
2913 if(!fsb.bits.columnsCompareStyle && diffIcon)
2916 h = diffIcon.height;
2917 /*if(cmpNot && notIcon)
2919 Surface s = diffIcon.GetSurface(0,0, {w,h});
2920 s.SetForeground(white);
2921 s.Blit(notIcon, x,y, 0,0, w,h);
2924 surface.SetForeground(white);
2925 surface.Blit(diffIcon, x,y, 0,0, w,h);
2926 if(cmpNot && notIcon)
2927 surface.Blit(notIcon, x,y, 0,0, w,h);
2931 else if(fsb.bits.columnsCompareStyle && exists && exists.count)
2934 for(c = d = 0; c < fsb.comparedPaths.count; c++)
2936 if(d == exists.count || exists[d] != c)
2940 diffIcon = fsb.compIcons[c].bitmap;
2944 h = diffIcon.height;
2945 surface.SetForeground(white);
2946 surface.Blit(diffIcon, x,y, 0,0, w,h);
2953 for(c = d = 0; c < exists.count; c++)
2958 x+=18*(exists[c]-d);
2962 diffIcon = fsb.compIcons[exists[c]].bitmap;
2966 h = diffIcon.height;
2967 surface.SetForeground(white);
2968 surface.Blit(diffIcon, x,y, 0,0, w,h);
2974 if(exists.count < fsb.comparedPaths.count && exists[exists.count-1] != d)
2976 x+=18*(exists[exists.count-1]-d);
2980 else if(fsb.bits.columnsCompareStyle)
2982 x+=18*fsb.comparedPaths.count;
2990 if(type == pictureFile && fsb.previewPictures && bitmap)
2992 surface.SetForeground(white);
2993 surface.blend = true;
2995 //surface.Filter(bitmap, (clientSize.w - w) / 2,(clientSize.h - h) / 2, 0,0, w, h, bitmap.width, bitmap.height);
2996 //surface.Filter(bitmap, x + indent/* * indentSize*/ + 2, y, 0, 0, w, h, bitmap.width, bitmap.height);
2997 surface.Filter(bitmap, x,y,0,0, w, h, bitmap.width, bitmap.height);
2999 // Until Filter / Stretch works with X
3000 //surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2,(clientSize.h - bitmap.height) / 2, 0,0, bitmap.width, bitmap.height);
3001 // surface.blend = true;
3002 //surface.Blit(bitmap, x + indent/* * indentSize*/ + 2, y,0,0, w, h);
3003 //surface.Blit(bitmap, x,y,0,0, bitmap.width, bitmap.height);
3010 //surface.blend = true;
3011 //surface.alphaWrite = blend;
3012 surface.SetForeground(white);
3013 //surface.Blit(icon, x + indent * indentSize, y,0,0, icon.width, icon.height);
3014 surface.Blit(icon, x,y, 0,0, w,h);
3019 Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
3023 dataBox, anchor = { 0, 0, 0, 0 };
3025 //borderStyle = contour;
3027 //background = white;
3031 //dataBox.borderStyle = none;
3032 dataBox.borderStyle = contour;
3033 dataBox.background = white;
3034 //dataBox.opacity = 0.0f;
3039 bool OnSaveEdit(EditBox editBox, void * object)
3041 bool changed = false;
3042 if(editBox.modifiedDocument)
3045 // how the heck did this work for PathBox? :S
3047 //changed = _class._vTbl[__ecereVMethodID_class_OnGetDataFromString](_class, &this, editBox.contents);
3049 //if(strcmp(editBox.contents, this.name))
3052 //changed = NotifyNodeRename(this.master, this, node);
3054 if(changed && RenameFile(name, editBox.contents))
3056 name = editBox.contents;
3068 int OnCompare(FileSystemNode b)
3071 FileSystemNode a = this;
3072 if(a.type == b.type || (a.type < folder && b.type < folder) || (a.type >= drive))
3074 if(!a.name || !b.name)
3075 PrintLn("error: FileSystemNode::OnCompare -- null-named node");
3076 result = strcmpi(a.name, b.name);
3080 if(a.type == folder && b.type < folder) result = -1;
3081 else if(a.type < folder && b.type == folder) result = 1;
3088 //int OnCompare(FileSystemNode b)
3091 //FileSystemNode a = this;
3092 //if(a.parent < b.parent) result = -1;
3093 //else if(a.parent > b.parent) result = 1;
3095 //result = fstrcmp(a.name, b.name);
3100 bool OnGetDataFromString(char * string)
3103 if(string && *string)
3105 int len = strlen(string) + 1;
3106 name = new char[len];
3107 CopyBytes(name, string, len);
3114 char * OnGetString(char * tempString, FileSystemToolWindow fileSysToolWnd, bool * needClass)
3116 return name ? name : "";
3120 /*FileSystemNode MakeFileSystemNode(const FileStats stats, const char * name)
3122 FileSystemNode node { stats = stats };
3123 node.name = CopyString(name);
3126 if(stats.attribs.isDirectory)
3128 node.type = (stats.attribs.isDrive) ? drive : folder;
3129 if(stats.attribs.isServer) node.type = server;
3130 if(stats.attribs.isShare) node.type = share;
3131 if(stats.attribs.isCDROM) node.type = cdrom;
3132 if(stats.attribs.isRemote) node.type = netDrive;
3133 if(stats.attribs.isRemovable)
3135 if(name[0] == 'A' || name[0] == 'B')
3138 node.type = removable;
3143 char extension[MAX_EXTENSION];
3144 GetExtension(node.name, extension);
3145 node.type = _FileType::SelectByExtension(extension);
3150 FileSystemNode MakeFileSystemNode(
3151 const FileStats stats,
3154 const bool pathAddName,
3155 const bool previewPicture,
3156 const bool isListItem,
3157 const DisplaySystem displaySystem)
3159 int len = strlen(name);
3160 char info[MAX_LOCATION];
3161 char name2[MAX_LOCATION];
3162 char extension[MAX_EXTENSION];
3164 FileSystemNode node { stats = stats };
3168 char o[MAX_LOCATION];
3169 //char r[MAX_LOCATION];
3170 //StripLastDirectory(path, o);
3171 GetLastDirectory(path, o);
3172 if(fstrcmp(name, o))
3173 //if(!FileExists(path))
3176 //if(stats.attribs.isFile) // TODO fix this in ecere -- WTH -- this has been fixed :/
3177 if(stats.attribs.isDirectory)
3179 extension[0] = '\0';
3181 node.type = (stats.attribs.isDrive) ? drive : folder;
3182 if(stats.attribs.isServer) node.type = server;
3183 if(stats.attribs.isShare) node.type = share;
3184 if(stats.attribs.isCDROM) node.type = cdrom;
3185 if(stats.attribs.isRemote) node.type = netDrive;
3186 if(stats.attribs.isRemovable)
3188 if(name[0] == 'A' || name[0] == 'B')
3191 node.type = removable;
3196 GetExtension(name, extension);
3199 node.type = _FileType::SelectByExtension(extension);
3202 if(stats.attribs.isDrive &&
3203 len > 3 && !strncmp(&name[1], ": [", 3))
3205 strncpy(name2, name, 2);
3207 strncpy(info, &name[4], len - 5);
3212 strcpy(name2, name);
3218 bool isFile = stats.attribs.isFile;
3219 bool isFolder = stats.attribs.isDirectory;
3220 char full[MAX_LOCATION];
3222 PathCat(full, name);
3223 node.path = full; //CopyString(full);
3226 node.path = path; //CopyString(path);
3227 node.name = name2; //CopyString(name2);
3229 node.info = info; //CopyString(info);
3230 node.extension = extension; //CopyString(extension);
3232 if(node.type == pictureFile && previewPicture)
3234 node.bitmap = Bitmap { alphaBlend = true };
3235 node.bitmap.Load(path, null, displaySystem);
3239 node.bits.isListItem = true;
3244 FileSystemNode MakeComparedFileSystemNode(
3245 const FileStats stats,
3248 const bool pathAddName,
3249 const bool previewPicture,
3252 const Array<int> exists,
3253 const DisplaySystem displaySystem)
3255 FileSystemNode node = MakeFileSystemNode(stats, name, path, pathAddName, previewPicture, false, displaySystem);
3258 node.cmpIcon = cmpIcon;
3259 node.cmpNot = cmpNot;
3260 node.exists = exists;
3265 #if 0 // could we do this?
3266 class BoolArrayInt : int
3268 // packing 32 bools in one int exposing them as an array
3269 bool [32]:1; // the :1 specifies the size of each element
3270 // byte [4]:8; // packing 4 bytes in an int exposing them as an arrat
3272 // allowing you to access each 32 bits with the following notation:
3279 for(c = 0; c < 32; c++)
3280 a[c] = SomFunction(...);
3283 class BoolArrayInt : int