From 75c41fa848c0f0ead653e34a1b294c308107635f Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Mon, 19 Jul 1999 14:43:48 +0000 Subject: [PATCH] r20: Drag and drop loading and saving works (locally and remotely). --- ROX-Filer/pixmaps/folder.xpm | 164 ---------------- ROX-Filer/src/dnd.c | 437 ++++++++++++++++++++++++++++++------------- ROX-Filer/src/filer.c | 22 ++- ROX-Filer/src/filer.h | 3 +- ROX-Filer/src/pixmaps.h | 3 + 5 files changed, 327 insertions(+), 302 deletions(-) delete mode 100644 ROX-Filer/pixmaps/folder.xpm diff --git a/ROX-Filer/pixmaps/folder.xpm b/ROX-Filer/pixmaps/folder.xpm deleted file mode 100644 index 4eb7f0f1..00000000 --- a/ROX-Filer/pixmaps/folder.xpm +++ /dev/null @@ -1,164 +0,0 @@ -/* XPM */ -static char * folder_xpm[] = { -"44 28 133 2", -" c None", -". c #000000000000", -"X c #53538E8EEDED", -"o c #52528D8DECEC", -"O c #51518C8CEBEB", -"+ c #51518A8AEBEB", -"@ c #50508989EAEA", -"# c #4F4F8888E9E9", -"$ c #4F4F8787E9E9", -"% c #4E4E8585E8E8", -"& c #4D4D8484E7E7", -"* c #4C4C8383E7E7", -"= c #4C4C8282E6E6", -"- c #4B4B8080E5E5", -"; c #4A4A7F7FE5E5", -": c #52528C8CECEC", -"> c #51518B8BEBEB", -", c #4F4F8888EAEA", -"< c #4E4E8686E8E8", -"1 c #4D4D8484E8E8", -"2 c #4D4D8383E7E7", -"3 c #4B4B8181E6E6", -"4 c #4A4A7E7EE4E4", -"5 c #49497D7DE4E4", -"6 c #50508A8AEAEA", -"7 c #4A4A7F7FE4E4", -"8 c #49497C7CE3E3", -"9 c #48487B7BE2E2", -"0 c #4E4E8686E9E9", -"q c #4C4C8181E6E6", -"w c #49497E7EE4E4", -"e c #48487B7BE3E3", -"r c #47477A7AE2E2", -"t c #47477979E1E1", -"y c #50508888EAEA", -"u c #48487C7CE3E3", -"i c #47477979E2E2", -"p c #45457676E0E0", -"a c #44447474DFDF", -"s c #43437373DEDE", -"d c #43437272DEDE", -"f c #42427171DDDD", -"g c #41416F6FDCDC", -"h c #41416E6EDCDC", -"j c #40406D6DDBDB", -"k c #3F3F6C6CDADA", -"l c #3E3E6A6ADADA", -"z c #3E3E6969D9D9", -"x c #3D3D6868D8D8", -"c c #3C3C6767D8D8", -"v c #3C3C6666D7D7", -"b c #3B3B6464D6D6", -"n c #3A3A6363D6D6", -"m c #39396262D5D5", -"M c #39396161D4D4", -"N c #38385F5FD4D4", -"B c #50508A8AEBEB", -"V c #46467979E1E1", -"C c #46467777E1E1", -"Z c #44447575DFDF", -"A c #41417070DDDD", -"S c #3F3F6C6CDBDB", -"D c #3F3F6B6BDADA", -"F c #3E3E6A6AD9D9", -"G c #3D3D6868D9D9", -"H c #3D3D6767D8D8", -"J c #3B3B6565D7D7", -"K c #3A3A6262D5D5", -"L c #39396161D5D5", -"P c #38386060D4D4", -"I c #38385E5ED3D3", -"U c #37375D5DD3D3", -"Y c #49497D7DE3E3", -"T c #46467878E1E1", -"R c #45457575DFDF", -"E c #42427070DDDD", -"W c #40406E6EDBDB", -"Q c #40406C6CDBDB", -"! c #3D3D6969D9D9", -"~ c #3A3A6363D5D5", -"^ c #38385F5FD3D3", -"/ c #37375E5ED3D3", -"( c #36365C5CD2D2", -") c #36365B5BD1D1", -"_ c #2D2D4B4BC9C9", -"` c #4C4C8282E7E7", -"' c #44447373DFDF", -"] c #37375D5DD2D2", -"[ c #35355B5BD1D1", -"{ c #35355959D0D0", -"} c #3A3A6464D6D6", -"| c #35355A5AD1D1", -" . c #34345858D0D0", -".. c #48487A7AE2E2", -"X. c #45457777E0E0", -"o. c #45457575E0E0", -"O. c #40406E6EDCDC", -"+. c #3C3C6666D8D8", -"@. c #39396060D4D4", -"#. c #36365D5DD2D2", -"$. c #36365B5BD2D2", -"%. c #34345959D0D0", -"&. c #4D4D8585E8E8", -"*. c #46467777E0E0", -"=. c #41417070DCDC", -"-. c #3E3E6B6BDADA", -";. c #33335757CFCF", -":. c #33335656CFCF", -">. c #4B4B8080E6E6", -",. c #42427272DDDD", -"<. c #32325555CECE", -"1. c #3C3C6565D7D7", -"2. c #32325454CECE", -"3. c #35355959D1D1", -"4. c #32325656CFCF", -"5. c #31315353CDCD", -"6. c #31315454CDCD", -"7. c #31315252CDCD", -"8. c #31315454CECE", -"9. c #30305151CCCC", -"0. c #44447373DEDE", -"q. c #30305252CCCC", -"w. c #30305252CDCD", -"e. c #2F2F5050CBCB", -"r. c #34345757D0D0", -"t. c #2F2F4F4FCBCB", -"y. c #2F2F5050CCCC", -"u. c #2E2E4E4ECACA", -"i. c #2E2E4E4ECBCB", -"p. c #2E2E4D4DCACA", -"a. c #2E2E4F4FCBCB", -"s. c #2D2D4C4CC9C9", -"d. c #2D2D4C4CCACA", -" . . . . . . . . . . . . . . ", -" . X X o O + @ # $ % & * = - ; . ", -" . X X o : > @ , $ < 1 2 = 3 ; 4 5 . ", -" . X X X : > 6 @ $ < % & = 3 - 7 5 8 9 . ", -" . X X X o > + @ # 0 % & * q - ; w 8 e r t . ", -". . o o o o o o o * * * * * * * * * r r r r . . . . . . . . . . . . . . . . . . . . ", -". X X o : > 6 y * * * 2 = 3 - 4 5 u 9 i r r p a s d f g h j k l z x c v b n m M N . . ", -". X X : > B @ $ 0 % & * 3 - ; w 8 e r V C p Z a d f A g j S D F G H v J n K L P I U . . ", -". X o O + @ # $ % & * = - ; 4 Y e r t T p R a s f E g W Q D F ! H v J b ~ L P ^ / ( ) . ", -". _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ . ", -". : > B @ $ 0 % & ` 3 - ; 5 8 e r T C p Z ' d f A h j S D z x c v b n K M P / ] ( [ { . ", -". > + @ # 0 % & * q - ; w Y e r t T p Z a s f E g W S D F ! H v J } K L P ^ U ( [ | .. ", -". > @ , $ < 1 2 = 3 ; 4 5 u ..i T X.o.a s d E g O.j D l z x +.J b n L @.N / #.$.| %. .. ", -". 6 y $ < &.2 = 3 - 4 5 u 9 r T *.p Z s d f =.h j k -.z x c v b n m M N / ] ( | %. .;.. ", -". @ # 0 % & * q - ; w 8 e r t C p Z a d f E g j S D F G H v J n K L P I U ( [ | .;.:.. ", -". , $ % 1 * = >.; 4 5 e r i T X.R a s ,.E g W j D F ! x v J b ~ L P ^ / ( ) | %.;.:.<.. ", -". $ < &.2 = 3 - 4 5 u 9 i T *.p a s d f g h j k l z x c 1.b n m @.N / ] $.| %. .;.<.2.. ", -". 0 % & ` 3 - ; 5 8 e r T C p Z a d f A g j S D F G c v J n K L P / U ( [ 3. .;.4.2.5.. ", -". % & * = - ; 4 Y e r t T p R a s f E g W Q D F ! H v J b K L P ^ U ( ) | .;.:.<.6.7.. ", -". 1 2 = 3 ; 4 5 u ..i T X.o.a s d f g O.j k l z x c J b n m @.N / #.$.| %. .:.<.8.5.9.. ", -". & ` 3 - 7 5 8 9 r T *.p Z 0.d f =.h j k D z x c v b n K M N / ] ( | { .;.<.2.5.q.9.. ", -". * q - ; w 8 e r t C p Z a d f E g W S D F ! H v J } K L P ^ U ( [ | .;.:.<.5.w.9.e.. ", -". = 3 ; 4 5 u ..i T X.o.a s d E g O.j D l z x +.J b n L @.N / ( $.| %.r.:.<.8.7.9.e.t.. ", -". 3 - 4 5 u 9 i T *.p a s d f g h j k -.z x c v b n m M N / ] ( | %. .;.<.2.5.q.y.t.u.. ", -". - ; w 8 e r t C p Z a d f E g j S D F G H v J n K L P I U ( [ 3. .;.:.2.5.w.9.t.i.p.. ", -". ; 4 Y e r t T p R a s f E g W Q D F ! x v J b ~ L P ^ / ( ) | %.;.:.<.6.7.9.e.a.p.s.. ", -". 4 5 u 9 i T *.p a s d f g h j k l z x c 1.b n m @.N / ] $.| %. .:.<.2.5.9.y.t.u.d._ . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "}; diff --git a/ROX-Filer/src/dnd.c b/ROX-Filer/src/dnd.c index d631b4aa..63ee42c1 100644 --- a/ROX-Filer/src/dnd.c +++ b/ROX-Filer/src/dnd.c @@ -9,7 +9,11 @@ #include #include +#include #include +#include +#include +#include #include #include @@ -53,7 +57,99 @@ static void drag_data_received(GtkWidget *widget, GtkSelectionData *selection_data, guint info, guint32 time); +static void got_data_xds_reply(GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint32 time); +static void got_data_raw(GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint32 time); +static gboolean load_file(char *pathname, char **data_out, long *length_out); + +void dnd_init() +{ + XdndDirectSave0 = gdk_atom_intern("XdndDirectSave0", FALSE); + text_plain = gdk_atom_intern("text/plain", FALSE); + application_octet_stream = gdk_atom_intern("application/octet-stream", + FALSE); +} + +/* Set the XdndDirectSave0 property on the source window for this context */ +static void set_xds_prop(GdkDragContext *context, char *text) +{ + gdk_property_change(context->source_window, + XdndDirectSave0, + text_plain, 8, + GDK_PROP_MODE_REPLACE, + text, + strlen(text)); +} +static char *get_xds_prop(GdkDragContext *context) +{ + guchar *prop_text; + gint length; + + if (gdk_property_get(context->source_window, + XdndDirectSave0, + text_plain, + 0, MAXURILEN, + FALSE, + NULL, NULL, + &length, &prop_text) && prop_text) + { + /* Terminate the string */ + prop_text = g_realloc(prop_text, length + 1); + prop_text[length] = '\0'; + return prop_text; + } + + return NULL; +} + +/* Is the sender willing to supply this target type? */ +static gboolean provides(GdkDragContext *context, GdkAtom target) +{ + GList *targets = context->targets; + + while (targets && ((GdkAtom) targets->data != target)) + targets = targets->next; + + return targets != NULL; +} + +/* Append all the URIs in the selection to the string */ +static void create_uri_list(GString *string, + Collection *collection, + FilerWindow *filer_window) +{ + GString *leader; + int i, num_selected; + + leader = g_string_new("file://"); + g_string_append(leader, our_host_name()); + g_string_append(leader, filer_window->path); + if (leader->str[leader->len - 1] != '/') + g_string_append_c(leader, '/'); + + num_selected = collection->number_selected; + + for (i = 0; num_selected > 0; i++) + { + if (collection->items[i].selected) + { + FileItem *item = (FileItem *) collection->items[i].data; + + g_string_append(string, leader->str); + g_string_append(string, item->leafname); + g_string_append(string, "\r\n"); + num_selected--; + } + } + + g_string_free(leader, TRUE); +} static FileItem *selected_item(Collection *collection) { @@ -72,8 +168,13 @@ static FileItem *selected_item(Collection *collection) return NULL; } +/* DRAGGING FROM US */ + /* The user has held the mouse button down over an item and moved - * start a drag. + * + * We always provide text/uri-list. If we are dragging a single, regular file + * then we also offer application/octet-stream. */ void drag_selection(Collection *collection, GdkEventMotion *event, @@ -90,11 +191,17 @@ void drag_selection(Collection *collection, {"text/uri-list", 0, TARGET_URI_LIST}, {"application/octet-stream", 0, TARGET_RAW}, }; + FileItem *item; + + if (number_selected == 1) + item = selected_item(collection); + else + item = NULL; widget = GTK_WIDGET(collection); target_list = gtk_target_list_new(target_table, - number_selected == 1 ? 2 : 1); + item && item->base_type == TYPE_FILE ? 2 : 1); context = gtk_drag_begin(widget, target_list, @@ -103,8 +210,7 @@ void drag_selection(Collection *collection, (GdkEvent *) event); g_dataset_set_data(context, "filer_window", filer_window); - image = number_selected == 1 ? selected_item(collection)->image - : &default_pixmap[TYPE_MULTIPLE]; + image = item ? item->image : &default_pixmap[TYPE_MULTIPLE]; gtk_drag_set_icon_pixmap(context, gtk_widget_get_colormap(widget), @@ -113,7 +219,10 @@ void drag_selection(Collection *collection, 0, 0); } -/* Called when a remote app wants us to send it some data */ +/* Called when a remote app wants us to send it some data. + * TODO: Maybe we should handle errors better (ie, let the remote app know + * the drag has failed)? + */ void drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, @@ -121,11 +230,12 @@ void drag_data_get(GtkWidget *widget, guint32 time) { char *to_send = "E"; /* Default to sending an error */ - int to_send_length = 1; + long to_send_length = 1; gboolean delete_once_sent = FALSE; GdkAtom type = XA_STRING; GString *string; FilerWindow *filer_window; + FileItem *item; filer_window = g_dataset_get_data(context, "filer_window"); g_return_if_fail(filer_window != NULL); @@ -133,15 +243,16 @@ void drag_data_get(GtkWidget *widget, switch (info) { case TARGET_RAW: - report_error("drag_data_get", "send file contents"); - /* - to_send = gtk_editable_get_chars(GTK_EDITABLE(text), - 0, -1); - to_send_length = gtk_text_get_length(GTK_TEXT(text)); - delete_once_sent = TRUE; - type = text_plain; - */ - break; + item = selected_item(filer_window->collection); + if (item && load_file(make_path(filer_window->path, + item->leafname)->str, + &to_send, &to_send_length)) + { + delete_once_sent = TRUE; + type = application_octet_stream; /* XXX */ + break; + } + return; case TARGET_URI_LIST: string = g_string_new(NULL); create_uri_list(string, @@ -167,38 +278,58 @@ void drag_data_get(GtkWidget *widget, g_free(to_send); } -/* Append all the URIs in the selection to the string */ -static void create_uri_list(GString *string, - Collection *collection, - FilerWindow *filer_window) +/* Load the file into memory. Return TRUE on success. */ +static gboolean load_file(char *pathname, char **data_out, long *length_out) { - GString *leader; - int i, num_selected; + FILE *file; + long length; + char *buffer; + gboolean retval = FALSE; - leader = g_string_new("file://"); - g_string_append(leader, our_host_name()); - g_string_append(leader, filer_window->path); - if (leader->str[leader->len - 1] != '/') - g_string_append_c(leader, '/'); + file = fopen(pathname, "r"); - num_selected = collection->number_selected; + if (!file) + { + report_error("Opening file for DND", g_strerror(errno)); + return FALSE; + } - for (i = 0; num_selected > 0; i++) + fseek(file, 0, SEEK_END); + length = ftell(file); + + buffer = malloc(length); + if (buffer) { - if (collection->items[i].selected) + fseek(file, 0, SEEK_SET); + fread(buffer, 1, length, file); + + if (ferror(file)) { - FileItem *item = (FileItem *) collection->items[i].data; - - g_string_append(string, leader->str); - g_string_append(string, item->leafname); - g_string_append(string, "\r\n"); - num_selected--; + report_error("Loading file for DND", g_strerror(errno)); + g_free(buffer); + } + else + { + *data_out = buffer; + *length_out = length; + retval = TRUE; } } + else + report_error("Loading file for DND", + "Can't allocate memory for buffer to " + "transfer this file"); - g_string_free(leader, TRUE); + fclose(file); + + return retval; } +/* DRAGGING TO US */ + +/* Set up this filer window as a drop target. Called once, when the + * filer window is first created. + */ void drag_set_dest(GtkWidget *widget, FilerWindow *filer_window) { GtkTargetEntry target_table[] = @@ -212,7 +343,8 @@ void drag_set_dest(GtkWidget *widget, FilerWindow *filer_window) GTK_DEST_DEFAULT_MOTION, target_table, sizeof(target_table) / sizeof(*target_table), - GDK_ACTION_COPY | GDK_ACTION_PRIVATE); + GDK_ACTION_COPY | GDK_ACTION_MOVE + | GDK_ACTION_LINK | GDK_ACTION_PRIVATE); gtk_signal_connect(GTK_OBJECT(widget), "drag_drop", GTK_SIGNAL_FUNC(drag_drop), filer_window); @@ -220,6 +352,9 @@ void drag_set_dest(GtkWidget *widget, FilerWindow *filer_window) GTK_SIGNAL_FUNC(drag_data_received), filer_window); } +/* User has tried to drop some data on us. Decide what format we would + * like the data in. + */ static gboolean drag_drop(GtkWidget *widget, GdkDragContext *context, gint x, @@ -236,41 +371,39 @@ static gboolean drag_drop(GtkWidget *widget, if (gtk_drag_get_source_widget(context) == widget) { - gtk_drag_finish(context, - FALSE, /* Success */ - FALSE, /* Delete */ - time); + /* Ignore drags within a single window */ + gtk_drag_finish(context, FALSE, FALSE, time); /* Failure */ return TRUE; } if (provides(context, XdndDirectSave0)) { - guchar *prop_text; /* Note - not terminated */ - guint length; - - if (gdk_property_get(context->source_window, - XdndDirectSave0, - text_plain, - 0, MAXURILEN, - FALSE, - NULL, NULL, - &length, &prop_text) - && prop_text) + leafname = get_xds_prop(context); + if (leafname) { - if (memchr(prop_text, '/', length)) + if (strchr(leafname, '/')) { error = "XDS protocol error: " "leafname may not contain '/'\n"; - g_free(prop_text); + g_free(leafname); + + leafname = NULL; } else { - /* Terminate the string */ - leafname = g_realloc(prop_text, length + 1); - leafname[length] = '\0'; + GString *uri; + + uri = g_string_new(NULL); + g_string_sprintf(uri, "file://%s%s", + our_host_name(), + make_path(filer_window->path, + leafname)->str); + set_xds_prop(context, uri->str); + g_string_free(uri, TRUE); - set_xds_prop(context, "file://wibble/bob"); target = XdndDirectSave0; + g_dataset_set_data_full(context, "leafname", + leafname, g_free); } } else @@ -292,43 +425,11 @@ static gboolean drag_drop(GtkWidget *widget, else gtk_drag_get_data(widget, context, target, time); - g_free(leafname); - return TRUE; } -/* Is the sender willing to supply this target type? */ -static gboolean provides(GdkDragContext *context, GdkAtom target) -{ - GList *targets = context->targets; - - while (targets && ((GdkAtom) targets->data != target)) - targets = targets->next; - - return targets != NULL; -} - -void dnd_init() -{ - XdndDirectSave0 = gdk_atom_intern("XdndDirectSave0", FALSE); - text_plain = gdk_atom_intern("text/plain", FALSE); - application_octet_stream = gdk_atom_intern("application/octet-stream", - FALSE); -} - -/* Set the XdndDirectSave0 property on the source window for this context */ -static void set_xds_prop(GdkDragContext *context, char *text) -{ - gdk_property_change(context->source_window, - XdndDirectSave0, - text_plain, 8, - GDK_PROP_MODE_REPLACE, - text, - strlen(text)); -} - /* Called when some data arrives from the remote app (which we asked for - * in drag_drop. + * in drag_drop). */ static void drag_data_received(GtkWidget *widget, GdkDragContext *context, @@ -341,57 +442,139 @@ static void drag_data_received(GtkWidget *widget, if (!selection_data->data) { /* Timeout? */ - gtk_drag_finish(context, FALSE, FALSE, time); + gtk_drag_finish(context, FALSE, FALSE, time); /* Failure */ return; } - if (selection_data->target == XdndDirectSave0) + switch (info) { - char response = *selection_data->data; - - if (selection_data->length != 1 || !strchr("SFE", response)) - { + case TARGET_XDS: + got_data_xds_reply(widget, context, + selection_data, time); + break; + case TARGET_RAW: + got_data_raw(widget, context, selection_data, time); + break; + case TARGET_URI_LIST: gtk_drag_finish(context, FALSE, FALSE, time); - report_error("ROX-Filer", - "XDS return code should be 'S', 'F' or 'E'\n"); - return; - } - - if (response == 'E') - { - /* Error reported by sender - abort silently */ + report_error("drag_data_received", "got URI list"); + break; + default: gtk_drag_finish(context, FALSE, FALSE, time); - return; - } + report_error("drag_data_received", "Unknown target"); + break; + } +} + +static void got_data_xds_reply(GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint32 time) +{ + gboolean mark_unsafe = TRUE; + char response = *selection_data->data; + char *error = NULL; + + if (selection_data->length != 1) + response = '?'; - if (response == 'F') + if (response == 'F') + { + /* Sender couldn't save there - ask for another + * type if possible. + */ + if (provides(context, application_octet_stream)) { - /* Sender couldn't save there - ask for another - * type if possible. - */ - if (provides(context, application_octet_stream)) - { - gtk_drag_get_data(widget, context, - application_octet_stream, time); - } - else - { - gtk_drag_finish(context, FALSE, FALSE, time); - report_error("ROX-Filer", - "Remote app can't or won't send me " - "the data - sorry"); - } + mark_unsafe = FALSE; /* Wait and see */ - return; + gtk_drag_get_data(widget, context, + application_octet_stream, time); } + else + error = "Remote app can't or won't send me " + "the data - sorry"; + } + else if (response == 'S') + { + FilerWindow *filer_window; + /* Success - data is saved */ + mark_unsafe = FALSE; /* It really is safe */ gtk_drag_finish(context, TRUE, FALSE, time); - report_error("ROX-Filer", "Saved OK"); + + filer_window = gtk_object_get_data(GTK_OBJECT(widget), + "filer_window"); + g_return_if_fail(filer_window != NULL); + + scan_dir(filer_window); } - else + else if (response != 'E') { - set_xds_prop(context, ""); /* Clear to indicate failure */ + error = "XDS protocol error: " + "return code should be 'S', 'F' or 'E'\n"; + } + /* else: error has been reported by the sender */ + + if (mark_unsafe) + { + set_xds_prop(context, ""); + /* Unsave also implies that the drag failed */ gtk_drag_finish(context, FALSE, FALSE, time); - report_error("drag_data_received", "got raw data"); } + + if (error) + { + report_error("ROX-Filer", error); + } +} + +static void got_data_raw(GtkWidget *widget, + GdkDragContext *context, + GtkSelectionData *selection_data, + guint32 time) +{ + FilerWindow *filer_window; + char *leafname; + int fd; + char *error = NULL; + gboolean using_XDS = TRUE; + + filer_window = gtk_object_get_data(GTK_OBJECT(widget), "filer_window"); + g_return_if_fail(filer_window != NULL); + + leafname = g_dataset_get_data(context, "leafname"); + + if (!leafname) + { + using_XDS = FALSE; + leafname = "UntitledData"; /* TODO: Find a better name */ + } + + fd = open(make_path(filer_window->path, leafname)->str, + O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, + S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IWGRP | S_IWOTH); + + if (fd == -1) + error = g_strerror(errno); + else + { + if (write(fd, + selection_data->data, + selection_data->length) != -1) + error = g_strerror(errno); + + if (close(fd) != -1 && !error) + error = g_strerror(errno); + + scan_dir(filer_window); + } + + if (error) + { + set_xds_prop(context, ""); + gtk_drag_finish(context, FALSE, FALSE, time); /* Failure */ + report_error("Error saving file", error); + } + else + gtk_drag_finish(context, TRUE, FALSE, time); /* Success! */ } diff --git a/ROX-Filer/src/filer.c b/ROX-Filer/src/filer.c index 3750be30..331afe6d 100644 --- a/ROX-Filer/src/filer.c +++ b/ROX-Filer/src/filer.c @@ -170,20 +170,23 @@ static void add_item(FilerWindow *filer_window, char *leafname) base_type = TYPE_UNKNOWN; } + item->base_type = base_type; + if (base_type == TYPE_DIRECTORY) { /* Might be an application directory - better check... */ path = g_string_append(path, "/AppInfo"); if (!stat(path->str, &info)) - { - base_type = TYPE_APPDIR; - } + item->flags |= ITEM_FLAG_APPDIR; } - item->base_type = base_type; + + if (item->flags & ITEM_FLAG_APPDIR) + item->image = default_pixmap + TYPE_APPDIR; + else + item->image = default_pixmap + base_type; item->text_width = gdk_string_width(filer_window->window->style->font, leafname); - item->image = default_pixmap + base_type; /* XXX: Must be a better way... */ item->pix_width = ((GdkPixmapPrivate *) item->image->pixmap)->width; @@ -332,16 +335,15 @@ void open_item(Collection *collection, switch (item->base_type) { - case TYPE_APPDIR: - if (event->type != GDK_2BUTTON_PRESS || - (event->state & GDK_SHIFT_MASK) == 0) + case TYPE_DIRECTORY: + if (item->flags & ITEM_FLAG_APPDIR && + (event->type != GDK_2BUTTON_PRESS || + (event->state & GDK_SHIFT_MASK) == 0)) { run_app(make_path(filer_window->path, item->leafname)->str); break; } - /* FALLTHROUGH */ - case TYPE_DIRECTORY: if (event->type != GDK_2BUTTON_PRESS || event->button == 1) { diff --git a/ROX-Filer/src/filer.h b/ROX-Filer/src/filer.h index 03ae5928..5b965dd5 100644 --- a/ROX-Filer/src/filer.h +++ b/ROX-Filer/src/filer.h @@ -19,7 +19,8 @@ typedef struct _FileItem FileItem; enum { - ITEM_FLAG_SYMLINK = 0x1, + ITEM_FLAG_SYMLINK = 0x1, /* Is a symlink */ + ITEM_FLAG_APPDIR = 0x2, /* Contains /AppInfo */ }; struct _FilerWindow diff --git a/ROX-Filer/src/pixmaps.h b/ROX-Filer/src/pixmaps.h index f4181596..313011f2 100644 --- a/ROX-Filer/src/pixmaps.h +++ b/ROX-Filer/src/pixmaps.h @@ -12,6 +12,7 @@ enum { + /* Base types */ TYPE_ERROR, TYPE_UNKNOWN, TYPE_SYMLINK, @@ -21,6 +22,8 @@ enum TYPE_BLOCK_DEVICE, TYPE_PIPE, TYPE_SOCKET, + + /* Extended types */ TYPE_MULTIPLE, TYPE_APPDIR, LAST_DEFAULT_PIXMAP -- 2.11.4.GIT