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