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