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