2007-03-29 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / FileDialog.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2006 Alexander Olk
21 //
22 // Authors:
23 //
24 //  Alexander Olk       alex.olk@googlemail.com
25 //  Gert Driesen (drieseng@users.sourceforge.net)
26 //
27 // TODO:
28 // Keyboard shortcuts (DEL, F5, F2)
29 // ??
30
31 using System;
32 using System.Collections;
33 using System.Collections.Specialized;
34 using System.ComponentModel;
35 using System.Drawing;
36 using System.IO;
37 using System.Resources;
38 using System.Text;
39 using System.Threading;
40 using System.Xml;
41
42 namespace System.Windows.Forms
43 {
44         #region FileDialog
45         [DefaultProperty ("FileName")]
46         [DefaultEvent ("FileOk")]
47         public abstract class FileDialog : CommonDialog
48         {
49                 protected static readonly object EventFileOk = new object ();
50                 private static int MaxFileNameItems = 10;
51                 
52                 internal enum FileDialogType
53                 {
54                         OpenFileDialog,
55                         SaveFileDialog
56                 }
57                 
58                 private bool addExtension = true;
59                 private bool checkFileExists;
60                 private bool checkPathExists = true;
61                 private string defaultExt;
62                 private bool dereferenceLinks = true;
63                 private string[] fileNames;
64                 private string filter = "";
65                 private int filterIndex = 1;
66                 private int setFilterIndex = 1;
67                 private string initialDirectory;
68                 private bool restoreDirectory;
69                 private bool showHelp;
70                 private string title;
71                 private bool validateNames = true;
72 #if NET_2_0
73                 private bool checkForIllegalChars = true;
74 #endif
75                 
76                 private Button cancelButton;
77                 private ToolBarButton upToolBarButton;
78                 private PopupButtonPanel popupButtonPanel;
79                 private Button openSaveButton;
80                 private Button helpButton;
81                 private Label fileTypeLabel;
82                 private ToolBarButton menueToolBarButton;
83                 private ContextMenu menueToolBarButtonContextMenu;
84                 private ToolBar smallButtonToolBar;
85                 private DirComboBox dirComboBox;
86                 private ComboBox fileNameComboBox;
87                 private Label fileNameLabel;
88                 private MWFFileView mwfFileView;
89                 private Label searchSaveLabel;
90                 private ToolBarButton newdirToolBarButton;
91                 private ToolBarButton backToolBarButton;
92                 private ComboBox fileTypeComboBox;
93                 private ImageList imageListTopToolbar;
94                 private CheckBox readonlyCheckBox;
95                 
96                 private bool multiSelect;
97                 
98                 private string restoreDirectoryString = String.Empty;
99                 
100                 internal FileDialogType fileDialogType;
101                 
102                 private bool do_not_call_OnSelectedIndexChangedFileTypeComboBox;
103                 
104                 private bool showReadOnly;
105                 private bool readOnlyChecked;
106                 internal bool createPrompt;
107                 internal bool overwritePrompt = true;
108                 
109                 internal FileFilter fileFilter;
110                 
111                 private string lastFolder = String.Empty;
112                 
113                 private MWFVFS vfs;
114                 
115                 private readonly string filedialog_string = "FileDialog";
116                 private readonly string lastfolder_string = "LastFolder";
117                 private readonly string width_string = "Width";
118                 private readonly string height_string = "Height";
119                 private readonly string filenames_string = "FileNames";
120                 private readonly string x_string = "X";
121                 private readonly string y_string = "Y";
122                 
123                 private bool disable_form_closed_event = false;
124                 
125                 internal FileDialog ()
126                 {
127                         vfs = new MWFVFS ();
128                         
129                         Size formConfigSize = Size.Empty;
130                         Point formConfigLocation = Point.Empty;
131                         string[] configFileNames = null;
132                         
133                         object formWidth = MWFConfig.GetValue (filedialog_string, width_string);
134                         
135                         object formHeight = MWFConfig.GetValue (filedialog_string, height_string);
136                         
137                         if (formHeight != null && formWidth != null)
138                                 formConfigSize = new Size ((int)formWidth, (int)formHeight);
139                         
140                         object formLocationX = MWFConfig.GetValue (filedialog_string, x_string);
141                         object formLocationY = MWFConfig.GetValue (filedialog_string, y_string);
142                         
143                         if (formLocationX != null && formLocationY != null)
144                                 formConfigLocation = new Point ((int)formLocationX, (int)formLocationY);
145                         
146                         configFileNames = (string[])MWFConfig.GetValue (filedialog_string, filenames_string);
147                         
148                         fileTypeComboBox = new ComboBox ();
149                         backToolBarButton = new ToolBarButton ();
150                         newdirToolBarButton = new ToolBarButton ();
151                         searchSaveLabel = new Label ();
152                         mwfFileView = new MWFFileView (vfs);
153                         fileNameLabel = new Label ();
154                         fileNameComboBox = new ComboBox ();
155                         dirComboBox = new DirComboBox (vfs);
156                         smallButtonToolBar = new ToolBar ();
157                         menueToolBarButton = new ToolBarButton ();
158                         fileTypeLabel = new Label ();
159                         openSaveButton = new Button ();
160                         form.AcceptButton = openSaveButton;
161                         helpButton = new Button ();
162                         popupButtonPanel = new PopupButtonPanel ();
163                         upToolBarButton = new ToolBarButton ();
164                         cancelButton = new Button ();
165                         form.CancelButton = cancelButton;
166                         imageListTopToolbar = new ImageList ();
167                         menueToolBarButtonContextMenu = new ContextMenu ();
168                         readonlyCheckBox = new CheckBox ();
169                         
170                         form.SuspendLayout ();
171                         
172                         //imageListTopToolbar
173                         imageListTopToolbar.ColorDepth = ColorDepth.Depth32Bit;
174                         imageListTopToolbar.ImageSize = new Size (16, 16); // 16, 16
175                         imageListTopToolbar.Images.Add (ResourceImageLoader.Get ("go-previous.png"));
176                         imageListTopToolbar.Images.Add (ResourceImageLoader.Get ("go-top.png"));
177                         imageListTopToolbar.Images.Add (ResourceImageLoader.Get ("folder-new.png"));
178                         imageListTopToolbar.Images.Add (ResourceImageLoader.Get ("preferences-system-windows.png"));
179                         imageListTopToolbar.TransparentColor = Color.Transparent;
180                         
181                         // searchLabel
182                         searchSaveLabel.FlatStyle = FlatStyle.System;
183                         searchSaveLabel.Location = new Point (7, 8);
184                         searchSaveLabel.Size = new Size (72, 21);
185                         searchSaveLabel.TextAlign = ContentAlignment.MiddleRight;
186                         
187                         // dirComboBox
188                         dirComboBox.Anchor = ((AnchorStyles)(((AnchorStyles.Top | AnchorStyles.Left) | AnchorStyles.Right)));
189                         dirComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
190                         dirComboBox.Location = new Point (99, 8);
191                         dirComboBox.Size = new Size (260, 21);
192                         dirComboBox.TabIndex = 7;
193                         
194                         // smallButtonToolBar
195                         smallButtonToolBar.Anchor = ((AnchorStyles)((AnchorStyles.Top | AnchorStyles.Right)));
196                         smallButtonToolBar.Appearance = ToolBarAppearance.Flat;
197                         smallButtonToolBar.AutoSize = false;
198                         smallButtonToolBar.Buttons.AddRange (new ToolBarButton [] {
199                                                                      backToolBarButton,
200                                                                      upToolBarButton,
201                                                                      newdirToolBarButton,
202                                                                      menueToolBarButton});
203                         smallButtonToolBar.ButtonSize = new Size (24, 24); // 21, 16
204                         smallButtonToolBar.Divider = false;
205                         smallButtonToolBar.Dock = DockStyle.None;
206                         smallButtonToolBar.DropDownArrows = true;
207                         smallButtonToolBar.ImageList = imageListTopToolbar;
208                         smallButtonToolBar.Location = new Point (372, 6);
209                         smallButtonToolBar.ShowToolTips = true;
210                         smallButtonToolBar.Size = new Size (140, 28);
211                         smallButtonToolBar.TabIndex = 8;
212                         smallButtonToolBar.TextAlign = ToolBarTextAlign.Right;
213                         
214                         // buttonPanel
215                         popupButtonPanel.Dock = DockStyle.None;
216                         popupButtonPanel.Location = new Point (7, 37);
217                         popupButtonPanel.TabIndex = 9;
218                         
219                         // mwfFileView
220                         mwfFileView.Anchor = ((AnchorStyles)((((AnchorStyles.Top | AnchorStyles.Bottom) | AnchorStyles.Left) | AnchorStyles.Right)));
221                         mwfFileView.Location = new Point (99, 37);
222                         mwfFileView.Size = new Size (449, 282);
223                         mwfFileView.Columns.Add (" Name", 170, HorizontalAlignment.Left);
224                         mwfFileView.Columns.Add ("Size ", 80, HorizontalAlignment.Right);
225                         mwfFileView.Columns.Add (" Type", 100, HorizontalAlignment.Left);
226                         mwfFileView.Columns.Add (" Last Access", 150, HorizontalAlignment.Left);
227                         mwfFileView.AllowColumnReorder = true;
228                         mwfFileView.MultiSelect = false;
229                         mwfFileView.TabIndex = 10;
230                         mwfFileView.RegisterSender (dirComboBox);
231                         mwfFileView.RegisterSender (popupButtonPanel);
232                         
233                         // fileNameLabel
234                         fileNameLabel.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Left)));
235                         fileNameLabel.FlatStyle = FlatStyle.System;
236                         fileNameLabel.Location = new Point (102, 330);
237                         fileNameLabel.Size = new Size (70, 21);
238                         fileNameLabel.Text = "File name:";
239                         fileNameLabel.TextAlign = ContentAlignment.MiddleLeft;
240                         
241                         // fileNameComboBox
242                         fileNameComboBox.Anchor = ((AnchorStyles)(((AnchorStyles.Bottom | AnchorStyles.Left) | AnchorStyles.Right)));
243                         fileNameComboBox.Location = new Point (195, 330);
244                         fileNameComboBox.Size = new Size (245, 21);
245                         fileNameComboBox.TabIndex = 1;
246                         fileNameComboBox.MaxDropDownItems = MaxFileNameItems;
247                         
248                         if (configFileNames != null) {
249                                 foreach (string configFileName in configFileNames) {
250                                         if (configFileName == null || configFileName.Trim ().Length == 0)
251                                                 continue;
252                                         // add no more than 10 items
253                                         if (fileNameComboBox.Items.Count >= MaxFileNameItems)
254                                                 break;
255                                         fileNameComboBox.Items.Add (configFileName);
256                                 }
257                         }
258                         
259                         // fileTypeLabel
260                         fileTypeLabel.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Left)));
261                         fileTypeLabel.FlatStyle = FlatStyle.System;
262                         fileTypeLabel.Location = new Point (102, 356);
263                         fileTypeLabel.Size = new Size (90, 21);
264                         fileTypeLabel.Text = "Files of type:";
265                         fileTypeLabel.TextAlign = ContentAlignment.MiddleLeft;
266                         
267                         // fileTypeComboBox
268                         fileTypeComboBox.Anchor = ((AnchorStyles)(((AnchorStyles.Bottom | AnchorStyles.Left) | AnchorStyles.Right)));
269                         fileTypeComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
270                         fileTypeComboBox.Location = new Point (195, 356);
271                         fileTypeComboBox.Size = new Size (245, 21);
272                         fileTypeComboBox.TabIndex = 2;
273                         
274                         // backToolBarButton
275                         backToolBarButton.ImageIndex = 0;
276                         backToolBarButton.Enabled = false;
277                         backToolBarButton.Style = ToolBarButtonStyle.PushButton;
278                         mwfFileView.AddControlToEnableDisableByDirStack (backToolBarButton);
279                         
280                         // upToolBarButton
281                         upToolBarButton.ImageIndex = 1;
282                         upToolBarButton.Style = ToolBarButtonStyle.PushButton;
283                         mwfFileView.SetFolderUpToolBarButton (upToolBarButton);
284                         
285                         // newdirToolBarButton
286                         newdirToolBarButton.ImageIndex = 2;
287                         newdirToolBarButton.Style = ToolBarButtonStyle.PushButton;
288                         
289                         // menueToolBarButton
290                         menueToolBarButton.ImageIndex = 3;
291                         menueToolBarButton.DropDownMenu = menueToolBarButtonContextMenu;
292                         menueToolBarButton.Style = ToolBarButtonStyle.DropDownButton;
293                         
294                         // menueToolBarButtonContextMenu
295                         menueToolBarButtonContextMenu.MenuItems.AddRange (mwfFileView.ViewMenuItems);
296                         
297                         // openSaveButton
298                         openSaveButton.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Right)));
299                         openSaveButton.FlatStyle = FlatStyle.System;
300                         openSaveButton.Location = new Point (475, 330);
301                         openSaveButton.Size = new Size (72, 21);
302                         openSaveButton.TabIndex = 4;
303                         openSaveButton.FlatStyle = FlatStyle.System;
304                         
305                         // cancelButton
306                         cancelButton.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Right)));
307                         cancelButton.FlatStyle = FlatStyle.System;
308                         cancelButton.Location = new Point (475, 356);
309                         cancelButton.Size = new Size (72, 21);
310                         cancelButton.TabIndex = 5;
311                         cancelButton.Text = "Cancel";
312                         cancelButton.FlatStyle = FlatStyle.System;
313                         
314                         // helpButton
315                         helpButton.Anchor = ((AnchorStyles)((AnchorStyles.Bottom | AnchorStyles.Right)));
316                         helpButton.FlatStyle = FlatStyle.System;
317                         helpButton.Location = new Point (475, 350);
318                         helpButton.Size = new Size (72, 21);
319                         helpButton.TabIndex = 6;
320                         helpButton.Text = "Help";
321                         helpButton.FlatStyle = FlatStyle.System;
322                         
323                         // checkBox
324                         readonlyCheckBox.Anchor = ((AnchorStyles)(((AnchorStyles.Bottom | AnchorStyles.Left) | AnchorStyles.Right)));
325                         readonlyCheckBox.Text = "Open Readonly";
326                         readonlyCheckBox.Location = new Point (195, 350);
327                         readonlyCheckBox.Size = new Size (245, 21);
328                         readonlyCheckBox.TabIndex = 3;
329                         readonlyCheckBox.FlatStyle = FlatStyle.System;
330                         
331                         form.SizeGripStyle = SizeGripStyle.Show;
332                         
333                         form.MaximizeBox = true;
334                         form.MinimizeBox = true;
335                         form.FormBorderStyle = FormBorderStyle.Sizable;
336                         form.MinimumSize = new Size (554, 405);
337                         
338                         form.ClientSize =  new Size (554, 405); // 384
339                         
340                         form.Controls.Add (smallButtonToolBar);
341                         form.Controls.Add (cancelButton);
342                         form.Controls.Add (openSaveButton);
343                         form.Controls.Add (mwfFileView);
344                         form.Controls.Add (fileTypeLabel);
345                         form.Controls.Add (fileNameLabel);
346                         form.Controls.Add (fileTypeComboBox);
347                         form.Controls.Add (fileNameComboBox);
348                         form.Controls.Add (dirComboBox);
349                         form.Controls.Add (searchSaveLabel);
350                         form.Controls.Add (popupButtonPanel);
351                         
352                         form.ResumeLayout (false);
353                         
354                         if (formConfigSize != Size.Empty) {
355                                 form.Size = formConfigSize;
356                         }
357                         
358                         if (formConfigLocation != Point.Empty) {
359                                 form.Location = formConfigLocation;
360                         }
361                         
362                         openSaveButton.Click += new EventHandler (OnClickOpenSaveButton);
363                         cancelButton.Click += new EventHandler (OnClickCancelButton);
364                         helpButton.Click += new EventHandler (OnClickHelpButton);
365                         
366                         smallButtonToolBar.ButtonClick += new ToolBarButtonClickEventHandler (OnClickSmallButtonToolBar);
367                         
368                         fileTypeComboBox.SelectedIndexChanged += new EventHandler (OnSelectedIndexChangedFileTypeComboBox);
369                         
370                         mwfFileView.SelectedFileChanged += new EventHandler (OnSelectedFileChangedFileView);
371                         mwfFileView.ForceDialogEnd += new EventHandler (OnForceDialogEndFileView);
372                         mwfFileView.SelectedFilesChanged += new EventHandler (OnSelectedFilesChangedFileView);
373                         
374                         dirComboBox.DirectoryChanged += new EventHandler (OnDirectoryChangedDirComboBox);
375                         popupButtonPanel.DirectoryChanged += new EventHandler (OnDirectoryChangedPopupButtonPanel);
376                         
377                         readonlyCheckBox.CheckedChanged += new EventHandler (OnCheckCheckChanged);
378 #if NET_2_0
379                         form.FormClosed += new FormClosedEventHandler (OnFileDialogFormClosed);
380 #else
381                         form.Closed += new EventHandler (OnFileDialogFormClosed);
382 #endif
383                 }
384                 
385                 [DefaultValue(true)]
386                 public bool AddExtension {
387                         get {
388                                 return addExtension;
389                         }
390                         
391                         set {
392                                 addExtension = value;
393                         }
394                 }
395                 
396                 [DefaultValue(false)]
397                 public virtual bool CheckFileExists {
398                         get {
399                                 return checkFileExists;
400                         }
401                         
402                         set {
403                                 checkFileExists = value;
404                         }
405                 }
406                 
407                 [DefaultValue(true)]
408                 public bool CheckPathExists {
409                         get {
410                                 return checkPathExists;
411                         }
412                         
413                         set {
414                                 checkPathExists = value;
415                         }
416                 }
417                 
418                 [DefaultValue("")]
419                 public string DefaultExt {
420                         get {
421                                 if (defaultExt == null)
422                                         return string.Empty;
423                                 return defaultExt;
424                         }
425                         set {
426                                 if (value != null && value.Length > 0) {
427                                         // remove leading dot
428                                         if (value [0] == '.')
429                                                 value = value.Substring (1);
430                                 }
431                                 defaultExt = value;
432                         }
433                 }
434                 
435                 // in MS.NET it doesn't make a difference if
436                 // DerefenceLinks is true or false
437                 // if the selected file is a link FileDialog
438                 // always returns the link
439                 [DefaultValue(true)]
440                 public bool DereferenceLinks {
441                         get {
442                                 return dereferenceLinks;
443                         }
444                         
445                         set {
446                                 dereferenceLinks = value;
447                         }
448                 }
449                 
450                 [DefaultValue("")]
451                 public string FileName {
452                         get {
453                                 if (fileNames == null || fileNames.Length == 0)
454                                         return string.Empty;
455
456                                 if (fileNames [0].Length == 0)
457                                         return string.Empty;
458
459 #if NET_2_0
460                                 // skip check for illegal characters if the filename was set
461                                 // through FileDialog API
462                                 if (!checkForIllegalChars)
463                                         return fileNames [0];
464 #endif
465
466                                 // ensure filename contains only valid characters
467                                 Path.GetFullPath (fileNames [0]);
468                                 // but return filename as is
469                                 return fileNames [0];
470
471                         }
472                         
473                         set {
474                                 if (value != null) {
475                                         fileNames = new string [1] { value };
476                                 } else {
477                                         fileNames = new string [0];
478                                 }
479
480 #if NET_2_0
481                                 // skip check for illegal characters if the filename was set
482                                 // through FileDialog API
483                                 checkForIllegalChars = false;
484 #endif
485                         }
486                 }
487                 
488                 [Browsable(false)]
489                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
490                 public string[] FileNames {
491                         get {
492                                 if (fileNames == null || fileNames.Length == 0) {
493                                         return new string [0];
494                                 }
495                                 
496                                 string[] new_filenames = new string [fileNames.Length];
497                                 fileNames.CopyTo (new_filenames, 0);
498
499 #if NET_2_0
500                                 // skip check for illegal characters if the filename was set
501                                 // through FileDialog API
502                                 if (!checkForIllegalChars)
503                                         return new_filenames;
504 #endif
505
506                                 foreach (string fileName in new_filenames) {
507                                         // ensure filename contains only valid characters
508                                         Path.GetFullPath (fileName);
509                                 }
510                                 return new_filenames;
511                         }
512                 }
513                 
514                 [DefaultValue("")]
515                 [Localizable(true)]
516                 public string Filter {
517                         get {
518                                 return filter;
519                         }
520                         
521                         set {
522                                 if (value == null) {
523                                         filter = "";
524                                         if (fileFilter != null)
525                                                 fileFilter.FilterArrayList.Clear ();
526                                 } else {
527                                         if (FileFilter.CheckFilter (value)) {
528                                                 filter = value;
529                                                 
530                                                 fileFilter = new FileFilter (filter);
531                                         } else
532                                                 throw new ArgumentException ("The provided filter string"
533                                                         + " is invalid. The filter string should contain a"
534                                                         + " description of the filter, followed by the "
535                                                         + " vertical bar (|) and the filter pattern. The"
536                                                         + " strings for different filtering options should"
537                                                         + " also be separated by the vertical bar. Example:"
538                                                         + " Text files (*.txt)|*.txt|All files (*.*)|*.*");
539                                 }
540                                 
541                                 UpdateFilters ();
542                         }
543                 }
544                 
545                 [DefaultValue(1)]
546                 public int FilterIndex {
547                         get {
548                                 return setFilterIndex;
549                         }
550                         
551                         set {
552                                 setFilterIndex = value;
553                                 
554                                 if (value < 1)
555                                         filterIndex = 1;
556                                 else
557                                         filterIndex = value;
558                                 
559                                 SelectFilter ();
560                         }
561                 }
562                 
563                 [DefaultValue("")]
564                 public string InitialDirectory {
565                         get {
566                                 if (initialDirectory == null)
567                                         return string.Empty;
568                                 return initialDirectory;
569                         }
570                         set {
571                                 initialDirectory = value;
572                         }
573                 }
574                 
575                 [DefaultValue(false)]
576                 public bool RestoreDirectory {
577                         get {
578                                 return restoreDirectory;
579                         }
580                         
581                         set {
582                                 restoreDirectory = value;
583                         }
584                 }
585                 
586                 [DefaultValue(false)]
587                 public bool ShowHelp {
588                         get {
589                                 return showHelp;
590                         }
591                         
592                         set {
593                                 showHelp = value;
594                                 ResizeAndRelocateForHelpOrReadOnly ();
595                         }
596                 }
597                 
598                 [DefaultValue("")]
599                 [Localizable(true)]
600                 public string Title {
601                         get {
602                                 if (title == null)
603                                         return string.Empty;
604                                 return title;
605                         }
606                         set {
607                                 title = value;
608                         }
609                 }
610                 
611                 // this one is a hard one ;)
612                 // Win32 filename:
613                 // - up to MAX_PATH characters (windef.h) = 260
614                 // - no trailing dots or spaces
615                 // - case preserving
616                 // - etc...
617                 // NTFS/Posix filename:
618                 // - up to 32,768 Unicode characters
619                 // - trailing periods or spaces
620                 // - case sensitive
621                 // - etc...
622                 [DefaultValue(true)]
623                 public bool ValidateNames {
624                         get {
625                                 return validateNames;
626                         }
627                         
628                         set {
629                                 validateNames = value;
630                         }
631                 }
632                 
633                 public override void Reset ()
634                 {
635                         addExtension = true;
636                         checkFileExists = false;
637                         checkPathExists = true;
638                         DefaultExt = null;
639                         dereferenceLinks = true;
640                         FileName = null;
641                         Filter = String.Empty;
642                         FilterIndex = 1;
643                         InitialDirectory = null;
644                         restoreDirectory = false;
645                         ShowHelp = false;
646                         Title = null;
647                         validateNames = true;
648                         
649                         UpdateFilters ();
650                 }
651                 
652                 public override string ToString ()
653                 {
654                         return String.Format("{0}: Title: {1}, FileName: {2}", base.ToString (), Title, FileName);
655                 }
656                 
657                 public event CancelEventHandler FileOk {
658                         add { Events.AddHandler (EventFileOk, value); }
659                         remove { Events.RemoveHandler (EventFileOk, value); }
660                 }
661                 
662                 protected virtual IntPtr Instance {
663                         get {
664                                 if (form == null)
665                                         return IntPtr.Zero;
666                                 return form.Handle;
667                         }
668                 }
669                 
670                 // This is just for internal use with MSs version, so it doesn't need to be implemented
671                 // as it can't really be accessed anyways
672                 protected int Options {
673                         get { return -1; }
674                 }
675
676                 internal virtual string DialogTitle {
677                         get {
678                                 return Title;
679                         }
680                 }
681                 
682                 [MonoTODO]
683                 protected  override IntPtr HookProc (IntPtr hWnd, int msg, IntPtr wparam, IntPtr lparam)
684                 {
685                         throw new NotImplementedException ();
686                 }
687                 
688                 protected void OnFileOk (CancelEventArgs e)
689                 {
690                         WriteConfigValues (e);
691                         
692                         CancelEventHandler fo = (CancelEventHandler) Events [EventFileOk];
693                         if (fo != null)
694                                 fo (this, e);
695                         
696                         Mime.CleanFileCache ();
697                         
698                         disable_form_closed_event = true;
699                 }
700                 
701                 protected override bool RunDialog (IntPtr hWndOwner)
702                 {
703                         ReadConfigValues ();
704                         form.Text = DialogTitle;
705
706                         // avoid using the FileNames property to skip the invalid characters
707                         // check
708                         string fileName = null;
709                         if (fileNames != null && fileNames.Length != 0)
710                                 fileName = fileNames [0];
711                         else
712                                 fileName = string.Empty;
713
714                         form.Refresh ();
715
716                         SetFileAndDirectory (fileName);
717                         fileNameComboBox.Select ();
718                         
719                         return true;
720                 }
721                 
722                 internal virtual bool ShowReadOnly {
723                         set {
724                                 showReadOnly = value;
725                                 ResizeAndRelocateForHelpOrReadOnly ();
726                         }
727                         
728                         get {
729                                 return showReadOnly;
730                         }
731                 }
732                 
733                 internal virtual bool ReadOnlyChecked {
734                         set {
735                                 readOnlyChecked = value;
736                                 readonlyCheckBox.Checked = value;
737                         }
738                         
739                         get {
740                                 return readOnlyChecked;
741                         }
742                 }
743                 
744                 internal bool BMultiSelect {
745                         set {
746                                 multiSelect = value;
747                                 mwfFileView.MultiSelect = value;
748                         }
749                         
750                         get {
751                                 return multiSelect;
752                         }
753                 }
754                 
755                 internal string OpenSaveButtonText {
756                         set {
757                                 openSaveButton.Text = value;
758                         }
759                 }
760                 
761                 internal string SearchSaveLabel {
762                         set {
763                                 searchSaveLabel.Text = value;
764                         }
765                 }
766
767                 internal string FileTypeLabel {
768                         set {
769                                 fileTypeLabel.Text = value;
770                         }
771                 }
772
773                 private void SelectFilter ()
774                 {
775                         if (mwfFileView.FilterArrayList == null || filterIndex > mwfFileView.FilterArrayList.Count)
776                                 return;
777                         
778                         do_not_call_OnSelectedIndexChangedFileTypeComboBox = true;
779                         fileTypeComboBox.BeginUpdate ();
780                         fileTypeComboBox.SelectedIndex = filterIndex - 1;
781                         fileTypeComboBox.EndUpdate ();
782                         do_not_call_OnSelectedIndexChangedFileTypeComboBox = false;
783                         mwfFileView.FilterIndex = filterIndex;
784                 }
785
786                 private void SetFileAndDirectory (string fname)
787                 {
788                         if (fname.Length != 0) {
789                                 bool rooted = Path.IsPathRooted (fname);
790                                 if (!rooted) {
791                                         mwfFileView.ChangeDirectory (null, lastFolder);
792                                         fileNameComboBox.Text = fname;
793                                 } else {
794                                         string dirname = Path.GetDirectoryName (fname);
795                                         if (dirname != null && dirname.Length > 0 && Directory.Exists (dirname)) {
796                                                 fileNameComboBox.Text = Path.GetFileName (fname);
797                                                 mwfFileView.ChangeDirectory (null, dirname);
798                                         } else {
799                                                 fileNameComboBox.Text = fname;
800                                                 mwfFileView.ChangeDirectory (null, lastFolder);
801                                         }
802                                 }
803                         } else {
804                                 mwfFileView.ChangeDirectory (null, lastFolder);
805                                 fileNameComboBox.Text = null;
806                         }
807                 }
808                 
809                 void OnClickOpenSaveButton (object sender, EventArgs e)
810                 {
811 #if NET_2_0
812                         // for filenames typed or selected by user, enable check for 
813                         // illegal characters in filename(s)
814                         checkForIllegalChars = true;
815 #endif
816
817                         if (fileDialogType == FileDialogType.OpenFileDialog) {
818                                 ListView.SelectedListViewItemCollection sl = mwfFileView.SelectedItems;
819                                 if (sl.Count > 0 && sl [0] != null) {
820                                         if (sl.Count == 1) {
821                                                 FileViewListViewItem item = sl [0] as FileViewListViewItem;
822                                                 FSEntry fsEntry = item.FSEntry;
823                                                 
824                                                 if (fsEntry.Attributes == FileAttributes.Directory) {
825                                                         mwfFileView.ChangeDirectory (null, fsEntry.FullName);
826                                                         return;
827                                                 }
828                                         } else {
829                                                 foreach (FileViewListViewItem item in sl) {
830                                                         FSEntry fsEntry = item.FSEntry;
831                                                         if (fsEntry.Attributes == FileAttributes.Directory) {
832                                                                 mwfFileView.ChangeDirectory (null, fsEntry.FullName);
833                                                                 return;
834                                                         }
835                                                 }
836                                         }
837                                 }
838                         }
839
840                         ArrayList files = new ArrayList ();
841                         FileNamesTokenizer tokenizer = new FileNamesTokenizer (
842                                 fileNameComboBox.Text, multiSelect);
843                         tokenizer.GetNextFile ();
844                         while (tokenizer.CurrentToken != TokenType.EOF) {
845                                 string fileName = tokenizer.TokenText;
846                                 string internalfullfilename;
847
848                                 if (!Path.IsPathRooted (fileName)) {
849                                         // on unix currentRealFolder for "Recently used files" is null,
850                                         // because recently used files don't get saved as links in a directory
851                                         // recently used files get saved in a xml file
852                                         if (mwfFileView.CurrentRealFolder != null)
853                                                 fileName = Path.Combine (mwfFileView.CurrentRealFolder, fileName);
854                                         else
855                                                 if (mwfFileView.CurrentFSEntry != null) {
856                                                         fileName = mwfFileView.CurrentFSEntry.FullName;
857                                                 }
858                                 }
859
860                                 FileInfo fileInfo = new FileInfo (fileName);
861
862                                 if (fileInfo.Exists || fileDialogType == FileDialogType.SaveFileDialog) {
863                                         internalfullfilename = fileName;
864                                 } else {
865                                         DirectoryInfo dirInfo = new DirectoryInfo (fileName);
866                                         if (dirInfo.Exists) {
867                                                 mwfFileView.ChangeDirectory (null, dirInfo.FullName);
868                                                 fileNameComboBox.Text = null;
869                                                 return;
870                                         } else {
871                                                 internalfullfilename = fileName;
872                                         }
873                                 }
874
875                                 if (fileDialogType == FileDialogType.OpenFileDialog) {
876                                         if (checkFileExists) {
877                                                 if (!File.Exists (internalfullfilename)) {
878                                                         string message = "\"" + internalfullfilename + "\" doesn't exist. Please verify that you have entered the correct file name.";
879                                                         MessageBox.Show (message, openSaveButton.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
880                                                         return;
881                                                 }
882                                         }
883                                 } else {
884                                         if (overwritePrompt) {
885                                                 if (File.Exists (internalfullfilename)) {
886                                                         string message = "\"" + internalfullfilename + "\" exists. Overwrite ?";
887                                                         DialogResult dr = MessageBox.Show (message, openSaveButton.Text, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
888                                                         if (dr == DialogResult.Cancel)
889                                                                 return;
890                                                 }
891                                         }
892
893                                         if (createPrompt) {
894                                                 if (!File.Exists (internalfullfilename)) {
895                                                         string message = "\"" + internalfullfilename + "\" doesn't exist. Create ?";
896                                                         DialogResult dr = MessageBox.Show (message, openSaveButton.Text, MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
897                                                         if (dr == DialogResult.Cancel)
898                                                                 return;
899                                                 }
900                                         }
901
902                                         if (addExtension) {
903                                                 string extension_to_use = String.Empty;
904                                                 string filter_exentsion = String.Empty;
905
906                                                 if (fileFilter != null) {
907                                                         FilterStruct filterstruct = (FilterStruct) fileFilter.FilterArrayList [filterIndex - 1];
908
909                                                         for (int i = 0; i < filterstruct.filters.Count; i++) {
910                                                                 string extension = filterstruct.filters [i];
911
912                                                                 if (extension.StartsWith ("*"))
913                                                                         extension = extension.Remove (0, 1);
914
915                                                                 if (extension.IndexOf ('*') != -1)
916                                                                         continue;
917
918                                                                 filter_exentsion = extension;
919                                                                 break;
920                                                         }
921                                                 }
922
923                                                 if (filter_exentsion != String.Empty)
924                                                         extension_to_use = filter_exentsion;
925                                                 else
926                                                         if (DefaultExt.Length > 0)
927                                                                 extension_to_use = "." + DefaultExt;
928
929                                                 if (!internalfullfilename.EndsWith (extension_to_use))
930                                                         internalfullfilename += extension_to_use;
931                                         }
932                                 }
933
934                                 files.Add (internalfullfilename);
935                                 tokenizer.GetNextFile ();
936                         }
937
938                         if (files.Count > 0) {
939                                 fileNames = new string [files.Count];
940                                 for (int i = 0; i < files.Count; i++) {
941                                         string fileName = (string) files [i];
942                                         fileNames [i] = fileName;
943                                         mwfFileView.WriteRecentlyUsed (fileName);
944
945                                         if (!File.Exists (fileName))
946                                                 // ignore files that do not exist
947                                                 continue;
948
949                                         if (fileNameComboBox.Items.IndexOf (fileName) == -1)
950                                                 fileNameComboBox.Items.Insert (0, fileName);
951                                 }
952
953                                 // remove items above the maximum items that we want to display
954                                 while (fileNameComboBox.Items.Count > MaxFileNameItems)
955                                         fileNameComboBox.Items.RemoveAt (MaxFileNameItems);
956                         }
957
958                         if (checkPathExists && mwfFileView.CurrentRealFolder != null) {
959                                 if (!Directory.Exists (mwfFileView.CurrentRealFolder)) {
960                                         string message = "\"" + mwfFileView.CurrentRealFolder + "\" doesn't exist. Please verify that you have entered the correct directory name.";
961                                         MessageBox.Show (message, openSaveButton.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
962
963                                         if (InitialDirectory.Length == 0 || !Directory.Exists (InitialDirectory))
964                                                 mwfFileView.ChangeDirectory (null, lastFolder);
965                                         else
966                                                 mwfFileView.ChangeDirectory (null, InitialDirectory);
967                                         return;
968                                 }
969                         }
970
971                         if (restoreDirectory) {
972                                 lastFolder = restoreDirectoryString;
973                         } else {
974                                 lastFolder = mwfFileView.CurrentFolder;
975                         }
976
977                         CancelEventArgs cancelEventArgs = new CancelEventArgs ();
978
979                         cancelEventArgs.Cancel = false;
980
981                         OnFileOk (cancelEventArgs);
982
983                         form.DialogResult = DialogResult.OK;
984                 }
985                 
986                 void OnClickCancelButton (object sender, EventArgs e)
987                 {
988                         if (restoreDirectory)
989                                 mwfFileView.CurrentFolder = restoreDirectoryString;
990                         
991                         CancelEventArgs cancelEventArgs = new CancelEventArgs ();
992                         
993                         cancelEventArgs.Cancel = true;
994                         
995                         OnFileOk (cancelEventArgs);
996                         
997                         form.DialogResult = DialogResult.Cancel;
998                 }
999                 
1000                 void OnClickHelpButton (object sender, EventArgs e)
1001                 {
1002                         OnHelpRequest (e);
1003                 }
1004                 
1005                 void OnClickSmallButtonToolBar (object sender, ToolBarButtonClickEventArgs e)
1006                 {
1007                         if (e.Button == upToolBarButton) {
1008                                 mwfFileView.OneDirUp ();
1009                         } else
1010                         if (e.Button == backToolBarButton) {
1011                                 mwfFileView.PopDir ();
1012                         } else
1013                         if (e.Button == newdirToolBarButton) {
1014                                 mwfFileView.CreateNewFolder ();
1015                         }
1016                 }
1017                 
1018                 void OnSelectedIndexChangedFileTypeComboBox (object sender, EventArgs e)
1019                 {
1020                         if (do_not_call_OnSelectedIndexChangedFileTypeComboBox) {
1021                                 do_not_call_OnSelectedIndexChangedFileTypeComboBox = false;
1022                                 return;
1023                         }
1024                         
1025                         filterIndex = fileTypeComboBox.SelectedIndex + 1;
1026                         
1027                         mwfFileView.FilterIndex = filterIndex;
1028                 }
1029                 
1030                 void OnSelectedFileChangedFileView (object sender, EventArgs e)
1031                 {
1032                         fileNameComboBox.Text = mwfFileView.CurrentFSEntry.Name;
1033                 }
1034                 
1035                 void OnSelectedFilesChangedFileView (object sender, EventArgs e)
1036                 {
1037                         string selectedFiles = mwfFileView.SelectedFilesString;
1038                         if (selectedFiles != null && selectedFiles.Length != 0)
1039                                 fileNameComboBox.Text = selectedFiles;
1040                 }
1041                 
1042                 void OnForceDialogEndFileView (object sender, EventArgs e)
1043                 {
1044                         OnClickOpenSaveButton (this, EventArgs.Empty);
1045                 }
1046                 
1047                 void OnDirectoryChangedDirComboBox (object sender, EventArgs e)
1048                 {
1049                         mwfFileView.ChangeDirectory (sender, dirComboBox.CurrentFolder);
1050                 }
1051                 
1052                 void OnDirectoryChangedPopupButtonPanel (object sender, EventArgs e)
1053                 {
1054                         mwfFileView.ChangeDirectory (sender, popupButtonPanel.CurrentFolder);
1055                 }
1056                 
1057                 void OnCheckCheckChanged (object sender, EventArgs e)
1058                 {
1059                         ReadOnlyChecked = readonlyCheckBox.Checked;
1060                 }
1061
1062 #if NET_2_0             
1063                 void OnFileDialogFormClosed (object sender, FormClosedEventArgs e)
1064                 {
1065                         HandleFormClosedEvent (sender);
1066                 }
1067 #else
1068                 void OnFileDialogFormClosed (object sender, EventArgs e)
1069                 {
1070                         HandleFormClosedEvent (sender);
1071                 }
1072 #endif
1073                 
1074                 void HandleFormClosedEvent (object sender)
1075                 {
1076                         if (!disable_form_closed_event)
1077                                 OnClickCancelButton (sender, EventArgs.Empty);
1078                         
1079                         disable_form_closed_event = false;
1080                 }
1081                 
1082                 private void UpdateFilters ()
1083                 {
1084                         if (fileFilter == null)
1085                                 fileFilter = new FileFilter ();
1086                         
1087                         ArrayList filters = fileFilter.FilterArrayList;
1088                         
1089                         fileTypeComboBox.BeginUpdate ();
1090                         
1091                         fileTypeComboBox.Items.Clear ();
1092                         
1093                         foreach (FilterStruct fs in filters) {
1094                                 fileTypeComboBox.Items.Add (fs.filterName);
1095                         }
1096                         
1097                         if (filters.Count > 0 && FilterIndex <= filters.Count)
1098                                 fileTypeComboBox.SelectedIndex = filterIndex - 1;
1099                         
1100                         fileTypeComboBox.EndUpdate ();
1101                         
1102                         mwfFileView.FilterArrayList = filters;
1103                         
1104                         mwfFileView.FilterIndex = filterIndex;
1105                 }
1106                 
1107                 private void ResizeAndRelocateForHelpOrReadOnly ()
1108                 {
1109                         form.SuspendLayout ();
1110                         if (ShowHelp || ShowReadOnly) {
1111                                 mwfFileView.Size = new Size (449, 250); 
1112                                 fileNameLabel.Location = new Point (102, 298);
1113                                 fileNameComboBox.Location = new Point (195, 298);
1114                                 fileTypeLabel.Location = new Point (102, 324);
1115                                 fileTypeComboBox.Location = new Point (195, 324);
1116                                 openSaveButton.Location = new Point (475, 298);
1117                                 cancelButton.Location = new Point (475, 324);
1118                         } else {
1119                                 mwfFileView.Size = new Size (449, 282);
1120                                 fileNameLabel.Location = new Point (102, 330);
1121                                 fileNameComboBox.Location = new Point (195, 330);
1122                                 fileTypeLabel.Location = new Point (102, 356);
1123                                 fileTypeComboBox.Location = new Point (195, 356);
1124                                 openSaveButton.Location = new Point (475, 330);
1125                                 cancelButton.Location = new Point (475, 356);
1126                         }
1127                         
1128                         if (ShowHelp)
1129                                 form.Controls.Add (helpButton);
1130                         else
1131                                 form.Controls.Remove (helpButton);
1132                         
1133                         if (ShowReadOnly)
1134                                 form.Controls.Add (readonlyCheckBox);
1135                         else
1136                                 form.Controls.Remove (readonlyCheckBox);
1137                         form.ResumeLayout ();
1138                 }
1139                 
1140                 private void WriteConfigValues (CancelEventArgs ce)
1141                 {
1142                         MWFConfig.SetValue (filedialog_string, width_string, form.Width);
1143                         MWFConfig.SetValue (filedialog_string, height_string, form.Height);
1144                         MWFConfig.SetValue (filedialog_string, x_string, form.Location.X);
1145                         MWFConfig.SetValue (filedialog_string, y_string, form.Location.Y);
1146                         
1147                         if (!ce.Cancel) {
1148                                 MWFConfig.SetValue (filedialog_string, lastfolder_string, lastFolder);
1149                                 
1150                                 string[] fileNameCBItems = new string [fileNameComboBox.Items.Count];
1151                                 
1152                                 fileNameComboBox.Items.CopyTo (fileNameCBItems, 0);
1153                                 
1154                                 MWFConfig.SetValue (filedialog_string, filenames_string, fileNameCBItems);
1155                         }
1156                 }
1157                 
1158                 private void ReadConfigValues ()
1159                 {
1160                         lastFolder = (string)MWFConfig.GetValue (filedialog_string, lastfolder_string);
1161                         
1162                         if (lastFolder != null && lastFolder.IndexOf ("://") == -1) {
1163                                 if (!Directory.Exists (lastFolder)) {
1164                                         lastFolder = MWFVFS.DesktopPrefix;
1165                                 }
1166                         }
1167                         
1168                         if (InitialDirectory.Length > 0 && Directory.Exists (InitialDirectory))
1169                                 lastFolder = InitialDirectory;
1170                         else
1171                                 if (lastFolder == null || lastFolder.Length == 0)
1172                                         lastFolder = Environment.CurrentDirectory;
1173                         
1174                         if (RestoreDirectory)
1175                                 restoreDirectoryString = lastFolder;
1176                 }
1177
1178                 class FileNamesTokenizer
1179                 {
1180                         public FileNamesTokenizer (string text, bool allowMultiple)
1181                         {
1182                                 _text = text;
1183                                 _position = 0;
1184                                 _tokenType = TokenType.BOF;
1185                                 _allowMultiple = allowMultiple;
1186                         }
1187
1188                         public TokenType CurrentToken {
1189                                 get { return _tokenType; }
1190                         }
1191
1192                         public string TokenText {
1193                                 get { return _tokenText; }
1194                         }
1195
1196                         public bool AllowMultiple {
1197                                 get { return _allowMultiple; }
1198                         }
1199
1200                         private int ReadChar ()
1201                         {
1202                                 if (_position < _text.Length) {
1203                                         return _text [_position++];
1204                                 } else {
1205                                         return -1;
1206                                 }
1207                         }
1208
1209                         private int PeekChar ()
1210                         {
1211                                 if (_position < _text.Length) {
1212                                         return _text [_position];
1213                                 } else {
1214                                         return -1;
1215                                 }
1216                         }
1217
1218                         private void SkipWhitespaceAndQuotes ()
1219                         {
1220                                 int ch;
1221
1222                                 while ((ch = PeekChar ()) != -1) {
1223                                         if ((char) ch != '"' && !char.IsWhiteSpace ((char) ch))
1224                                                 break;
1225                                         ReadChar ();
1226                                 }
1227                         }
1228
1229                         public void GetNextFile ()
1230                         {
1231                                 if (_tokenType == TokenType.EOF)
1232                                         throw new Exception ("");
1233
1234                                 int ch;
1235
1236                                 SkipWhitespaceAndQuotes ();
1237
1238                                 if (PeekChar () == -1) {
1239                                         _tokenType = TokenType.EOF;
1240                                         return;
1241                                 }
1242
1243                                 _tokenType = TokenType.FileName;
1244                                 StringBuilder sb = new StringBuilder ();
1245
1246                                 while ((ch = PeekChar ()) != -1) {
1247                                         if ((char) ch == '"') {
1248                                                 ReadChar ();
1249                                                 if (AllowMultiple)
1250                                                         break;
1251                                                 int pos = _position;
1252
1253                                                 SkipWhitespaceAndQuotes ();
1254                                                 if (PeekChar () == -1) {
1255                                                         break;
1256                                                 }
1257                                                 _position = ++pos;
1258                                                 sb.Append ((char) ch);
1259                                         } else {
1260                                                 sb.Append ((char) ReadChar ());
1261                                         }
1262                                 }
1263
1264                                 _tokenText = sb.ToString ();
1265                         }
1266
1267                         private readonly bool _allowMultiple;
1268                         private int _position;
1269                         private readonly string _text;
1270                         private TokenType _tokenType;
1271                         private string _tokenText;
1272                 }
1273
1274                 internal enum TokenType
1275                 {
1276                         BOF,
1277                         EOF,
1278                         FileName,
1279                 }
1280         }
1281         #endregion
1282         
1283         #region PopupButtonPanel
1284         internal class PopupButtonPanel : Control, IUpdateFolder
1285         {
1286                 #region PopupButton
1287                 internal class PopupButton : Control
1288                 {
1289                         internal enum PopupButtonState
1290                         { Normal, Down, Up}
1291                         
1292                         private Image image = null;
1293                         private PopupButtonState popupButtonState = PopupButtonState.Normal;
1294                         private StringFormat text_format = new StringFormat();
1295                         private Rectangle text_rect = Rectangle.Empty;
1296                         
1297                         public PopupButton ()
1298                         {
1299                                 text_format.Alignment = StringAlignment.Center;
1300                                 text_format.LineAlignment = StringAlignment.Near;
1301                                 
1302                                 SetStyle (ControlStyles.DoubleBuffer, true);
1303                                 SetStyle (ControlStyles.AllPaintingInWmPaint, true);
1304                                 SetStyle (ControlStyles.UserPaint, true);
1305                                 SetStyle (ControlStyles.Selectable, false);
1306                         }
1307                         
1308                         public Image Image {
1309                                 set {
1310                                         image = value;
1311                                         Invalidate ();
1312                                 }
1313                                 
1314                                 get {
1315                                         return image;
1316                                 }
1317                         }
1318                         
1319                         public PopupButtonState ButtonState {
1320                                 set {
1321                                         popupButtonState = value;
1322                                         Invalidate ();
1323                                 }
1324                                 
1325                                 get {
1326                                         return popupButtonState;
1327                                 }
1328                         }
1329                         
1330                         protected override void OnPaint (PaintEventArgs pe)
1331                         {
1332                                 Draw (pe);
1333                                 
1334                                 base.OnPaint (pe);
1335                         }
1336                         
1337                         private void Draw (PaintEventArgs pe)
1338                         {
1339                                 Graphics gr = pe.Graphics;
1340                                 
1341                                 gr.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), ClientRectangle);
1342                                 
1343                                 // draw image
1344                                 if (image != null) {
1345                                         int i_x = (ClientSize.Width - image.Width) / 2;
1346                                         int i_y = 4;
1347                                         gr.DrawImage (image, i_x, i_y);
1348                                 }
1349                                 
1350                                 if (Text != String.Empty) {
1351                                         if (text_rect == Rectangle.Empty)
1352                                                 text_rect = new Rectangle (0, Height - 30, Width, Height - 30); 
1353                                         
1354                                         gr.DrawString (Text, Font, Brushes.White, text_rect, text_format);
1355                                 }
1356                                 
1357                                 switch (popupButtonState) {
1358                                         case PopupButtonState.Up:
1359                                                 gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.White), 0, 0, ClientSize.Width - 1, 0);
1360                                                 gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.White), 0, 0, 0, ClientSize.Height - 1);
1361                                                 gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.Black), ClientSize.Width - 1, 0, ClientSize.Width - 1, ClientSize.Height - 1);
1362                                                 gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.Black), 0, ClientSize.Height - 1, ClientSize.Width - 1, ClientSize.Height - 1);
1363                                                 break;
1364                                                 
1365                                         case PopupButtonState.Down:
1366                                                 gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.Black), 0, 0, ClientSize.Width - 1, 0);
1367                                                 gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.Black), 0, 0, 0, ClientSize.Height - 1);
1368                                                 gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.White), ClientSize.Width - 1, 0, ClientSize.Width - 1, ClientSize.Height - 1);
1369                                                 gr.DrawLine (ThemeEngine.Current.ResPool.GetPen (Color.White), 0, ClientSize.Height - 1, ClientSize.Width - 1, ClientSize.Height - 1);
1370                                                 break;
1371                                 }
1372                         }
1373                         
1374                         protected override void OnMouseEnter (EventArgs e)
1375                         {
1376                                 if (popupButtonState != PopupButtonState.Down)
1377                                         popupButtonState = PopupButtonState.Up;
1378                                 
1379                                 PopupButtonPanel panel = Parent as PopupButtonPanel;
1380                                 
1381                                 if (panel.focusButton != null && panel.focusButton.ButtonState == PopupButtonState.Up) {
1382                                         panel.focusButton.ButtonState = PopupButtonState.Normal;
1383                                         panel.focusButton = null;
1384                                 }
1385                                 Invalidate ();
1386                                 base.OnMouseEnter (e);
1387                         }
1388                         
1389                         protected override void OnMouseLeave (EventArgs e)
1390                         {
1391                                 if (popupButtonState == PopupButtonState.Up)
1392                                         popupButtonState = PopupButtonState.Normal;
1393                                 Invalidate ();
1394                                 base.OnMouseLeave (e);
1395                         }
1396                         
1397                         protected override void OnClick (EventArgs e)
1398                         {
1399                                 popupButtonState = PopupButtonState.Down;
1400                                 Invalidate ();
1401                                 base.OnClick (e);
1402                         }
1403                 }
1404                 #endregion
1405                 
1406                 private PopupButton recentlyusedButton;
1407                 private PopupButton desktopButton;
1408                 private PopupButton personalButton;
1409                 private PopupButton mycomputerButton;
1410                 private PopupButton networkButton;
1411                 
1412                 private PopupButton lastPopupButton = null;
1413                 private PopupButton focusButton = null;
1414                 
1415                 private string currentPath;
1416                 
1417                 private int currentFocusIndex;
1418                 
1419                 public PopupButtonPanel ()
1420                 {
1421                         SuspendLayout ();
1422                         
1423                         BackColor = Color.FromArgb (128, 128, 128);
1424                         Size = new Size (85, 336);
1425                         
1426                         recentlyusedButton = new PopupButton ();
1427                         desktopButton = new PopupButton ();
1428                         personalButton = new PopupButton ();
1429                         mycomputerButton = new PopupButton ();
1430                         networkButton = new PopupButton ();
1431                         
1432                         recentlyusedButton.Size = new Size (81, 64);
1433                         recentlyusedButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesRecentDocuments, 32);
1434                         recentlyusedButton.BackColor = BackColor;
1435                         recentlyusedButton.ForeColor = Color.Black;
1436                         recentlyusedButton.Location = new Point (2, 2);
1437                         recentlyusedButton.Text = "Recently\nused";
1438                         recentlyusedButton.Click += new EventHandler (OnClickButton);
1439                         
1440                         desktopButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesDesktop, 32);
1441                         desktopButton.BackColor = BackColor;
1442                         desktopButton.ForeColor = Color.Black;
1443                         desktopButton.Size = new Size (81, 64);
1444                         desktopButton.Location = new Point (2, 66);
1445                         desktopButton.Text = "Desktop";
1446                         desktopButton.Click += new EventHandler (OnClickButton);
1447                         
1448                         personalButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesPersonal, 32);
1449                         personalButton.BackColor = BackColor;
1450                         personalButton.ForeColor = Color.Black;
1451                         personalButton.Size = new Size (81, 64);
1452                         personalButton.Location = new Point (2, 130);
1453                         personalButton.Text = "Personal";
1454                         personalButton.Click += new EventHandler (OnClickButton);
1455                         
1456                         mycomputerButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesMyComputer, 32);
1457                         mycomputerButton.BackColor = BackColor;
1458                         mycomputerButton.ForeColor = Color.Black;
1459                         mycomputerButton.Size = new Size (81, 64);
1460                         mycomputerButton.Location = new Point (2, 194);
1461                         mycomputerButton.Text = "My Computer";
1462                         mycomputerButton.Click += new EventHandler (OnClickButton);
1463                         
1464                         networkButton.Image = ThemeEngine.Current.Images (UIIcon.PlacesMyNetwork, 32);
1465                         networkButton.BackColor = BackColor;
1466                         networkButton.ForeColor = Color.Black;
1467                         networkButton.Size = new Size (81, 64);
1468                         networkButton.Location = new Point (2, 258);
1469                         networkButton.Text = "My Network";
1470                         networkButton.Click += new EventHandler (OnClickButton);
1471                         
1472                         Controls.Add (recentlyusedButton);
1473                         Controls.Add (desktopButton);
1474                         Controls.Add (personalButton);
1475                         Controls.Add (mycomputerButton);
1476                         Controls.Add (networkButton);
1477                         
1478                         ResumeLayout (false);
1479                         
1480                         KeyDown += new KeyEventHandler (Key_Down);
1481                         
1482                         SetStyle (ControlStyles.StandardClick, false);
1483                 }
1484                 
1485                 void OnClickButton (object sender, EventArgs e)
1486                 {
1487                         if (lastPopupButton != null && lastPopupButton != sender as PopupButton)
1488                                 lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal;
1489                         lastPopupButton = sender as PopupButton;
1490                         
1491                         if (sender == recentlyusedButton) {
1492                                 currentPath = MWFVFS.RecentlyUsedPrefix;
1493                         } else
1494                         if (sender == desktopButton) {
1495                                 currentPath = MWFVFS.DesktopPrefix;
1496                         } else
1497                         if (sender == personalButton) {
1498                                 currentPath = MWFVFS.PersonalPrefix;
1499                         } else
1500                         if (sender == mycomputerButton) {
1501                                 currentPath = MWFVFS.MyComputerPrefix;
1502                         } else
1503                         if (sender == networkButton) {
1504                                 currentPath = MWFVFS.MyNetworkPrefix;
1505                         }
1506                         
1507                         EventHandler eh = (EventHandler)(Events [PDirectoryChangedEvent]);
1508                         if (eh != null)
1509                                 eh (this, EventArgs.Empty);
1510                 }
1511                 
1512                 public string CurrentFolder {
1513                         set {
1514                                 string currentPath = value;
1515                                 if (currentPath == MWFVFS.RecentlyUsedPrefix) {
1516                                         if (lastPopupButton != recentlyusedButton) {
1517                                                 if (lastPopupButton != null)
1518                                                         lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal;
1519                                                 recentlyusedButton.ButtonState = PopupButton.PopupButtonState.Down;
1520                                                 lastPopupButton = recentlyusedButton;
1521                                         }
1522                                 } else
1523                                 if (currentPath == MWFVFS.DesktopPrefix) {
1524                                         if (lastPopupButton != desktopButton) {
1525                                                 if (lastPopupButton != null)
1526                                                         lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal;
1527                                                 desktopButton.ButtonState = PopupButton.PopupButtonState.Down;
1528                                                 lastPopupButton = desktopButton;
1529                                         }
1530                                 } else
1531                                 if (currentPath == MWFVFS.PersonalPrefix) {
1532                                         if (lastPopupButton != personalButton) {
1533                                                 if (lastPopupButton != null)
1534                                                         lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal;
1535                                                 personalButton.ButtonState = PopupButton.PopupButtonState.Down;
1536                                                 lastPopupButton = personalButton;
1537                                         }
1538                                 } else
1539                                 if (currentPath == MWFVFS.MyComputerPrefix) {
1540                                         if (lastPopupButton != mycomputerButton) {
1541                                                 if (lastPopupButton != null)
1542                                                         lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal;
1543                                                 mycomputerButton.ButtonState = PopupButton.PopupButtonState.Down;
1544                                                 lastPopupButton = mycomputerButton;
1545                                         }
1546                                 } else
1547                                 if (currentPath == MWFVFS.MyNetworkPrefix) {
1548                                         if (lastPopupButton != networkButton) {
1549                                                 if (lastPopupButton != null)
1550                                                         lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal;
1551                                                 networkButton.ButtonState = PopupButton.PopupButtonState.Down;
1552                                                 lastPopupButton = networkButton;
1553                                         }
1554                                 } else {
1555                                         if (lastPopupButton != null) {
1556                                                 lastPopupButton.ButtonState = PopupButton.PopupButtonState.Normal;
1557                                                 lastPopupButton = null;
1558                                         }
1559                                 }
1560                         }
1561                         get {
1562                                 return currentPath;
1563                         }
1564                 }
1565                 
1566                 protected override void OnPaint (PaintEventArgs e)
1567                 {
1568                         ControlPaint.DrawBorder3D (e.Graphics, ClientRectangle, Border3DStyle.Sunken);
1569                         base.OnPaint (e);
1570                 }
1571                 
1572                 protected override void OnGotFocus (EventArgs e)
1573                 {
1574                         if (lastPopupButton != recentlyusedButton) {
1575                                 recentlyusedButton.ButtonState = PopupButton.PopupButtonState.Up;
1576                                 focusButton = recentlyusedButton;
1577                         }
1578                         currentFocusIndex = 0;
1579                         
1580                         base.OnGotFocus (e);
1581                 }
1582                 
1583                 protected override void OnLostFocus (EventArgs e)
1584                 {
1585                         if (focusButton != null && focusButton.ButtonState != PopupButton.PopupButtonState.Down)
1586                                 focusButton.ButtonState = PopupButton.PopupButtonState.Normal;
1587                         base.OnLostFocus (e);
1588                 }
1589                 
1590                 protected override bool IsInputKey (Keys key)
1591                 {
1592                         switch (key) {
1593                                 case Keys.Up:
1594                                 case Keys.Down:
1595                                 case Keys.Right:
1596                                 case Keys.Left:
1597                                 case Keys.Enter:
1598                                         return true;
1599                         }
1600                         return base.IsInputKey (key);
1601                 }
1602                 
1603                 private void Key_Down (object sender, KeyEventArgs e)
1604                 {
1605                         bool update_focus = false;
1606                         
1607                         if (e.KeyCode == Keys.Left || e.KeyCode == Keys.Up) {
1608                                 currentFocusIndex --;
1609                                 
1610                                 if (currentFocusIndex < 0)
1611                                         currentFocusIndex = Controls.Count - 1;
1612                                 
1613                                 update_focus = true;
1614                         } else
1615                         if (e.KeyCode == Keys.Down || e.KeyCode == Keys.Right) {
1616                                 currentFocusIndex++;
1617                                 
1618                                 if (currentFocusIndex == Controls.Count)
1619                                         currentFocusIndex = 0;
1620                                 
1621                                 update_focus = true;
1622                         } else
1623                         if (e.KeyCode == Keys.Enter) {
1624                                 focusButton.ButtonState = PopupButton.PopupButtonState.Down;
1625                                 OnClickButton (focusButton, EventArgs.Empty);
1626                         }
1627                         
1628                         if (update_focus) {
1629                                 PopupButton newfocusButton = Controls [currentFocusIndex] as PopupButton;
1630                                 if (focusButton != null && focusButton.ButtonState != PopupButton.PopupButtonState.Down)
1631                                         focusButton.ButtonState = PopupButton.PopupButtonState.Normal;
1632                                 if (newfocusButton.ButtonState != PopupButton.PopupButtonState.Down)
1633                                         newfocusButton.ButtonState = PopupButton.PopupButtonState.Up;
1634                                 focusButton = newfocusButton;
1635                         }
1636                         
1637                         e.Handled = true;
1638                 }
1639                 
1640                 static object PDirectoryChangedEvent = new object ();
1641                 
1642                 public event EventHandler DirectoryChanged {
1643                         add { Events.AddHandler (PDirectoryChangedEvent, value); }
1644                         remove { Events.RemoveHandler (PDirectoryChangedEvent, value); }
1645                 }
1646         }
1647         #endregion
1648         
1649         #region DirComboBox
1650         internal class DirComboBox : ComboBox, IUpdateFolder
1651         {
1652                 #region DirComboBoxItem
1653                 internal class DirComboBoxItem
1654                 {
1655                         private int imageIndex;
1656                         private string name;
1657                         private string path;
1658                         private int xPos;
1659                         private ImageList imageList;
1660                         
1661                         public DirComboBoxItem (ImageList imageList, int imageIndex, string name, string path, int xPos)
1662                         {
1663                                 this.imageList = imageList;
1664                                 this.imageIndex = imageIndex;
1665                                 this.name = name;
1666                                 this.path = path;
1667                                 this.xPos = xPos;
1668                         }
1669                         
1670                         public int ImageIndex {
1671                                 get {
1672                                         return imageIndex;
1673                                 }
1674                         }
1675                         
1676                         public string Name {
1677                                 get {
1678                                         return name;
1679                                 }
1680                         }
1681                         
1682                         public string Path {
1683                                 get {
1684                                         return path;
1685                                 }
1686                         }
1687                         
1688                         public int XPos {
1689                                 get {
1690                                         return xPos;
1691                                 }
1692                         }
1693                         
1694                         public ImageList ImageList {
1695                                 set {
1696                                         imageList = value;
1697                                 }
1698                                 
1699                                 get {
1700                                         return imageList;
1701                                 }
1702                         }
1703                 }
1704                 #endregion
1705                 
1706                 private ImageList imageList = new ImageList();
1707                 
1708                 private string currentPath;
1709                 
1710                 private Stack folderStack = new Stack();
1711                 
1712                 private static readonly int indent = 6;
1713                 
1714                 private DirComboBoxItem recentlyUsedDirComboboxItem;
1715                 private DirComboBoxItem desktopDirComboboxItem;
1716                 private DirComboBoxItem personalDirComboboxItem;
1717                 private DirComboBoxItem myComputerDirComboboxItem;
1718                 private DirComboBoxItem networkDirComboboxItem;
1719                 
1720                 private ArrayList myComputerItems = new ArrayList ();
1721                 
1722                 private DirComboBoxItem mainParentDirComboBoxItem = null;
1723                 private DirComboBoxItem real_parent = null;
1724                 
1725                 private MWFVFS vfs;
1726                 
1727                 public DirComboBox (MWFVFS vfs)
1728                 {
1729                         this.vfs = vfs;
1730
1731                         SuspendLayout ();
1732                         
1733                         DrawMode = DrawMode.OwnerDrawFixed;
1734                         
1735                         imageList.ColorDepth = ColorDepth.Depth32Bit;
1736                         imageList.ImageSize = new Size (16, 16);
1737                         imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesRecentDocuments, 16));
1738                         imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesDesktop, 16));
1739                         imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesPersonal, 16));
1740                         imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesMyComputer, 16));
1741                         imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.PlacesMyNetwork, 16));
1742                         imageList.Images.Add (ThemeEngine.Current.Images (UIIcon.NormalFolder, 16));
1743                         imageList.TransparentColor = Color.Transparent;
1744                         
1745                         recentlyUsedDirComboboxItem = new DirComboBoxItem (imageList, 0, "Recently used", MWFVFS.RecentlyUsedPrefix, 0);
1746                         desktopDirComboboxItem = new DirComboBoxItem (imageList, 1, "Desktop", MWFVFS.DesktopPrefix, 0);
1747                         personalDirComboboxItem = new DirComboBoxItem (imageList, 2, "Personal folder", MWFVFS.PersonalPrefix, indent);
1748                         myComputerDirComboboxItem = new DirComboBoxItem (imageList, 3, "My Computer", MWFVFS.MyComputerPrefix, indent);
1749                         networkDirComboboxItem = new DirComboBoxItem (imageList, 4, "My Network", MWFVFS.MyNetworkPrefix, indent);
1750                         
1751                         ArrayList al = this.vfs.GetMyComputerContent ();
1752                         
1753                         foreach (FSEntry fsEntry in al) {
1754                                 myComputerItems.Add (new DirComboBoxItem (MimeIconEngine.LargeIcons, fsEntry.IconIndex, fsEntry.Name, fsEntry.FullName, indent * 2));
1755                         }
1756                         
1757                         al.Clear ();
1758                         al = null;
1759                         
1760                         mainParentDirComboBoxItem = myComputerDirComboboxItem;
1761                         
1762                         ResumeLayout (false);
1763                 }
1764                 
1765                 public string CurrentFolder {
1766                         set {
1767                                 currentPath = value;
1768                                 
1769                                 CreateComboList ();
1770                         }
1771                         get {
1772                                 return currentPath;
1773                         }
1774                 }
1775                 
1776                 private void CreateComboList ()
1777                 {
1778                         real_parent = null;
1779                         DirComboBoxItem selection = null;
1780                         
1781                         if (currentPath == MWFVFS.RecentlyUsedPrefix) {
1782                                 mainParentDirComboBoxItem = recentlyUsedDirComboboxItem;
1783                                 selection = recentlyUsedDirComboboxItem;
1784                         } else
1785                         if (currentPath == MWFVFS.DesktopPrefix) {
1786                                 selection = desktopDirComboboxItem;
1787                                 mainParentDirComboBoxItem = desktopDirComboboxItem;
1788                         } else
1789                         if (currentPath == MWFVFS.PersonalPrefix) {
1790                                 selection = personalDirComboboxItem;
1791                                 mainParentDirComboBoxItem = personalDirComboboxItem;
1792                         } else
1793                         if (currentPath == MWFVFS.MyComputerPrefix) {
1794                                 selection = myComputerDirComboboxItem;
1795                                 mainParentDirComboBoxItem = myComputerDirComboboxItem;
1796                         } else
1797                         if (currentPath == MWFVFS.MyNetworkPrefix) {
1798                                 selection = networkDirComboboxItem;
1799                                 mainParentDirComboBoxItem = networkDirComboboxItem;
1800                         } else {
1801                                 foreach (DirComboBoxItem dci in myComputerItems) {
1802                                         if (dci.Path == currentPath) {
1803                                                 mainParentDirComboBoxItem = selection = dci;
1804                                                 break;
1805                                         }
1806                                 }
1807                         }
1808                         
1809                         BeginUpdate ();
1810                         
1811                         Items.Clear ();
1812                         
1813                         Items.Add (recentlyUsedDirComboboxItem);
1814                         Items.Add (desktopDirComboboxItem);
1815                         Items.Add (personalDirComboboxItem);
1816                         Items.Add (myComputerDirComboboxItem);
1817                         Items.AddRange (myComputerItems);
1818                         Items.Add (networkDirComboboxItem);
1819                         
1820                         if (selection == null) {
1821                                 real_parent = CreateFolderStack ();
1822                         }
1823                         
1824                         if (real_parent != null) {
1825                                 int local_indent = 0;
1826                                 
1827                                 if (real_parent == desktopDirComboboxItem)
1828                                         local_indent = 1;
1829                                 else
1830                                 if (real_parent == personalDirComboboxItem || real_parent == networkDirComboboxItem)
1831                                         local_indent = 2;
1832                                 else
1833                                         local_indent = 3;
1834                                 
1835                                 selection = AppendToParent (local_indent, real_parent);
1836                         }
1837                         
1838                         EndUpdate ();
1839                         
1840                         if (selection != null)
1841                                 SelectedItem = selection;
1842                 }
1843                 
1844                 private DirComboBoxItem CreateFolderStack ()
1845                 {
1846                         folderStack.Clear ();
1847                         
1848                         DirectoryInfo di = new DirectoryInfo (currentPath);
1849                         
1850                         folderStack.Push (di);
1851                         
1852                         while (di.Parent != null) {
1853                                 di = di.Parent;
1854                                 
1855                                 if (mainParentDirComboBoxItem != personalDirComboboxItem && di.FullName == ThemeEngine.Current.Places (UIIcon.PlacesDesktop))
1856                                         return desktopDirComboboxItem;
1857                                 else
1858                                 if (mainParentDirComboBoxItem == personalDirComboboxItem) {
1859                                         if (di.FullName == ThemeEngine.Current.Places (UIIcon.PlacesPersonal))
1860                                                 return personalDirComboboxItem;
1861                                 } else
1862                                         foreach (DirComboBoxItem dci in myComputerItems) {
1863                                                 if (dci.Path == di.FullName) {
1864                                                         return dci;
1865                                                 }
1866                                         }
1867                                 
1868                                 
1869                                 folderStack.Push (di);
1870                         }
1871                         
1872                         return null;
1873                 }
1874                 
1875                 private DirComboBoxItem AppendToParent (int nr_indents, DirComboBoxItem parentDirComboBoxItem)
1876                 {
1877                         DirComboBoxItem selection = null;
1878                         
1879                         int index = Items.IndexOf (parentDirComboBoxItem) + 1;
1880                         
1881                         int xPos = indent * nr_indents;
1882                         
1883                         while (folderStack.Count != 0) {
1884                                 DirectoryInfo dii = folderStack.Pop () as DirectoryInfo;
1885                                 
1886                                 DirComboBoxItem dci = new DirComboBoxItem (imageList, 5, dii.Name, dii.FullName, xPos);
1887                                 
1888                                 Items.Insert (index, dci);
1889                                 index++;
1890                                 selection = dci;
1891                                 xPos += indent;
1892                         }
1893                         
1894                         return selection;
1895                 }
1896                 
1897                 protected override void OnDrawItem (DrawItemEventArgs e)
1898                 {
1899                         if (e.Index == -1)
1900                                 return;
1901                         
1902                         DirComboBoxItem dcbi = Items [e.Index] as DirComboBoxItem;
1903                         
1904                         Bitmap bmp = new Bitmap (e.Bounds.Width, e.Bounds.Height, e.Graphics);
1905                         Graphics gr = Graphics.FromImage (bmp);
1906                         
1907                         Color backColor = e.BackColor;
1908                         Color foreColor = e.ForeColor;
1909                         
1910                         int xPos = dcbi.XPos;
1911
1912                         if ((e.State & DrawItemState.ComboBoxEdit) != 0)
1913                                 xPos = 0;
1914
1915                         gr.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (backColor),
1916                                         new Rectangle (0, 0, bmp.Width, bmp.Height));
1917                         
1918                         if ((e.State & DrawItemState.Selected) == DrawItemState.Selected &&
1919                                         (!DroppedDown || (e.State & DrawItemState.ComboBoxEdit) != DrawItemState.ComboBoxEdit)) {
1920                                 foreColor = ThemeEngine.Current.ColorHighlightText;
1921
1922                                 int w = (int) gr.MeasureString (dcbi.Name, e.Font).Width;
1923
1924                                 gr.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (ThemeEngine.Current.ColorHighlight),
1925                                                 new Rectangle (xPos + 23, 1, w + 3, e.Bounds.Height - 2));
1926                                 if ((e.State & DrawItemState.Focus) == DrawItemState.Focus) {
1927                                         ControlPaint.DrawFocusRectangle (gr, new Rectangle (xPos + 22, 0, w + 5,
1928                                                         e.Bounds.Height), foreColor, ThemeEngine.Current.ColorHighlight);
1929                                 }
1930                         }
1931
1932                         gr.DrawString (dcbi.Name, e.Font , ThemeEngine.Current.ResPool.GetSolidBrush (foreColor), new Point (24 + xPos, (bmp.Height - e.Font.Height) / 2));
1933                         gr.DrawImage (dcbi.ImageList.Images [dcbi.ImageIndex], new Rectangle (new Point (xPos + 2, 0), new Size (16, 16)));
1934                         
1935                         e.Graphics.DrawImage (bmp, e.Bounds.X, e.Bounds.Y);
1936                         gr.Dispose ();
1937                         bmp.Dispose ();
1938                 }
1939                 
1940                 protected override void OnSelectedIndexChanged (EventArgs e)
1941                 {
1942                         if (Items.Count > 0) {
1943                                 DirComboBoxItem dcbi = Items [SelectedIndex] as DirComboBoxItem;
1944                                 
1945                                 currentPath = dcbi.Path;
1946                         }
1947                 }
1948                 
1949                 protected override void OnSelectionChangeCommitted (EventArgs e)
1950                 {
1951                         EventHandler eh = (EventHandler)(Events [CDirectoryChangedEvent]);
1952                         if (eh != null)
1953                                 eh (this, EventArgs.Empty);
1954                 }
1955                 
1956                 static object CDirectoryChangedEvent = new object ();
1957                 
1958                 public event EventHandler DirectoryChanged {
1959                         add { Events.AddHandler (CDirectoryChangedEvent, value); }
1960                         remove { Events.RemoveHandler (CDirectoryChangedEvent, value); }
1961                 }
1962         }
1963         #endregion
1964         
1965         #region FilterStruct
1966         internal struct FilterStruct
1967         {
1968                 public string filterName;
1969                 public StringCollection filters;
1970                 
1971                 public FilterStruct (string filterName, string filter)
1972                 {
1973                         this.filterName = filterName;
1974                         
1975                         filters =  new StringCollection ();
1976                         
1977                         SplitFilters (filter);
1978                 }
1979                 
1980                 private void SplitFilters (string filter)
1981                 {
1982                         string[] split = filter.Split (new char [] {';'});
1983                         foreach (string s in split) {
1984                                 filters.Add (s.Trim ());
1985                         }
1986                 }
1987         }
1988         #endregion
1989         
1990         #region FileFilter
1991         internal class FileFilter
1992         {
1993                 private ArrayList filterArrayList = new ArrayList();
1994                 
1995                 private string filter;
1996                 
1997                 public FileFilter ()
1998                 {}
1999                 
2000                 public FileFilter (string filter) : base ()
2001                 {
2002                         this.filter = filter;
2003                         
2004                         SplitFilter ();
2005                 }
2006                 
2007                 public static bool CheckFilter (string val)
2008                 {
2009                         if (val.Length == 0)
2010                                 return true;
2011                         
2012                         string[] filters = val.Split (new char [] {'|'});
2013                         
2014                         if ((filters.Length % 2) != 0)
2015                                 return false;
2016                         
2017                         return true;
2018                 }
2019                 
2020                 public ArrayList FilterArrayList {
2021                         set {
2022                                 filterArrayList = value;
2023                         }
2024                         
2025                         get {
2026                                 return filterArrayList;
2027                         }
2028                 }
2029                 
2030                 public string Filter {
2031                         set {
2032                                 filter = value;
2033                                 
2034                                 SplitFilter ();
2035                         }
2036                         
2037                         get {
2038                                 return filter;
2039                         }
2040                 }
2041                 
2042                 private void SplitFilter ()
2043                 {
2044                         filterArrayList.Clear ();
2045                         
2046                         if (filter.Length == 0)
2047                                 return;
2048                         
2049                         string[] filters = filter.Split (new char [] {'|'});
2050                         
2051                         for (int i = 0; i < filters.Length; i += 2) {
2052                                 FilterStruct filterStruct = new FilterStruct (filters [i], filters [i + 1]);
2053                                 
2054                                 filterArrayList.Add (filterStruct);
2055                         }
2056                 }
2057         }
2058         #endregion
2059         
2060         #region MWFFileView             
2061         // MWFFileView
2062         internal class MWFFileView : ListView
2063         {
2064                 private ArrayList filterArrayList;
2065                 
2066                 private bool showHiddenFiles = false;
2067                 
2068                 private string selectedFilesString;
2069                 
2070                 private int filterIndex = 1;
2071                 
2072                 private ToolTip toolTip;
2073                 private int oldItemIndexForToolTip = -1;
2074                 
2075                 private ContextMenu contextMenu;
2076                 
2077                 private MenuItem menuItemView;
2078                 private MenuItem menuItemNew;
2079                 
2080                 private MenuItem smallIconMenutItem;
2081                 private MenuItem tilesMenutItem;
2082                 private MenuItem largeIconMenutItem;
2083                 private MenuItem listMenutItem;
2084                 private MenuItem detailsMenutItem;
2085                 
2086                 private MenuItem newFolderMenuItem; 
2087                 private MenuItem showHiddenFilesMenuItem;
2088                 
2089                 private int previousCheckedMenuItemIndex;
2090                 
2091                 private ArrayList viewMenuItemClones = new ArrayList ();
2092                 
2093                 private FSEntry currentFSEntry = null;
2094                 
2095                 private string currentFolder;
2096                 private string currentRealFolder;
2097                 private FSEntry currentFolderFSEntry;
2098                 
2099                 // store DirectoryInfo for a back button for example
2100                 private Stack directoryStack = new Stack();
2101                 
2102                 // list of controls(components to enable or disable depending on current directoryStack.Count
2103                 private ArrayList dirStackControlsOrComponents = new ArrayList ();
2104                 
2105                 private ToolBarButton folderUpToolBarButton;
2106                 
2107                 private ArrayList registered_senders = new ArrayList ();
2108                 
2109                 private bool should_push = true;
2110                 
2111                 private MWFVFS vfs;
2112                 
2113                 private View old_view;
2114                 
2115                 private int old_menuitem_index;
2116                 private bool do_update_view = false;
2117                 
2118                 private int platform = (int) Environment.OSVersion.Platform;
2119                 
2120                 public MWFFileView (MWFVFS vfs)
2121                 {
2122                         this.vfs = vfs;
2123                         this.vfs.RegisterUpdateDelegate (new MWFVFS.UpdateDelegate (RealFileViewUpdate), this);
2124                         
2125                         SuspendLayout ();
2126                         
2127                         contextMenu = new ContextMenu ();
2128                         
2129                         toolTip = new ToolTip ();
2130                         toolTip.InitialDelay = 300;
2131                         toolTip.ReshowDelay = 0; 
2132                         
2133                         // contextMenu
2134                         
2135                         // View menu item
2136                         menuItemView = new MenuItem ("View");
2137                         
2138                         smallIconMenutItem = new MenuItem ("Small Icon", new EventHandler (OnClickViewMenuSubItem));
2139                         smallIconMenutItem.RadioCheck = true;
2140                         menuItemView.MenuItems.Add (smallIconMenutItem);
2141                         
2142                         tilesMenutItem = new MenuItem ("Tiles", new EventHandler (OnClickViewMenuSubItem));
2143                         tilesMenutItem.RadioCheck = true;
2144                         menuItemView.MenuItems.Add (tilesMenutItem);
2145                         
2146                         largeIconMenutItem = new MenuItem ("Large Icon", new EventHandler (OnClickViewMenuSubItem));
2147                         largeIconMenutItem.RadioCheck = true;
2148                         menuItemView.MenuItems.Add (largeIconMenutItem);
2149                         
2150                         listMenutItem = new MenuItem ("List", new EventHandler (OnClickViewMenuSubItem));
2151                         listMenutItem.RadioCheck = true;
2152                         listMenutItem.Checked = true;
2153                         menuItemView.MenuItems.Add (listMenutItem);
2154                         previousCheckedMenuItemIndex = listMenutItem.Index;
2155                         
2156                         detailsMenutItem = new MenuItem ("Details", new EventHandler (OnClickViewMenuSubItem));
2157                         detailsMenutItem.RadioCheck = true;
2158                         menuItemView.MenuItems.Add (detailsMenutItem);
2159                         
2160                         contextMenu.MenuItems.Add (menuItemView);
2161                         
2162                         contextMenu.MenuItems.Add (new MenuItem ("-"));
2163                         
2164                         // New menu item
2165                         menuItemNew = new MenuItem ("New");
2166                         
2167                         newFolderMenuItem = new MenuItem ("New Folder", new EventHandler (OnClickNewFolderMenuItem));
2168                         menuItemNew.MenuItems.Add (newFolderMenuItem);
2169                         
2170                         contextMenu.MenuItems.Add (menuItemNew);
2171                         
2172                         contextMenu.MenuItems.Add (new MenuItem ("-"));
2173                         
2174                         // Show hidden files menu item
2175                         showHiddenFilesMenuItem = new MenuItem ("Show hidden files", new EventHandler (OnClickContextMenu));
2176                         showHiddenFilesMenuItem.Checked = showHiddenFiles;
2177                         contextMenu.MenuItems.Add (showHiddenFilesMenuItem);
2178                         
2179                         LabelWrap = true;
2180                         
2181                         SmallImageList = MimeIconEngine.SmallIcons;
2182                         LargeImageList = MimeIconEngine.LargeIcons;
2183                         
2184                         View = old_view = View.List;
2185                         LabelEdit = true;
2186                         
2187                         ContextMenu = contextMenu;
2188                         
2189                         ResumeLayout (false);
2190                         
2191                         KeyDown += new KeyEventHandler (MWF_KeyDown);
2192                 }
2193                 
2194                 public string CurrentFolder {
2195                         get {
2196                                 return currentFolder;
2197                         }
2198                         set {
2199                                 currentFolder = value;
2200                         }
2201                 }
2202                 
2203                 public string CurrentRealFolder {
2204                         get {
2205                                 return currentRealFolder;
2206                         }
2207                 }
2208                 
2209                 public FSEntry CurrentFSEntry {
2210                         get {
2211                                 return currentFSEntry;
2212                         }
2213                 }
2214                 
2215                 public MenuItem[] ViewMenuItems {
2216                         get {
2217                                 MenuItem[] menuItemClones = new MenuItem [] {
2218                                         smallIconMenutItem.CloneMenu (),
2219                                         tilesMenutItem.CloneMenu (),
2220                                         largeIconMenutItem.CloneMenu (),
2221                                         listMenutItem.CloneMenu (),
2222                                         detailsMenutItem.CloneMenu ()
2223                                 };
2224                                 
2225                                 viewMenuItemClones.Add (menuItemClones);
2226                                 
2227                                 return menuItemClones;
2228                         }
2229                 }
2230                 
2231                 public ArrayList FilterArrayList {
2232                         set {
2233                                 filterArrayList = value;
2234                         }
2235                         
2236                         get {
2237                                 return filterArrayList;
2238                         }
2239                 }
2240                 
2241                 public bool ShowHiddenFiles {
2242                         set {
2243                                 showHiddenFiles = value;
2244                         }
2245                         
2246                         get {
2247                                 return showHiddenFiles;
2248                         }
2249                 }
2250                 
2251                 public int FilterIndex {
2252                         set {
2253                                 filterIndex = value;
2254                                 if (Visible)
2255                                         UpdateFileView ();
2256                         }
2257                         
2258                         get {
2259                                 return filterIndex;
2260                         }
2261                 }
2262                 
2263                 public string SelectedFilesString {
2264                         set {
2265                                 selectedFilesString = value;
2266                         }
2267                         
2268                         get {
2269                                 return selectedFilesString;
2270                         }
2271                 }
2272                 
2273                 public void PushDir ()
2274                 {
2275                         if (currentFolder != null)
2276                                 directoryStack.Push (currentFolder);
2277                         
2278                         EnableOrDisableDirstackObjects ();
2279                 }
2280                 
2281                 public void PopDir ()
2282                 {
2283                         if (directoryStack.Count == 0)
2284                                 return;
2285                         
2286                         string new_folder = directoryStack.Pop () as string;
2287                         
2288                         EnableOrDisableDirstackObjects ();
2289                         
2290                         should_push = false;
2291                         
2292                         ChangeDirectory (null, new_folder);
2293                 }
2294                 
2295                 public void RegisterSender (IUpdateFolder iud)
2296                 {
2297                         registered_senders.Add (iud);
2298                 }
2299                 
2300                 public void CreateNewFolder ()
2301                 {
2302                         if (currentFolder == MWFVFS.MyComputerPrefix ||
2303                             currentFolder == MWFVFS.RecentlyUsedPrefix)
2304                                 return;
2305                         
2306                         FSEntry fsEntry = new FSEntry ();
2307                         fsEntry.Attributes = FileAttributes.Directory;
2308                         fsEntry.FileType = FSEntry.FSEntryType.Directory;
2309                         fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("inode/directory");
2310                         fsEntry.LastAccessTime = DateTime.Now;
2311                         
2312                         // FIXME: when ListView.LabelEdit is available use it
2313 //                      listViewItem.BeginEdit();
2314                         
2315                         TextEntryDialog ted = new TextEntryDialog ();
2316                         ted.IconPictureBoxImage = MimeIconEngine.LargeIcons.Images.GetImage (fsEntry.IconIndex);
2317                         
2318                         string folder = String.Empty;
2319                         
2320                         if (currentFolderFSEntry.RealName != null)
2321                                 folder = currentFolderFSEntry.RealName;
2322                         else
2323                                 folder = currentFolder;
2324                         
2325                         string tmp_filename = "New Folder";
2326                         
2327                         if (Directory.Exists (Path.Combine (folder, tmp_filename))) {
2328                                 int i = 1;
2329                                 
2330                                 if ((platform == 4) || (platform == 128)) {
2331                                         tmp_filename = tmp_filename + "-" + i;
2332                                 } else {
2333                                         tmp_filename = tmp_filename + " (" + i + ")";
2334                                 }
2335                                 
2336                                 while (Directory.Exists (Path.Combine (folder, tmp_filename))) {
2337                                         i++;
2338                                         if ((platform == 4) || (platform == 128)) {
2339                                                 tmp_filename = "New Folder" + "-" + i;
2340                                         } else {
2341                                                 tmp_filename = "New Folder" + " (" + i + ")";
2342                                         }
2343                                 }
2344                         }
2345                         
2346                         ted.FileName = tmp_filename;
2347                         
2348                         if (ted.ShowDialog () == DialogResult.OK) {
2349                                 string new_folder = Path.Combine (folder, ted.FileName);
2350                                 
2351                                 if (vfs.CreateFolder (new_folder)) {
2352                                         fsEntry.FullName = new_folder;
2353                                         fsEntry.Name = ted.FileName;
2354                                         
2355                                         FileViewListViewItem listViewItem = new FileViewListViewItem (fsEntry);
2356                                         
2357                                         BeginUpdate ();
2358                                         Items.Add (listViewItem);
2359                                         EndUpdate ();
2360                                         
2361                                         listViewItem.EnsureVisible ();
2362                                 }
2363                         }
2364                 }
2365                 
2366                 public void SetSelectedIndexTo (string fname)
2367                 {
2368                         foreach (FileViewListViewItem item in Items) {
2369                                 if (item.Text == fname) {
2370                                         BeginUpdate ();
2371                                         SelectedItems.Clear ();
2372                                         item.Selected = true;
2373                                         EndUpdate ();
2374                                         break;
2375                                 }
2376                         }
2377                 }
2378                 
2379                 public void OneDirUp ()
2380                 {
2381                         string parent_folder = vfs.GetParent ();
2382                         if (parent_folder != null)
2383                                 ChangeDirectory (null, parent_folder);
2384                 }
2385                 
2386                 public void ChangeDirectory (object sender, string folder)
2387                 {
2388                         if (folder == MWFVFS.DesktopPrefix || folder == MWFVFS.RecentlyUsedPrefix)
2389                                 folderUpToolBarButton.Enabled = false;
2390                         else
2391                                 folderUpToolBarButton.Enabled = true;
2392                         
2393                         foreach (IUpdateFolder iuf in registered_senders) {
2394                                 iuf.CurrentFolder = folder;
2395                         }
2396                         
2397                         if (should_push)
2398                                 PushDir ();
2399                         else
2400                                 should_push = true;
2401                         
2402                         currentFolderFSEntry = vfs.ChangeDirectory (folder);
2403                         
2404                         currentFolder = folder;
2405                         
2406                         if (currentFolder.IndexOf ("://") != -1)
2407                                 currentRealFolder = currentFolderFSEntry.RealName;
2408                         else
2409                                 currentRealFolder = currentFolder;
2410                         
2411                         BeginUpdate ();
2412                         
2413                         Items.Clear ();
2414                         SelectedItems.Clear ();
2415                         
2416                         if (folder == MWFVFS.RecentlyUsedPrefix) {
2417                                 old_view = View;
2418                                 View = View.Details;
2419                                 old_menuitem_index = previousCheckedMenuItemIndex;
2420                                 UpdateMenuItems (detailsMenutItem);
2421                                 do_update_view = true;
2422                         } else
2423                         if (View != old_view && do_update_view) {
2424                                 UpdateMenuItems (menuItemView.MenuItems [old_menuitem_index]);
2425                                 View = old_view;
2426                                 do_update_view = false;
2427                         }
2428                         EndUpdate ();
2429
2430                         try {
2431                                 UpdateFileView ();
2432                         } catch (Exception e) {
2433                                 if (should_push)
2434                                         PopDir ();
2435                                 MessageBox.Show (e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
2436                         }
2437                 }
2438                 
2439                 public void UpdateFileView ()
2440                 {
2441                         if (filterArrayList != null && filterArrayList.Count != 0) {
2442                                 FilterStruct fs = (FilterStruct)filterArrayList [filterIndex - 1];
2443                                 
2444                                 vfs.GetFolderContent (fs.filters);
2445                         } else
2446                                 vfs.GetFolderContent ();
2447                 }
2448                 
2449                 public void RealFileViewUpdate (ArrayList directoriesArrayList, ArrayList fileArrayList)
2450                 {
2451                         BeginUpdate ();
2452                         
2453                         Items.Clear ();
2454                         SelectedItems.Clear ();
2455                         
2456                         foreach (FSEntry directoryFSEntry in directoriesArrayList) {
2457                                 if (!ShowHiddenFiles)
2458                                         if (directoryFSEntry.Name.StartsWith (".") || directoryFSEntry.Attributes == FileAttributes.Hidden)
2459                                                 continue;
2460                                 
2461                                 FileViewListViewItem listViewItem = new FileViewListViewItem (directoryFSEntry);
2462                                 
2463                                 Items.Add (listViewItem);
2464                         }
2465                         
2466                         StringCollection collection = new StringCollection ();
2467                         
2468                         foreach (FSEntry fsEntry in fileArrayList) {
2469                                 
2470                                 // remove duplicates. that can happen when you read recently used files for example
2471                                 if (collection.Contains (fsEntry.Name)) {
2472                                         
2473                                         string fileName = fsEntry.Name;
2474                                         
2475                                         if (collection.Contains (fileName)) {
2476                                                 int i = 1;
2477                                                 
2478                                                 while (collection.Contains (fileName + "(" + i + ")")) {
2479                                                         i++;
2480                                                 }
2481                                                 
2482                                                 fileName = fileName + "(" + i + ")";
2483                                         }
2484                                         
2485                                         fsEntry.Name = fileName;
2486                                 }
2487                                 
2488                                 collection.Add (fsEntry.Name);
2489                                 
2490                                 DoOneFSEntry (fsEntry);
2491                         }
2492                         
2493                         EndUpdate ();
2494                         
2495                         collection.Clear ();
2496                         collection = null;
2497                         
2498                         directoriesArrayList.Clear ();
2499                         fileArrayList.Clear ();
2500                 }
2501                 
2502                 public void AddControlToEnableDisableByDirStack (object control)
2503                 {
2504                         dirStackControlsOrComponents.Add (control);
2505                 }
2506                 
2507                 public void SetFolderUpToolBarButton (ToolBarButton tb)
2508                 {
2509                         folderUpToolBarButton = tb;
2510                 }
2511                 
2512                 public void WriteRecentlyUsed (string fullfilename)
2513                 {
2514                         vfs.WriteRecentlyUsedFiles (fullfilename);
2515                 }
2516                 
2517                 private void EnableOrDisableDirstackObjects ()
2518                 {
2519                         foreach (object o in dirStackControlsOrComponents) {
2520                                 if (o is Control) {
2521                                         Control c = o as Control;
2522                                         c.Enabled = (directoryStack.Count > 1);
2523                                 } else
2524                                 if (o is ToolBarButton) {
2525                                         ToolBarButton t = o as ToolBarButton;
2526                                         t.Enabled = (directoryStack.Count > 0);
2527                                 }
2528                         }
2529                 }
2530                 
2531                 private void DoOneFSEntry (FSEntry fsEntry) 
2532                 {
2533                         if (!ShowHiddenFiles)
2534                                 if (fsEntry.Name.StartsWith (".")  || fsEntry.Attributes == FileAttributes.Hidden)
2535                                         return;
2536                         
2537                         FileViewListViewItem listViewItem = new FileViewListViewItem (fsEntry);
2538                         
2539                         Items.Add (listViewItem);
2540                 }
2541                 
2542                 private void MWF_KeyDown (object sender, KeyEventArgs e)
2543                 {
2544                         if (e.KeyCode == Keys.Back) {
2545                                 OneDirUp ();
2546                         }
2547                 }
2548                 
2549                 protected override void OnClick (EventArgs e)
2550                 {
2551                         if (!MultiSelect) {
2552                                 if (SelectedItems.Count > 0) {
2553                                         FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem;
2554                                         
2555                                         FSEntry fsEntry = listViewItem.FSEntry;
2556                                         
2557                                         if (fsEntry.FileType == FSEntry.FSEntryType.File) {
2558                                                 currentFSEntry = fsEntry;
2559                                                 
2560                                                 EventHandler eh = (EventHandler)(Events [MSelectedFileChangedEvent]);
2561                                                 if (eh != null)
2562                                                         eh (this, EventArgs.Empty);
2563                                         }
2564                                 }
2565                         }
2566                         
2567                         base.OnClick (e);
2568                 }
2569                 
2570                 protected override void OnDoubleClick (EventArgs e)
2571                 {
2572                         if (SelectedItems.Count > 0) {
2573                                 FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem;
2574                                 
2575                                 FSEntry fsEntry = listViewItem.FSEntry;
2576                                 
2577                                 if (fsEntry.Attributes == FileAttributes.Directory) {
2578                                         
2579                                         ChangeDirectory (null, fsEntry.FullName);
2580                                         
2581                                         EventHandler eh = (EventHandler)(Events [MDirectoryChangedEvent]);
2582                                         if (eh != null)
2583                                                 eh (this, EventArgs.Empty);
2584                                 } else {
2585                                         currentFSEntry = fsEntry;
2586                                         
2587                                         EventHandler eh = (EventHandler)(Events [MSelectedFileChangedEvent]);
2588                                         if (eh != null)
2589                                                 eh (this, EventArgs.Empty);
2590                                         
2591                                         eh = (EventHandler)(Events [MForceDialogEndEvent]);
2592                                         if (eh != null)
2593                                                 eh (this, EventArgs.Empty);
2594                                         
2595                                         return;
2596                                 }
2597                         }
2598                         
2599                         base.OnDoubleClick (e);
2600                 }
2601                 
2602                 protected override void OnSelectedIndexChanged (EventArgs e)
2603                 {
2604                         if (SelectedItems.Count > 0) {
2605                                 selectedFilesString = String.Empty;
2606                                 
2607                                 if (SelectedItems.Count == 1) {
2608                                         FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem;
2609                                         
2610                                         FSEntry fsEntry = listViewItem.FSEntry;
2611
2612                                         if (fsEntry.Attributes != FileAttributes.Directory)
2613                                                 selectedFilesString = SelectedItems [0].Text;
2614                                 } else {
2615                                         foreach (FileViewListViewItem lvi in SelectedItems) {
2616                                                 FSEntry fsEntry = lvi.FSEntry;
2617
2618                                                 if (fsEntry.Attributes != FileAttributes.Directory)
2619                                                         selectedFilesString = selectedFilesString + "\"" + lvi.Text + "\" ";
2620                                         }
2621                                 }
2622
2623                                 EventHandler eh = (EventHandler)(Events [MSelectedFilesChangedEvent]);
2624                                 if (eh != null)
2625                                         eh (this, EventArgs.Empty);
2626                         }
2627
2628                         base.OnSelectedIndexChanged (e);
2629                 }
2630                 
2631                 protected override void OnMouseMove (MouseEventArgs e)
2632                 {
2633                         FileViewListViewItem item = GetItemAt (e.X, e.Y) as FileViewListViewItem;
2634                         
2635                         if (item != null) {
2636                                 int currentItemIndex = item.Index;
2637                                 
2638                                 if (currentItemIndex != oldItemIndexForToolTip) {
2639                                         oldItemIndexForToolTip = currentItemIndex;
2640                                         
2641                                         if (toolTip != null && toolTip.Active)
2642                                                 toolTip.Active = false;
2643                                         
2644                                         FSEntry fsEntry = item.FSEntry;
2645                                         
2646                                         string output = String.Empty;
2647                                         
2648                                         if (fsEntry.FileType == FSEntry.FSEntryType.Directory)
2649                                                 output = "Directory: " + fsEntry.FullName;
2650                                         else if (fsEntry.FileType == FSEntry.FSEntryType.Device)
2651                                                 output = "Device: "+ fsEntry.FullName;
2652                                         else if (fsEntry.FileType == FSEntry.FSEntryType.Network)
2653                                                 output = "Network: " + fsEntry.FullName;
2654                                         else
2655                                                 output = "File: " + fsEntry.FullName;
2656                                         
2657                                         toolTip.SetToolTip (this, output);      
2658                                         
2659                                         toolTip.Active = true;
2660                                 }
2661                         } else
2662                                 toolTip.Active = false;
2663                         
2664                         base.OnMouseMove (e);
2665                 }
2666                 
2667                 void OnClickContextMenu (object sender, EventArgs e)
2668                 {
2669                         MenuItem senderMenuItem = sender as MenuItem;
2670                         
2671                         if (senderMenuItem == showHiddenFilesMenuItem) {
2672                                 senderMenuItem.Checked = !senderMenuItem.Checked;
2673                                 showHiddenFiles = senderMenuItem.Checked;
2674                                 UpdateFileView ();
2675                         }
2676                 }
2677                 
2678                 void OnClickViewMenuSubItem (object sender, EventArgs e)
2679                 {
2680                         MenuItem senderMenuItem = (MenuItem)sender;
2681                         
2682                         UpdateMenuItems (senderMenuItem);
2683                         
2684                         // update me
2685                         
2686                         switch (senderMenuItem.Index) {
2687                                 case 0:
2688                                         View = View.SmallIcon;
2689                                         break;
2690                                 case 1:
2691                                         View = View.LargeIcon;
2692                                         break;
2693                                 case 2:
2694                                         View = View.LargeIcon;
2695                                         break;
2696                                 case 3:
2697                                         View = View.List;
2698                                         break;
2699                                 case 4:
2700                                         View = View.Details;
2701                                         break;
2702                                 default:
2703                                         break;
2704                         }
2705                 }
2706
2707                 protected override void OnBeforeLabelEdit (LabelEditEventArgs e)
2708                 {
2709                         FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem;
2710                         FSEntry fsEntry = listViewItem.FSEntry;
2711
2712                         // only allow editing of files or directories
2713                         if (fsEntry.FileType != FSEntry.FSEntryType.Directory &&
2714                                 fsEntry.FileType != FSEntry.FSEntryType.File)
2715                                 e.CancelEdit = true;
2716
2717                         base.OnBeforeLabelEdit (e);
2718                 }
2719
2720                 protected override void OnAfterLabelEdit (LabelEditEventArgs e)
2721                 {
2722                         base.OnAfterLabelEdit (e);
2723
2724                         // no changes were made
2725                         if (e.Label == null || Items [e.Item].Text == e.Label)
2726                                 return;
2727
2728                         FileViewListViewItem listViewItem = SelectedItems [0] as FileViewListViewItem;
2729                         FSEntry fsEntry = listViewItem.FSEntry;
2730
2731                         string folder = (currentFolderFSEntry.RealName != null) ?
2732                                 currentFolderFSEntry.RealName : currentFolder;
2733
2734                         switch (fsEntry.FileType) {
2735                         case FSEntry.FSEntryType.Directory:
2736                                 string sourceDir = (fsEntry.RealName != null) ? fsEntry.RealName : fsEntry.FullName;
2737                                 string destDir = Path.Combine (folder, e.Label);
2738                                 if (!vfs.MoveFolder (sourceDir, destDir)) {
2739                                         e.CancelEdit = true;
2740                                 } else {
2741                                         if (fsEntry.RealName != null)
2742                                                 fsEntry.RealName = destDir;
2743                                         else
2744                                                 fsEntry.FullName = destDir;
2745                                 }
2746                                 break;
2747                         case FSEntry.FSEntryType.File:
2748                                 string sourceFile = (fsEntry.RealName != null) ? fsEntry.RealName : fsEntry.FullName;
2749                                 string destFile = Path.Combine (folder, e.Label);
2750                                 if (!vfs.MoveFile (sourceFile, destFile)) {
2751                                         e.CancelEdit = true;
2752                                 } else {
2753                                         if (fsEntry.RealName != null)
2754                                                 fsEntry.RealName = destFile;
2755                                         else
2756                                                 fsEntry.FullName = destFile;
2757                                 }
2758                                 break;
2759                         }
2760                 }
2761
2762                 private void UpdateMenuItems (MenuItem senderMenuItem)
2763                 {
2764                         menuItemView.MenuItems [previousCheckedMenuItemIndex].Checked = false;
2765                         menuItemView.MenuItems [senderMenuItem.Index].Checked = true;
2766                         
2767                         foreach (MenuItem[] items in viewMenuItemClones) {
2768                                 items [previousCheckedMenuItemIndex].Checked = false;
2769                                 items [senderMenuItem.Index].Checked = true;
2770                         }
2771                         
2772                         previousCheckedMenuItemIndex = senderMenuItem.Index;
2773                 }
2774                 
2775                 void OnClickNewFolderMenuItem (object sender, EventArgs e)
2776                 {
2777                         CreateNewFolder ();
2778                 }
2779                 
2780                 static object MSelectedFileChangedEvent = new object ();
2781                 static object MSelectedFilesChangedEvent = new object ();
2782                 static object MDirectoryChangedEvent = new object ();
2783                 static object MForceDialogEndEvent = new object ();
2784                 
2785                 public event EventHandler SelectedFileChanged {
2786                         add { Events.AddHandler (MSelectedFileChangedEvent, value); }
2787                         remove { Events.RemoveHandler (MSelectedFileChangedEvent, value); }
2788                 }
2789                 
2790                 public event EventHandler SelectedFilesChanged {
2791                         add { Events.AddHandler (MSelectedFilesChangedEvent, value); }
2792                         remove { Events.RemoveHandler (MSelectedFilesChangedEvent, value); }
2793                 }
2794                 
2795                 public event EventHandler DirectoryChanged {
2796                         add { Events.AddHandler (MDirectoryChangedEvent, value); }
2797                         remove { Events.RemoveHandler (MDirectoryChangedEvent, value); }
2798                 }
2799                 
2800                 public event EventHandler ForceDialogEnd {
2801                         add { Events.AddHandler (MForceDialogEndEvent, value); }
2802                         remove { Events.RemoveHandler (MForceDialogEndEvent, value); }
2803                 }
2804         }
2805         #endregion
2806         
2807         #region FileListViewItem
2808         internal class FileViewListViewItem : ListViewItem
2809         {
2810                 private FSEntry fsEntry;
2811                 
2812                 public FileViewListViewItem (FSEntry fsEntry)
2813                 {
2814                         this.fsEntry = fsEntry;
2815                         
2816                         ImageIndex = fsEntry.IconIndex;
2817                         
2818                         Text = fsEntry.Name;
2819                         
2820                         switch (fsEntry.FileType) {
2821                                 case FSEntry.FSEntryType.Directory:
2822                                         SubItems.Add (String.Empty);
2823                                         SubItems.Add ("Directory");
2824                                         SubItems.Add (fsEntry.LastAccessTime.ToShortDateString () + " " + fsEntry.LastAccessTime.ToShortTimeString ()); 
2825                                         break;
2826                                 case FSEntry.FSEntryType.File:
2827                                         long fileLen = 1;
2828                                         try {
2829                                                 if (fsEntry.FileSize > 1024)
2830                                                         fileLen = fsEntry.FileSize / 1024;
2831                                         } catch (Exception) {
2832                                                 fileLen = 1;
2833                                         }
2834                                         
2835                                         SubItems.Add (fileLen.ToString () + " KB");
2836                                         SubItems.Add ("File");
2837                                         SubItems.Add (fsEntry.LastAccessTime.ToShortDateString () + " " + fsEntry.LastAccessTime.ToShortTimeString ()); 
2838                                         break;
2839                                 case FSEntry.FSEntryType.Device:
2840                                         SubItems.Add (String.Empty);
2841                                         SubItems.Add ("Device");
2842                                         SubItems.Add (fsEntry.LastAccessTime.ToShortDateString () + " " + fsEntry.LastAccessTime.ToShortTimeString ()); 
2843                                         break;
2844                                 case FSEntry.FSEntryType.RemovableDevice:
2845                                         SubItems.Add (String.Empty);
2846                                         SubItems.Add ("RemovableDevice");
2847                                         SubItems.Add (fsEntry.LastAccessTime.ToShortDateString () + " " + fsEntry.LastAccessTime.ToShortTimeString ()); 
2848                                         break;
2849                                 default:
2850                                         break;
2851                         }
2852                 }
2853                 
2854                 public FSEntry FSEntry {
2855                         set {
2856                                 fsEntry = value;
2857                         }
2858                         
2859                         get {
2860                                 return fsEntry;
2861                         }
2862                 }
2863         }
2864         #endregion
2865         
2866         #region IUpdateFolder
2867         internal interface IUpdateFolder
2868         {
2869                 string CurrentFolder {get; set;}
2870         }
2871         #endregion
2872         
2873         #region TextEntryDialog
2874         // FIXME: When ListView.LabelEdit is implemented remove me
2875         internal class TextEntryDialog : Form
2876         {
2877                 private Label label1;
2878                 private Button okButton;
2879                 private TextBox newNameTextBox;
2880                 private PictureBox iconPictureBox;
2881                 private Button cancelButton;
2882                 private GroupBox groupBox1;
2883                 
2884                 public TextEntryDialog ()
2885                 {
2886                         groupBox1 = new GroupBox ();
2887                         cancelButton = new Button ();
2888                         iconPictureBox = new PictureBox ();
2889                         newNameTextBox = new TextBox ();
2890                         okButton = new Button ();
2891                         label1 = new Label ();
2892                         groupBox1.SuspendLayout ();
2893                         SuspendLayout ();
2894                         
2895                         // groupBox1
2896                         groupBox1.Controls.Add (newNameTextBox);
2897                         groupBox1.Controls.Add (label1);
2898                         groupBox1.Controls.Add (iconPictureBox);
2899                         groupBox1.Location = new Point (8, 8);
2900                         groupBox1.Size = new Size (232, 160);
2901                         groupBox1.TabIndex = 5;
2902                         groupBox1.TabStop = false;
2903                         groupBox1.Text = "New Name";
2904                         
2905                         // cancelButton
2906                         cancelButton.DialogResult = DialogResult.Cancel;
2907                         cancelButton.Location = new Point (168, 176);
2908                         cancelButton.TabIndex = 4;
2909                         cancelButton.Text = "Cancel";
2910                         
2911                         // iconPictureBox
2912                         iconPictureBox.BorderStyle = BorderStyle.Fixed3D;
2913                         iconPictureBox.Location = new Point (86, 24);
2914                         iconPictureBox.Size = new Size (60, 60);
2915                         iconPictureBox.TabIndex = 3;
2916                         iconPictureBox.TabStop = false;
2917                         iconPictureBox.SizeMode = PictureBoxSizeMode.CenterImage;
2918                         
2919                         // newNameTextBox
2920                         newNameTextBox.Location = new Point (16, 128);
2921                         newNameTextBox.Size = new Size (200, 20);
2922                         newNameTextBox.TabIndex = 5;
2923                         newNameTextBox.Text = String.Empty;
2924                         
2925                         // okButton
2926                         okButton.DialogResult = DialogResult.OK;
2927                         okButton.Location = new Point (80, 176);
2928                         okButton.TabIndex = 3;
2929                         okButton.Text = "OK";
2930                         
2931                         // label1
2932                         label1.Location = new Point (16, 96);
2933                         label1.Size = new Size (200, 23);
2934                         label1.TabIndex = 4;
2935                         label1.Text = "Enter Name:";
2936                         label1.TextAlign = ContentAlignment.MiddleCenter;
2937                         
2938                         // MainForm
2939                         AcceptButton = okButton;
2940                         AutoScaleBaseSize = new Size (5, 13);
2941                         CancelButton = cancelButton;
2942                         ClientSize = new Size (248, 205);
2943                         Controls.Add (groupBox1);
2944                         Controls.Add (cancelButton);
2945                         Controls.Add (okButton);
2946                         FormBorderStyle = FormBorderStyle.FixedDialog;
2947                         Text = "New Folder or File";
2948                         groupBox1.ResumeLayout (false);
2949                         ResumeLayout (false);
2950                         
2951                         newNameTextBox.Select ();
2952                 }
2953                 
2954                 public Image IconPictureBoxImage {
2955                         set {
2956                                 iconPictureBox.Image = value;
2957                         }
2958                 }
2959                 
2960                 public string FileName {
2961                         get {
2962                                 return newNameTextBox.Text;
2963                         }
2964                         set {
2965                                 newNameTextBox.Text = value;
2966                         }
2967                 }
2968         }
2969         #endregion
2970         
2971         #region MWFVFS  
2972         internal class MWFVFS
2973         {
2974                 private FileSystem fileSystem;
2975                 
2976                 private int platform = (int) Environment.OSVersion.Platform;
2977                 
2978                 public static readonly string DesktopPrefix = "Desktop://";
2979                 public static readonly string PersonalPrefix = "Personal://";
2980                 public static readonly string MyComputerPrefix = "MyComputer://";
2981                 public static readonly string RecentlyUsedPrefix = "RecentlyUsed://";
2982                 public static readonly string MyNetworkPrefix = "MyNetwork://";
2983                 public static readonly string MyComputerPersonalPrefix = "MyComputerPersonal://";
2984                 
2985                 public static Hashtable MyComputerDevicesPrefix = new Hashtable ();
2986                 
2987                 public delegate void UpdateDelegate (ArrayList folders, ArrayList files);
2988                 private UpdateDelegate updateDelegate;
2989                 private Control calling_control;
2990                 
2991                 private ThreadStart get_folder_content_thread_start;
2992                 private Thread worker;
2993                 private WorkerThread workerThread = null;
2994                 private StringCollection the_filters;
2995                 
2996                 public MWFVFS ()
2997                 {
2998                         if ((platform == 4) || (platform == 128)) {
2999                                 fileSystem = new UnixFileSystem ();
3000                         } else {
3001                                 fileSystem = new WinFileSystem ();
3002                         }
3003                 }
3004                 
3005                 public FSEntry ChangeDirectory (string folder)
3006                 {
3007                         return fileSystem.ChangeDirectory (folder);
3008                 }
3009                 
3010                 public void GetFolderContent ()
3011                 {
3012                         GetFolderContent (null);
3013                 }
3014                 
3015                 public void GetFolderContent (StringCollection filters)
3016                 {
3017                         the_filters = filters;
3018
3019                         if (workerThread != null) {
3020                                 workerThread.Stop ();
3021                                 workerThread = null;
3022                         }
3023
3024                         // Added next line to ensure the control is created before BeginInvoke is called on it
3025                         calling_control.CreateControl();
3026                         workerThread = new WorkerThread (fileSystem, the_filters, updateDelegate, calling_control);
3027                         
3028                         get_folder_content_thread_start = new ThreadStart (workerThread.GetFolderContentThread);
3029                         worker = new Thread (get_folder_content_thread_start);
3030                         worker.IsBackground = true;
3031                         worker.Start();
3032                 }
3033                 
3034                 internal class WorkerThread
3035                 {
3036                         private FileSystem fileSystem;
3037                         private StringCollection the_filters;
3038                         private UpdateDelegate updateDelegate;
3039                         private Control calling_control;
3040                         private readonly object lockobject = new object ();
3041                         private bool stopped = false;
3042                         
3043                         public WorkerThread (FileSystem fileSystem, StringCollection the_filters, UpdateDelegate updateDelegate, Control calling_control)
3044                         {
3045                                 this.fileSystem = fileSystem;
3046                                 this.the_filters = the_filters;
3047                                 this.updateDelegate = updateDelegate;
3048                                 this.calling_control = calling_control;
3049                         }
3050                         
3051                         public void GetFolderContentThread()
3052                         {
3053                                 ArrayList folders;
3054                                 ArrayList files;
3055                                 
3056                                 fileSystem.GetFolderContent (the_filters, out folders, out files);
3057                                 
3058                                 if (stopped)
3059                                         return;
3060                                 
3061                                 if (updateDelegate != null) {
3062                                         lock (this) {
3063                                                 object[] objectArray = new object[2];
3064                                                 
3065                                                 objectArray[0] = folders;
3066                                                 objectArray[1] = files;
3067                                                 
3068                                                 calling_control.BeginInvoke (updateDelegate, objectArray);
3069                                         }
3070                                 }
3071                         }
3072                         
3073                         public void Stop ()
3074                         {
3075                                 lock (lockobject) {
3076                                         stopped = true;
3077                                 }
3078                         }
3079                 }
3080                 
3081                 public ArrayList GetFoldersOnly ()
3082                 {
3083                         return fileSystem.GetFoldersOnly ();
3084                 }
3085                 
3086                 public void WriteRecentlyUsedFiles (string filename)
3087                 {
3088                         fileSystem.WriteRecentlyUsedFiles (filename);
3089                 }
3090                 
3091                 public ArrayList GetRecentlyUsedFiles ()
3092                 {
3093                         return fileSystem.GetRecentlyUsedFiles ();
3094                 }
3095                 
3096                 public ArrayList GetMyComputerContent ()
3097                 {
3098                         return fileSystem.GetMyComputerContent ();
3099                 }
3100                 
3101                 public ArrayList GetMyNetworkContent ()
3102                 {
3103                         return fileSystem.GetMyNetworkContent ();
3104                 }
3105                 
3106                 public bool CreateFolder (string new_folder)
3107                 {
3108                         try {
3109                                 if (Directory.Exists (new_folder)) {
3110                                         string message = "Folder \"" + new_folder + "\" already exists.";
3111                                         MessageBox.Show (message, new_folder, MessageBoxButtons.OK,
3112                                                 MessageBoxIcon.Error);
3113                                         return false;
3114                                 } else
3115                                         Directory.CreateDirectory (new_folder);
3116                         } catch (Exception e) {
3117                                 MessageBox.Show (e.Message, new_folder, MessageBoxButtons.OK, MessageBoxIcon.Error);
3118                                 return false;
3119                         }
3120                         
3121                         return true;
3122                 }
3123
3124                 public bool MoveFolder (string sourceDirName, string destDirName)
3125                 {
3126                         try {
3127                                 if (Directory.Exists (destDirName)) {
3128                                         string message = "Cannot rename " + Path.GetFileName (sourceDirName)
3129                                                 + ": A folder with the name you specified already exists."
3130                                                 + " Specify a different folder name.";
3131                                         MessageBox.Show (message, "Error Renaming Folder", MessageBoxButtons.OK,
3132                                                 MessageBoxIcon.Error);
3133                                         return false;
3134                                 } else
3135                                         Directory.Move (sourceDirName, destDirName);
3136                         } catch (Exception e) {
3137                                 MessageBox.Show (e.Message, "Error Renaming Folder", 
3138                                         MessageBoxButtons.OK, MessageBoxIcon.Error);
3139                                 return false;
3140                         }
3141
3142                         return true;
3143                 }
3144
3145                 public bool MoveFile (string sourceFileName, string destFileName)
3146                 {
3147                         try {
3148                                 if (File.Exists (destFileName)) {
3149                                         string message = "Cannot rename " + Path.GetFileName (sourceFileName)
3150                                                 + ": A file with the name you specified already exists."
3151                                                 + " Specify a different file name.";
3152                                         MessageBox.Show (message, "Error Renaming File",
3153                                                 MessageBoxButtons.OK, MessageBoxIcon.Error);
3154                                         return false;
3155                                 } else
3156                                         File.Move (sourceFileName, destFileName);
3157                         } catch (Exception e) {
3158                                 MessageBox.Show (e.Message, "Error Renaming Folder",
3159                                         MessageBoxButtons.OK, MessageBoxIcon.Error);
3160                                 return false;
3161                         }
3162
3163                         return true;
3164                 }
3165
3166                 public string GetParent ()
3167                 {
3168                         return fileSystem.GetParent ();
3169                 }
3170                 
3171                 public void RegisterUpdateDelegate(UpdateDelegate updateDelegate, Control control)
3172                 {
3173                         this.updateDelegate = updateDelegate;
3174                         calling_control = control;
3175                 }
3176         }
3177         #endregion
3178         
3179         #region FileSystem
3180         internal abstract class FileSystem
3181         {
3182                 protected string currentTopFolder = String.Empty;
3183                 protected FSEntry currentFolderFSEntry = null;
3184                 protected FSEntry currentTopFolderFSEntry = null;
3185                 private FileInfoComparer fileInfoComparer = new FileInfoComparer ();
3186                 
3187                 public FSEntry ChangeDirectory (string folder)
3188                 {
3189                         if (folder == MWFVFS.DesktopPrefix) {
3190                                 currentTopFolder = MWFVFS.DesktopPrefix;
3191                                 currentTopFolderFSEntry = currentFolderFSEntry = GetDesktopFSEntry ();
3192                         } else
3193                         if (folder == MWFVFS.PersonalPrefix) {
3194                                 currentTopFolder = MWFVFS.PersonalPrefix;
3195                                 currentTopFolderFSEntry = currentFolderFSEntry = GetPersonalFSEntry ();
3196                         } else
3197                         if (folder == MWFVFS.MyComputerPersonalPrefix) {
3198                                 currentTopFolder = MWFVFS.MyComputerPersonalPrefix;
3199                                 currentTopFolderFSEntry = currentFolderFSEntry = GetMyComputerPersonalFSEntry ();
3200                         } else
3201                         if (folder == MWFVFS.RecentlyUsedPrefix) {
3202                                 currentTopFolder = MWFVFS.RecentlyUsedPrefix;
3203                                 currentTopFolderFSEntry = currentFolderFSEntry = GetRecentlyUsedFSEntry ();
3204                         } else
3205                         if (folder == MWFVFS.MyComputerPrefix) {
3206                                 currentTopFolder = MWFVFS.MyComputerPrefix;
3207                                 currentTopFolderFSEntry = currentFolderFSEntry = GetMyComputerFSEntry ();
3208                         } else
3209                         if (folder == MWFVFS.MyNetworkPrefix) {
3210                                 currentTopFolder = MWFVFS.MyNetworkPrefix;
3211                                 currentTopFolderFSEntry = currentFolderFSEntry = GetMyNetworkFSEntry ();
3212                         } else {
3213                                 bool found = false;
3214                                 
3215                                 foreach (DictionaryEntry entry in MWFVFS.MyComputerDevicesPrefix) {
3216                                         FSEntry fsEntry = entry.Value as FSEntry;
3217                                         if (folder == fsEntry.FullName) {
3218                                                 currentTopFolder = entry.Key as string;
3219                                                 currentTopFolderFSEntry = currentFolderFSEntry = fsEntry;
3220                                                 found = true;
3221                                                 break;
3222                                         }
3223                                 }
3224                                 
3225                                 if (!found) {
3226                                         currentFolderFSEntry = GetDirectoryFSEntry (new DirectoryInfo (folder), currentTopFolderFSEntry);
3227                                 }
3228                         }
3229                         
3230                         return currentFolderFSEntry;
3231                 }
3232                 
3233                 public string GetParent ()
3234                 {
3235                         return currentFolderFSEntry.Parent;
3236                 }
3237                 
3238                 // directories_out and files_out contain FSEntry objects
3239                 public void GetFolderContent (StringCollection filters, out ArrayList directories_out, out ArrayList files_out)
3240                 {
3241                         directories_out = new ArrayList ();
3242                         files_out = new ArrayList ();
3243                         
3244                         if (currentFolderFSEntry.FullName == MWFVFS.DesktopPrefix) {
3245                                 FSEntry personalFSEntry = GetPersonalFSEntry ();
3246                                 
3247                                 directories_out.Add (personalFSEntry);
3248                                 
3249                                 FSEntry myComputerFSEntry = GetMyComputerFSEntry ();
3250                                 
3251                                 directories_out.Add (myComputerFSEntry);
3252                                 
3253                                 FSEntry myNetworkFSEntry = GetMyNetworkFSEntry ();
3254                                 
3255                                 directories_out.Add (myNetworkFSEntry);
3256                                 
3257                                 ArrayList d_out = null;
3258                                 ArrayList f_out = null;
3259                                 GetNormalFolderContent (ThemeEngine.Current.Places (UIIcon.PlacesDesktop), filters, out d_out, out f_out);
3260                                 directories_out.AddRange (d_out);
3261                                 files_out.AddRange (f_out);
3262                                 
3263                         } else
3264                         if (currentFolderFSEntry.FullName == MWFVFS.RecentlyUsedPrefix) {
3265                                 files_out = GetRecentlyUsedFiles ();
3266                         } else
3267                         if (currentFolderFSEntry.FullName == MWFVFS.MyComputerPrefix) {
3268                                 directories_out.AddRange (GetMyComputerContent ());
3269                         } else
3270                         if (currentFolderFSEntry.FullName == MWFVFS.PersonalPrefix || currentFolderFSEntry.FullName == MWFVFS.MyComputerPersonalPrefix) {
3271                                 ArrayList d_out = null;
3272                                 ArrayList f_out = null;
3273                                 GetNormalFolderContent (ThemeEngine.Current.Places (UIIcon.PlacesPersonal), filters, out d_out, out f_out);
3274                                 directories_out.AddRange (d_out);
3275                                 files_out.AddRange (f_out);
3276                         } else
3277                         if (currentFolderFSEntry.FullName == MWFVFS.MyNetworkPrefix) {
3278                                 directories_out.AddRange (GetMyNetworkContent ());
3279                         } else {
3280                                 GetNormalFolderContent (currentFolderFSEntry.FullName, filters, out directories_out, out files_out);
3281                         }
3282                 }
3283                 
3284                 public ArrayList GetFoldersOnly ()
3285                 {
3286                         ArrayList directories_out = new ArrayList ();
3287                         
3288                         if (currentFolderFSEntry.FullName == MWFVFS.DesktopPrefix) {
3289                                 FSEntry personalFSEntry = GetPersonalFSEntry ();
3290                                 
3291                                 directories_out.Add (personalFSEntry);
3292                                 
3293                                 FSEntry myComputerFSEntry = GetMyComputerFSEntry ();
3294                                 
3295                                 directories_out.Add (myComputerFSEntry);
3296                                 
3297                                 FSEntry myNetworkFSEntry = GetMyNetworkFSEntry ();
3298                                 
3299                                 directories_out.Add (myNetworkFSEntry);
3300                                 
3301                                 ArrayList d_out = GetNormalFolders (ThemeEngine.Current.Places (UIIcon.PlacesDesktop));
3302                                 directories_out.AddRange (d_out);
3303                                 
3304                         } else
3305                         if (currentFolderFSEntry.FullName == MWFVFS.RecentlyUsedPrefix) {
3306                                 //files_out = GetRecentlyUsedFiles ();
3307                         } else
3308                         if (currentFolderFSEntry.FullName == MWFVFS.MyComputerPrefix) {
3309                                 directories_out.AddRange (GetMyComputerContent ());
3310                         } else
3311                         if (currentFolderFSEntry.FullName == MWFVFS.PersonalPrefix || currentFolderFSEntry.FullName == MWFVFS.MyComputerPersonalPrefix) {
3312                                 ArrayList d_out = GetNormalFolders (ThemeEngine.Current.Places (UIIcon.PlacesPersonal));
3313                                 directories_out.AddRange (d_out);
3314                         } else
3315                         if (currentFolderFSEntry.FullName == MWFVFS.MyNetworkPrefix) {
3316                                 directories_out.AddRange (GetMyNetworkContent ());
3317                         } else {
3318                                 directories_out = GetNormalFolders (currentFolderFSEntry.FullName);
3319                         }
3320                         return directories_out;
3321                 }
3322                 
3323                 protected void GetNormalFolderContent (string from_folder, StringCollection filters, out ArrayList directories_out, out ArrayList files_out)
3324                 {
3325                         DirectoryInfo dirinfo = new DirectoryInfo (from_folder);
3326                         
3327                         directories_out = new ArrayList ();
3328                         
3329                         DirectoryInfo[] dirs = null;
3330                         
3331                         try {
3332                                 dirs = dirinfo.GetDirectories ();
3333                         } catch (Exception) {}
3334                         
3335                         if (dirs != null)
3336                                 for (int i = 0; i < dirs.Length; i++) {
3337                                         directories_out.Add (GetDirectoryFSEntry (dirs [i], currentTopFolderFSEntry));
3338                                 }
3339                         
3340                         files_out = new ArrayList ();
3341                         
3342                         ArrayList files = new ArrayList ();
3343                         
3344                         try {
3345                                 if (filters == null) {
3346                                         files.AddRange (dirinfo.GetFiles ());
3347                                 } else {
3348                                         foreach (string s in filters)
3349                                                 files.AddRange (dirinfo.GetFiles (s));
3350                                         
3351                                         files.Sort (fileInfoComparer);
3352                                 }
3353                         } catch (Exception) {}
3354                         
3355                         for (int i = 0; i < files.Count; i++) {
3356                                 FSEntry fs = GetFileFSEntry (files [i] as FileInfo);
3357                                 if (fs != null)
3358                                         files_out.Add (fs);
3359                         }
3360                 }
3361                 
3362                 protected ArrayList GetNormalFolders (string from_folder)
3363                 {
3364                         DirectoryInfo dirinfo = new DirectoryInfo (from_folder);
3365                         
3366                         ArrayList directories_out = new ArrayList ();
3367                         
3368                         DirectoryInfo[] dirs = null;
3369                         
3370                         try {
3371                                 dirs = dirinfo.GetDirectories ();
3372                         } catch (Exception) {}
3373                         
3374                         if (dirs != null)
3375                                 for (int i = 0; i < dirs.Length; i++) {
3376                                         directories_out.Add (GetDirectoryFSEntry (dirs [i], currentTopFolderFSEntry));
3377                                 }
3378                         
3379                         return directories_out;
3380                 }
3381                 
3382                 protected virtual FSEntry GetDirectoryFSEntry (DirectoryInfo dirinfo, FSEntry topFolderFSEntry)
3383                 {
3384                         FSEntry fs = new FSEntry ();
3385                         
3386                         fs.Attributes = dirinfo.Attributes;
3387                         fs.FullName = dirinfo.FullName;
3388                         fs.Name = dirinfo.Name;
3389                         fs.MainTopNode = topFolderFSEntry;
3390                         fs.FileType = FSEntry.FSEntryType.Directory;
3391                         fs.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("inode/directory");
3392                         fs.LastAccessTime = dirinfo.LastAccessTime;
3393                         
3394                         return fs;
3395                 }
3396                 
3397                 protected virtual FSEntry GetFileFSEntry (FileInfo fileinfo)
3398                 {
3399                         // *sigh* FileInfo gives us no usable information for links to directories
3400                         // so, return null
3401                         if ((fileinfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
3402                                 return null;
3403                         
3404                         FSEntry fs = new FSEntry ();
3405                         
3406                         fs.Attributes = fileinfo.Attributes;
3407                         fs.FullName = fileinfo.FullName;
3408                         fs.Name = fileinfo.Name;
3409                         fs.FileType = FSEntry.FSEntryType.File;
3410                         fs.IconIndex = MimeIconEngine.GetIconIndexForFile (fileinfo.FullName);
3411                         fs.FileSize = fileinfo.Length;
3412                         fs.LastAccessTime = fileinfo.LastAccessTime;
3413                         
3414                         return fs;
3415                 }
3416                 
3417                 internal class FileInfoComparer : IComparer
3418                 {
3419                         public int Compare (object fileInfo1, object fileInfo2)
3420                         {
3421                                 return String.Compare (((FileInfo)fileInfo1).Name, ((FileInfo)fileInfo2).Name);
3422                         }
3423                 }
3424                 
3425                 protected abstract FSEntry GetDesktopFSEntry ();
3426                 
3427                 protected abstract FSEntry GetRecentlyUsedFSEntry ();
3428                 
3429                 protected abstract FSEntry GetPersonalFSEntry ();
3430                 
3431                 protected abstract FSEntry GetMyComputerPersonalFSEntry ();
3432                 
3433                 protected abstract FSEntry GetMyComputerFSEntry ();
3434                 
3435                 protected abstract FSEntry GetMyNetworkFSEntry ();
3436                 
3437                 public abstract void WriteRecentlyUsedFiles (string fileToAdd);
3438                 
3439                 public abstract ArrayList GetRecentlyUsedFiles ();
3440                 
3441                 public abstract ArrayList GetMyComputerContent ();
3442                 
3443                 public abstract ArrayList GetMyNetworkContent ();
3444         }
3445         #endregion
3446         
3447         #region UnixFileSystem
3448         internal class UnixFileSystem : FileSystem
3449         {
3450                 private MasterMount masterMount = new MasterMount ();
3451                 private FSEntry desktopFSEntry = null;
3452                 private FSEntry recentlyusedFSEntry = null;
3453                 private FSEntry personalFSEntry = null;
3454                 private FSEntry mycomputerpersonalFSEntry = null;
3455                 private FSEntry mycomputerFSEntry = null;
3456                 private FSEntry mynetworkFSEntry = null;
3457                 
3458                 private string personal_folder;
3459                 private string recently_used_path;
3460                 private string full_kde_recent_document_dir;
3461                 
3462                 public UnixFileSystem ()
3463                 {
3464                         personal_folder = ThemeEngine.Current.Places (UIIcon.PlacesPersonal);
3465                         recently_used_path = Path.Combine (personal_folder, ".recently-used");
3466                         
3467                         full_kde_recent_document_dir = personal_folder + "/.kde/share/apps/RecentDocuments";
3468                         
3469                         desktopFSEntry = new FSEntry ();
3470                         
3471                         desktopFSEntry.Attributes = FileAttributes.Directory;
3472                         desktopFSEntry.FullName = MWFVFS.DesktopPrefix;
3473                         desktopFSEntry.Name = "Desktop";
3474                         desktopFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesDesktop);
3475                         desktopFSEntry.FileType = FSEntry.FSEntryType.Directory;
3476                         desktopFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("desktop/desktop");
3477                         desktopFSEntry.LastAccessTime = DateTime.Now;
3478                         
3479                         recentlyusedFSEntry = new FSEntry ();
3480                         
3481                         recentlyusedFSEntry.Attributes = FileAttributes.Directory;
3482                         recentlyusedFSEntry.FullName = MWFVFS.RecentlyUsedPrefix;
3483                         recentlyusedFSEntry.Name = "Recently Used";
3484                         recentlyusedFSEntry.FileType = FSEntry.FSEntryType.Directory;
3485                         recentlyusedFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("recently/recently");
3486                         recentlyusedFSEntry.LastAccessTime = DateTime.Now;
3487                         
3488                         personalFSEntry = new FSEntry ();
3489                         
3490                         personalFSEntry.Attributes = FileAttributes.Directory;
3491                         personalFSEntry.FullName = MWFVFS.PersonalPrefix;
3492                         personalFSEntry.Name = "Personal";
3493                         personalFSEntry.MainTopNode = GetDesktopFSEntry ();
3494                         personalFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesPersonal);
3495                         personalFSEntry.FileType = FSEntry.FSEntryType.Directory;
3496                         personalFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("directory/home");
3497                         personalFSEntry.LastAccessTime = DateTime.Now;
3498                         
3499                         mycomputerpersonalFSEntry = new FSEntry ();
3500                         
3501                         mycomputerpersonalFSEntry.Attributes = FileAttributes.Directory;
3502                         mycomputerpersonalFSEntry.FullName = MWFVFS.MyComputerPersonalPrefix;
3503                         mycomputerpersonalFSEntry.Name = "Personal";
3504                         mycomputerpersonalFSEntry.MainTopNode = GetMyComputerFSEntry ();
3505                         mycomputerpersonalFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesPersonal);
3506                         mycomputerpersonalFSEntry.FileType = FSEntry.FSEntryType.Directory;
3507                         mycomputerpersonalFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("directory/home");
3508                         mycomputerpersonalFSEntry.LastAccessTime = DateTime.Now;
3509                         
3510                         mycomputerFSEntry = new FSEntry ();
3511                         
3512                         mycomputerFSEntry.Attributes = FileAttributes.Directory;
3513                         mycomputerFSEntry.FullName = MWFVFS.MyComputerPrefix;
3514                         mycomputerFSEntry.Name = "My Computer";
3515                         mycomputerFSEntry.MainTopNode = GetDesktopFSEntry ();
3516                         mycomputerFSEntry.FileType = FSEntry.FSEntryType.Directory;
3517                         mycomputerFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("workplace/workplace");
3518                         mycomputerFSEntry.LastAccessTime = DateTime.Now;
3519                         
3520                         mynetworkFSEntry = new FSEntry ();
3521                         
3522                         mynetworkFSEntry.Attributes = FileAttributes.Directory;
3523                         mynetworkFSEntry.FullName = MWFVFS.MyNetworkPrefix;
3524                         mynetworkFSEntry.Name = "My Network";
3525                         mynetworkFSEntry.MainTopNode = GetDesktopFSEntry ();
3526                         mynetworkFSEntry.FileType = FSEntry.FSEntryType.Directory;
3527                         mynetworkFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("network/network");
3528                         mynetworkFSEntry.LastAccessTime = DateTime.Now;
3529                 }
3530                 
3531                 public override void WriteRecentlyUsedFiles (string fileToAdd)
3532                 {
3533                         if (File.Exists (recently_used_path) && new FileInfo (recently_used_path).Length > 0) {
3534                                 XmlDocument xml_doc = new XmlDocument ();
3535                                 xml_doc.Load (recently_used_path);
3536                                 
3537                                 XmlNode grand_parent_node = xml_doc.SelectSingleNode ("RecentFiles");
3538                                 
3539                                 if (grand_parent_node != null) {
3540                                         // create a new element
3541                                         XmlElement new_recent_item_node = xml_doc.CreateElement ("RecentItem");
3542                                         
3543                                         XmlElement new_child = xml_doc.CreateElement ("URI");
3544                                         UriBuilder ub = new UriBuilder ();
3545                                         ub.Path = fileToAdd;
3546                                         ub.Host = null;
3547                                         ub.Scheme = "file";
3548                                         XmlText new_text_child = xml_doc.CreateTextNode (ub.ToString ());
3549                                         new_child.AppendChild (new_text_child);
3550                                         
3551                                         new_recent_item_node.AppendChild (new_child);
3552                                         
3553                                         new_child = xml_doc.CreateElement ("Mime-Type");
3554                                         new_text_child = xml_doc.CreateTextNode (Mime.GetMimeTypeForFile (fileToAdd));
3555                                         new_child.AppendChild (new_text_child);
3556                                         
3557                                         new_recent_item_node.AppendChild (new_child);
3558                                         
3559                                         new_child = xml_doc.CreateElement ("Timestamp");
3560                                         long seconds = (long)(DateTime.UtcNow - new DateTime (1970, 1, 1)).TotalSeconds;
3561                                         new_text_child = xml_doc.CreateTextNode (seconds.ToString ());
3562                                         new_child.AppendChild (new_text_child);
3563                                         
3564                                         new_recent_item_node.AppendChild (new_child);
3565                                         
3566                                         new_child = xml_doc.CreateElement ("Groups");
3567                                         
3568                                         new_recent_item_node.AppendChild (new_child);
3569                                         
3570                                         // now search the nodes in grand_parent_node for another instance of the new uri and if found remove it
3571                                         // so that the new node is the first one
3572                                         foreach (XmlNode n in grand_parent_node.ChildNodes) {
3573                                                 XmlNode uri_node = n.SelectSingleNode ("URI");
3574                                                 if (uri_node != null) {
3575                                                         XmlNode uri_node_child = uri_node.FirstChild;
3576                                                         if (uri_node_child is XmlText)
3577                                                                 if (ub.ToString () == ((XmlText)uri_node_child).Data) {
3578                                                                         grand_parent_node.RemoveChild (n);
3579                                                                         break;
3580                                                                 }
3581                                                 }
3582                                         }
3583                                         
3584                                         // prepend the new recent item to the grand parent node list
3585                                         grand_parent_node.PrependChild (new_recent_item_node);
3586                                         
3587                                         // limit the # of RecentItems to 10
3588                                         if (grand_parent_node.ChildNodes.Count > 10) {
3589                                                 while (grand_parent_node.ChildNodes.Count > 10)
3590                                                         grand_parent_node.RemoveChild (grand_parent_node.LastChild);
3591                                         }
3592                                         
3593                                         try {
3594                                                 xml_doc.Save (recently_used_path);
3595                                         } catch (Exception) {
3596                                         }
3597                                 }
3598                         } else {
3599                                 XmlDocument xml_doc = new XmlDocument ();
3600                                 xml_doc.AppendChild (xml_doc.CreateXmlDeclaration ("1.0", String.Empty, String.Empty));
3601                                 
3602                                 XmlElement recentFiles_element = xml_doc.CreateElement ("RecentFiles");
3603                                 
3604                                 XmlElement new_recent_item_node = xml_doc.CreateElement ("RecentItem");
3605                                 
3606                                 XmlElement new_child = xml_doc.CreateElement ("URI");
3607                                 UriBuilder ub = new UriBuilder ();
3608                                 ub.Path = fileToAdd;
3609                                 ub.Host = null;
3610                                 ub.Scheme = "file";
3611                                 XmlText new_text_child = xml_doc.CreateTextNode (ub.ToString ());
3612                                 new_child.AppendChild (new_text_child);
3613                                 
3614                                 new_recent_item_node.AppendChild (new_child);
3615                                 
3616                                 new_child = xml_doc.CreateElement ("Mime-Type");
3617                                 new_text_child = xml_doc.CreateTextNode (Mime.GetMimeTypeForFile (fileToAdd));
3618                                 new_child.AppendChild (new_text_child);
3619                                 
3620                                 new_recent_item_node.AppendChild (new_child);
3621                                 
3622                                 new_child = xml_doc.CreateElement ("Timestamp");
3623                                 long seconds = (long)(DateTime.UtcNow - new DateTime (1970, 1, 1)).TotalSeconds;
3624                                 new_text_child = xml_doc.CreateTextNode (seconds.ToString ());
3625                                 new_child.AppendChild (new_text_child);
3626                                 
3627                                 new_recent_item_node.AppendChild (new_child);
3628                                 
3629                                 new_child = xml_doc.CreateElement ("Groups");
3630                                 
3631                                 new_recent_item_node.AppendChild (new_child);
3632                                 
3633                                 recentFiles_element.AppendChild (new_recent_item_node);
3634                                 
3635                                 xml_doc.AppendChild (recentFiles_element);
3636                                 
3637                                 try {
3638                                         xml_doc.Save (recently_used_path);
3639                                 } catch (Exception) {
3640                                 }
3641                         }
3642                 }
3643                 
3644                 // return an ArrayList with FSEntry objects
3645                 public override ArrayList GetRecentlyUsedFiles ()
3646                 {
3647                         // check for GNOME and KDE
3648                         
3649                         ArrayList files_al = new ArrayList ();
3650                         
3651                         // GNOME
3652                         if (File.Exists (recently_used_path)) {
3653                                 try {
3654                                         XmlTextReader xtr = new XmlTextReader (recently_used_path);
3655                                         while (xtr.Read ()) {
3656                                                 if (xtr.NodeType == XmlNodeType.Element && xtr.Name.ToUpper () == "URI") {
3657                                                         xtr.Read ();
3658                                                         Uri uri = new Uri (xtr.Value);
3659                                                         if (!files_al.Contains (uri.LocalPath))
3660                                                                 if (File.Exists (uri.LocalPath)) {
3661                                                                         FSEntry fs = GetFileFSEntry (new FileInfo (uri.LocalPath));
3662                                                                         if (fs != null)
3663                                                                                 files_al.Add (fs);
3664                                                                 }
3665                                                 }
3666                                         }
3667                                         xtr.Close ();
3668                                 } catch (Exception) {
3669                                         
3670                                 }
3671                         }
3672                         
3673                         // KDE
3674                         if (Directory.Exists (full_kde_recent_document_dir)) {
3675                                 string[] files = Directory.GetFiles (full_kde_recent_document_dir, "*.desktop");
3676                                 
3677                                 foreach (string file_name in files) {
3678                                         StreamReader sr = new StreamReader (file_name);
3679                                         
3680                                         string line = sr.ReadLine ();
3681                                         
3682                                         while (line != null) {
3683                                                 line = line.Trim ();
3684                                                 
3685                                                 if (line.StartsWith ("URL=")) {
3686                                                         line = line.Replace ("URL=", String.Empty);
3687                                                         line = line.Replace ("$HOME", personal_folder);
3688                                                         
3689                                                         Uri uri = new Uri (line);
3690                                                         if (!files_al.Contains (uri.LocalPath))
3691                                                                 if (File.Exists (uri.LocalPath)) {
3692                                                                         FSEntry fs = GetFileFSEntry (new FileInfo (uri.LocalPath));
3693                                                                         if (fs != null)
3694                                                                                 files_al.Add (fs);
3695                                                                 }
3696                                                         break;
3697                                                 }
3698                                                 
3699                                                 line = sr.ReadLine ();
3700                                         }
3701                                         
3702                                         sr.Close ();
3703                                 }
3704                         }
3705                         
3706                         
3707                         return files_al;
3708                 }
3709                 
3710                 // return an ArrayList with FSEntry objects
3711                 public override ArrayList GetMyComputerContent ()
3712                 {
3713                         ArrayList my_computer_content_arraylist = new ArrayList ();
3714                         
3715                         if (masterMount.ProcMountAvailable) {
3716                                 masterMount.GetMounts ();
3717                                 
3718                                 foreach (MasterMount.Mount mount in masterMount.Block_devices) {
3719                                         FSEntry fsEntry = new FSEntry ();
3720                                         fsEntry.FileType = FSEntry.FSEntryType.Device;
3721                                         
3722                                         fsEntry.FullName = mount.mount_point;
3723                                         
3724                                         fsEntry.Name = "HDD (" +  mount.fsType + ", " + mount.device_short + ")";
3725                                         
3726                                         fsEntry.FsType = mount.fsType;
3727                                         fsEntry.DeviceShort = mount.device_short;
3728                                         
3729                                         fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("harddisk/harddisk");
3730                                         
3731                                         fsEntry.Attributes = FileAttributes.Directory;
3732                                         
3733                                         fsEntry.MainTopNode = GetMyComputerFSEntry ();
3734                                         
3735                                         my_computer_content_arraylist.Add (fsEntry);
3736                                         
3737                                         if (!MWFVFS.MyComputerDevicesPrefix.Contains (fsEntry.FullName + "://"))
3738                                                 MWFVFS.MyComputerDevicesPrefix.Add (fsEntry.FullName + "://", fsEntry);
3739                                 }
3740                                 
3741                                 foreach (MasterMount.Mount mount in masterMount.Removable_devices) {
3742                                         FSEntry fsEntry = new FSEntry ();
3743                                         fsEntry.FileType = FSEntry.FSEntryType.RemovableDevice;
3744                                         
3745                                         fsEntry.FullName = mount.mount_point;
3746                                         
3747                                         bool is_dvd_cdrom = mount.fsType == MasterMount.FsTypes.usbfs ? false : true;
3748                                         string type_name = is_dvd_cdrom ? "DVD/CD-Rom" : "USB";
3749                                         string mime_type = is_dvd_cdrom ? "cdrom/cdrom" : "removable/removable";
3750                                         
3751                                         fsEntry.Name = type_name +" (" + mount.device_short + ")";
3752                                         
3753                                         fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType (mime_type);
3754                                         
3755                                         fsEntry.FsType = mount.fsType;
3756                                         fsEntry.DeviceShort = mount.device_short;
3757                                         
3758                                         fsEntry.Attributes = FileAttributes.Directory;
3759                                         
3760                                         fsEntry.MainTopNode = GetMyComputerFSEntry ();
3761                                         
3762                                         my_computer_content_arraylist.Add (fsEntry);
3763                                         
3764                                         string contain_string = fsEntry.FullName + "://";
3765                                         if (!MWFVFS.MyComputerDevicesPrefix.Contains (contain_string))
3766                                                 MWFVFS.MyComputerDevicesPrefix.Add (contain_string, fsEntry);
3767                                 }
3768                         }
3769                         
3770                         my_computer_content_arraylist.Add (GetMyComputerPersonalFSEntry ());
3771                         
3772                         return my_computer_content_arraylist;
3773                 }
3774                 
3775                 public override ArrayList GetMyNetworkContent ()
3776                 {
3777                         ArrayList fsEntries = new ArrayList ();
3778                         
3779                         foreach (MasterMount.Mount mount in masterMount.Network_devices) {
3780                                 FSEntry fsEntry = new FSEntry ();
3781                                 fsEntry.FileType = FSEntry.FSEntryType.Network;
3782                                 
3783                                 fsEntry.FullName = mount.mount_point;
3784                                 
3785                                 fsEntry.FsType = mount.fsType;
3786                                 fsEntry.DeviceShort = mount.device_short;
3787                                 
3788                                 fsEntry.Name = "Network (" + mount.fsType + ", " + mount.device_short + ")";
3789                                 
3790                                 switch (mount.fsType) {
3791                                         case MasterMount.FsTypes.nfs:
3792                                                 fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("nfs/nfs");
3793                                                 break;
3794                                         case MasterMount.FsTypes.smbfs:
3795                                                 fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("smb/smb");
3796                                                 break;
3797                                         case MasterMount.FsTypes.ncpfs:
3798                                                 fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("network/network");
3799                                                 break;
3800                                         case MasterMount.FsTypes.cifs:
3801                                                 fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("network/network");
3802                                                 break;
3803                                         default:
3804                                                 break;
3805                                 }
3806                                 
3807                                 fsEntry.Attributes = FileAttributes.Directory;
3808                                 
3809                                 fsEntry.MainTopNode = GetMyNetworkFSEntry ();
3810                                 
3811                                 fsEntries.Add (fsEntry);
3812                         }
3813                         return fsEntries;
3814                 }
3815                 
3816                 protected override FSEntry GetDesktopFSEntry ()
3817                 {
3818                         return desktopFSEntry;
3819                 }
3820                 
3821                 protected override FSEntry GetRecentlyUsedFSEntry ()
3822                 {
3823                         return recentlyusedFSEntry;
3824                 }
3825                 
3826                 protected override FSEntry GetPersonalFSEntry ()
3827                 {
3828                         return personalFSEntry;
3829                 }
3830                 
3831                 protected override FSEntry GetMyComputerPersonalFSEntry ()
3832                 {
3833                         return mycomputerpersonalFSEntry;
3834                 }
3835                 
3836                 protected override FSEntry GetMyComputerFSEntry ()
3837                 {
3838                         return mycomputerFSEntry;
3839                 }
3840                 
3841                 protected override FSEntry GetMyNetworkFSEntry ()
3842                 {
3843                         return mynetworkFSEntry;
3844                 }
3845         }
3846         #endregion
3847         
3848         #region WinFileSystem
3849         internal class WinFileSystem : FileSystem
3850         {
3851                 private FSEntry desktopFSEntry = null;
3852                 private FSEntry recentlyusedFSEntry = null;
3853                 private FSEntry personalFSEntry = null;
3854                 private FSEntry mycomputerpersonalFSEntry = null;
3855                 private FSEntry mycomputerFSEntry = null;
3856                 private FSEntry mynetworkFSEntry = null;
3857                 
3858                 public WinFileSystem ()
3859                 {
3860                         desktopFSEntry = new FSEntry ();
3861                         
3862                         desktopFSEntry.Attributes = FileAttributes.Directory;
3863                         desktopFSEntry.FullName = MWFVFS.DesktopPrefix;
3864                         desktopFSEntry.Name = "Desktop";
3865                         desktopFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesDesktop);
3866                         desktopFSEntry.FileType = FSEntry.FSEntryType.Directory;
3867                         desktopFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("desktop/desktop");
3868                         desktopFSEntry.LastAccessTime = DateTime.Now;
3869                         
3870                         recentlyusedFSEntry = new FSEntry ();
3871                         
3872                         recentlyusedFSEntry.Attributes = FileAttributes.Directory;
3873                         recentlyusedFSEntry.FullName = MWFVFS.RecentlyUsedPrefix;
3874                         recentlyusedFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesRecentDocuments);
3875                         recentlyusedFSEntry.Name = "Recently Used";
3876                         recentlyusedFSEntry.FileType = FSEntry.FSEntryType.Directory;
3877                         recentlyusedFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("recently/recently");
3878                         recentlyusedFSEntry.LastAccessTime = DateTime.Now;
3879                         
3880                         personalFSEntry = new FSEntry ();
3881                         
3882                         personalFSEntry.Attributes = FileAttributes.Directory;
3883                         personalFSEntry.FullName = MWFVFS.PersonalPrefix;
3884                         personalFSEntry.Name = "Personal";
3885                         personalFSEntry.MainTopNode = GetDesktopFSEntry ();
3886                         personalFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesPersonal);
3887                         personalFSEntry.FileType = FSEntry.FSEntryType.Directory;
3888                         personalFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("directory/home");
3889                         personalFSEntry.LastAccessTime = DateTime.Now;
3890                         
3891                         mycomputerpersonalFSEntry = new FSEntry ();
3892                         
3893                         mycomputerpersonalFSEntry.Attributes = FileAttributes.Directory;
3894                         mycomputerpersonalFSEntry.FullName = MWFVFS.MyComputerPersonalPrefix;
3895                         mycomputerpersonalFSEntry.Name = "Personal";
3896                         mycomputerpersonalFSEntry.MainTopNode = GetMyComputerFSEntry ();
3897                         mycomputerpersonalFSEntry.RealName = ThemeEngine.Current.Places (UIIcon.PlacesPersonal);
3898                         mycomputerpersonalFSEntry.FileType = FSEntry.FSEntryType.Directory;
3899                         mycomputerpersonalFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("directory/home");
3900                         mycomputerpersonalFSEntry.LastAccessTime = DateTime.Now;
3901                         
3902                         mycomputerFSEntry = new FSEntry ();
3903                         
3904                         mycomputerFSEntry.Attributes = FileAttributes.Directory;
3905                         mycomputerFSEntry.FullName = MWFVFS.MyComputerPrefix;
3906                         mycomputerFSEntry.Name = "My Computer";
3907                         mycomputerFSEntry.MainTopNode = GetDesktopFSEntry ();
3908                         mycomputerFSEntry.FileType = FSEntry.FSEntryType.Directory;
3909                         mycomputerFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("workplace/workplace");
3910                         mycomputerFSEntry.LastAccessTime = DateTime.Now;
3911                         
3912                         mynetworkFSEntry = new FSEntry ();
3913                         
3914                         mynetworkFSEntry.Attributes = FileAttributes.Directory;
3915                         mynetworkFSEntry.FullName = MWFVFS.MyNetworkPrefix;
3916                         mynetworkFSEntry.Name = "My Network";
3917                         mynetworkFSEntry.MainTopNode = GetDesktopFSEntry ();
3918                         mynetworkFSEntry.FileType = FSEntry.FSEntryType.Directory;
3919                         mynetworkFSEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("network/network");
3920                         mynetworkFSEntry.LastAccessTime = DateTime.Now;
3921                 }
3922                 
3923                 public override void WriteRecentlyUsedFiles (string fileToAdd)
3924                 {
3925                         // TODO: Implement this method
3926                         // use SHAddToRecentDocs ?
3927                 }
3928                 
3929                 public override ArrayList GetRecentlyUsedFiles ()
3930                 {
3931                         ArrayList al = new ArrayList ();
3932                         
3933                         DirectoryInfo di = new DirectoryInfo (recentlyusedFSEntry.RealName);
3934                         
3935                         FileInfo[] fileinfos = di.GetFiles ();
3936                         
3937                         foreach (FileInfo fi in fileinfos) {
3938                                 FSEntry fs = GetFileFSEntry (fi);
3939                                 if (fs != null)
3940                                         al.Add (fs);
3941                         }
3942                         
3943                         return al;
3944                 }
3945                 
3946                 public override ArrayList GetMyComputerContent ()
3947                 {
3948                         string[] logical_drives = Directory.GetLogicalDrives ();
3949                         
3950                         ArrayList my_computer_content_arraylist = new ArrayList ();
3951                         
3952                         foreach (string drive in logical_drives) {
3953                                 FSEntry fsEntry = new FSEntry ();
3954                                 fsEntry.FileType = FSEntry.FSEntryType.Device;
3955                                 
3956                                 fsEntry.FullName = drive;
3957                                 
3958                                 fsEntry.Name = drive;
3959                                 
3960                                 fsEntry.IconIndex = MimeIconEngine.GetIconIndexForMimeType ("harddisk/harddisk");
3961                                 
3962                                 fsEntry.Attributes = FileAttributes.Directory;
3963                                 
3964                                 fsEntry.MainTopNode = GetMyComputerFSEntry ();
3965                                 
3966                                 my_computer_content_arraylist.Add (fsEntry);
3967                                 
3968                                 string contain_string = fsEntry.FullName + "://";
3969                                 if (!MWFVFS.MyComputerDevicesPrefix.Contains (contain_string))
3970                                         MWFVFS.MyComputerDevicesPrefix.Add (contain_string, fsEntry);
3971                         }
3972                         
3973                         my_computer_content_arraylist.Add (GetMyComputerPersonalFSEntry ());
3974                         
3975                         return my_computer_content_arraylist;
3976                 }
3977                 
3978                 public override ArrayList GetMyNetworkContent ()
3979                 {
3980                         // TODO: Implement this method
3981                         return new ArrayList ();
3982                 }
3983                 protected override FSEntry GetDesktopFSEntry ()
3984                 {
3985                         return desktopFSEntry;
3986                 }
3987                 
3988                 protected override FSEntry GetRecentlyUsedFSEntry ()
3989                 {
3990                         return recentlyusedFSEntry;
3991                 }
3992                 
3993                 protected override FSEntry GetPersonalFSEntry ()
3994                 {
3995                         return personalFSEntry;
3996                 }
3997                 
3998                 protected override FSEntry GetMyComputerPersonalFSEntry ()
3999                 {
4000                         return mycomputerpersonalFSEntry;
4001                 }
4002                 
4003                 protected override FSEntry GetMyComputerFSEntry ()
4004                 {
4005                         return mycomputerFSEntry;
4006                 }
4007                 
4008                 protected override FSEntry GetMyNetworkFSEntry ()
4009                 {
4010                         return mynetworkFSEntry;
4011                 }
4012         }
4013         #endregion
4014         
4015         #region FSEntry
4016         internal class FSEntry
4017         {
4018                 public enum FSEntryType
4019                 {
4020                         Desktop,
4021                         RecentlyUsed,
4022                         MyComputer,
4023                         File,
4024                         Directory,
4025                         Device,
4026                         RemovableDevice,
4027                         Network
4028                 }
4029                 
4030                 private MasterMount.FsTypes fsType;
4031                 private string device_short;
4032                 private string fullName;
4033                 private string name;
4034                 private string realName = null;
4035                 private FileAttributes attributes = FileAttributes.Normal;
4036                 private long fileSize;
4037                 private FSEntryType fileType;
4038                 private DateTime lastAccessTime;
4039                 private FSEntry mainTopNode = null;
4040                 
4041                 private int iconIndex;
4042                 
4043                 private string parent;
4044                 
4045                 public MasterMount.FsTypes FsType {
4046                         set {
4047                                 fsType = value;
4048                         }
4049                         
4050                         get {
4051                                 return fsType;
4052                         }
4053                 }
4054                 
4055                 public string DeviceShort {
4056                         set {
4057                                 device_short = value;
4058                         }
4059                         
4060                         get {
4061                                 return device_short;
4062                         }
4063                 }
4064                 
4065                 public string FullName {
4066                         set {
4067                                 fullName = value;
4068                         }
4069                         
4070                         get {
4071                                 return fullName;
4072                         }
4073                 }
4074                 
4075                 public string Name {
4076                         set {
4077                                 name = value;
4078                         }
4079                         
4080                         get {
4081                                 return name;
4082                         }
4083                 }
4084                 
4085                 public string RealName {
4086                         set {
4087                                 realName = value;
4088                         }
4089                         
4090                         get {
4091                                 return realName;
4092                         }
4093                 }
4094                 
4095                 public FileAttributes Attributes {
4096                         set {
4097                                 attributes = value;
4098                         }
4099                         
4100                         get {
4101                                 return attributes;
4102                         }
4103                 }
4104                 
4105                 public long FileSize {
4106                         set {
4107                                 fileSize = value;
4108                         }
4109                         
4110                         get {
4111                                 return fileSize;
4112                         }
4113                 }
4114                 
4115                 public FSEntryType FileType {
4116                         set {
4117                                 fileType = value;
4118                         }
4119                         
4120                         get {
4121                                 return fileType;
4122                         }
4123                 }
4124                 
4125                 public DateTime LastAccessTime {
4126                         set {
4127                                 lastAccessTime = value;
4128                         }
4129                         
4130                         get {
4131                                 return lastAccessTime;
4132                         }
4133                 }
4134                 
4135                 public int IconIndex {
4136                         set {
4137                                 iconIndex = value;
4138                         }
4139                         
4140                         get {
4141                                 return iconIndex;
4142                         }
4143                 }
4144                 
4145                 public FSEntry MainTopNode {
4146                         set {
4147                                 mainTopNode = value;
4148                         }
4149                         
4150                         get {
4151                                 return mainTopNode;
4152                         }
4153                 }
4154                 
4155                 public string Parent {
4156                         set {
4157                                 parent = value;
4158                         }
4159                         
4160                         get {
4161                                 parent = GetParent ();
4162                                 
4163                                 return parent;
4164                         }
4165                 }
4166                 
4167                 private string GetParent ()
4168                 {
4169                         if (fullName == MWFVFS.PersonalPrefix) {
4170                                 return MWFVFS.DesktopPrefix;
4171                         } else
4172                         if (fullName == MWFVFS.MyComputerPersonalPrefix) {
4173                                 return MWFVFS.MyComputerPrefix;
4174                         } else
4175                         if (fullName == MWFVFS.MyComputerPrefix) {
4176                                 return MWFVFS.DesktopPrefix;
4177                         } else
4178                         if (fullName == MWFVFS.MyNetworkPrefix) {
4179                                 return MWFVFS.DesktopPrefix;
4180                         } else
4181                         if (fullName == MWFVFS.DesktopPrefix) {
4182                                 return null;
4183                         } else
4184                         if (fullName == MWFVFS.RecentlyUsedPrefix) {
4185                                 return null;
4186                         } else {
4187                                 foreach (DictionaryEntry entry in MWFVFS.MyComputerDevicesPrefix) {
4188                                         FSEntry fsEntry = entry.Value as FSEntry;
4189                                         if (fullName == fsEntry.FullName) {
4190                                                 return fsEntry.MainTopNode.FullName;
4191                                         }
4192                                 }
4193                                 
4194                                 DirectoryInfo dirInfo = new DirectoryInfo (fullName);
4195                                 
4196                                 DirectoryInfo dirInfoParent = dirInfo.Parent;
4197                                 
4198                                 if (dirInfoParent != null) {
4199                                         FSEntry fsEntry = MWFVFS.MyComputerDevicesPrefix [dirInfoParent.FullName + "://"] as FSEntry;
4200                                         
4201                                         if (fsEntry != null) {
4202                                                 return fsEntry.FullName;
4203                                         }
4204                                         
4205                                         if (mainTopNode != null) {
4206                                                 if (dirInfoParent.FullName == ThemeEngine.Current.Places (UIIcon.PlacesDesktop) &&
4207                                                     mainTopNode.FullName == MWFVFS.DesktopPrefix) {
4208                                                         return mainTopNode.FullName;
4209                                                 } else
4210                                                 if (dirInfoParent.FullName == ThemeEngine.Current.Places (UIIcon.PlacesPersonal) &&
4211                                                     mainTopNode.FullName == MWFVFS.PersonalPrefix) {
4212                                                         return mainTopNode.FullName;
4213                                                 } else
4214                                                 if (dirInfoParent.FullName == ThemeEngine.Current.Places (UIIcon.PlacesPersonal) &&
4215                                                     mainTopNode.FullName == MWFVFS.MyComputerPersonalPrefix) {
4216                                                         return mainTopNode.FullName;
4217                                                 }
4218                                         }
4219                                         
4220                                         return dirInfoParent.FullName;
4221                                 }
4222                         }
4223                         
4224                         return null;
4225                 }
4226         }
4227         #endregion
4228         
4229         #region MasterMount
4230         // Alexsantas little *nix helper
4231         internal class MasterMount
4232         {
4233                 // add more...
4234                 internal enum FsTypes
4235                 {
4236                         none,
4237                         ext2,
4238                         ext3,
4239                         hpfs,
4240                         iso9660,
4241                         jfs,
4242                         minix,
4243                         msdos,
4244                         ntfs,
4245                         reiserfs,
4246                         ufs,
4247                         umsdos,
4248                         vfat,
4249                         sysv,
4250                         xfs,
4251                         ncpfs,
4252                         nfs,
4253                         smbfs,
4254                         usbfs,
4255                         cifs
4256                 }
4257                 
4258                 internal struct Mount
4259                 {
4260                         public string device_or_filesystem;
4261                         public string device_short;
4262                         public string mount_point;
4263                         public FsTypes fsType;
4264                 }
4265                 
4266                 bool proc_mount_available = false;
4267                 
4268                 ArrayList block_devices = new ArrayList ();
4269                 ArrayList network_devices = new ArrayList ();
4270                 ArrayList removable_devices = new ArrayList ();
4271                 
4272                 private int platform = (int) Environment.OSVersion.Platform;
4273                 private MountComparer mountComparer = new MountComparer ();
4274                 
4275                 public MasterMount ()
4276                 {
4277                         // maybe check if the current user can access /proc/mounts
4278                         if ((platform == 4) || (platform == 128))
4279                                 if (File.Exists ("/proc/mounts"))
4280                                         proc_mount_available = true;
4281                 }
4282                 
4283                 public ArrayList Block_devices {
4284                         get {
4285                                 return block_devices;
4286                         }
4287                 }
4288                 
4289                 public ArrayList Network_devices {
4290                         get {
4291                                 return network_devices;
4292                         }
4293                 }
4294                 
4295                 public ArrayList Removable_devices {
4296                         get {
4297                                 return removable_devices;
4298                         }
4299                 }
4300                 
4301                 public bool ProcMountAvailable {
4302                         get {
4303                                 return proc_mount_available;
4304                         }
4305                 }
4306                 
4307                 public void GetMounts ()
4308                 {
4309                         if (!proc_mount_available)
4310                                 return;
4311                         
4312                         block_devices.Clear ();
4313                         network_devices.Clear ();
4314                         removable_devices.Clear ();
4315                         
4316                         try {
4317                                 StreamReader sr = new StreamReader ("/proc/mounts");
4318                                 
4319                                 string line = sr.ReadLine ();
4320                                 
4321                                 ArrayList lines = new ArrayList ();
4322                                 while (line != null) {
4323                                         if (lines.IndexOf (line) == -1) { // Avoid duplicates
4324                                                 ProcessProcMountLine (line);
4325                                                 lines.Add (line);
4326                                         }
4327                                         line = sr.ReadLine ();
4328                                 }
4329                                 
4330                                 sr.Close ();
4331                                 
4332                                 block_devices.Sort (mountComparer);
4333                                 network_devices.Sort (mountComparer);
4334                                 removable_devices.Sort (mountComparer);
4335                         } catch {
4336                                 // bla
4337                         }
4338                 }
4339                 
4340                 private void ProcessProcMountLine (string line)
4341                 {
4342                         string[] split = line.Split (new char [] {' '});
4343                         
4344                         if (split != null && split.Length > 0) {
4345                                 Mount mount = new Mount ();
4346                                 
4347                                 if (split [0].StartsWith ("/dev/"))
4348                                         mount.device_short = split [0].Replace ("/dev/", String.Empty);
4349                                 else 
4350                                         mount.device_short = split [0];
4351                                 
4352                                 mount.device_or_filesystem = split [0];
4353                                 mount.mount_point = split [1];
4354                                 
4355                                 // TODO: other removable devices, floppy
4356                                 // ssh
4357                                 
4358                                 // network mount
4359                                 if (split [2] == "nfs") {
4360                                         mount.fsType = FsTypes.nfs;
4361                                         network_devices.Add (mount);
4362                                 } else if (split [2] == "smbfs") {
4363                                         mount.fsType = FsTypes.smbfs;
4364                                         network_devices.Add (mount);
4365                                 } else if (split [2] == "cifs") {
4366                                         mount.fsType = FsTypes.cifs;
4367                                         network_devices.Add (mount);
4368                                 } else if (split [2] == "ncpfs") {
4369                                         mount.fsType = FsTypes.ncpfs;
4370                                         network_devices.Add (mount);
4371                                         
4372                                 } else if (split [2] == "iso9660") { //cdrom
4373                                         mount.fsType = FsTypes.iso9660;
4374                                         removable_devices.Add (mount);
4375                                 } else if (split [2] == "usbfs") { //usb ? not tested
4376                                         mount.fsType = FsTypes.usbfs;
4377                                         removable_devices.Add (mount);
4378                                         
4379                                 } else if (split [0].StartsWith ("/")) { //block devices
4380                                         if (split [1].StartsWith ("/dev/"))  // root static, do not add
4381                                                 return;
4382                                         
4383                                         if (split [2] == "ext2")
4384                                                 mount.fsType = FsTypes.ext2;
4385                                         else if (split [2] == "ext3")
4386                                                 mount.fsType = FsTypes.ext3;
4387                                         else if (split [2] == "reiserfs")
4388                                                 mount.fsType = FsTypes.reiserfs;
4389                                         else if (split [2] == "xfs")
4390                                                 mount.fsType = FsTypes.xfs;
4391                                         else if (split [2] == "vfat")
4392                                                 mount.fsType = FsTypes.vfat;
4393                                         else if (split [2] == "ntfs")
4394                                                 mount.fsType = FsTypes.ntfs;
4395                                         else if (split [2] == "msdos")
4396                                                 mount.fsType = FsTypes.msdos;
4397                                         else if (split [2] == "umsdos")
4398                                                 mount.fsType = FsTypes.umsdos;
4399                                         else if (split [2] == "hpfs")
4400                                                 mount.fsType = FsTypes.hpfs;
4401                                         else if (split [2] == "minix")
4402                                                 mount.fsType = FsTypes.minix;
4403                                         else if (split [2] == "jfs")
4404                                                 mount.fsType = FsTypes.jfs;
4405                                         
4406                                         block_devices.Add (mount);
4407                                 }
4408                         }
4409                 }
4410                 
4411                 public class MountComparer : IComparer
4412                 {
4413                         public int Compare (object mount1, object mount2)
4414                         {
4415                                 return String.Compare (((Mount)mount1).device_short, ((Mount)mount2).device_short);
4416                         }
4417                 }
4418         }
4419         #endregion
4420                 
4421         #region MWFConfig
4422         // easy to use class to store and read internal MWF config settings.
4423         // the config values are stored in the users home dir as a hidden xml file called "mwf_config".
4424         // currently supports int, string, byte, color and arrays (including byte arrays)
4425         // don't forget, when you read a value you still have to cast this value.
4426         //
4427         // usage:
4428         // MWFConfig.SetValue ("SomeClass", "What", value);
4429         // object o = MWFConfig.GetValue ("SomeClass", "What");
4430         //
4431         // example:
4432         // 
4433         // string[] configFileNames = (string[])MWFConfig.GetValue ("FileDialog", "FileNames");
4434         // MWFConfig.SetValue ("FileDialog", "LastFolder", "/home/user");
4435         
4436         internal class MWFConfig
4437         {
4438                 private static MWFConfigInstance Instance = new MWFConfigInstance ();
4439                 
4440                 private static object lock_object = new object();
4441                 
4442                 public static object GetValue (string class_name, string value_name)
4443                 {
4444                         lock (lock_object) {
4445                                 return Instance.GetValue (class_name, value_name);
4446                         }
4447                 }
4448                 
4449                 public static void SetValue (string class_name, string value_name, object value)
4450                 {
4451                         lock (lock_object) {
4452                                 Instance.SetValue (class_name, value_name, value);
4453                         }
4454                 }
4455                 
4456                 public static void Flush ()
4457                 {
4458                         lock (lock_object) {
4459                                 Instance.Flush ();
4460                         }
4461                 }
4462                 
4463                 public static void RemoveClass (string class_name)
4464                 {
4465                         lock (lock_object) {
4466                                 Instance.RemoveClass (class_name);
4467                         }
4468                 }
4469                 
4470                 public static void RemoveClassValue (string class_name, string value_name)
4471                 {
4472                         lock (lock_object) {
4473                                 Instance.RemoveClassValue (class_name, value_name);
4474                         }
4475                 }
4476                 
4477                 public static void RemoveAllClassValues (string class_name)
4478                 {
4479                         lock (lock_object) {
4480                                 Instance.RemoveAllClassValues (class_name);
4481                         }
4482                 }
4483         
4484                 internal class MWFConfigInstance
4485                 {
4486                         Hashtable classes_hashtable = new Hashtable ();
4487                         static string full_file_name;
4488                         static string default_file_name;
4489                         readonly string configName = "MWFConfig";
4490                         static int platform = (int) Environment.OSVersion.Platform;
4491
4492                         static bool IsUnix ()
4493                         {
4494                                 return (platform == 4 || platform == 128);
4495                         }
4496
4497                         static MWFConfigInstance ()
4498                         {
4499                                 string b = "mwf_config";
4500                                 string dir = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
4501                                         
4502                                 if (IsUnix ()){
4503                                         dir = Path.Combine (dir, ".mono");
4504                                         try {
4505                                                 Directory.CreateDirectory (dir);
4506                                         } catch {}
4507                                 } 
4508
4509                                 default_file_name = Path.Combine (dir, b);
4510                                 full_file_name = default_file_name;
4511                         }
4512                         
4513                         public MWFConfigInstance ()
4514                         {
4515                                 Open (default_file_name);
4516                         }
4517                         
4518                         // only for testing
4519                         public MWFConfigInstance (string filename)
4520                         {
4521                                 string path = Path.GetDirectoryName (filename);
4522                                 if (path == null || path == String.Empty) {
4523                                         path = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
4524                                         
4525                                         full_file_name = Path.Combine (path, filename);
4526                                 }  else 
4527                                         full_file_name = filename;
4528
4529                                 Open (full_file_name);
4530                         }                               
4531                         
4532                         ~MWFConfigInstance ()
4533                         {
4534                                 Flush ();
4535                         }
4536                         
4537                         public object GetValue (string class_name, string value_name)
4538                         {
4539                                 ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry;
4540                                 
4541                                 if (class_entry != null)
4542                                         return class_entry.GetValue (value_name);
4543                                 
4544                                 return null;
4545                         }
4546                         
4547                         public void SetValue (string class_name, string value_name, object value)
4548                         {
4549                                 ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry;
4550                                 
4551                                 if (class_entry == null) {
4552                                         class_entry = new ClassEntry ();
4553                                         class_entry.ClassName = class_name;
4554                                         classes_hashtable [class_name] = class_entry;
4555                                 }
4556                                 
4557                                 class_entry.SetValue (value_name, value);
4558                         }
4559                         
4560                         private void Open (string filename)
4561                         {
4562                                 try {
4563                                         XmlTextReader xtr = new XmlTextReader (filename);
4564                                         
4565                                         ReadConfig (xtr);
4566                                         
4567                                         xtr.Close ();
4568                                 } catch (Exception) {
4569                                 }
4570                         }
4571                         
4572                         public void Flush ()
4573                         {
4574                                 try {
4575                                         XmlTextWriter xtw = new XmlTextWriter (full_file_name, null);
4576                                         xtw.Formatting = Formatting.Indented;
4577                                         
4578                                         WriteConfig (xtw);
4579                                         
4580                                         xtw.Close ();
4581
4582                                         if (!IsUnix ())
4583                                                 File.SetAttributes (full_file_name, FileAttributes.Hidden);
4584                                 } catch (Exception){
4585                                 }
4586                         }
4587                         
4588                         public void RemoveClass (string class_name)
4589                         {
4590                                 ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry;
4591                                 
4592                                 if (class_entry != null) {
4593                                         class_entry.RemoveAllClassValues ();
4594                                         
4595                                         classes_hashtable.Remove (class_name);
4596                                 }
4597                         }
4598                         
4599                         public void RemoveClassValue (string class_name, string value_name)
4600                         {
4601                                 ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry;
4602                                 
4603                                 if (class_entry != null) {
4604                                         class_entry.RemoveClassValue (value_name);
4605                                 }
4606                         }
4607                         
4608                         public void RemoveAllClassValues (string class_name)
4609                         {
4610                                 ClassEntry class_entry = classes_hashtable [class_name] as ClassEntry;
4611                                 
4612                                 if (class_entry != null) {
4613                                         class_entry.RemoveAllClassValues ();
4614                                 }
4615                         }
4616                         
4617                         private void ReadConfig (XmlTextReader xtr)
4618                         {
4619                                 if (!CheckForMWFConfig (xtr))
4620                                         return;
4621                                 
4622                                 while (xtr.Read ()) {
4623                                         switch (xtr.NodeType) {
4624                                                 case XmlNodeType.Element:
4625                                                         ClassEntry class_entry = classes_hashtable [xtr.Name] as ClassEntry;
4626                                                         
4627                                                         if (class_entry == null) {
4628                                                                 class_entry = new ClassEntry ();
4629                                                                 class_entry.ClassName = xtr.Name;
4630                                                                 classes_hashtable [xtr.Name] = class_entry;
4631                                                         }
4632                                                         
4633                                                         class_entry.ReadXml (xtr);
4634                                                         break;
4635                                         }
4636                                 }
4637                         }
4638                         
4639                         private bool CheckForMWFConfig (XmlTextReader xtr)
4640                         {
4641                                 if (xtr.Read ()) {
4642                                         if (xtr.NodeType == XmlNodeType.Element) {
4643                                                 if (xtr.Name == configName)
4644                                                         return true;
4645                                         }
4646                                 }
4647                                 
4648                                 return false;
4649                         }
4650                         
4651                         private void WriteConfig (XmlTextWriter xtw)
4652                         {
4653                                 if (classes_hashtable.Count == 0)
4654                                         return;
4655                                 
4656                                 xtw.WriteStartElement (configName);
4657                                 foreach (DictionaryEntry entry in classes_hashtable) {
4658                                         ClassEntry class_entry = entry.Value as ClassEntry;
4659                                         
4660                                         class_entry.WriteXml (xtw);
4661                                 }
4662                                 xtw.WriteEndElement ();
4663                         }
4664                         
4665                         internal class ClassEntry
4666                         {
4667                                 private Hashtable classvalues_hashtable = new Hashtable ();
4668                                 private string className;
4669                                 
4670                                 public string ClassName {
4671                                         set {
4672                                                 className = value;
4673                                         }
4674                                         
4675                                         get {
4676                                                 return className;
4677                                         }
4678                                 }
4679                                 
4680                                 public void SetValue (string value_name, object value)
4681                                 {
4682                                         ClassValue class_value = classvalues_hashtable [value_name] as ClassValue;
4683                                         
4684                                         if (class_value == null) {
4685                                                 class_value = new ClassValue ();
4686                                                 class_value.Name = value_name;
4687                                                 classvalues_hashtable [value_name] = class_value;
4688                                         }
4689                                         
4690                                         class_value.SetValue (value);
4691                                 }
4692                                 
4693                                 public object GetValue (string value_name)
4694                                 {
4695                                         ClassValue class_value = classvalues_hashtable [value_name] as ClassValue;
4696                                         
4697                                         if (class_value == null) {
4698                                                 return null;
4699                                         }
4700                                         
4701                                         return class_value.GetValue ();
4702                                 }
4703                                 
4704                                 public void RemoveAllClassValues ()
4705                                 {
4706                                         classvalues_hashtable.Clear ();
4707                                 }
4708                                 
4709                                 public void RemoveClassValue (string value_name)
4710                                 {
4711                                         ClassValue class_value = classvalues_hashtable [value_name] as ClassValue;
4712                                         
4713                                         if (class_value != null) {
4714                                                 classvalues_hashtable.Remove (value_name);
4715                                         }
4716                                 }
4717                                 
4718                                 public void ReadXml (XmlTextReader xtr)
4719                                 {
4720                                         while (xtr.Read ()) {
4721                                                 switch (xtr.NodeType) {
4722                                                         case XmlNodeType.Element:
4723                                                                 string name = xtr.GetAttribute ("name");
4724                                                                 
4725                                                                 ClassValue class_value = classvalues_hashtable [name] as ClassValue;
4726                                                                 
4727                                                                 if (class_value == null) {
4728                                                                         class_value = new ClassValue ();
4729                                                                         class_value.Name = name;
4730                                                                         classvalues_hashtable [name] = class_value;
4731                                                                 }
4732                                                                 
4733                                                                 class_value.ReadXml (xtr);
4734                                                                 break;
4735                                                                 
4736                                                         case XmlNodeType.EndElement:
4737                                                                 return;
4738                                                 }
4739                                         }
4740                                 }
4741                                 
4742                                 public void WriteXml (XmlTextWriter xtw)
4743                                 {
4744                                         if (classvalues_hashtable.Count == 0)
4745                                                 return;
4746                                         
4747                                         xtw.WriteStartElement (className);
4748                                         
4749                                         foreach (DictionaryEntry entry in classvalues_hashtable) {
4750                                                 ClassValue class_value = entry.Value as ClassValue;
4751                                                 
4752                                                 class_value.WriteXml (xtw);
4753                                         }
4754                                         
4755                                         xtw.WriteEndElement ();
4756                                 }
4757                         }
4758                         
4759                         internal class ClassValue
4760                         {
4761                                 private object value;
4762                                 private string name;
4763                                 
4764                                 public string Name {
4765                                         set {
4766                                                 name = value;
4767                                         }
4768                                         
4769                                         get {
4770                                                 return name;
4771                                         }
4772                                 }
4773                                 
4774                                 public void SetValue (object value)
4775                                 {
4776                                         this.value = value;
4777                                 }
4778                                 public object GetValue ()
4779                                 {
4780                                         return value;
4781                                 }
4782                                 
4783                                 public void ReadXml (XmlTextReader xtr)
4784                                 {
4785                                         string type;
4786                                         string single_value;
4787                                         
4788                                         type = xtr.GetAttribute ("type");
4789                                         
4790                                         if (type == "byte_array" || type.IndexOf ("-array") == -1) {
4791                                                 single_value = xtr.ReadString ();
4792                                                 
4793                                                 if (type == "string") {
4794                                                         value = single_value;
4795                                                 } else
4796                                                 if (type == "int") {
4797                                                         value = Int32.Parse (single_value);
4798                                                 } else
4799                                                 if (type == "byte") {
4800                                                         value = Byte.Parse (single_value);
4801                                                 } else
4802                                                 if (type == "color") {
4803                                                         int color = Int32.Parse (single_value);
4804                                                         value = Color.FromArgb (color);
4805                                                 } else
4806                                                 if (type == "byte-array") {
4807                                                         byte[] b_array = Convert.FromBase64String (single_value);
4808                                                         value = b_array;
4809                                                 }
4810                                         } else {
4811                                                 ReadXmlArrayValues (xtr, type);
4812                                         }
4813                                 }
4814                                 
4815                                 private void ReadXmlArrayValues (XmlTextReader xtr, string type)
4816                                 {
4817                                         ArrayList al = new ArrayList ();
4818                                         
4819                                         while (xtr.Read ()) {
4820                                                 switch (xtr.NodeType) {
4821                                                         case XmlNodeType.Element:
4822                                                                 string single_value = xtr.ReadString ();
4823                                                                 
4824                                                                 if (type == "int-array") {
4825                                                                         int int_val = Int32.Parse (single_value);
4826                                                                         al.Add (int_val);
4827                                                                 } else
4828                                                                 if (type == "string-array") {
4829                                                                         string str_val = single_value;
4830                                                                         al.Add (str_val);
4831                                                                 }
4832                                                                 break;
4833                                                                 
4834                                                         case XmlNodeType.EndElement:
4835                                                                 if (xtr.Name == "value") {
4836                                                                         if (type == "int-array") {
4837                                                                                 value = al.ToArray (typeof(int));
4838                                                                         } else
4839                                                                         if (type == "string-array") {
4840                                                                                 value = al.ToArray (typeof(string));
4841                                                                         } 
4842                                                                         return;
4843                                                                 }
4844                                                                 break;
4845                                                 }
4846                                         }
4847                                 }
4848                                 
4849                                 public void WriteXml (XmlTextWriter xtw)
4850                                 {
4851                                         xtw.WriteStartElement ("value");
4852                                         xtw.WriteAttributeString ("name", name);
4853                                         if (value is Array) {
4854                                                 WriteArrayContent (xtw);
4855                                         } else {
4856                                                 WriteSingleContent (xtw);
4857                                         }
4858                                         xtw.WriteEndElement ();
4859                                 }
4860                                 
4861                                 private void WriteSingleContent (XmlTextWriter xtw)
4862                                 {
4863                                         string type_string = String.Empty;
4864                                         
4865                                         if (value is string)
4866                                                 type_string = "string";
4867                                         else
4868                                         if (value is int)
4869                                                 type_string = "int";
4870                                         else
4871                                         if (value is byte)
4872                                                 type_string = "byte";
4873                                         else
4874                                         if (value is Color)
4875                                                 type_string = "color";
4876                                         
4877                                         xtw.WriteAttributeString ("type", type_string);
4878                                         
4879                                         if (value is Color)
4880                                                 xtw.WriteString (((Color)value).ToArgb ().ToString ());
4881                                         else
4882                                                 xtw.WriteString (value.ToString ());
4883                                 }
4884                                 
4885                                 private void WriteArrayContent (XmlTextWriter xtw)
4886                                 {
4887                                         string type_string = String.Empty;
4888                                         string type_name = String.Empty;
4889                                         
4890                                         if (value is string[]) {
4891                                                 type_string = "string-array";
4892                                                 type_name = "string";
4893                                         } else
4894                                         if (value is int[]) {
4895                                                 type_string = "int-array";
4896                                                 type_name = "int";
4897                                         } else
4898                                         if (value is byte[]) {
4899                                                 type_string = "byte-array";
4900                                                 type_name = "byte";
4901                                         }
4902                                         
4903                                         xtw.WriteAttributeString ("type", type_string);
4904                                         
4905                                         if (type_string != "byte-array") {
4906                                                 Array array = value as Array;
4907                                                 
4908                                                 foreach (object o in array) {
4909                                                         xtw.WriteStartElement (type_name);
4910                                                         xtw.WriteString (o.ToString ());
4911                                                         xtw.WriteEndElement ();
4912                                                 }
4913                                         } else {
4914                                                 byte[] b_array = value as byte [];
4915                                                 
4916                                                 xtw.WriteString (Convert.ToBase64String (b_array, 0, b_array.Length));
4917                                         }
4918                                 }
4919                         }
4920                 }
4921         }
4922         #endregion
4923 }