2 * openfile.cpp: File Access and I/O
5 * Moonlight List (moonlight-list@lists.ximian.com)
7 * Copyright 2007, 2009 Novell, Inc. (http://www.novell.com)
9 * See the LICENSE file included with the distribution for details.
16 // FIXME: Silverlight 1.1 (alpha, refresh) doesn't allow the selection(*) of
17 // symlinks on Mac OSX. (*) actually it de-selects them on the fly. We should
18 // be able to duplicate this with lstat and the selection-changed event.
21 set_filters (GtkFileChooser
*chooser
, const char* filter
, int idx
)
23 if (!filter
|| (strlen (filter
) <= 1))
26 char **filters
= g_strsplit (filter
, "|", 0);
28 // to be valid (managed code) we know we have an even number of items
29 // (if not we're still safe by dropping the last one)
31 int n
= g_strv_length (filters
) >> 1;
32 for (int i
=0; i
< n
; i
++) {
33 char *name
= g_strstrip (filters
[pos
++]);
34 if (strlen (name
) < 1)
37 char *pattern
= g_strstrip (filters
[pos
++]);
38 if (strlen (pattern
) < 1)
41 GtkFileFilter
*ff
= gtk_file_filter_new ();
42 gtk_file_filter_set_name (ff
, g_strdup (name
));
43 // there can be multiple patterns in a single string
44 if (g_strrstr (pattern
, ";")) {
46 char **patterns
= g_strsplit (pattern
, ";", 0);
47 while (char *p
= patterns
[n
++])
48 gtk_file_filter_add_pattern (ff
, g_strdup (p
));
49 g_strfreev (patterns
);
52 gtk_file_filter_add_pattern (ff
, g_strdup (pattern
));
54 gtk_file_chooser_add_filter (chooser
, ff
);
55 // idx (FilterIndex) is 1 (not 0) based
57 gtk_file_chooser_set_filter (chooser
, ff
);
63 open_file_dialog_show (const char *title
, bool multsel
, const char *filter
, int idx
)
65 GtkWidget
*widget
= gtk_file_chooser_dialog_new (title
, NULL
,
66 GTK_FILE_CHOOSER_ACTION_OPEN
,
67 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
68 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
, NULL
);
70 GtkFileChooser
*chooser
= GTK_FILE_CHOOSER (widget
);
71 set_filters (chooser
, filter
, idx
);
72 gtk_file_chooser_set_select_multiple (chooser
, multsel
? TRUE
: FALSE
);
75 if (gtk_dialog_run (GTK_DIALOG (widget
)) == GTK_RESPONSE_ACCEPT
){
76 GSList
*k
, *l
= gtk_file_chooser_get_filenames (chooser
);
77 int i
, count
= g_slist_length (l
);
79 ret
= g_new (char *, count
+ 1);
82 for (i
= 0, k
= l
; k
; k
= k
->next
)
83 ret
[i
++] = (char *) k
->data
;
88 gtk_widget_destroy (widget
);
94 save_file_dialog_show (const char *title
, const char *filter
, int idx
)
96 GtkWidget
*widget
= gtk_file_chooser_dialog_new (title
, NULL
,
97 GTK_FILE_CHOOSER_ACTION_SAVE
,
98 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
99 GTK_STOCK_SAVE
, GTK_RESPONSE_ACCEPT
, NULL
);
101 GtkFileChooser
*chooser
= GTK_FILE_CHOOSER (widget
);
102 set_filters (chooser
, filter
, idx
);
103 gtk_file_chooser_set_do_overwrite_confirmation (chooser
, TRUE
);
106 if (gtk_dialog_run (GTK_DIALOG (widget
)) == GTK_RESPONSE_ACCEPT
)
107 ret
= gtk_file_chooser_get_filename (chooser
);
109 gtk_widget_destroy (widget
);
114 // NOTE: this is used from 'mscorlib.dll' System.IO.IsolatedStorage/MoonIsolatedStorageFile.cs
115 // NOTE: we let the caller supply the string so i18n can occur in managed land only
117 isolated_storage_increase_quota_to (const char *primary_text
, const char* secondary_text
)
119 // the dialog is displayed only if the action leading to this call was initiated directly from the user
120 if (!Deployment::GetCurrent ()->GetSurface ()->IsUserInitiatedEvent ())
123 GtkWidget
*widget
= gtk_message_dialog_new_with_markup (NULL
,
125 GTK_MESSAGE_QUESTION
,
129 gtk_window_set_title (GTK_WINDOW (widget
), PACKAGE_STRING
);
130 gtk_message_dialog_format_secondary_markup (GTK_MESSAGE_DIALOG (widget
), secondary_text
);
132 gboolean result
= (gtk_dialog_run (GTK_DIALOG (widget
)) == GTK_RESPONSE_YES
);
133 gtk_widget_destroy (widget
);
137 // recursively calculate the size of the specified directory
139 get_size (const char *root
)
141 // NOTE: just like Silverlight we give a minimum cost of 1KB for each
142 // directory and file to avoid disk exhaustion by empty files/directories.
143 long result
= MOONLIGHT_MINIMUM_FILE_ENTRY_COST
;
145 if (g_lstat (root
, &info
) != 0)
148 // there should be no link in IS but, if any, we're not following them
149 if (S_ISLNK (info
.st_mode
))
152 if (S_ISDIR (info
.st_mode
)) {
153 // scan everythins inside the directory
154 GDir
*dir
= g_dir_open (root
, 0, NULL
);
156 return result
; // should never happen
158 // note: g_dir_read_name *smartly* skips '.' and '..'
159 const char *entry_name
= g_dir_read_name (dir
);
161 char name
[PATH_MAX
];
162 if (g_snprintf (name
, PATH_MAX
, "%s/%s", root
, entry_name
) <= PATH_MAX
)
163 result
+= get_size (name
);
165 entry_name
= g_dir_read_name (dir
);
169 // file size is computed at 1KB boundaries, minimum of 1KB (fixed cost for a file-system entry)
170 result
= (info
.st_size
& ~MOONLIGHT_FILE_SIZE_MASK
);
171 if ((result
== 0) || (info
.st_size
& MOONLIGHT_FILE_SIZE_MASK
))
172 result
+= MOONLIGHT_MINIMUM_FILE_ENTRY_COST
;
178 // NOTE: this is used from 'mscorlib.dll' System.IO.IsolatedStorage/MoonIsolatedStorage.cs
180 isolated_storage_get_current_usage (const char* root
)
182 // XXX we should cache the value and invalidate it if something changed (e.g. using inotify)
183 return get_size (root
);