151df78ff24570d45779774a2cd3092259cd564d
[ede] / libede / src / FileSystemBox.ec
1 public import "ecere"
2
3 #ifdef __WIN32__
4 static char * rootName = "Entire Computer";
5 static char * msNetwork = "Microsoft Windows Network";
6 #else
7 static char * rootName = "File System";
8 #endif
9
10 private:
11 define guiApp = ((GuiApplication)__thisModule);
12 define selectionColor = guiApp.currentSkin.selectionColor; //Color { 10, 36, 106 };
13
14 static char * fileIconNames[] = 
15 {
16    "<:ecere>mimeTypes/file.png",         /* none */
17
18    "<:ecere>mimeTypes/file.png",         /* normalFile */
19    "<:ecere>mimeTypes/textEcereWorkspace.png",          /* ewsFile */
20    "<:ecere>mimeTypes/textEcereProject.png",      /* epjFile */
21    "<:ecere>mimeTypes/textEcereSource.png",         /* ecFile */
22    "<:ecere>mimeTypes/textEcereHeader.png",         /* ehFile */
23    "<:ecere>mimeTypes/textCSource.png",          /* cFile */
24    "<:ecere>mimeTypes/textCHeader.png",          /* hFile */
25    "<:ecere>mimeTypes/textC++Source.png",        /* cppFile */
26    "<:ecere>mimeTypes/textC++Header.png",        /* hppFile */
27    "<:ecere>mimeTypes/text.png",         /* textFile */
28    "<:ecere>mimeTypes/textHyperTextMarkup.png",              /* webFile */
29    "<:ecere>mimeTypes/image.png",        /* pictureFile */
30    "<:ecere>status/audioVolumeHigh.png",         /* soundFile */
31    "<:ecere>mimeTypes/package.png",      /* archiveFile */
32    "<:ecere>mimeTypes/packageSoftware.png",     /* packageFile */
33    "<:ecere>mimeTypes/packageOpticalDisc.png", /* opticalMediaImageFile */
34
35    "<:ecere>places/folder.png",                    /* folder */
36    "<:ecere>status/folderOpen.png",               /* folderOpen */
37    "<:ecere>devices/computer.png",                 /* computer */
38    "<:ecere>devices/driveHardDisk.png",           /* drive */
39    "<:ecere>places/driveRemote.png",              /* netDrive */
40    "<:ecere>devices/mediaOptical.png",            /* cdrom */
41    "<:ecere>devices/driveRemovableMedia.png",    /* removable */
42    "<:ecere>devices/mediaFloppy.png",             /* floppy */
43    "<:ecere>places/networkWorkgroup.png",         /* network */
44    "<:ecere>places/networkServer.png",            /* server */
45    "<:ecere>places/folderRemote.png",             /* share */
46
47    "<:ecere>mimeTypes/package.png",      /* treeLoader */
48    "<:ecere>places/startHere.png",                /* lineNumbers */
49    
50    ""
51 };
52
53 public enum ExplorerFileType
54 {
55    none,
56    
57    normalFile, ewsFile, epjFile, ecFile, ehFile, cFile, hFile, cppFile, hppFile,
58    textFile, webFile, pictureFile, soundFile,
59    archiveFile, packageFile, opticalMediaImageFile, /* these (all previous) are sort equal */
60    
61    folder, folderOpen, computer,
62    drive, netDrive, cdrom, removable, floppy, network, server, share, // these are sort equal
63    
64    // utilities
65    treeLoader,
66    lineNumbers;
67
68
69    /*property char * 
70    {
71       set
72       {
73          this = SelectByExtension(value);
74       }
75    }*/
76
77    public property bool isFolderType
78    {
79       get { return this >= folder && this <= share; }
80    }
81
82    public property bool isFileType
83    {
84       get { return this >= normalFile && this <= opticalMediaImageFile; }
85    }
86
87    ExplorerFileType ::SelectByExtension(char * extension)
88    {
89       if(!strcmpi(extension, "ews"))
90          return ewsFile;
91       else if(!strcmpi(extension, "epj"))
92          return epjFile;
93       else if(!strcmpi(extension, "ec"))
94          return ecFile;
95       else if(!strcmpi(extension, "eh"))
96          return ehFile;
97       else if(!strcmpi(extension, "cpp") ||
98             !strcmpi(extension, "cc") || !strcmpi(extension, "cxx"))
99          return cppFile;
100       else if(!strcmpi(extension, "hpp") ||
101             !strcmpi(extension, "hh") || !strcmpi(extension, "hxx"))
102          return hppFile;
103       else if(!strcmpi(extension, "c"))
104          return cFile;
105       else if(!strcmpi(extension, "h"))
106          return hFile;
107       else if(!strcmpi(extension, "txt") || !strcmpi(extension, "text") ||
108             !strcmpi(extension, "nfo") || !strcmpi(extension, "info"))
109          return textFile;
110       else if(!strcmpi(extension, "htm") || !strcmpi(extension, "html") ||
111             !strcmpi(extension, "css") || !strcmpi(extension, "php") ||
112             !strcmpi(extension, "js"))
113          return webFile;
114       else if(!strcmpi(extension, "bmp") || !strcmpi(extension, "pcx") ||
115             !strcmpi(extension, "jpg") || !strcmpi(extension, "jpeg") ||
116             !strcmpi(extension, "gif") || !strcmpi(extension, "png") ||
117             !strcmpi(extension, "ico"))
118          return pictureFile;
119       else if(!strcmpi(extension, "wav") || !strcmpi(extension, "mp3") ||
120             !strcmpi(extension, "ogg") || !strcmpi(extension, "snd"))
121          return soundFile;
122       else if(!strcmpi(extension, "ear") || !strcmpi(extension, "7z") ||
123             !strcmpi(extension, "rar") || !strcmpi(extension, "zip") ||
124             !strcmpi(extension, "gz") || !strcmpi(extension, "bz2") ||
125             !strcmpi(extension, "tar") || !strcmpi(extension, "arj") ||
126             !strcmpi(extension, "lza") || !strcmpi(extension, "lzh") ||
127             !strcmpi(extension, "cpio") || !strcmpi(extension, "z"))
128          return archiveFile;
129       else if(!strcmpi(extension, "cab") || !strcmpi(extension, "deb") ||
130             !strcmpi(extension, "rpm"))
131          return packageFile;
132       else if(!strcmpi(extension, "iso") || !strcmpi(extension, "mds") ||
133             !strcmpi(extension, "cue") || !strcmpi(extension, "bin") ||
134             !strcmpi(extension, "ccd") || !strcmpi(extension, "bwt") ||
135             !strcmpi(extension, "cdi") || !strcmpi(extension, "nrg"))
136          return opticalMediaImageFile;
137       return normalFile;
138    }
139 };
140
141 #if 0
142 class ExplorerControl : Window
143 {
144    bool previewPictures;
145
146    BitmapResource fileIcons[ExplorerFileType];
147
148    ExplorerControl()
149    {
150       ExplorerFileType c;
151       for(c = 0; c < ExplorerFileType::enumSize; c++)
152       {
153          fileIcons[c] = BitmapResource { fileIconNames[c], alphaBlend = true };
154          AddResource(fileIcons[c]);
155       }
156    }
157 }
158 #endif
159
160 #if 0
161 class ExplorerView : ExplorerControl
162 {
163    borderStyle = none;
164    hasHorzScroll = false;
165    hasVertScroll = false;
166
167    virtual void Load(ExplorerFileBranch parent);
168    virtual void Refresh();
169
170    virtual void LaunchNotifyItemSelect(Window master, ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems)
171    {
172       view.NotifyItemSelect(master, view, item, selectedItems);
173    }
174
175    virtual bool Window::NotifyItemSelect(ExplorerView view, ExplorerFileItem item, ExplorerFileItemArray selectedItems);
176    virtual bool Window::NotifyItemOpen(ExplorerView view, ExplorerFileItem item);
177
178    ListBox list
179    {
180       master = master, parent = this;
181       //this, master;
182       borderStyle = none;
183       hasHorzScroll = true;
184       hasVertScroll = true;
185       resizable = true;
186       sortable = true;
187       fullRowSelect = false;
188       multiSelect = true;
189
190       anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
191
192       bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
193       {
194          ExplorerView view = (ExplorerView)listBox.parent;
195          if(listBox.currentRow)
196          {
197             DataRow listRow;
198             ExplorerFileItemArray selectedItems { growingFactor = 16 };
199             for(listRow = listBox.firstRow; listRow; listRow = listRow.next)
200                if(listRow.selected)
201                   selectedItems.Add((ExplorerFileItem)listRow.tag);
202             //view.NotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag);
203             view.LaunchNotifyItemSelect(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag, selectedItems);
204          }
205          return true;
206       }
207
208       bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods)
209       {
210          ExplorerView view = (ExplorerView)listBox.parent;
211          view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag);
212          return false;
213       }
214
215       bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
216       {
217          if((SmartKey)key == enter)
218          {
219             ExplorerView view = (ExplorerView)listBox.parent;
220             view.NotifyItemOpen(listBox.parent.master, view, (ExplorerFileItem)listBox.currentRow.tag);
221          }
222          return true;
223       }
224    };
225
226    ExplorerView()
227    {
228    }
229 }
230 #endif
231
232 #if 0
233 class ExplorerViewList : ExplorerView
234 {
235
236    ExplorerFileBranch location;
237
238 public:
239
240    DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
241
242    ExplorerViewDetails()
243    {
244       list.AddField(nameField);
245    }
246
247    void Refresh()
248    {
249       Load(location);
250    }
251
252    void Load(ExplorerFileBranch location)
253    {
254       char path[MAX_LOCATION];
255       this.location = location;
256       location.GetPath(path);
257       {
258          FileListing listing { path };
259          
260          ExplorerFileItem item;
261          DataRow row;
262
263          list.Clear();
264
265          while(listing.Find())
266          {
267             item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
268
269             row = list.AddRow();
270             row.tag = (int)item;
271             row.SetData(nameField, item);
272          }
273          list.Sort(nameField, 1);
274       }
275    }
276 }
277 #endif
278
279 #if 0
280 class ExplorerViewDetails : ExplorerView
281 {
282    list.hasHeader = true;
283    list.moveFields = true;
284    list.resizable = true;
285    list.sortable = true;
286
287    ExplorerFileBranch location;
288
289 public:
290
291    DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
292    DataField typeField { header = "Type", dataType = /*"String"*/ "char *", width = 40 };
293    DataField sizeField { header = "Size", dataType = "FileSize", width = 96, alignment = right };
294
295    ExplorerViewDetails()
296    {
297       list.AddField(nameField);
298       list.AddField(typeField);
299       list.AddField(sizeField);
300    }
301
302    void Refresh()
303    {
304       Load(location);
305    }
306
307    void Load(ExplorerFileBranch location)
308    {
309       char path[MAX_LOCATION];
310       this.location = location;
311       location.GetPath(path);
312       {
313          FileListing listing { path };
314          
315          ExplorerFileItem item;
316          DataRow row;
317
318          list.Clear();
319
320          while(listing.Find())
321          {
322             item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
323
324             row = list.AddRow();
325             row.tag = (int)item;
326             row.SetData(nameField, item);
327             row.SetData(typeField, CopyString(item.extension));
328             row.SetData(sizeField, (uint)listing.stats.size);
329          }
330          list.Sort(nameField, 1);
331       }
332    }
333 }
334 #endif
335
336 #if 0
337 class ExplorerViewIcons : ExplorerView
338 {
339
340    ExplorerFileBranch location;
341
342 public:
343
344    DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
345
346    ExplorerViewDetails()
347    {
348       list.AddField(nameField);
349    }
350
351    void Refresh()
352    {
353       Load(location);
354    }
355
356    void Load(ExplorerFileBranch location)
357    {
358       char path[MAX_LOCATION];
359       this.location = location;
360       location.GetPath(path);
361       {
362          FileListing listing { path };
363          
364          ExplorerFileItem item;
365          DataRow row;
366
367          list.Clear();
368
369          while(listing.Find())
370          {
371             item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
372
373             row = list.AddRow();
374             row.tag = (int)item;
375             row.SetData(nameField, item);
376          }
377          list.Sort(nameField, 1);
378       }
379    }
380 }
381 #endif
382
383 #if 0
384 class ExplorerViewCards : ExplorerView
385 {
386
387    ExplorerFileBranch location;
388
389 public:
390
391    DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 304, editable = true, userData = this };
392
393    ExplorerViewDetails()
394    {
395       list.AddField(nameField);
396    }
397
398    void Refresh()
399    {
400       Load(location);
401    }
402
403    void Load(ExplorerFileBranch location)
404    {
405       char path[MAX_LOCATION];
406       this.location = location;
407       location.GetPath(path);
408       {
409          FileListing listing { path };
410          
411          ExplorerFileItem item;
412          DataRow row;
413
414          list.Clear();
415
416          while(listing.Find())
417          {
418             item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
419
420             row = list.AddRow();
421             row.tag = (int)item;
422             row.SetData(nameField, item);
423          }
424          list.Sort(nameField, 1);
425       }
426    }
427 }
428 #endif
429
430 #if 0
431 public class BitmapArray : RedjArray
432 {
433    type = class(Bitmap);
434 public:
435    Bitmap * const _;
436    Bitmap * Add(Bitmap bitmap)
437    {
438       uint pos = _count;
439       Append(1);
440       _[pos] = bitmap;
441       return &_[pos];
442    }
443    Bitmap * AddBefore(uint position, Bitmap bitmap)
444    {
445       Insert(position, 1);
446       _[position] = bitmap;
447       return &_[position];
448    }
449    void Clear()
450    {
451       int c;
452       for(c = 0; c < _count; c++)
453       {
454          _[c].Free();
455          delete _[c];
456       }  
457       count = 0;
458       size = 0;
459    }
460 }
461 #endif
462
463 #if 0
464 class ExplorerViewShowcase : ExplorerView
465 {
466    list.anchor = Anchor { left = 0, top = 0, bottom = 0 };
467    list.size = Size { w = 200 };
468
469    ExplorerFileBranch location;
470
471 public:
472
473    DataField nameField { header = "Name", dataType = "ExplorerFileItem", width = 180, editable = true, userData = this };
474
475    Bitmap bitmap;
476    BitmapArray bitmaps { growingFactor = 16 };
477
478    Window show
479    {
480       this;
481       borderStyle = none;
482       anchor = Anchor { top = 0, right = 0, bottom = 0 };
483
484       void OnRedraw(Surface surface)
485       {
486          ExplorerViewShowcase view = (ExplorerViewShowcase)parent;
487          if(view.bitmap)
488          {
489             int wBmp = view.bitmap.width;
490             int hBmp = view.bitmap.height;
491             int wWnd = clientSize.w;
492             int hWnd = clientSize.h;
493
494             int wList = view.list.size.w + view.split.size.w;
495             
496             float scale = Min((float)(wWnd - 10) / wBmp, (float)(hWnd - 10) / hBmp);
497             
498             int wDraw = (int)(wBmp * scale);
499             int hDraw = (int)(hBmp * scale);
500
501       #ifndef __linux__
502             surface.Filter(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw, wBmp, hBmp);
503       #else
504             // Until Filter / Stretch works with X
505             surface.Blit(view.bitmap, (wWnd - wDraw) / 2, (hWnd - hDraw) / 2, 0, 0, wDraw, hDraw);
506       #endif
507          }
508          else
509          {
510             surface.SetForeground(white);
511             surface.Area(0, 0, view.clientSize.w - 1, view.clientSize.h - 1);
512          }
513       }
514    }
515
516    SplitWindow split
517    {
518       this;
519       leftPane = list;
520       rightPane = show;
521       split = 200;
522       tabCycle = true;
523    };
524
525    ExplorerViewDetails()
526    {
527       list.AddField(nameField);
528    }
529
530    void LaunchNotifyItemSelect(Window master, ExplorerViewShowcase view, ExplorerFileItem item, ExplorerFileItemArray selectedItems)
531    {
532       int pos;
533       ExplorerFileItem selItem;
534       if(view.bitmap)
535          view.bitmap.Free();
536       delete view.bitmap;
537       if(item && item.type == pictureFile)
538       {
539          view.bitmap = Bitmap { };
540          view.bitmap.Load(item.path, null, displaySystem);
541       }
542
543       view.bitmaps.Clear();
544       view.bitmaps = BitmapArray { };
545       for(pos = 0; pos < selectedItems.count; pos++)
546       {
547          Bitmap bitmap { };
548          selItem = (ExplorerFileItem)selectedItems._[pos]; 
549          bitmap.Load(selItem.path, null, displaySystem);
550          //view.bitmaps.Add(bitmap);
551       }  
552       if(item && item.type == pictureFile)
553       {
554          view.bitmap = Bitmap { };
555          view.bitmap.Load(item.path, null, displaySystem);
556       }
557
558       view.show.Update(null);
559       view.NotifyItemSelect(master, view, item, selectedItems);
560    }
561
562    void Refresh()
563    {
564       Load(location);
565    }
566
567    void Load(ExplorerFileBranch location)
568    {
569       char path[MAX_LOCATION];
570       this.location = location;
571       location.GetPath(path);
572       {
573          FileListing listing { path };
574          
575          ExplorerFileItem item;
576          DataRow row;
577
578          list.Clear();
579
580          while(listing.Find())
581          {
582             item = MakeFileItem(listing.stats.attribs, listing.name, listing.path, previewPictures, displaySystem);
583
584             row = list.AddRow();
585             row.tag = (int)item;
586             row.SetData(nameField, item);
587          }
588          list.Sort(nameField, 1);
589       }
590    }
591 }
592 #endif
593
594 #if 0
595 class ExplorerTree : ExplorerControl
596 {
597    hasHorzScroll = false;
598    hasVertScroll = false;
599
600    menu = Menu { };
601
602 public:
603
604    DataField nameField { dataType = "ExplorerFileBranch", width = 240, userData = this };
605
606    ExplorerFileBranch root;
607    ExplorerFileBranch selection;
608
609    virtual bool Window::NotifyBranchSelect(ExplorerTree tree, ExplorerFileBranch branch);
610    
611    property ExplorerFileBranch branch
612    {
613       get
614       {
615          if(!tree)
616             return null;
617          if(!tree.currentRow)
618             return null;
619          if(!tree.currentRow.tag)
620             return null;
621          return (ExplorerFileBranch)tree.currentRow.tag;
622       }
623    }
624
625    void Select(ExplorerFileBranch branch)
626    {
627       if(branch.row)
628       {
629          branch.EnsureVisible(false);
630          tree.SelectRow(branch.row);
631       }
632    }
633
634    ExplorerFileBranch Find(const char * name, ExplorerFileBranch parent)
635    {
636       ExplorerFileBranch branch;
637       ExplorerFileBranch start = parent ? parent : root;
638       if(!start.loaded || !start.childrenLoaded)
639          BranchLoad(start, tree);
640       for(branch = start.children.first; branch; branch = branch.next)
641          if(branch.name && !strcmpi(branch.name, name))
642             return branch;
643       return null;
644    }
645
646    ListBox tree
647    {
648       master = master, parent = this;
649       //this, master;
650       borderStyle = none;
651       hasHorzScroll = true;
652       hasVertScroll = true;
653       fullRowSelect = false;
654       treeBranches = true;
655       collapseControl = true;
656       rootCollapseButton = true;
657
658       anchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
659
660       // WHY is this not working ?
661       /*void OnResize(int width, int height)
662       {
663          if(vertScroll.visible)
664             nameField.width = width - vertScroll.size.w;
665          else
666             nameField.width = width;
667       }*/
668
669       bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed)
670       {
671          if(row)
672          {
673             ExplorerFileBranch branch = (ExplorerFileBranch)row.tag;
674             ExplorerFileBranch child;
675             if(collapsed)
676             {
677                /*
678                for(child = branch.children.last; child; child = branch.children.last)
679                {
680                   listBox.DeleteRow(child.row);
681                   child.Free();
682                   delete child;
683                }
684                branch.childrenLoaded = false;
685                */
686             }
687             else
688             {
689                if(!branch.loaded || !branch.childrenLoaded)
690                   BranchLoad(branch, tree);
691                for(child = branch.children.first; child && child.next; child = child.next);
692                if(child)
693                   child.EnsureVisible(false);
694             }
695          }
696          return true;
697       }
698       
699       bool NotifyRightClick(ListBox listBox, int x, int y, Modifiers mods)
700       {
701          DataRow row = listBox.currentRow;
702          if(row)
703          {
704             ExplorerFileBranch branch = (ExplorerFileBranch)row.tag;
705             if(branch)
706             {
707                PopupMenu popup;
708                Menu menu { };
709
710                MenuItem { menu, "Cut\tCtrl+X", t, NotifySelect = null, disabled = false };
711                MenuItem { menu, "Copy\tCtrl+C", c, NotifySelect = null, disabled = false };
712                MenuItem { menu, "Paste\tCtrl+V", p, NotifySelect = null, disabled = false /*!clipboard*/ };
713                MenuItem { menu, "Delete\tDel", d, NotifySelect = null, disabled = false };
714                //MenuDivider { menu };
715
716                popup = PopupMenu
717                   {
718                      master = this, menu = menu,
719                      position = { 
720                         x + clientStart.x + absPosition.x - guiApp.desktop.position.x, 
721                         y + clientStart.y + absPosition.y - guiApp.desktop.position.y }
722                   };
723                popup.Create();
724             }
725          }
726          return true;
727       }
728
729       bool NotifySelect(ListBox listBox, DataRow row, Modifiers mods)
730       {
731          if(row)
732          {
733             ExplorerFileBranch branch = (ExplorerFileBranch)row.tag;
734             NotifyBranchSelect(listBox.parent.master, this, branch);
735             selection = branch;
736          }
737          return true;
738       }
739
740       bool NotifyEditing(ListBox listBox, DataRow row)
741       {
742          if(row)
743          {
744             ExplorerFileBranch branch = (ExplorerFileBranch)row.tag;
745          }
746          return true;
747       }
748
749       bool NotifyEdited(ListBox listBox, DataRow row)
750       {
751          if(row)
752          {
753             ExplorerFileBranch branch = (ExplorerFileBranch)row.tag;
754          }
755          return true;
756       }
757
758       bool NotifyEditDone(ListBox listBox, DataRow row)
759       {
760          if(row)
761          {
762             ExplorerFileBranch branch = (ExplorerFileBranch)row.tag;
763          }
764          return true;
765       }
766    };
767
768    // Edit Menu
769    Menu editMenu { menu, "Edit", e };
770    MenuItem itemEditCut
771    {
772       editMenu, "Cut\tCtrl+X", t, disabled = true;
773
774       bool NotifySelect(MenuItem selection, Modifiers mods)
775       {
776          //EditCut();
777          return true;
778       }
779    };
780    MenuItem itemEditCopy
781    {
782       editMenu, "Copy\tCtrl+C", c, disabled = true;
783
784       bool NotifySelect(MenuItem selection, Modifiers mods)
785       {
786          //EditCopy();
787          return true;
788       }
789    };
790    MenuItem itemEditPaste
791    {
792       editMenu, "Paste\tCtrl+V", p;
793    
794       bool NotifySelect(MenuItem selection, Modifiers mods)
795       {
796          //EditPaste();
797          return true;
798       }
799    };
800    MenuItem itemEditDelete
801    {
802       editMenu, "Delete\tDel", d, disabled = true;
803
804       bool NotifySelect(MenuItem selection, Modifiers mods)
805       {
806          //EditDelete();
807          return true;
808       }
809    };
810
811    // WHY is this crashing ? 
812    /*void OnResize(int width, int height)
813    {
814       if(this && nameField)
815          nameField.width = width - 80;
816    }*/
817
818    ExplorerTree()
819    {
820       tree.AddField(nameField);
821    }
822
823    void Load()
824    {
825       ExplorerFileBranch parent;
826       ExplorerFileBranch branch;
827       FileListing listing { "/" };
828
829       tree.Clear();
830
831       root = ExplorerFileBranch { type = computer, loaded = true, childrenLoaded = true };
832    #ifdef __WIN32__
833       root.name = rootName;
834    #else
835       root.name = "/";
836    #endif
837       AddBranch(root, true, false, null, tree);
838
839    // How can this make sense for linux? 
840    #ifdef __WIN32__
841       while(listing.Find())
842       {
843          int len = strlen(listing.name);
844          char info[MAX_LOCATION];
845          char name[MAX_LOCATION];
846          if(listing.stats.attribs.isDrive && 
847                len > 3 && !strncmp(&listing.name[1], ": [", 3))
848          {
849             strncpy(name, listing.name, 2);
850             name[2] = 0;
851             strncpy(info, &listing.name[4], len - 5);
852             info[len - 5] = 0;
853          }
854          else
855          {
856             strcpy(name, listing.name);
857             info[0] = 0;
858          }
859
860          parent = MakeFileBranch(listing.stats, name);
861          if(info[0])
862             parent.info = CopyString(info);
863          parent.loaded = true;
864          AddBranch(parent, !listing.stats.attribs.isDirectory, listing.stats.attribs.isDirectory, root, tree);
865          if(!listing.stats.attribs.isDirectory)
866             parent.childrenLoaded = true;
867       }
868
869       branch = ExplorerFileBranch { name = msNetwork, type = network };
870       AddBranch(branch, false, true, null, tree);
871       branch.row.collapsed = true;
872       tree.Sort(nameField, 1);
873       tree.SelectRow(root.row);
874    #endif
875    }
876
877 /*
878 public class ClipBoardFiles
879 {
880
881 public:
882
883    property
884
885 }
886
887    // CLIPBOARD
888    void Copy()
889    {
890       if(this)
891       {
892          int size = SelSize();
893          if(size)
894          {
895             // Try to allocate memory
896             ClipBoard clipBoard { };
897             if(clipBoard.Allocate(size+1))
898             {
899                GetSel(clipBoard.memory, true);   
900                // Save clipboard
901                clipBoard.Save();
902             }
903             delete clipBoard;
904          }
905       }
906    }
907
908    void Paste()
909    {
910       if(this)
911       {
912          ClipBoard clipBoard { };
913          if(clipBoard.Load())
914             PutS(clipBoard.memory);
915          delete clipBoard;
916       }
917    }
918
919    void Cut()
920    {
921       if(this)
922       {
923          Copy();
924          DelSel();
925          SetViewToCursor(true);
926          Modified();
927       }
928    }
929
930 Private Type DROPFILES
931    pFiles As Long
932    pt As POINTAPI
933    fNC As Long
934    fWide As Long
935 End Type
936 For iCounter = 0 To filelist.ListCount - 1
937   If filelist.Selected(iCounter) = True Then
938     strFiles = strFiles & FixPath(filelist.Path) & filelist.List(iCounter) & vbNullChar
939   End If
940 Next
941 'all selected items are now put in strFiles
942
943 hGlobal = GlobalAlloc(GHND, Len(DF) + Len(strFiles)) 'put all files to a exclusive number
944 If hGlobal Then 'if the globalalloc worked
945   lpGlobal = GlobalLock(hGlobal) 'lock the hGlobal
946   DF.pFiles = Len(DF) 'set the size of the files
947   
948   Call CopyMem(ByVal lpGlobal, DF, Len(DF)) 'copy df to the lpglobal
949   Call CopyMem(ByVal (lpGlobal + Len(DF)), ByVal strFiles, Len(strFiles)) 'copy strfiles to lpglobal
950   Call GlobalUnlock(hGlobal) 'unlock hglobal again
951   
952   SetClipboardData CF_HDROP, hGlobal 'put files to the clipboard
953 End If
954
955    bool SaveFile(const char * filePath)
956    {
957    }
958 */
959
960 }
961 #endif
962
963 #if 0
964 public class FileTreeBranchBSArray : ArrayBinarySorted
965 {
966    type = class(ExplorerFileBranch);
967 public:
968    ExplorerFileBranch * const _;
969    BSloc Add(ExplorerFileBranch item)
970    {
971       BSloc result = Find(item);
972       if(!result.valid)
973       {
974          Insert(result.pos, 1);
975          _[result.pos] = item;
976       }
977       return result;
978    }
979    BSloc Remove(ExplorerFileBranch item)
980    {
981       
982    }
983 }
984 #endif
985
986 #if 0
987 public class FileTreeBranchArray : RedjArray
988 {
989    type = class(ExplorerFileBranch);
990 public:
991    ExplorerFileBranch * const _;
992    ExplorerFileBranch * Add(ExplorerFileBranch item)
993    {
994       uint pos = _count;
995       Append(1);
996       _[pos] = item;
997       return &_[pos];
998    }
999    ExplorerFileBranch * AddBefore(uint position, ExplorerFileBranch item)
1000    {
1001       Insert(position, 1);
1002       _[position] = item;
1003       return &_[position];
1004    }
1005 }
1006 #endif
1007
1008 #if 0
1009 public class ExplorerFileItem : struct
1010 {
1011    char * path;
1012    char * name;
1013    char * info;
1014    char * extension;
1015    ExplorerFileType type;
1016    int indent;
1017
1018    Bitmap bitmap;
1019
1020    void OnDisplay(Surface surface, int x, int y, int width, ExplorerControl control, Alignment alignment, DataDisplayFlags displayFlags)
1021    {
1022       int indentSize = (displayFlags.dropBox) ? 0 : 10;
1023       int textOffset;
1024       int len;
1025       char label[MAX_FILENAME];
1026
1027       //float scale = Min((float)clientSize.w / (float)bitmap.width, (float)clientSize.h / (float)bitmap.height);
1028       int w = 16; //(int)(bitmap.width * scale);
1029       int h = 16; //(int)(bitmap.height * scale);
1030    
1031       Bitmap icon;
1032
1033       icon = control.fileIcons[type].bitmap;
1034       if(!icon)
1035       {
1036          if(type == folder || type == folderOpen)
1037             surface.SetForeground(red); //Color { 170, 170, 0 } // REDJ What is that color?
1038          indentSize = 8;
1039       }
1040       textOffset = indent * indentSize + (icon ? (icon.width + 6) : 0);
1041       
1042       if(info)
1043          sprintf(label, "%s [%s]", name, info);
1044       else
1045          strcpy(label, name);
1046       len = strlen(label);
1047
1048       surface.WriteTextDots
1049          (alignment, x + textOffset, y + 2, width - textOffset, label, len);
1050       if(type == pictureFile && control.previewPictures && bitmap)
1051       {
1052 #ifndef __linux__
1053          //surface.Filter(bitmap, (clientSize.w - w) / 2,(clientSize.h - h) / 2, 0,0, w, h, bitmap.width, bitmap.height);
1054          surface.Filter(bitmap, x + indent * indentSize + 2, y, 0, 0, w, h, bitmap.width, bitmap.height);
1055 #else
1056          // Until Filter / Stretch works with X
1057          //surface.Blit(bitmap, (clientSize.w - bitmap.width) / 2,(clientSize.h - bitmap.height) / 2, 0,0, bitmap.width, bitmap.height);
1058          surface.blend = true;
1059          surface.Blit(bitmap, x + indent * indentSize + 2, y,0,0, w, h);
1060 #endif
1061          //bitmap.Free();
1062          //delete bitmap;
1063       }
1064       else if(icon)
1065          surface.Blit(icon, x + indent * indentSize + 2, y,0,0, icon.width, icon.height);
1066    }
1067
1068    int OnCompare(ExplorerFileItem b)
1069    {
1070       int result;
1071       if(type == b.type || (type < folder && b.type < folder) || (type >= drive))
1072          result = strcmpi(name, b.name);
1073       else
1074       {
1075          if(type == folder && b.type < folder) result = -1;
1076          else if(type < folder && b.type == folder) result = 1;
1077       }
1078       return result;
1079    }
1080
1081    void OnCopy(ExplorerFileItem newData)
1082    {
1083       type = newData.type;
1084       indent = newData.indent;
1085       if(newData.name)
1086       {
1087          int len = strlen(newData.name) + 1;
1088          name = new char[len];
1089          CopyBytes(name, newData.name, len);
1090       }
1091    }
1092
1093    bool OnGetDataFromString(char * string)
1094    {
1095       int len = strlen(string) + 1;
1096       name = new char[len];
1097       CopyBytes(name, string, len);
1098       return true;
1099    }
1100
1101    void OnFree()
1102    {
1103       delete path;
1104       delete name;
1105       delete info;
1106       delete extension;
1107       if(bitmap)
1108          bitmap.Free();
1109    }
1110
1111    char * OnGetString(char * string, void * fieldData, bool * needClass)
1112    {
1113       return name;
1114    }
1115 };
1116
1117 public class ExplorerFileItemArray : RedjArray
1118 {
1119    type = class(ExplorerFileItem);
1120 public:
1121    ExplorerFileItem * const _;
1122    ExplorerFileItem * Add(ExplorerFileItem item)
1123    {
1124       uint pos = _count;
1125       Append(1);
1126       _[pos] = item;
1127       return &_[pos];
1128    }
1129    ExplorerFileItem * AddBefore(uint position, ExplorerFileItem item)
1130    {
1131       Insert(position, 1);
1132       _[position] = item;
1133       return &_[position];
1134    }
1135    void Clear()
1136    {
1137       int c;
1138       for(c = 0; c < _count; c++)
1139       {
1140          //_[c].Free()
1141          delete _[c];
1142       }  
1143       count = 0;
1144       size = 0;
1145    }
1146 }
1147
1148 ExplorerFileItem MakeFileItem(const FileAttribs attribs, const char * fileName, const char * filePath, const bool previewPicture, const DisplaySystem displaySystem)
1149 {
1150    int len = strlen(fileName);
1151    char info[MAX_LOCATION];
1152    char name[MAX_LOCATION];
1153    char extension[MAX_EXTENSION];
1154    
1155    ExplorerFileItem item { };
1156
1157    //if(attribs.isFile) // TODO fix this in ecere
1158    if(attribs.isDirectory)
1159    {
1160       extension[0] = 0;
1161
1162       item.type = (attribs.isDrive) ? drive : folder;
1163       if(attribs.isServer)
1164          item.type = server;
1165       if(attribs.isShare)
1166          item.type = share;
1167       if(attribs.isCDROM)
1168          item.type = cdrom;
1169       if(attribs.isRemote)
1170          item.type = netDrive;
1171       if(attribs.isRemovable) 
1172       {
1173          if(fileName[0] == 'A' || fileName[0] == 'B')
1174             item.type = floppy;
1175          else
1176             item.type = removable;
1177       }
1178    }
1179    else
1180    {
1181       GetExtension(fileName, extension);
1182       //strupr(extension);
1183       strlwr(extension);
1184       
1185       item.type = ExplorerFileType::SelectByExtension(extension);
1186    }
1187
1188    if(attribs.isDrive && 
1189          len > 3 && !strncmp(&fileName[1], ": [", 3))
1190    {
1191       strncpy(name, fileName, 2);
1192       name[2] = 0;
1193       strncpy(info, &fileName[4], len - 5);
1194       info[len - 5] = 0;
1195    }
1196    else
1197    {
1198       strcpy(name, fileName);
1199       info[0] = 0;
1200    }
1201
1202    item.path = CopyString(filePath);
1203    item.name = CopyString(name);
1204    if(info[0])
1205       item.info = CopyString(info);
1206    item.extension = CopyString(extension);
1207
1208    if(item.type == pictureFile && previewPicture)
1209    {
1210       item.bitmap = Bitmap { };
1211       item.bitmap.Load(filePath, null, displaySystem);
1212    }
1213
1214    return item;
1215 }
1216 #endif
1217
1218 #if 0
1219 public class ExplorerFileBranch : struct
1220 {
1221    ExplorerFileBranch prev, next;
1222
1223    bool loaded, childrenLoaded;
1224    int indent;
1225    char * name;
1226    char * info;
1227    DataRow row;
1228    OldList children;
1229    ExplorerFileType type;
1230    ExplorerFileBranch parent;
1231
1232    FileStats stats;
1233
1234    void GetPath(String outputPath)
1235    {  
1236       ExplorerFileBranch up;
1237       if(parent)
1238       {
1239          strcpy(outputPath, name);
1240          for(up = parent; up; up = up.parent)
1241          {
1242             char temp[MAX_LOCATION];
1243             strcpy(temp, up.name);
1244             PathCat(temp, outputPath);
1245             strcpy(outputPath, temp);
1246          }
1247       }
1248       else
1249 #ifdef __WIN32__
1250          strcpy(outputPath, "/");
1251 #else
1252          strcpy(outputPath, name);
1253 #endif
1254
1255    }
1256
1257    bool IsChildOf(ExplorerFileBranch branch)
1258    {
1259       ExplorerFileBranch test;
1260       for(test = parent; test; test = test.parent)
1261          if(test == branch)
1262             return true;
1263       return false;
1264    }
1265
1266    void DuplicateChildren(bool recursive, bool forceExpanded, ExplorerFileBranch addTo, ListBox tree)
1267    {
1268       if(children.first)
1269       {
1270          ExplorerFileBranch child;
1271          
1272          for(child = children.first; child; child = child.next)
1273          {
1274             ExplorerFileBranch copy { };
1275             copy.name = CopyString(child.name);
1276             copy.type = child.type;
1277             AddBranch(copy, child.loaded, false, addTo, tree);
1278             if(forceExpanded)
1279                copy.row.collapsed = false;
1280             if(recursive)
1281                child.DuplicateChildren(recursive, forceExpanded, copy, tree);
1282          }
1283       }
1284    }
1285    
1286    void EnsureVisible(bool expand)
1287    {
1288       if(parent)
1289          parent.EnsureVisible(true);
1290       if(expand)
1291          row.collapsed = false;
1292       // TODO: row.EnsureVisible(); // making the row visible by scrolling
1293    }
1294
1295    void OnFree()
1296    {
1297       //delete name;
1298    }
1299
1300    void Free()
1301    {
1302       ExplorerFileBranch child;
1303       for(; (child = children.first); )
1304       {
1305          child.Free();
1306          children.Delete(child);
1307       }
1308       //if(name)
1309       delete name;
1310       delete info;
1311    }
1312
1313    void Delete()
1314    {
1315       Free();
1316       if(parent)
1317          parent.children.Delete(this);
1318    }
1319
1320    void OnDisplay(Surface surface, int x, int y, int width, ExplorerControl control, Alignment alignment, DataDisplayFlags displayFlags)
1321    {
1322       //int indentSize = (displayFlags.dropBox) ? 0 : 10;
1323       int indent = 16;
1324       int xStart;
1325       int len;
1326       int w, h;
1327       //int textOffset;
1328       char label[MAX_FILENAME];
1329
1330       Bitmap icon;
1331
1332       if(!this)
1333          return;
1334       
1335       icon = control.fileIcons[type].bitmap;
1336       //xStart = indent * indent + x + (icon ? (icon.width + 5) : 0);
1337       xStart = x + (icon ? (icon.width + 5) : 0);
1338
1339       if(!name)
1340          return;
1341
1342       if(info)
1343          sprintf(label, "%s [%s]", name, info);
1344       else
1345          strcpy(label, name);
1346       len = strlen(label);
1347       
1348       if(!icon)
1349       {
1350          if(type == folder || type == folderOpen)
1351             surface.SetForeground(yellow);
1352          //indentSize = 8;
1353          indent = 8;
1354       }
1355       //textOffset = indent * indentSize + (icon ? (icon.width + 4) : 0);
1356       
1357       surface.TextOpacity(false);
1358       surface.TextExtent(label, len, &w, &h);
1359       h = Max(h, 16);
1360     
1361       // Draw the current row stipple
1362       if(displayFlags.selected)
1363          //surface.Area(xStart - 1, y, xStart - 1, y + h - 1);
1364          //surface.Area(xStart + w - 1, y, xStart + w + 1, y + h - 1);
1365          surface.Area(xStart - 3, y, xStart + w + 1, y + h - 1);
1366       
1367       //surface.WriteTextDots(alignment, x + textOffset, y + 2, width - textOffset, name, strlen(name));
1368       surface.WriteTextDots(alignment, xStart, y + 2, width, label, len);
1369
1370       if(!guiApp.textMode)
1371       {
1372          if(displayFlags.current)
1373          {
1374             if(displayFlags.active)
1375             {
1376                surface.LineStipple(0x5555);
1377                if(displayFlags.selected)
1378                   surface.SetForeground(0xFFFFFF80);
1379                else
1380                   surface.SetForeground(black);
1381             }
1382             else
1383             {
1384                surface.SetForeground(selectionColor);
1385             }
1386             surface.Rectangle(xStart - 3, y, xStart + w + 1, y + h - 1);
1387             surface.LineStipple(0);
1388          }
1389
1390          if(icon)
1391          {
1392             //surface.blend = true;
1393             //surface.alphaWrite = blend;
1394             surface.SetForeground(white);
1395             //surface.Blit(icon, x + indent * indentSize, y,0,0, icon.width, icon.height);
1396             surface.Blit(icon, x,y,0,0, icon.width, icon.height);
1397          }
1398       }
1399    }
1400
1401    int OnCompare(ExplorerFileBranch b)
1402    {
1403       int result;
1404       if(type == b.type || (type < folder && b.type < folder) || (type >= drive))
1405          result = strcmpi(name, b.name);
1406       else
1407       {
1408          if(type == folder && b.type < folder) result = -1;
1409          else if(type < folder && b.type == folder) result = 1;
1410       }
1411       return result;
1412    }
1413
1414    char * OnGetString(char * tempString, FileSystemToolWindow fileSysToolWnd, bool * needClass)
1415    {
1416       return name ? name : "";
1417    }
1418 };
1419
1420 ExplorerFileBranch MakeFileBranch(const FileStats stats, const char * name)
1421 {
1422    ExplorerFileBranch fileTreeBranch { stats = stats };
1423    fileTreeBranch.name = CopyString(name);
1424    if(!fileTreeBranch.name)
1425       fileTreeBranch.name = null;
1426    if(stats.attribs.isDirectory)
1427    {
1428       fileTreeBranch.type = (stats.attribs.isDrive) ? drive : folder;
1429       if(stats.attribs.isServer) fileTreeBranch.type = server;
1430       if(stats.attribs.isShare) fileTreeBranch.type = share;
1431       if(stats.attribs.isCDROM) fileTreeBranch.type = cdrom;
1432       if(stats.attribs.isRemote) fileTreeBranch.type = netDrive;
1433       if(stats.attribs.isRemovable) 
1434       {
1435          if(name[0] == 'A' || name[0] == 'B')
1436             fileTreeBranch.type = floppy;
1437          else
1438             fileTreeBranch.type = removable;
1439       }
1440    }
1441    else
1442    {
1443       char extension[MAX_EXTENSION];
1444       GetExtension(fileTreeBranch.name, extension);
1445       fileTreeBranch.type = ExplorerFileType::SelectByExtension(extension);
1446    }
1447    return fileTreeBranch;
1448 }
1449
1450 void AddBranch(ExplorerFileBranch branch, bool loaded, bool addLoader, ExplorerFileBranch addTo, ListBox tree)
1451 {
1452    DataRow row = (addTo && addTo.row) ? addTo.row.AddRow() : tree.AddRow();
1453    if(addTo)
1454    {
1455       branch.parent = addTo;
1456       branch.indent = addTo.indent + 1;
1457       addTo.children.Add(branch);
1458    }
1459    row.tag = (int)branch;
1460    branch.row = row;
1461    row.SetData(null, branch);
1462
1463    branch.loaded = loaded;
1464    if(addLoader)
1465       //AddBranch(ExplorerFileBranch { }, false, false, branch, tree); // why would this create a compile error?
1466       AddBranch(ExplorerFileBranch { type = none }, false, false, branch, tree);
1467
1468    if(branch.indent > 0)
1469       row.collapsed = true;
1470    else if(branch.type == folder)
1471       branch.type = folderOpen;
1472 }
1473
1474 void BranchLoad(ExplorerFileBranch branch, ListBox tree)
1475 {
1476    if(!branch.loaded)
1477    {
1478       char path[MAX_LOCATION];
1479       branch.GetPath(path);
1480       {
1481          FileListing listing { path };
1482          if(branch.children.count == 1)
1483          DeleteBranch(branch.children.first, tree);
1484
1485          while(listing.Find())
1486          {
1487             if(listing.stats.attribs.isDirectory)
1488             {
1489                ExplorerFileBranch child = MakeFileBranch(listing.stats, listing.name);
1490                AddBranch(child, true, false, branch, tree);
1491                BranchChildLoad(child, branch, tree);
1492             }
1493          }
1494       }
1495       branch.childrenLoaded = true;
1496       branch.loaded = true;
1497       branch.row.SortSubRows(false);
1498    }
1499    else if(!branch.childrenLoaded)
1500    {
1501       ExplorerFileBranch child;
1502       if(branch.children.first)
1503       {
1504          for(child = branch.children.first; child; child = child.next)
1505          {
1506             if(!child.loaded)
1507                BranchLoad(child, tree);
1508             else if(!child.childrenLoaded)
1509                BranchChildLoad(child, branch, tree);
1510          }
1511          branch.childrenLoaded = true;
1512          branch.row.SortSubRows(false);
1513       }
1514    }
1515 }
1516
1517 static void BranchChildLoad(ExplorerFileBranch parent, ExplorerFileBranch branch, ListBox tree)
1518 {
1519    char path[MAX_LOCATION];
1520    parent.GetPath(path);
1521    {
1522       bool added = false;
1523       FileListing listing { path };
1524       while(listing.Find())
1525       {
1526          if(listing.stats.attribs.isDirectory)
1527          {
1528             ExplorerFileBranch child = MakeFileBranch(listing.stats, listing.name);
1529             AddBranch(child, true, false, parent, tree);
1530             added = true;
1531          }
1532       }
1533       if(!added)
1534          added = true;
1535    }
1536    //parent.childrenLoaded = true;
1537 }
1538
1539 void DeleteBranch(ExplorerFileBranch branch, ListBox tree)
1540 {
1541    ExplorerFileBranch child;
1542    for(; (child = branch.children.first); )
1543       DeleteBranch(child, tree);
1544    tree.DeleteRow(branch.row);
1545    branch.Delete();
1546 }
1547 #endif