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 path = CopyString("");
472 InitCompIcons(); // todo: these icons should not be initialize, they should be set
473 // or at least initalized when the comparison listing is requested
474 // and we know how many paths are being compared.
475 list.AddField(nameField);
476 bits.autoLoad = true;
477 //iteratorClass = class(FileSystemIterator);
488 list.background = background;
494 for(c = 0; c < _FileType::enumSize; c++)
496 fileIcons[c] = BitmapResource { fileIconNames[c], alphaBlend = true };
497 AddResource(fileIcons[c]);
504 for(c = 0; c < countOfCompIconNames; c++)
506 compIcons[c] = BitmapResource { compIconNames[c], alphaBlend = true };
507 AddResource(compIcons[c]);
511 DataField nameField { header = "Name", dataType = "FileSystemNode", width = 240, userData = this, freeData = false/*, editable = true*/; };
512 DataField pathField { header = "Location", dataType = /*"String"*/ "char *", width = 300, freeData = true };
513 DataField typeField { header = "Type", dataType = /*"String"*/ "char *", width = 40, freeData = false };
514 DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right, freeData = false };
515 DataField modifiedField { header = "Modified", dataType = "SecSince1970", width = 96, alignment = right, freeData = false };
523 char wd[MAX_LOCATION];
524 GetWorkingDir(wd, sizeof(wd));
537 hasHorzScroll = true;
538 hasVertScroll = true;
539 fullRowSelect = false;
541 alwaysHighLight = true;
543 anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
545 // WHY is this not working ?
546 /*void OnResize(int width, int height)
548 if(vertScroll.visible)
549 nameField.width = width - vertScroll.size.w;
551 nameField.width = width;
554 bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed)
558 FileSystemNode node = (FileSystemNode)row.tag;
559 FileSystemNode child;
563 for(child = node.children.last; child; child = node.children.last)
565 listBox.DeleteRow(child.row);
569 node.childrenLoaded = false;
574 if(!node.bits.loaded || !node.bits.childrenLoaded)
577 //list.Sort(nameField, 1);
580 for(child = node.children.first; child && child.next; child = child.next);
582 child.EnsureVisible(false);
588 bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods)
590 DataRow row = listBox.currentRow;
593 FileSystemNode node = (FileSystemNode)row.tag;
600 NotifyNodeMenu(master, this, menu, selection);
605 text = PrintString("Open ", node.name);
606 MenuItem { menu, text, o, NotifySelect = MenuOpen, disabled = false }; //delete text;
608 if(node.bits.isListItem/* && TODO: unless node is at root location*/)
610 MenuDivider { menu };
611 MenuItem { menu, "Replace by Parent\tCtrl+R", r, NotifySelect = MenuReplaceListItemByContainingDir, disabled = false };
613 else if(bits.mode == list)
615 MenuDivider { menu };
616 MenuItem { menu, "Replace List Item\tCtrl+R", r, NotifySelect = MenuReplaceListItemByChild, disabled = false };
618 MenuDivider { menu };
619 MenuItem { menu, "Cut\tCtrl+X", t, NotifySelect = null, disabled = false };
620 MenuItem { menu, "Copy\tCtrl+C", c, NotifySelect = null, disabled = false };
621 MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /*!clipboard*/ };
622 MenuItem { menu, "Delete\tDel", d, NotifySelect = null, disabled = false };
623 //MenuDivider { menu };
628 master = this, menu = menu,
630 x + clientStart.x + absPosition.x - guiApp.desktop.position.x,
631 y + clientStart.y + absPosition.y - guiApp.desktop.position.y }
639 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
644 selection.nodes.Free();
645 list.GetMultiSelection(rows);
646 for(item = rows.first; item; item = item.next)
648 DataRow row = item.data;
649 FileSystemNode node = (FileSystemNode)row.tag;
650 selection.nodes.Add(node);
655 selection.node = (FileSystemNode)row.tag;
657 selection.node = null;
659 if(selection.node && bits.preview)
662 FileSystemNode node = selection.node;
666 if(node && node.type == pictureFile)
669 bitmap.Load(node.path, null, displaySystem);
673 bitmaps = BitmapArray { };
674 for(pos = 0; pos < selectedItems.count; pos++)
677 selItem = (ExplorerFileItem)selectedItems._[pos];
678 bitmap.Load(selItem.path, null, displaySystem);
679 //bitmaps.Add(bitmap);
681 if(node && node.type == pictureFile)
684 bitmap.Load(node.path, null, displaySystem);
688 //NotifyItemSelect(master, view, item, selectedItems);
691 NotifyNodeSelect(listBox.parent.master, this, selection);
695 bool NotifyEditing(ListBox listBox, DataRow row)
699 FileSystemNode node = (FileSystemNode)row.tag;
704 bool NotifyEdited(ListBox listBox, DataRow row)
708 FileSystemNode node = (FileSystemNode)row.tag;
713 bool NotifyEditDone(ListBox listBox, DataRow row)
717 FileSystemNode node = (FileSystemNode)row.tag;
722 bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods)
724 bool result = !(selection.node && selection.node.type.isFolder && bits.navigateFolders);
729 bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
732 if((SmartKey)key == enter)
735 else if((SmartKey)key == f2)
736 result = RenameNode();
738 else if((SmartKey)key == f2)
740 FileSystemNode node = selection.node;
741 node.row.Edit(nameField);
765 anchor = Anchor { top = 0, right = 0, bottom = 0 };
767 void OnRedraw(Surface surface)
769 FileSystemBox fsb = (FileSystemBox)parent;
772 int wBmp = fsb.bitmap.width;
773 int hBmp = fsb.bitmap.height;
774 int wWnd = fsb.show.clientSize.w;
775 int hWnd = fsb.show.clientSize.h;
777 int wList = 0;//fsb.list.size.w + fsb.split.size.w;
779 float scale = Min((float)(wWnd - 10) / wBmp, (float)(hWnd - 10) / hBmp);
781 int wDraw = (int)(wBmp * scale);
782 int hDraw = (int)(hBmp * scale);
785 surface.Filter(fsb.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw, wBmp, hBmp);
787 // Until Filter / Stretch works with X
788 surface.Blit(fsb.bitmap, (wWnd - wBmp) / 2, (hWnd - hBmp) / 2, 0, 0, wBmp, hBmp);
793 surface.SetForeground(white);
794 surface.Area(0, 0, fsb.clientSize.w - 1, fsb.clientSize.h - 1);
802 FileSystemBoxSelection sel = this.selection.Copy();
803 //FileSystemNode node = selection.node;
804 for(node : sel.nodes)
807 if(node && node.type.isFolder && bits.navigateFolders)
808 property::path = node.path;
809 if(NotifyNodeOpen(this.master, this, sel) && !result)
820 //FileSystemBoxSelection selection = this.selection.Copy();
821 FileSystemNode node = selection.node;
822 //if(node && node.type.isFolder && bits.navigateFolders)
823 // property::path = node.path;
824 // ------------------------------------------- working here ---------------------------
826 /*result = NotifyNodeRename(this.master, this, node);
829 if(RenameFile(oldn, newn))
839 Menu editMenu { menu, "Edit", e };
842 editMenu, "Cut\tCtrl+X", t, disabled = true;
844 bool NotifySelect(MenuItem selection, Modifiers mods)
850 MenuItem itemEditCopy
852 editMenu, "Copy\tCtrl+C", c, disabled = true;
854 bool NotifySelect(MenuItem selection, Modifiers mods)
860 MenuItem itemEditPaste
862 editMenu, "Paste\tCtrl+V", p;
864 bool NotifySelect(MenuItem selection, Modifiers mods)
870 MenuItem itemEditDelete
872 editMenu, "Delete\tDel", d, disabled = true;
874 bool NotifySelect(MenuItem selection, Modifiers mods)
881 // WHY is this crashing ?
882 /*void OnResize(int width, int height)
884 if(this && nameField)
885 nameField.width = width - 80;
888 void ChangeViewType()
892 list.resizable = bits.details || bits.pathColumn;
893 list.moveFields = bits.details || bits.pathColumn;
894 list.hasHeader = bits.details || bits.pathColumn;
895 list.AddField(nameField);
897 list.AddField(pathField);
900 list.AddField(typeField);
901 list.AddField(sizeField);
902 list.AddField(modifiedField);
909 // this is crashing in for designer when details = true // can't save the file, always yields a crash
910 /*if(list && created)
913 list.AddField(nameField);
916 list.AddField(typeField);
917 list.AddField(sizeField);
921 if(comparedPaths && !bits.treeBranches)
925 FileAttribs pathAttribs = FileExists(path);
928 if(pathAttribs.isDirectory)
930 if(bits.treeBranches)
940 else if(pathAttribs.isFile) // we assume this is a file list
942 File f = FileOpen(path, read);
945 if(bits.treeBranches)
952 MessageBoxTodo($"unable to open file list");
955 MessageBoxTodo($"path is not a directory nor is it a file");
958 MessageBoxTodo($"path does not exist");
960 list.Sort(nameField, 1);
963 void LoadTreeDirectory()
965 bool isRoot = !strcmp(path, "/");
966 char name[MAX_LOCATION];
967 FileSystemNode parent;
969 FileListing listing { path, extensions = extensions };
972 GetLastDirectory(path, name);
977 GetWorkingDir(startPath, sizeof(startPath));
979 strcpy(path, startPath);*/
981 bits.mode = directory;
987 root = FileSystemNode { bits.loaded = true, bits.childrenLoaded = true };
988 AddTreeNode(root, true, false, false, null);
989 while(listing.Find())
991 int len = strlen(listing.name);
992 char info[MAX_LOCATION];
993 char name[MAX_LOCATION];
994 if(listing.stats.attribs.isDrive &&
995 len > 3 && !strncmp(&listing.name[1], ": [", 3))
997 strncpy(name, listing.name, 2);
999 strncpy(info, &listing.name[4], len - 5);
1004 strcpy(name, listing.name);
1013 false, bits.previewPictures, false,
1016 parent.info = info; //CopyString(info);
1017 parent.bits.loaded = true;
1020 !listing.stats.attribs.isDirectory,
1022 listing.stats.attribs.isDirectory,
1024 if(!listing.stats.attribs.isDirectory)
1025 parent.bits.childrenLoaded = true;
1028 node = FileSystemNode { name = msNetwork, type = network };
1029 AddTreeNode(node, false, false, true, null);
1030 node.row.collapsed = true;
1036 FileGetStats(path, stats);
1037 root = MakeFileSystemNode(stats, name, path, false, bits.previewPictures, false, displaySystem);
1038 AddTreeNode(root, false, false, true, null);
1044 root.type = computer;
1045 root.label = rootName;
1048 list.Sort(nameField, 1);
1049 list.SelectRow(root.row);
1052 void LoadListDirectory()
1054 FileListing listing { path, extensions = extensions };
1056 bits.mode = directory;
1057 while(listing.Find())
1058 ProcessListItem(listing.name, listing.path, listing.stats, false);
1061 void LoadListFileList(File f)
1065 while(f.GetLine(line, 65536))
1068 char name[MAX_FILENAME];
1069 FileGetStats(line, stats);
1070 GetLastDirectory(line, name);
1071 ProcessListItem(name, line, stats, true);
1075 void LoadTreeFileList(File f)
1079 while(f.GetLine(line, 65536))
1082 char name[MAX_FILENAME];
1083 FileSystemNode node;
1084 FileGetStats(line, stats);
1085 GetLastDirectory(line, name);
1086 node = ProcessTreeItem(name, line, stats, node);
1090 void LoadListIterator()
1092 FileSystemIterator iterator = eInstance_New(iteratorClass);
1095 iterator.owner = this;
1096 iterator.OnObject = ListIterator_OnObject;
1097 //iterator.OnLeavingDirectory = ListIterator_OnLeavingDirectory;
1098 NotifyIteratorInit(master, this, iterator);
1099 iterator.Iterate(path, true);
1104 bool ListIterator_OnObject(char * name, char * path, FileStats stats, bool isRootObject)
1106 ProcessListItem(name, path, stats, false);
1110 //void ListIterator_OnLeavingDirectory(char * path) { }
1112 void ProcessListItem(char * name, char * path, FileStats stats, bool isListItem)
1114 if((!bits.foldersOnly && !bits.filesOnly) || (bits.foldersOnly && stats.attribs.isDirectory) || (bits.filesOnly && stats.attribs.isFile))
1116 FileSystemNode node = MakeFileSystemNode(stats, name, path, false, bits.previewPictures, isListItem, displaySystem);
1121 FileSystemNode ProcessTreeItem(char * name, char * path, FileStats stats, FileSystemNode parent)
1123 FileSystemNode node = MakeFileSystemNode(stats, name, path, false, bits.previewPictures, true, displaySystem);
1124 AddTreeNode(parent, false, false, true, null);
1125 //LoadTreeNode(node);
1129 void LoadTreeNode(FileSystemNode node)
1131 if(!node.bits.loaded)
1133 char path[MAX_LOCATION];
1136 FileListing listing { path, extensions = extensions };
1137 if(node.children.count == 1)
1138 DeleteNode(node.children.first);
1140 while(listing.Find())
1143 FileSystemNode child = null;
1144 if(!listing.stats.attribs.isRemovable && ((!bits.foldersOnly && !bits.filesOnly) ||
1145 (bits.foldersOnly && listing.stats.attribs.isDirectory) ||
1146 (bits.filesOnly && listing.stats.attribs.isFile)))
1147 child = MakeAndAddToTreeFileSystemNodeFromFileListing(listing, node);
1149 NodeChildLoad(child, node);
1155 node.bits.childrenLoaded = true;
1156 node.bits.loaded = true;
1157 node.row.SortSubRows(false);
1159 else if(!node.bits.childrenLoaded)
1161 FileSystemNode child;
1162 if(node.children.first)
1164 for(child = node.children.first; child; child = child.next)
1166 if(!child.bits.loaded)
1167 LoadTreeNode(child);
1168 else if(!child.bits.childrenLoaded)
1169 NodeChildLoad(child, node);
1171 node.bits.childrenLoaded = true;
1172 node.row.SortSubRows(false);
1177 void NodeChildLoad(FileSystemNode parent, FileSystemNode node)
1179 char path[MAX_LOCATION];
1180 parent.GetPath(path);
1181 if(bits.textFileLinesStyle && FileExists(path).isFile)
1188 FileListing listing { path, extensions = extensions };
1189 while(listing.Find())
1192 FileSystemNode child = null;
1193 if((!bits.foldersOnly && !bits.filesOnly) ||
1194 (bits.foldersOnly && listing.stats.attribs.isDirectory) ||
1195 (bits.filesOnly && listing.stats.attribs.isFile))
1196 child = MakeAndAddToTreeFileSystemNodeFromFileListing(listing, parent);
1206 parent.bits.childrenLoaded = true;
1209 void LoadComparedList()
1211 int c, cmp/*, smallest*/, icon;//, equalCount;
1212 int count = comparedPaths ? comparedPaths.count : 0;
1213 //bool allDone = false;
1216 char path[MAX_LOCATION];
1217 //Array<ComparisonState> states { };
1218 //Array<FileListing> listings { };
1219 //Array<int> equals { };
1220 //Array<MapNode<String, int>> mapNodes { };
1222 //Array<Map<String, int>> lists { };
1223 //Map<int, bool> equals{ };
1226 MapNode<String, /*Map<int, */Array<int>> na;
1227 //MapNode<int, int> nb;
1228 Map<String, /*Map<int, */Array<int>> names { };
1229 //Map<String, Array<bool>> names { };
1230 //Map<String, bool[16]> names { }; // does not seem to be working
1231 //Map<String, BoolArrayInt> names { };
1233 for(c = 0; c < comparedPaths.count; c++)
1235 FileListing listing { comparedPaths[c], extensions = extensions };
1236 while(listing.Find())
1238 /*Map<int, int>*/Array<int> m = names[listing.name];
1241 names[listing.name] = m;
1242 /*/m[c] = */m.Add(c);
1245 /* // compiles and should work but better solution?
1246 for(c = 0; c < comparedPaths.count; c++)
1248 FileListing listing { comparedPaths[c], extensions = extensions };
1249 while(listing.Find())
1251 Array<bool> a = names[listing.name];
1254 names[listing.name] = a;
1259 /* // does not seem to be working
1260 for(c = 0; c < comparedPaths.count; c++)
1262 FileListing listing { comparedPaths[c], extensions = extensions };
1263 while(listing.Find())
1265 names[listing.name][c] = true;
1270 if(comparedPaths.count > 0)
1272 FileListing listing { comparedPaths[0], extensions = extensions };
1273 while(listing.Find())
1275 // should be able to just do names[listing.name]._0 = true;
1276 BoolArrayInt bai = names[listing.name];
1278 names[listing.name] = bai;
1281 if(comparedPaths.count > 1)
1283 FileListing listing { comparedPaths[1], extensions = extensions };
1284 while(listing.Find())
1286 // should be able to just do names[listing.name]._1 = true;
1287 BoolArrayInt bai = names[listing.name];
1289 names[listing.name] = bai;
1297 for(dirPath : comparedPaths)
1300 if(FileExists(dirPath).isDirectory)
1302 FileListing listing { dirPath, extensions = extensions };
1303 //MapNode<String, int> mn;
1304 Map<String, int> list { };
1305 //states.Add(listing.Find() == true ? matching : endOfListing);
1306 while(listing.Find())
1307 list[listing.name] = 0;
1308 //for(mn = ; mn; mn = mn.next)
1309 //mn = list.root.minimum;
1310 mapNodes.Add(/-*mn*-/list.root.minimum);
1312 //PrintLn(dirPath, " -- .Find() -- ", states[states.count-1] == matching ? listing.name : "endOfListing*");
1313 //listings.Add(listing);
1316 MapNode<String, int> mn;
1317 PrintLn("------------- DIR LISTING FOR ", dirPath);
1318 for(mn = list.root.minimum; mn; mn = mn.next)
1327 for(na = names.root.minimum; na; na = na.next)
1329 /*Map<int, */Array<int> equals = na.value;
1330 //MapNode<int, int> nb;
1336 for(c = 1; c < count; c++)
1338 //if(states[c] == endOfListing) continue;
1339 if(!mapNodes[c]) continue;
1340 // todo: use better comparison method
1341 // it should compare file type (dir/file) before
1342 // comparing file name.
1343 // should also provide alternative methods
1344 // of comparison including ones that consider
1345 // date changes as differences of some kind.
1346 // pethaps a OnCompare(a, b) to allow implementation
1347 // of custom methods of comparison.
1348 // note: this (or these) method(s) depend on files
1349 // being listed in sorted order by FileListing.
1350 // different comparison methods should have
1351 // appropriatly different sorting in FileListing.
1353 //cmp = strcmp(listings[smallest].name, listings[c].name);
1354 cmp = fstrcmp(mapNodes[smallest].key, mapNodes[c].key);
1355 PrintLn("COMPARING - ", mapNodes[smallest].key, " and ", mapNodes[c].key);
1368 if(equals.count == count) // all are equal, no diff icon
1373 else if(equals.count == count-1) // all are equal but one, not-sign icon for singled out missing
1377 for(nb = equals.root.minimum, i = 0; nb; nb = nb.next, i++)
1381 for(i = 0; i < equals.count; i++)
1390 if(i == equals.count)
1394 else if(equals.count == 1) // only one is present, all others missing, present-sign for singled out present
1396 //icon = equals.root.minimum.key+1;
1407 if(equals.count == count) // all are equal, no diff icon
1409 else if(count/2 - equals.count < 0) // more than half are equal, use not-sign icons for all missing
1411 else // less than half are equal, use present-sign icons for all present
1415 /*if((!bits.foldersOnly && !bits.filesOnly) ||
1416 (bits.foldersOnly && listings[smallest].stats.attribs.isDirectory) ||
1417 (bits.filesOnly && listings[smallest].stats.attribs.isFile))*/
1418 strcpy(path, comparedPaths[/*smallest*/equals[0]]);
1419 PathCat(path, /*mapNodes[smallest].key*/na.key);
1420 FileGetStats(path, stats);
1421 if((!bits.foldersOnly && !bits.filesOnly) ||
1422 (bits.foldersOnly && stats.attribs.isDirectory) ||
1423 (bits.filesOnly && stats.attribs.isFile))
1425 FileSystemNode node =
1426 MakeComparedFileSystemNode(
1428 /*mapNodes[smallest].key*/na.key,
1430 false, bits.previewPictures,
1438 mapNodes[equal] = mapNodes[equal].next;
1439 //states[equal] = listings[equal].Find() == true ? matching : endOfListing;
1440 //PrintLn(comparedPaths[equal], " -- .Find() -- ", states[equal] == matching ? listings[equal].name : "endOfListing*");
1443 //for(c = 0; c < count && states[c] == endOfListing; c++);
1444 for(c = 0; c < count && !mapNodes[c]; c++);
1449 list.Sort(nameField, 1);
1452 void AddNode(FileSystemNode node)
1454 DataRow row = list.AddRow();
1455 row.tag = (int)node;
1458 row.SetData(nameField, node);
1461 char path[MAX_LOCATION];
1462 StripLastDirectory(node.path, path);
1463 row.SetData(pathField, CopyString(path));
1467 if(node.type.isFile)
1469 row.SetData(typeField, node.extension);
1470 row.SetData(sizeField, /*(void *)*/node.stats.size);
1472 row.SetData(modifiedField, node.stats.modified);
1476 FileSystemNode MakeAndAddToTreeFileSystemNodeFromFileListing(FileListing listing, FileSystemNode parent)
1478 FileSystemNode result = null;
1479 /*if((!bits.foldersOnly && !bits.filesOnly) ||
1480 (bits.foldersOnly && listing.stats.attribs.isDirectory) ||
1481 (bits.filesOnly && listing.stats.attribs.isFile))*/
1482 /*if(!listing.stats.attribs.isRemovable && ((!bits.foldersOnly && !bits.filesOnly) ||
1483 (bits.foldersOnly && listing.stats.attribs.isDirectory) ||
1484 (bits.filesOnly && listing.stats.attribs.isFile)))*/
1486 bool textFileLinesStyle = false;
1487 char * test = listing.name;
1490 result = MakeFileSystemNode(listing.stats, listing.name, listing.path, false, bits.previewPictures, false, displaySystem);
1494 if(bits.textFileLinesStyle)
1496 char ext[MAX_LOCATION];
1497 GetExtension(listing.name, ext);
1498 if(!strcmpi(ext, "txt") || !strcmpi(ext, "text"))
1499 textFileLinesStyle = true;
1501 //AddTreeNode(result, true, false, textFileLinesStyle, parent);
1502 AddTreeNode(result, !textFileLinesStyle && listing.stats.attribs.isFile, false, !listing.stats.attribs.isFile || textFileLinesStyle, parent);
1511 FileSystemNode node,
1513 bool childrenLoaded,
1515 FileSystemNode addTo)
1517 DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : list.AddRow();
1520 node.parent = addTo;
1521 node.indent = addTo.indent + 1;
1522 addTo.children.Add(node);
1524 row.tag = (int)node;
1526 row.SetData(null, node);
1529 char path[MAX_LOCATION];
1530 StripLastDirectory(node.path, path);
1531 row.SetData(pathField, CopyString(path));
1535 if(node.type.isFile)
1537 row.SetData(typeField, node.extension);
1538 row.SetData(sizeField, /*(void *)*/node.stats.size);
1540 row.SetData(modifiedField, node.stats.modified);
1543 node.bits.loaded = loaded;
1544 node.bits.childrenLoaded = childrenLoaded;
1546 //AddTreeNode(FileSystemNode { }, false, false, node); // why would this create a compile error?
1547 AddTreeNode(FileSystemNode { type = none, name = "Loader" }, false, false, false, node);
1549 if(node.indent > 0 || bits.mode == list)
1550 row.collapsed = true;
1551 else if(node.type == folder)
1552 node.type = folderOpen;
1555 void DeleteNode(FileSystemNode node)
1557 FileSystemNode child;
1560 for(; (child = node.children.first); )
1563 list.DeleteRow(node.row);
1570 enum ComparisonState { endOfListing, matching };
1574 class ExplorerView : FileSystemBox
1577 hasHorzScroll = false;
1578 hasVertScroll = false;
1580 virtual void Load(FileSystemNode parent);
1581 virtual void Refresh();
1583 virtual void LaunchNotifyItemSelect(Window master, ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems)
1585 view.NotifyItemSelect(master, view, item, selectedItems);
1588 virtual bool Window::NotifyItemSelect(ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems);
1589 virtual bool Window::NotifyItemOpen(ExplorerView view, ExplorerFileItem item);
1593 master = master, parent = this;
1596 hasHorzScroll = true;
1597 hasVertScroll = true;
1600 fullRowSelect = false;
1603 anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
1605 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
1607 ExplorerView view = (ExplorerView)listBox.parent;
1608 if(listBox.currentRow)
1611 ExplorerFileItemArray selectedItems { growingFactor = 16 };
1612 for(listRow = listBox.firstRow; listRow; listRow = listRow.next)
1613 if(listRow.selected)
1614 selectedItems.Add((ExplorerFileItem)listRow.tag);
1615 //view.NotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag);
1616 view.LaunchNotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag, selectedItems);
1621 bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods)
1623 ExplorerView view = (ExplorerView)listBox.parent;
1624 view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag);
1628 bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
1630 if((SmartKey)key == enter)
1632 ExplorerView view = (ExplorerView)listBox.parent;
1633 view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag);
1646 class ExplorerViewList : ExplorerView
1649 FileSystemNode location;
1653 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
1655 ExplorerViewDetails()
1657 list.AddField(nameField);
1665 void Load(FileSystemNode location)
1667 char path[MAX_LOCATION];
1668 this.location = location;
1669 location.GetPath(path);
1671 FileListing listing { path };
1673 ExplorerFileItem item;
1678 while(listing.Find())
1680 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
1682 row = list.AddRow();
1683 row.tag = (int)item;
1684 row.SetData(nameField, item);
1686 list.Sort(nameField, 1);
1693 class ExplorerViewDetails : ExplorerView
1695 list.hasHeader = true;
1696 list.moveFields = true;
1697 list.resizable = true;
1698 list.sortable = true;
1700 FileSystemNode location;
1704 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
1705 DataField typeField { header = "Type", dataType = /-*"String"*-/ "char *", width = 40 };
1706 DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right };
1708 ExplorerViewDetails()
1710 list.AddField(nameField);
1711 list.AddField(typeField);
1712 list.AddField(sizeField);
1720 void Load(FileSystemNode location)
1722 char path[MAX_LOCATION];
1723 this.location = location;
1724 location.GetPath(path);
1726 FileListing listing { path };
1728 ExplorerFileItem item;
1733 while(listing.Find())
1735 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
1737 row = list.AddRow();
1738 row.tag = (int)item;
1739 row.SetData(nameField, item);
1740 row.SetData(typeField, CopyString(item.extension));
1741 row.SetData(sizeField, (uint)listing.stats.size);
1743 list.Sort(nameField, 1);
1750 class ExplorerViewIcons : ExplorerView
1753 FileSystemNode location;
1757 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
1759 ExplorerViewDetails()
1761 list.AddField(nameField);
1769 void Load(FileSystemNode location)
1771 char path[MAX_LOCATION];
1772 this.location = location;
1773 location.GetPath(path);
1775 FileListing listing { path };
1777 ExplorerFileItem item;
1782 while(listing.Find())
1784 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
1786 row = list.AddRow();
1787 row.tag = (int)item;
1788 row.SetData(nameField, item);
1790 list.Sort(nameField, 1);
1797 class ExplorerViewCards : ExplorerView
1800 FileSystemNode location;
1804 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
1806 ExplorerViewDetails()
1808 list.AddField(nameField);
1816 void Load(FileSystemNode location)
1818 char path[MAX_LOCATION];
1819 this.location = location;
1820 location.GetPath(path);
1822 FileListing listing { path };
1824 ExplorerFileItem item;
1829 while(listing.Find())
1831 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
1833 row = list.AddRow();
1834 row.tag = (int)item;
1835 row.SetData(nameField, item);
1837 list.Sort(nameField, 1);
1844 public class BitmapArray : RedjArray
1846 type = class(Bitmap);
1849 Bitmap * Add(Bitmap bitmap)
1856 Bitmap * AddBefore(uint position, Bitmap bitmap)
1858 Insert(position, 1);
1859 _[position] = bitmap;
1860 return &_[position];
1865 for(c = 0; c < _count; c++)
1877 class ExplorerViewShowcase : ExplorerView
1879 list.anchor = Anchor { left = 0, top = 0, bottom = 0 };
1880 list.size = Size { w = 200 };
1882 FileSystemNode location;
1886 DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 180, editable = true, userData = this };
1889 BitmapArray bitmaps { growingFactor = 16 };
1895 anchor = Anchor { top = 0, right = 0, bottom = 0 };
1897 void OnRedraw(Surface surface)
1899 ExplorerViewShowcase view = (ExplorerViewShowcase)parent;
1902 int wBmp = view.bitmap.width;
1903 int hBmp = view.bitmap.height;
1904 int wWnd = clientSize.w;
1905 int hWnd = clientSize.h;
1907 int wList = view.list.size.w + view.split.size.w;
1909 float scale = Min((float)(wWnd - 10) / wBmp, (float)(hWnd - 10) / hBmp);
1911 int wDraw = (int)(wBmp * scale);
1912 int hDraw = (int)(hBmp * scale);
1915 surface.Filter(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw, wBmp, hBmp);
1917 // Until Filter / Stretch works with X
1918 surface.Blit(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw);
1923 surface.SetForeground(white);
1924 surface.Area(0, 0, view.clientSize.w - 1, view.clientSize.h - 1);
1938 ExplorerViewDetails()
1940 list.AddField(nameField);
1943 void LaunchNotifyItemSelect(Window master, ExplorerViewShowcase view, ExplorerFileItem item, ExplorerFileItemArray selectedItems)
1946 ExplorerFileItem selItem;
1950 if(item && item.type == pictureFile)
1952 view.bitmap = Bitmap { };
1953 view.bitmap.Load(item.path, null, displaySystem);
1956 view.bitmaps.Clear();
1957 view.bitmaps = BitmapArray { };
1958 for(pos = 0; pos < selectedItems.count; pos++)
1961 selItem = (ExplorerFileItem)selectedItems._[pos];
1962 bitmap.Load(selItem.path, null, displaySystem);
1963 //view.bitmaps.Add(bitmap);
1965 if(item && item.type == pictureFile)
1967 view.bitmap = Bitmap { };
1968 view.bitmap.Load(item.path, null, displaySystem);
1971 view.show.Update(null);
1972 view.NotifyItemSelect(master, view, item, selectedItems);
1980 void Load(FileSystemNode location)
1982 char path[MAX_LOCATION];
1983 this.location = location;
1984 location.GetPath(path);
1986 FileListing listing { path };
1988 ExplorerFileItem item;
1993 while(listing.Find())
1995 item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
1997 row = list.AddRow();
1998 row.tag = (int)item;
1999 row.SetData(nameField, item);
2001 list.Sort(nameField, 1);
2008 class ExplorerTree : FileSystemBox
2010 hasHorzScroll = false;
2011 hasVertScroll = false;
2017 DataField nameField { dataType = "FileSystemNode", width = 240, userData = this };
2019 FileSystemNode root;
2020 FileSystemNode selection;
2022 virtual bool Window::NotifyNodeSelect(ExplorerTree tree, FileSystemNode node);
2024 property FileSystemNode node
2030 if(!tree.currentRow)
2032 if(!tree.currentRow.tag)
2034 return (FileSystemNode)tree.currentRow.tag;
2038 void Select(FileSystemNode node)
2042 node.EnsureVisible(false);
2043 tree.SelectRow(node.row);
2047 FileSystemNode Find(const char * name, FileSystemNode parent)
2049 FileSystemNode node;
2050 FileSystemNode start = parent ? parent : root;
2051 if(!start.loaded || !start.childrenLoaded)
2052 LoadTreeNode(start, tree);
2053 for(node = start.children.first; node; node = node.next)
2054 if(node.name && !strcmpi(node.name, name))
2061 master = master, parent = this;
2064 hasHorzScroll = true;
2065 hasVertScroll = true;
2066 fullRowSelect = false;
2068 collapseControl = true;
2069 rootCollapseButton = true;
2071 anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
2073 // WHY is this not working ?
2074 /-*void OnResize(int width, int height)
2076 if(vertScroll.visible)
2077 nameField.width = width - vertScroll.size.w;
2079 nameField.width = width;
2082 bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed)
2086 FileSystemNode node = (FileSystemNode)row.tag;
2087 FileSystemNode child;
2091 for(child = node.children.last; child; child = node.children.last)
2093 listBox.DeleteRow(child.row);
2097 node.childrenLoaded = false;
2102 if(!node.loaded || !node.childrenLoaded)
2103 LoadTreeNode(node, tree);
2104 for(child = node.children.first; child && child.next; child = child.next);
2106 child.EnsureVisible(false);
2112 bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods)
2114 DataRow row = listBox.currentRow;
2117 FileSystemNode node = (FileSystemNode)row.tag;
2123 MenuItem { menu, "Cut\tCtrl+X", t, NotifySelect = null, disabled = false };
2124 MenuItem { menu, "Copy\tCtrl+C", c, NotifySelect = null, disabled = false };
2125 MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /-*!clipboard*-/ };
2126 MenuItem { menu, "Delete\tDel", d, NotifySelect = null, disabled = false };
2127 //MenuDivider { menu };
2131 master = this, menu = menu,
2133 x + clientStart.x + absPosition.x - guiApp.desktop.position.x,
2134 y + clientStart.y + absPosition.y - guiApp.desktop.position.y }
2142 bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
2146 FileSystemNode node = (FileSystemNode)row.tag;
2147 NotifyNodeSelect(listBox.parent.master, this, node);
2153 bool NotifyEditing(ListBox listBox, DataRow row)
2157 FileSystemNode node = (FileSystemNode)row.tag;
2162 bool NotifyEdited(ListBox listBox, DataRow row)
2166 FileSystemNode node = (FileSystemNode)row.tag;
2171 bool NotifyEditDone(ListBox listBox, DataRow row)
2175 FileSystemNode node = (FileSystemNode)row.tag;
2182 Menu editMenu { menu, "Edit", e };
2183 MenuItem itemEditCut
2185 editMenu, "Cut\tCtrl+X", t, disabled = true;
2187 bool NotifySelect(MenuItem selection, Modifiers mods)
2193 MenuItem itemEditCopy
2195 editMenu, "Copy\tCtrl+C", c, disabled = true;
2197 bool NotifySelect(MenuItem selection, Modifiers mods)
2203 MenuItem itemEditPaste
2205 editMenu, "Paste\tCtrl+V", p;
2207 bool NotifySelect(MenuItem selection, Modifiers mods)
2213 MenuItem itemEditDelete
2215 editMenu, "Delete\tDel", d, disabled = true;
2217 bool NotifySelect(MenuItem selection, Modifiers mods)
2224 // WHY is this crashing ?
2225 /-*void OnResize(int width, int height)
2227 if(this && nameField)
2228 nameField.width = width - 80;
2233 tree.AddField(nameField);
2238 FileSystemNode parent;
2239 FileSystemNode node;
2240 FileListing listing { "/" };
2244 root = FileSystemNode { type = computer, loaded = true, childrenLoaded = true };
2246 root.name = rootName;
2250 AddTreeNode(root, true, false, false, null, tree);
2252 // How can this make sense for linux?
2254 while(listing.Find())
2256 int len = strlen(listing.name);
2257 char info[MAX_LOCATION];
2258 char name[MAX_LOCATION];
2259 if(listing.stats.attribs.isDrive &&
2260 len > 3 && !strncmp(&listing.name[1], ": [", 3))
2262 strncpy(name, listing.name, 2);
2264 strncpy(info, &listing.name[4], len - 5);
2269 strcpy(name, listing.name);
2273 parent = MakeFileSystemNode(listing.stats, name);
2275 parent.info = CopyString(info);
2276 parent.loaded = true;
2277 AddTreeNode(parent, !listing.stats.attribs.isDirectory, false, listing.stats.attribs.isDirectory, root, tree);
2278 if(!listing.stats.attribs.isDirectory)
2279 parent.childrenLoaded = true;
2282 node = FileSystemNode { name = msNetwork, type = network };
2283 AddTreeNode(node, false, false, true, null, tree);
2284 node.row.collapsed = true;
2285 tree.Sort(nameField, 1);
2286 tree.SelectRow(root.row);
2291 public class ClipBoardFiles
2305 int size = SelSize();
2308 // Try to allocate memory
2309 ClipBoard clipBoard { };
2310 if(clipBoard.Allocate(size+1))
2312 GetSel(clipBoard.memory, true);
2325 ClipBoard clipBoard { };
2326 if(clipBoard.Load())
2327 PutS(clipBoard.memory);
2338 SetViewToCursor(true);
2344 Private Type DROPFILES
2350 For iCounter = 0 To filelist.ListCount - 1
2351 If filelist.Selected(iCounter) = True Then
2352 strFiles = strFiles & FixPath(filelist.Path) & filelist.List(iCounter) & vbNullChar
2355 'all selected items are now put in strFiles
2357 hGlobal = GlobalAlloc(GHND, Len(DF) + Len(strFiles)) 'put all files to a exclusive number
2358 If hGlobal Then 'if the globalalloc worked
2359 lpGlobal = GlobalLock(hGlobal) 'lock the hGlobal
2360 DF.pFiles = Len(DF) 'set the size of the files
2362 Call CopyMem(ByVal lpGlobal, DF, Len(DF)) 'copy df to the lpglobal
2363 Call CopyMem(ByVal (lpGlobal + Len(DF)), ByVal strFiles, Len(strFiles)) 'copy strfiles to lpglobal
2364 Call GlobalUnlock(hGlobal) 'unlock hglobal again
2366 SetClipboardData CF_HDROP, hGlobal 'put files to the clipboard
2369 bool SaveFile(const char * filePath)
2375 public class FileTreeNodeBSArray : ArrayBinarySorted
2377 type = class(FileSystemNode);
2379 FileSystemNode * const _;
2380 BSloc Add(FileSystemNode item)
2382 BSloc result = Find(item);
2385 Insert(result.pos, 1);
2386 _[result.pos] = item;
2390 BSloc Remove(FileSystemNode item)
2398 public class FileTreeNodeArray : RedjArray
2400 type = class(FileSystemNode);
2402 FileSystemNode * const _;
2403 FileSystemNode * Add(FileSystemNode item)
2410 FileSystemNode * AddBefore(uint position, FileSystemNode item)
2412 Insert(position, 1);
2414 return &_[position];
2420 public class ExplorerFileItem : struct
2431 void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox control, Alignment alignment, DataDisplayFlags displayFlags)
2433 int indentSize = (displayFlags.dropBox) ? 0 : 10;
2436 char label[MAX_FILENAME];
2438 //float scale = Min((float)clientSize.w / (float)bitmap.width, (float)clientSize.h / (float)bitmap.height);
2439 int w = 16; //(int)(bitmap.width * scale);
2440 int h = 16; //(int)(bitmap.height * scale);
2444 icon = control.fileIcons[type].bitmap;
2447 if(type == folder || type == folderOpen)
2448 surface.SetForeground(red); //Color { 170, 170, 0 } // REDJ What is that color?
2451 textOffset = indent * indentSize + (icon ? (icon.width + 6) : 0);
2454 sprintf(label, "%s [%s]", name, info);
2456 strcpy(label, name);
2457 len = strlen(label);
2459 surface.WriteTextDots
2460 (alignment, x + textOffset, y + 2, width - textOffset, label, len);
2461 if(type == pictureFile && control.previewPictures && bitmap)
2464 //surface.Filter(bitmap, (clientSize.w - w) / 2,(clientSize.h - h) / 2, 0,0, w, h, bitmap.width, bitmap.height);
2465 surface.Filter(bitmap, x + indent * indentSize + 2, y, 0, 0, w, h, bitmap.width, bitmap.height);
2467 // Until Filter / Stretch works with X
2468 //surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2,(clientSize.h - bitmap.height) / 2, 0,0, bitmap.width, bitmap.height);
2469 surface.blend = true;
2470 surface.Blit(bitmap, x + indent * indentSize + 2, y,0,0, w, h);
2476 surface.Blit(icon, x + indent * indentSize + 2, y,0,0, icon.width, icon.height);
2479 int OnCompare(ExplorerFileItem b)
2482 if(type == b.type || (type < folder && b.type < folder) || (type >= drive))
2483 result = strcmpi(name, b.name);
2486 if(type == folder && b.type < folder) result = -1;
2487 else if(type < folder && b.type == folder) result = 1;
2492 void OnCopy(ExplorerFileItem newData)
2494 type = newData.type;
2495 indent = newData.indent;
2498 int len = strlen(newData.name) + 1;
2499 name = new char[len];
2500 CopyBytes(name, newData.name, len);
2504 bool OnGetDataFromString(char * string)
2506 int len = strlen(string) + 1;
2507 name = new char[len];
2508 CopyBytes(name, string, len);
2522 char * OnGetString(char * string, void * fieldData, bool * needClass)
2528 public class ExplorerFileItemArray : RedjArray
2530 type = class(ExplorerFileItem);
2532 ExplorerFileItem * const _;
2533 ExplorerFileItem * Add(ExplorerFileItem item)
2540 ExplorerFileItem * AddBefore(uint position, ExplorerFileItem item)
2542 Insert(position, 1);
2544 return &_[position];
2549 for(c = 0; c < _count; c++)
2559 ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, const char * filePath, const bool previewPicture, const DisplaySystem displaySystem)
2561 int len = strlen(fileName);
2562 char info[MAX_LOCATION];
2563 char name[MAX_LOCATION];
2564 char extension[MAX_EXTENSION];
2566 ExplorerFileItem item { };
2568 //if(stats.attribs.isFile) // -- should work now
2569 if(attribs.isDirectory)
2573 item.type = (attribs.isDrive) ? drive : folder;
2574 if(attribs.isServer)
2580 if(attribs.isRemote)
2581 item.type = netDrive;
2582 if(attribs.isRemovable)
2584 if(fileName[0] == 'A' || fileName[0] == 'B')
2587 item.type = removable;
2592 GetExtension(fileName, extension);
2593 //strupr(extension);
2596 item.type = _FileType::SelectByExtension(extension);
2599 if(attribs.isDrive &&
2600 len > 3 && !strncmp(&fileName[1], ": [", 3))
2602 strncpy(name, fileName, 2);
2604 strncpy(info, &fileName[4], len - 5);
2609 strcpy(name, fileName);
2613 item.path = CopyString(filePath);
2614 item.name = CopyString(name);
2616 item.info = CopyString(info);
2617 item.extension = CopyString(extension);
2619 if(item.type == pictureFile && previewPicture)
2621 item.bitmap = Bitmap { };
2622 item.bitmap.Load(filePath, null, displaySystem);
2630 public class FileSystemBoxSelection
2633 FileSystemNode node;
2634 Array<FileSystemNode> nodes { };
2637 FileSystemBoxSelection Copy()
2639 FileSystemBoxSelection copy { node = node };
2642 copy.nodes.Add(node);
2648 ~FileSystemBoxSelection()
2654 class FileSystemNodeBits
2656 bool loaded:1, childrenLoaded:1, isListItem:1;
2659 public class FileSystemNode
2663 FileSystemNodeBits bits;
2676 /*//LinkElement<FileSystemNode> link;
2677 FileSystemNode parent;
2679 FileSystemNodeType type;
2683 FileSystemNode prev, next;
2687 property bool isListItem { set { bits.isListItem = value; } get { return bits.isListItem; } };
2689 property char * path
2691 set { delete path; if(value && value[0]) path = CopyString(value); }
2692 get { return path; } isset { return path && path[0]; }
2694 property char * name
2696 set { delete name; if(value && value[0]) name = CopyString(value); }
2697 get { return name; } isset { return name && name[0]; }
2699 property char * extension
2701 set { delete extension; if(value && value[0]) extension = CopyString(value); }
2702 get { return extension; } isset { return extension && extension[0]; }
2704 property char * label
2706 set { delete label; if(value && value[0]) label = CopyString(value); }
2707 get { return label; } isset { return label && label[0]; }
2709 property char * info
2711 set { delete info; if(value && value[0]) info = CopyString(value); }
2712 get { return info; } isset { return info && info[0]; }
2718 FileSystemNode parent;
2726 Array<int> exists; // would use (see) BoolArrayInt to pack this into an int if could be accessed as an array
2728 void GetPath(String outputPath)
2731 strcpy(outputPath, path);
2736 strcpy(outputPath, name);
2737 for(up = parent; up; up = up.parent)
2739 char temp[MAX_LOCATION];
2740 strcpy(temp, up.name);
2741 PathCat(temp, outputPath);
2742 strcpy(outputPath, temp);
2747 strcpy(outputPath, "/");
2749 //strcpy(outputPath, name);
2750 strcpy(outputPath, path);
2751 PathCat(outputPath, name);
2757 bool IsChildOf(FileSystemNode node)
2759 FileSystemNode test;
2760 for(test = parent; test; test = test.parent)
2766 void DuplicateChildren(bool recursive, bool forceExpanded, FileSystemNode addTo, FileSystemBox fsb)
2770 FileSystemNode child;
2772 for(child = children.first; child; child = child.next)
2774 FileSystemNode copy { };
2775 copy.name = child.name; //CopyString(child.name);
2776 copy.type = child.type;
2777 fsb.AddTreeNode(copy, child.bits.loaded, false, false, addTo);
2779 copy.row.collapsed = false;
2781 child.DuplicateChildren(recursive, forceExpanded, copy, fsb);
2786 void EnsureVisible(bool expand)
2789 parent.EnsureVisible(true);
2791 row.collapsed = false;
2792 // TODO: row.EnsureVisible(); // making the row visible by scrolling
2802 FileSystemNode child;
2803 for(; (child = children.first); )
2806 children.Delete(child);
2820 parent.children.Delete(this);
2823 void OnDisplay(Surface surface, int x, int y, int width, FileSystemBox fsb, Alignment alignment, DataDisplayFlags displayFlags)
2825 //int indentSize = (displayFlags.dropBox) ? 0 : 10;
2832 char text[MAX_LOCATION];
2842 comp = fsb.comparedPaths && fsb.comparedPaths.count > 1;
2843 icon = fsb.fileIcons[type].bitmap;
2844 alt = bits.isListItem ? path : name;
2845 if(comp && !fsb.bits.columnsCompareStyle && cmpIcon)
2848 diffIcon = Bitmap { };
2849 diffIcon.AllocateDD(
2850 surface.display.displaySystem,
2851 fsb.compIcons[cmpIcon].bitmap.width,
2852 fsb.compIcons[cmpIcon].bitmap.height);
2853 if(fsb.compIcons[cmpIcon].bitmap)
2854 diffIcon.Copy(fsb.compIcons[cmpIcon].bitmap);
2856 diffIcon = fsb.compIcons[cmpIcon-1].bitmap;
2857 notIcon = fsb.compIcons[countOfCompIconNames-1].bitmap;
2859 //xStart = indent * indent + x + (icon ? (icon.width + 5) : 0);
2860 xStart = x + (icon ? (icon.width + 5) : 0) + (comp ? 18*(fsb.bits.columnsCompareStyle ? fsb.comparedPaths.count : 1) : 0);
2866 sprintf(text, "%s [%s]", label ? label : alt, info);
2868 strcpy(text, label ? label : alt); //"%d-%d/%s", stats.inode, stats.nlink
2869 //sprintf(text, "%d-%d/%s", stats.inode, stats.nlink, label ? label : alt);
2874 if(type == folder || type == folderOpen)
2875 surface.SetForeground(yellow);
2879 //textOffset = indent * indentSize + (icon ? (icon.width + 4) : 0);
2881 surface.SetForeground(displayFlags.selected ? fsb.selectionText : fsb.foreground);
2882 surface.TextOpacity(false);
2883 surface.TextExtent(text, len, &w, &h);
2886 // Draw the current row stipple
2887 if(displayFlags.selected)
2888 //surface.Area(xStart - 1, y, xStart - 1, y + h - 1);
2889 //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1);
2890 surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1);
2892 //surface.WriteTextDots(alignment, x + textOffset, y + 2, width - textOffset, alt, strlen(alt));
2893 surface.WriteTextDots(alignment, xStart, y + 2, width, text, len);
2895 if(!guiApp.textMode)
2897 if(displayFlags.current)
2899 if(displayFlags.active)
2901 surface.LineStipple(0x5555);
2902 if(displayFlags.selected)
2903 surface.SetForeground(0xFFFFFF80);
2905 surface.SetForeground(black);
2909 surface.SetForeground(selectionColor);
2911 surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1);
2912 surface.LineStipple(0);
2917 if(!fsb.bits.columnsCompareStyle && diffIcon)
2920 h = diffIcon.height;
2921 /*if(cmpNot && notIcon)
2923 Surface s = diffIcon.GetSurface(0,0, {w,h});
2924 s.SetForeground(white);
2925 s.Blit(notIcon, x,y, 0,0, w,h);
2928 surface.SetForeground(white);
2929 surface.Blit(diffIcon, x,y, 0,0, w,h);
2930 if(cmpNot && notIcon)
2931 surface.Blit(notIcon, x,y, 0,0, w,h);
2935 else if(fsb.bits.columnsCompareStyle && exists && exists.count)
2938 for(c = d = 0; c < fsb.comparedPaths.count; c++)
2940 if(d == exists.count || exists[d] != c)
2944 diffIcon = fsb.compIcons[c].bitmap;
2948 h = diffIcon.height;
2949 surface.SetForeground(white);
2950 surface.Blit(diffIcon, x,y, 0,0, w,h);
2957 for(c = d = 0; c < exists.count; c++)
2962 x+=18*(exists[c]-d);
2966 diffIcon = fsb.compIcons[exists[c]].bitmap;
2970 h = diffIcon.height;
2971 surface.SetForeground(white);
2972 surface.Blit(diffIcon, x,y, 0,0, w,h);
2978 if(exists.count < fsb.comparedPaths.count && exists[exists.count-1] != d)
2980 x+=18*(exists[exists.count-1]-d);
2984 else if(fsb.bits.columnsCompareStyle)
2986 x+=18*fsb.comparedPaths.count;
2994 if(type == pictureFile && fsb.previewPictures && bitmap)
2996 surface.SetForeground(white);
2997 surface.blend = true;
2999 //surface.Filter(bitmap, (clientSize.w - w) / 2,(clientSize.h - h) / 2, 0,0, w, h, bitmap.width, bitmap.height);
3000 //surface.Filter(bitmap, x + indent/* * indentSize*/ + 2, y, 0, 0, w, h, bitmap.width, bitmap.height);
3001 surface.Filter(bitmap, x,y,0,0, w, h, bitmap.width, bitmap.height);
3003 // Until Filter / Stretch works with X
3004 //surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2,(clientSize.h - bitmap.height) / 2, 0,0, bitmap.width, bitmap.height);
3005 // surface.blend = true;
3006 //surface.Blit(bitmap, x + indent/* * indentSize*/ + 2, y,0,0, w, h);
3007 //surface.Blit(bitmap, x,y,0,0, bitmap.width, bitmap.height);
3014 //surface.blend = true;
3015 //surface.alphaWrite = blend;
3016 surface.SetForeground(white);
3017 //surface.Blit(icon, x + indent * indentSize, y,0,0, icon.width, icon.height);
3018 surface.Blit(icon, x,y, 0,0, w,h);
3023 Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
3027 dataBox, anchor = { 0, 0, 0, 0 };
3029 //borderStyle = contour;
3031 //background = white;
3035 //dataBox.borderStyle = none;
3036 dataBox.borderStyle = contour;
3037 dataBox.background = white;
3038 //dataBox.opacity = 0.0f;
3043 bool OnSaveEdit(EditBox editBox, void * object)
3045 bool changed = false;
3046 if(editBox.modifiedDocument)
3049 // how the heck did this work for PathBox? :S
3051 //changed = _class._vTbl[__ecereVMethodID_class_OnGetDataFromString](_class, &this, editBox.contents);
3053 //if(strcmp(editBox.contents, this.name))
3056 //changed = NotifyNodeRename(this.master, this, node);
3058 if(changed && RenameFile(name, editBox.contents))
3060 name = editBox.contents;
3072 int OnCompare(FileSystemNode b)
3075 FileSystemNode a = this;
3076 if(a.type == b.type || (a.type < folder && b.type < folder) || (a.type >= drive))
3078 if(!a.name || !b.name)
3079 PrintLn("error: FileSystemNode::OnCompare -- null-named node");
3080 result = strcmpi(a.name, b.name);
3084 if(a.type == folder && b.type < folder) result = -1;
3085 else if(a.type < folder && b.type == folder) result = 1;
3092 //int OnCompare(FileSystemNode b)
3095 //FileSystemNode a = this;
3096 //if(a.parent < b.parent) result = -1;
3097 //else if(a.parent > b.parent) result = 1;
3099 //result = fstrcmp(a.name, b.name);
3104 bool OnGetDataFromString(char * string)
3107 if(string && *string)
3109 int len = strlen(string) + 1;
3110 name = new char[len];
3111 CopyBytes(name, string, len);
3118 char * OnGetString(char * tempString, FileSystemToolWindow fileSysToolWnd, bool * needClass)
3120 return name ? name : "";
3124 /*FileSystemNode MakeFileSystemNode(const FileStats stats, const char * name)
3126 FileSystemNode node { stats = stats };
3127 node.name = CopyString(name);
3130 if(stats.attribs.isDirectory)
3132 node.type = (stats.attribs.isDrive) ? drive : folder;
3133 if(stats.attribs.isServer) node.type = server;
3134 if(stats.attribs.isShare) node.type = share;
3135 if(stats.attribs.isCDROM) node.type = cdrom;
3136 if(stats.attribs.isRemote) node.type = netDrive;
3137 if(stats.attribs.isRemovable)
3139 if(name[0] == 'A' || name[0] == 'B')
3142 node.type = removable;
3147 char extension[MAX_EXTENSION];
3148 GetExtension(node.name, extension);
3149 node.type = _FileType::SelectByExtension(extension);
3154 FileSystemNode MakeFileSystemNode(
3155 const FileStats stats,
3158 const bool pathAddName,
3159 const bool previewPicture,
3160 const bool isListItem,
3161 const DisplaySystem displaySystem)
3163 int len = strlen(name);
3164 char info[MAX_LOCATION];
3165 char name2[MAX_LOCATION];
3166 char extension[MAX_EXTENSION];
3168 FileSystemNode node { stats = stats };
3172 char o[MAX_LOCATION];
3173 //char r[MAX_LOCATION];
3174 //StripLastDirectory(path, o);
3175 GetLastDirectory(path, o);
3176 if(fstrcmp(name, o))
3177 //if(!FileExists(path))
3180 //if(stats.attribs.isFile) // TODO fix this in ecere -- WTH -- this has been fixed :/
3181 if(stats.attribs.isDirectory)
3183 extension[0] = '\0';
3185 node.type = (stats.attribs.isDrive) ? drive : folder;
3186 if(stats.attribs.isServer) node.type = server;
3187 if(stats.attribs.isShare) node.type = share;
3188 if(stats.attribs.isCDROM) node.type = cdrom;
3189 if(stats.attribs.isRemote) node.type = netDrive;
3190 if(stats.attribs.isRemovable)
3192 if(name[0] == 'A' || name[0] == 'B')
3195 node.type = removable;
3200 GetExtension(name, extension);
3203 node.type = _FileType::SelectByExtension(extension);
3206 if(stats.attribs.isDrive &&
3207 len > 3 && !strncmp(&name[1], ": [", 3))
3209 strncpy(name2, name, 2);
3211 strncpy(info, &name[4], len - 5);
3216 strcpy(name2, name);
3222 bool isFile = stats.attribs.isFile;
3223 bool isFolder = stats.attribs.isDirectory;
3224 char full[MAX_LOCATION];
3226 PathCat(full, name);
3227 node.path = full; //CopyString(full);
3230 node.path = path; //CopyString(path);
3231 node.name = name2; //CopyString(name2);
3233 node.info = info; //CopyString(info);
3234 node.extension = extension; //CopyString(extension);
3236 if(node.type == pictureFile && previewPicture)
3238 node.bitmap = Bitmap { alphaBlend = true };
3239 node.bitmap.Load(path, null, displaySystem);
3243 node.bits.isListItem = true;
3248 FileSystemNode MakeComparedFileSystemNode(
3249 const FileStats stats,
3252 const bool pathAddName,
3253 const bool previewPicture,
3256 const Array<int> exists,
3257 const DisplaySystem displaySystem)
3259 FileSystemNode node = MakeFileSystemNode(stats, name, path, pathAddName, previewPicture, false, displaySystem);
3262 node.cmpIcon = cmpIcon;
3263 node.cmpNot = cmpNot;
3264 node.exists = exists;
3269 #if 0 // could we do this?
3270 class BoolArrayInt : int
3272 // packing 32 bools in one int exposing them as an array
3273 bool [32]:1; // the :1 specifies the size of each element
3274 // byte [4]:8; // packing 4 bytes in an int exposing them as an arrat
3276 // allowing you to access each 32 bits with the following notation:
3283 for(c = 0; c < 32; c++)
3284 a[c] = SomFunction(...);
3287 class BoolArrayInt : int