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