1 /******************************* LICENCE **************************************
2 * Any code in this file may be redistributed or modified under the terms of
3 * the GNU General Public Licence as published by the Free Software
4 * Foundation; version 2 of the licence.
5 ****************************** END LICENCE ***********************************/
6 
7 /******************************************************************************
8 * Author:
9 * Andrew Smith, http://littlesvr.ca/misc/contactandrew.php
10 *
11 * Contributors:
12 *
13 ******************************************************************************/
14 
15 #include <gtk/gtk.h>
16 #include <string.h>
17 #include <sys/stat.h>
18 #include <libintl.h>
19 
20 #include "isomaster.h"
21 
22 /* this file has thigs shared by the fs and the iso browser */
23 
24 /* menu-sized pixbufs of a directory and a file */
25 GdkPixbuf* GBLdirPixbuf;
26 GdkPixbuf* GBLfilePixbuf;
27 //~ GdkPixbuf* GBLsymlinkPixbuf;
28 
29 /* text box for showing the path and name of the current directory on the fs */
30 GtkWidget* GBLfsCurrentDirField;
31 /* the view used for the contents of the fs browser */
32 GtkWidget* GBLfsTreeView;
33 /* the list store used for the contents of the fs browser */
34 GtkListStore* GBLfsListStore;
35 /* slash-terminated, the dir being displayed in the fs browser */
36 char* GBLfsCurrentDir = NULL;
37 
38 /* text box for showing the path and name of the current directory on the iso */
39 GtkWidget* GBLisoCurrentDirField;
40 /* the view used for the contents of the fs browser */
41 GtkWidget* GBLisoTreeView;
42 /* the list store used for the contents of the fs browser */
43 GtkListStore* GBLisoListStore;
44 /* slash-terminated, the dir being displayed in the iso browser */
45 char* GBLisoCurrentDir = NULL;
46 
47 extern GtkWidget* GBLmainWindow;
48 extern VolInfo GBLvolInfo;
49 extern bool GBLisoPaneActive;
50 extern AppSettings GBLappSettings;
51 
52 /* connected to the activate signal of a text entry in a dialog */
acceptDialogCbk(GtkEntry * entry,GtkDialog * dialog)53 void acceptDialogCbk(GtkEntry *entry, GtkDialog* dialog)
54 {
55     gtk_dialog_response(dialog, GTK_RESPONSE_ACCEPT);
56 }
57 
createDirCbk(GtkButton * button,gpointer onFs)58 void createDirCbk(GtkButton *button, gpointer onFs)
59 {
60     GtkWidget* dialog;
61     GtkWidget* warningDialog;
62     int response;
63     GtkWidget* textEntry;
64     const char* newDirName;
65     int rc;
66 
67     if(!onFs && !GBLisoPaneActive)
68     /* asked to create dir on iso but no iso is open */
69         return;
70 
71     dialog = gtk_dialog_new_with_buttons(_("Enter name for new directory"),
72                                          GTK_WINDOW(GBLmainWindow),
73                                          GTK_DIALOG_DESTROY_WITH_PARENT,
74                                          GTK_STOCK_OK,
75                                          GTK_RESPONSE_ACCEPT,
76                                          GTK_STOCK_CANCEL,
77                                          GTK_RESPONSE_REJECT,
78                                          NULL);
79 
80     textEntry = gtk_entry_new();
81     gtk_entry_set_width_chars(GTK_ENTRY(textEntry), 40);
82     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), textEntry);
83     gtk_widget_show(textEntry);
84     g_signal_connect(textEntry, "activate", (GCallback)acceptDialogCbk, dialog);
85     g_signal_connect(dialog, "close", G_CALLBACK(rejectDialogCbk), NULL);
86 
87     response = gtk_dialog_run(GTK_DIALOG(dialog));
88 
89     if(response == GTK_RESPONSE_ACCEPT)
90     {
91         newDirName = gtk_entry_get_text(GTK_ENTRY(textEntry));
92 
93         if(onFs)
94         {
95             char* pathAndName;
96 
97             pathAndName = malloc(strlen(GBLfsCurrentDir) + strlen(newDirName) + 1);
98             if(pathAndName == NULL)
99                 fatalError("createDirCbk(): malloc(strlen(GBLfsCurrentDir) + "
100                            "strlen(newDirName) + 1) failed");
101 
102             strcpy(pathAndName, GBLfsCurrentDir);
103             strcat(pathAndName, newDirName);
104 
105             rc = mkdir(pathAndName, 0755);
106             if(rc == -1)
107             {
108                 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
109                                                        GTK_DIALOG_DESTROY_WITH_PARENT,
110                                                        GTK_MESSAGE_ERROR,
111                                                        GTK_BUTTONS_CLOSE,
112                                                        _("Failed to create directory %s"),
113                                                        pathAndName);
114                 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
115                 gtk_dialog_run(GTK_DIALOG(warningDialog));
116                 gtk_widget_destroy(warningDialog);
117                 gtk_widget_destroy(dialog);
118                 return;
119             }
120 
121             free(pathAndName);
122 
123             refreshFsView();
124         }
125         else
126         /* on iso */
127         {
128             rc = bk_create_dir(&GBLvolInfo, GBLisoCurrentDir, newDirName);
129             if(rc <= 0)
130             {
131                 warningDialog = gtk_message_dialog_new(GTK_WINDOW(GBLmainWindow),
132                                                        GTK_DIALOG_DESTROY_WITH_PARENT,
133                                                        GTK_MESSAGE_ERROR,
134                                                        GTK_BUTTONS_CLOSE,
135                                                        _("Failed to create directory %s: '%s'"),
136                                                        newDirName,
137                                                        bk_get_error_string(rc));
138                 gtk_window_set_modal(GTK_WINDOW(warningDialog), TRUE);
139                 gtk_dialog_run(GTK_DIALOG(warningDialog));
140                 gtk_widget_destroy(warningDialog);
141                 gtk_widget_destroy(dialog);
142                 return;
143             }
144 
145             refreshIsoView();
146         }
147         fflush(NULL);
148     }
149 
150     gtk_widget_destroy(dialog);
151 }
152 
formatSize(bk_off_t sizeInt,char * sizeStr,int sizeStrLen)153 void formatSize(bk_off_t sizeInt, char* sizeStr, int sizeStrLen)
154 {
155     if(sizeInt > 1073741824)
156     /* print gibibytes */
157         snprintf(sizeStr, sizeStrLen, "%.1f GB", (double)sizeInt / 1073741824);
158     else if(sizeInt > 1048576)
159     /* print mebibytes */
160         snprintf(sizeStr, sizeStrLen, "%.1f MB", (double)sizeInt / 1048576);
161     else if(sizeInt > 1024)
162     /* print kibibytes */
163         snprintf(sizeStr, sizeStrLen, "%.1f KB", (double)sizeInt / 1024);
164     else
165     /* print bytes */
166         snprintf(sizeStr, sizeStrLen, "%llu B", (long long unsigned)sizeInt);
167 
168     sizeStr[sizeStrLen - 1] = '\0';
169 }
170 
refreshBothViewsCbk(GtkWidget * widget,GdkEvent * event)171 void refreshBothViewsCbk(GtkWidget *widget, GdkEvent *event)
172 {
173     refreshFsView();
174     if(GBLisoPaneActive)
175         refreshIsoView();
176 }
177 
178 /* formats the file size text for displaying */
sizeCellDataFunc32(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)179 void sizeCellDataFunc32(GtkTreeViewColumn *col, GtkCellRenderer *renderer,
180                         GtkTreeModel *model, GtkTreeIter *iter,
181                         gpointer data)
182 {
183     unsigned sizeInt;
184     unsigned long long sizeLlInt;
185     int fileType;
186     char sizeStr[20];
187 
188     gtk_tree_model_get(model, iter, COLUMN_SIZE, &sizeInt,
189                                     COLUMN_HIDDEN_TYPE, &fileType, -1);
190 
191     sizeLlInt = sizeInt;
192 
193     if(fileType == FILE_TYPE_DIRECTORY)
194     {
195         snprintf(sizeStr, sizeof(sizeStr), "dir");
196         sizeStr[sizeof(sizeStr) - 1] = '\0';
197     }
198     else if(fileType == FILE_TYPE_SYMLINK)
199     {
200         snprintf(sizeStr, sizeof(sizeStr), "link");
201         sizeStr[sizeof(sizeStr) - 1] = '\0';
202     }
203     else
204         formatSize(sizeLlInt, sizeStr, sizeof(sizeStr));
205 
206     g_object_set(renderer, "text", sizeStr, NULL);
207 }
208 
209 /* formats the file size text for displaying */
sizeCellDataFunc64(GtkTreeViewColumn * col,GtkCellRenderer * renderer,GtkTreeModel * model,GtkTreeIter * iter,gpointer data)210 void sizeCellDataFunc64(GtkTreeViewColumn *col, GtkCellRenderer *renderer,
211                         GtkTreeModel *model, GtkTreeIter *iter,
212                         gpointer data)
213 {
214     unsigned long long sizeInt;
215     int fileType;
216     char sizeStr[20];
217 
218     gtk_tree_model_get(model, iter, COLUMN_SIZE, &sizeInt,
219                                     COLUMN_HIDDEN_TYPE, &fileType, -1);
220 
221     if(fileType == FILE_TYPE_DIRECTORY)
222     {
223         snprintf(sizeStr, sizeof(sizeStr), "dir");
224         sizeStr[sizeof(sizeStr) - 1] = '\0';
225     }
226     else if(fileType == FILE_TYPE_SYMLINK)
227     {
228         snprintf(sizeStr, sizeof(sizeStr), "link");
229         sizeStr[sizeof(sizeStr) - 1] = '\0';
230     }
231     else
232         formatSize(sizeInt, sizeStr, sizeof(sizeStr));
233 
234     g_object_set(renderer, "text", sizeStr, NULL);
235 }
236 
sortByName(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)237 gint sortByName(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
238 {
239     if(GBLappSettings.sortDirectoriesFirst)
240     /* directories before files */
241     {
242         int aFileType;
243         int bFileType;
244         gint unused;
245         GtkSortType order;
246 
247         gtk_tree_model_get(model, a, COLUMN_HIDDEN_TYPE, &aFileType, -1);
248         gtk_tree_model_get(model, b, COLUMN_HIDDEN_TYPE, &bFileType, -1);
249 
250         /* have to make sure directories come first regardless of sort order,
251         * that's why all the fancyness in the rest of this block */
252         gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model), &unused, &order);
253 
254         if(aFileType == FILE_TYPE_DIRECTORY && bFileType != FILE_TYPE_DIRECTORY)
255         {
256             if(order == GTK_SORT_ASCENDING)
257                 return -1;
258             else
259                 return 1;
260         }
261         else if(aFileType != FILE_TYPE_DIRECTORY && bFileType == FILE_TYPE_DIRECTORY)
262         {
263             if(order == GTK_SORT_ASCENDING)
264                 return 1;
265             else
266                 return -1;
267         }
268     }
269 
270     char* aName;
271     char* bName;
272     gint toReturn;
273 
274     gtk_tree_model_get(model, a, COLUMN_FILENAME, &aName, -1);
275     gtk_tree_model_get(model, b, COLUMN_FILENAME, &bName, -1);
276 
277     if(GBLappSettings.caseSensitiveSort)
278         toReturn = strcmp(aName, bName);
279     else
280         toReturn = strcasecmp(aName, bName);
281 
282     g_free(aName);
283     g_free(bName);
284 
285     return toReturn;
286 }
287 
sortBySize(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)288 gint sortBySize(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
289 {
290     if(GBLappSettings.sortDirectoriesFirst)
291     /* directories before files */
292     {
293         int aFileType;
294         int bFileType;
295         gint unused;
296         GtkSortType order;
297 
298         gtk_tree_model_get(model, a, COLUMN_HIDDEN_TYPE, &aFileType, -1);
299         gtk_tree_model_get(model, b, COLUMN_HIDDEN_TYPE, &bFileType, -1);
300 
301         /* have to make sure directories come first regardless of sort order,
302         * that's why all the fancyness below */
303         gtk_tree_sortable_get_sort_column_id(GTK_TREE_SORTABLE(model), &unused, &order);
304 
305         if(aFileType == FILE_TYPE_DIRECTORY && bFileType != FILE_TYPE_DIRECTORY)
306         {
307             if(order == GTK_SORT_ASCENDING)
308                 return -1;
309             else
310                 return 1;
311         }
312         else if(aFileType != FILE_TYPE_DIRECTORY && bFileType == FILE_TYPE_DIRECTORY)
313         {
314             if(order == GTK_SORT_ASCENDING)
315                 return 1;
316             else
317                 return -1;
318         }
319     }
320 
321     guint64 aSize;
322     guint64 bSize;
323 
324     gtk_tree_model_get(model, a, COLUMN_SIZE, &aSize, -1);
325     gtk_tree_model_get(model, b, COLUMN_SIZE, &bSize, -1);
326 
327     if(aSize < bSize)
328         return -1;
329     else
330         return 1;
331 }
332 
333 /* this function exists to deal with the gtk stupidity that sorting can't be disabled */
sortVoid(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer userdata)334 gint sortVoid(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata)
335 {
336     return 0;
337 }
338