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