- Add renaming support to FileIconView. Also some tweaks to renaming in

FileDetailsView (accidental renaming should now be rare).
- Fix keyboard support for edelib::ExpandableGroup in FIV. The remaining bugs 
are in ExpandableGroup class and not in efiler.
This commit is contained in:
Vedran Ljubovic 2007-08-24 07:51:02 +00:00
parent 9b7ea5dca2
commit 7a59ab12a4
6 changed files with 332 additions and 63 deletions

View File

@ -5,5 +5,7 @@ will be assumed.
- Callback for tree view widget is erratic - it usually doesn't work on Enter - Callback for tree view widget is erratic - it usually doesn't work on Enter
key and sometimes it is sufficient to press arrow up or down to enter a key and sometimes it is sufficient to press arrow up or down to enter a
directory. directory.
- Pressing F2 doesn't start renaming the file
- In icon view, holding shift while clicking has the same effect as ctrl (i.e. - In icon view, holding shift while clicking has the same effect as ctrl (i.e.
adds just the focused widget to selection, not the ones in between) adds just the focused widget to selection, not the ones in between)
- Icon view: sometimes files with @ in name aren't properly aligned

View File

@ -16,6 +16,7 @@
#include <FL/Fl_Input.H> #include <FL/Fl_Input.H>
#include <FL/Fl_Shared_Image.H> #include <FL/Fl_Shared_Image.H>
#include <FL/Fl.H> #include <FL/Fl.H>
#include <FL/Fl_Window.H> // for window() used in ctor
#include <FL/filename.H> // used in update_path() #include <FL/filename.H> // used in update_path()
#include <edelib/Nls.h> #include <edelib/Nls.h>
@ -69,6 +70,7 @@ void FileDetailsView::show_editbox(int row) {
// unselect the row with focus - it's prettier that way // unselect the row with focus - it's prettier that way
select(row,0); select(row,0);
editbox_row=row;
// Copy filename to editbox // Copy filename to editbox
char* filename = strdup(text(row)); char* filename = strdup(text(row));
@ -78,7 +80,6 @@ void FileDetailsView::show_editbox(int row) {
bucket.add(filename); bucket.add(filename);
// make the row "invisible" // make the row "invisible"
editbox_row=row;
char* ntext = (char*)malloc(sizeof(char)*(strlen(text(row))+8)); // add 7 places for format chars char* ntext = (char*)malloc(sizeof(char)*(strlen(text(row))+8)); // add 7 places for format chars
strncpy(ntext+7, text(row), strlen(text(row))); strncpy(ntext+7, text(row), strlen(text(row)));
strncpy(ntext, "@C255@.", 7); strncpy(ntext, "@C255@.", 7);
@ -161,6 +162,7 @@ FileDetailsView::FileDetailsView(int X, int Y, int W, int H, char*label) : EDE_B
//first=0; //first=0;
editbox_ = new EditBox(0, 0, 0, 0); editbox_ = new EditBox(0, 0, 0, 0);
window()->add(editbox_); // this is required to make editbox visible
editbox_->box(FL_BORDER_BOX); editbox_->box(FL_BORDER_BOX);
editbox_->parent(this); editbox_->parent(this);
editbox_->hide(); editbox_->hide();
@ -327,6 +329,8 @@ int FileDetailsView::handle(int e) {
// Click once on item that is already selected AND focused to rename it // Click once on item that is already selected AND focused to rename it
if (e==FL_PUSH && !editbox_->visible() && Fl::event_clicks()==0 && Fl::event_button()==1) { if (e==FL_PUSH && !editbox_->visible() && Fl::event_clicks()==0 && Fl::event_button()==1) {
// allow to click for focusing
if (Fl::focus()!=this) return EDE_Browser::handle(e);
// we're only interested in the first column // we're only interested in the first column
// columns 2-5 are "safe haven" where user can click without renaming anything // columns 2-5 are "safe haven" where user can click without renaming anything
@ -352,8 +356,9 @@ int FileDetailsView::handle(int e) {
renaming=true; // On next event, we will check if it's doubleclick renaming=true; // On next event, we will check if it's doubleclick
} }
if (renaming && (e==FL_DRAG || e==FL_RELEASE || e==FL_MOVE) && Fl::event_is_click()==0) { if (renaming && (e==FL_RELEASE || e==FL_MOVE) && Fl::event_is_click()!=0 && Fl::event_clicks()==0) {
// Fl::event_is_click() will be >0 on doubleclick // Fl::event_is_click() will be ==0 on drag
// Fl::event_clicks() will be >0 on doubleclick
show_editbox(get_focus()); show_editbox(get_focus());
renaming=false; renaming=false;
// don't pass mouse event, otherwise item will become reselected which is a bit ugly // don't pass mouse event, otherwise item will become reselected which is a bit ugly
@ -402,7 +407,7 @@ EDEBUG(DBG "DnD buffer: '%s'\n", selected_items.c_str());
static bool dndrelease=false; // so we know if paste is from dnd or not static bool dndrelease=false; // so we know if paste is from dnd or not
if (e==FL_DND_RELEASE) { if (e==FL_DND_RELEASE) {
EDEBUG(DBG "FL_DND_RELEASE '%s'\n", Fl::event_text()); EDEBUG(DBG "FL_DND_RELEASE (%d,%d)\n", Fl::event_x(), Fl::event_y());
// Sometimes drag is accidental // Sometimes drag is accidental
if (abs(Fl::event_x()-dragx)>MIN_DISTANCE_FOR_DND || abs(Fl::event_y()-dragy)>MIN_DISTANCE_FOR_DND) { if (abs(Fl::event_x()-dragx)>MIN_DISTANCE_FOR_DND || abs(Fl::event_y()-dragy)>MIN_DISTANCE_FOR_DND) {

View File

@ -18,6 +18,7 @@
#include <FL/filename.H> // for FL_PATH_MAX #include <FL/filename.H> // for FL_PATH_MAX
#include <FL/fl_draw.H> // for fl_measure and drawing selection box #include <FL/fl_draw.H> // for fl_measure and drawing selection box
#include <FL/Fl_Shared_Image.H> #include <FL/Fl_Shared_Image.H>
#include <FL/Fl_Window.H> // for window() used in ctor
#include <edelib/Nls.h> #include <edelib/Nls.h>
#include <edelib/String.h> #include <edelib/String.h>
@ -29,6 +30,118 @@
#define DBG "FileIconView: " #define DBG "FileIconView: "
// Dimensions
#define ICONW 70
#define ICONH 80
// Spacing to use between icons
#define ICON_SPACING 5
// Used to make edges of icons less sensitive to selection box, dnd and such
// (e.g. if selection laso only touches a widget with <5px, it will not be selected)
#define SELECTION_EDGE 5
// Sometimes I accidentaly "drag" an icon - don't want dnd to trigger
#define MIN_DISTANCE_FOR_DND 10
// size of editbox
#define EDITBOX_WIDTH (ICONW+50)
// --------------------------------------
//
// File renaming stuff
//
// --------------------------------------
// EditBox is displayed when renaming a file
// We subclass Fl_Input so we can handle keyboard
int FileIconView::EditBox::handle (int e) {
EDEBUG(DBG " Editbox handle(%d)\n", e);
FileIconView* view = (FileIconView*)parent();
// in FIV we handle FL_KEYDOWN and FL_KEYUP - they shouldn't be sent!
if ((e==FL_KEYBOARD || e==FL_KEYDOWN || e==FL_KEYUP) && visible()) {
int k = Fl::event_key();
if (Fl::event_key()==FL_Enter && visible()) {
view->hide_editbox();
view->finish_rename();
} else if (k==FL_Up || k==FL_Down || k==FL_Page_Up || k==FL_Page_Down) {
view->hide_editbox();
return 0; // let the view scroll
} else if (k==FL_F+2 || k==FL_Escape)
view->hide_editbox();
else
Fl_Input::handle(e);
return 1; // don't send keys to view
}
if (e==FL_MOUSEWHEEL && visible()) view->hide_editbox();
return Fl_Input::handle(e);
}
// show editbox at specified row and make the row "invisible" (bgcolor same as fgcolor)
void FileIconView::show_editbox(int row) {
if (!rename_callback_) return;
if (row<1 || row>children()) return; // nothing selected
Fl_Widget* w = child(row-1);
const char* label = w->label();
if (label[0]=='.' && label[1]=='.' && label[2]=='\0') return; // can't rename "go up" button
// unselect the icon with focus - it's prettier that way
select(row,0);
editbox_row=row;
// Copy filename to editbox
char* path_ = strdup(path(row));
if (path_[strlen(path_)-1] == '/') path_[strlen(path_)-1]='\0';
const char* filename = fl_filename_name(path_);
editbox_->value(filename);
free(path_);
// make the label "invisible"
w->labelcolor(FL_BACKGROUND2_COLOR);
// calculate location for editbox
// "Magic constants" here are just nice spacing
int X=w->x() + (w->w()/2) - (EDITBOX_WIDTH/2);
if (X<x()) X=x();
int Y=w->y() + edelib::ICON_SIZE_MEDIUM + 5;
int W=EDITBOX_WIDTH;
int H=FL_NORMAL_SIZE + 4;
EDEBUG(DBG"editbox (%d,%d,%d,%d) \n",X,Y,W,H);
editbox_->resize(X,Y,W,H);
editbox_->show();
editbox_->take_focus();
redraw();
w->redraw();
editbox_->redraw();
}
void FileIconView::hide_editbox() {
EDEBUG(DBG "hide_editbox()\n");
editbox_->hide();
// Make the edited row visible again
Fl_Widget* w = child(editbox_row-1);
w->labelcolor(FL_FOREGROUND_COLOR);
w->redraw(); // label will be updated by rename_callback, if necessary
}
// This is called to actually rename file (when user presses Enter in editbox)
void FileIconView::finish_rename() {
EDEBUG(DBG "finish_rename()\n");
rename_callback_(editbox_->value());
}
// ctor // ctor
#ifdef USE_FLU_WRAP_GROUP #ifdef USE_FLU_WRAP_GROUP
@ -51,6 +164,12 @@ FileIconView::FileIconView(int X, int Y, int W, int H, char*label) : edelib::Exp
rename_callback_ = 0; rename_callback_ = 0;
paste_callback_ = 0; paste_callback_ = 0;
context_callback_ = 0; context_callback_ = 0;
editbox_ = new EditBox(0, 0, 0, 0);
window()->add(editbox_); // this is required to make editbox visible
editbox_->box(FL_BORDER_BOX);
editbox_->parent(this);
editbox_->hide();
} }
@ -129,15 +248,15 @@ void FileIconView::insert(int row, FileItem *item) {
} }
void FileIconView::remove(FileItem *item) { void FileIconView::remove(FileItem *item) {
Fl_Button* b = find_button(item->realpath); Fl_Widget* w = find_icon(item->realpath);
if (b) { if (w) {
#ifdef USE_FLU_WRAP_GROUP #ifdef USE_FLU_WRAP_GROUP
Flu_Wrap_Group::remove(*b); // note that FWG requires to dereference the pointer Flu_Wrap_Group::remove(*w); // note that FWG requires to dereference the pointer
#else #else
edelib::ExpandableGroup::remove(b); edelib::ExpandableGroup::remove(w);
#endif #endif
//remove(b); //remove(w);
delete b; delete w;
} }
} }
@ -155,26 +274,63 @@ void FileIconView::remove(int row) {
void FileIconView::update(FileItem *item) { void FileIconView::update(FileItem *item) {
Fl_Button* b = find_button(item->realpath); Fl_Widget* w = find_icon(item->realpath);
if (!b) return; if (!w) return;
// Tooltip text // Tooltip text
edelib::String tooltip = _("Name: ")+item->name+_("\nSize: ")+item->size+_("\nType: ")+item->description+_("\nDate: ")+item->date+_("\nPermissions: ")+item->permissions; edelib::String tooltip = _("Name: ")+item->name+_("\nSize: ")+item->size+_("\nType: ")+item->description+_("\nDate: ")+item->date+_("\nPermissions: ")+item->permissions;
b->tooltip(strdup(tooltip.c_str())); w->tooltip(strdup(tooltip.c_str()));
// Set icon // Set icon
edelib::String icon = edelib::IconTheme::get(item->icon.c_str(),edelib::ICON_SIZE_MEDIUM); edelib::String icon = edelib::IconTheme::get(item->icon.c_str(),edelib::ICON_SIZE_MEDIUM);
if (icon=="") icon = edelib::IconTheme::get("misc",edelib::ICON_SIZE_MEDIUM,edelib::ICON_CONTEXT_MIMETYPE); if (icon=="") icon = edelib::IconTheme::get("misc",edelib::ICON_SIZE_MEDIUM,edelib::ICON_CONTEXT_MIMETYPE);
b->image(Fl_Shared_Image::get(icon.c_str())); w->image(Fl_Shared_Image::get(icon.c_str()));
b->redraw(); w->redraw();
} }
// This method is needed because update() uses path to find item in list // This method is needed because update() uses path to find item in list
void FileIconView::update_path(const char* oldpath,const char* newpath) { void FileIconView::update_path(const char* oldpath,const char* newpath) {
Fl_Button* b = find_button(oldpath); Fl_Widget* w = find_icon(oldpath);
if (!b) return; if (!w) return;
b->user_data(strdup(newpath)); w->user_data(strdup(newpath));
// Set the label
char buffer[FL_PATH_MAX];
const char* name = fl_filename_name(newpath);
uint j=0;
for (uint i=0; i<strlen(name); i++,j++) {
buffer[j] = name[i];
buffer[j+1] = '\0';
if (buffer[j] == '@') { // escape @
buffer[++j] = '@';
buffer[j+1] = '\0';
}
w->copy_label(buffer);
int lw =0, lh = 0;
fl_measure(w->label(), lw, lh);
if (lw>ICONW) {
if (j==i+2) { // already added 2 newlines
buffer[j-2]='.';
buffer[j-1]='.';
buffer[j]='.';
buffer[j+1]='\0';
j+=2;
break; // for
} else { // add newline
buffer[j+1]=buffer[j];
buffer[j]='\n';
buffer[j+2]='\0';
j++;
}
}
}
while (j<=strlen(name)+2){
buffer[j++]='\n';
//buffer[j++]='L';
}
buffer[j]='\0';
w->copy_label(buffer);
} }
// Select item (if value==1) or unselect (if value==0) // Select item (if value==1) or unselect (if value==0)
@ -219,30 +375,30 @@ EDEBUG(DBG"show_item(%d)\n", row);
Fl_Button* b = (Fl_Button*)child(row-1); Fl_Button* b = (Fl_Button*)child(row-1);
#ifdef USE_FLU_WRAP_GROUP #ifdef USE_FLU_WRAP_GROUP
// scroll_to() will scroll until icon is at the top of view Fl_Scrollbar* s = &scrollbar;
#else
Fl_Scrollbar* s = get_scroll();
#endif
// Flu_Wrap_Group::scroll_to() will scroll until icon is at the top of view
// I prefer that view is scrolled just enough so icon is visible // I prefer that view is scrolled just enough so icon is visible
// FIXME: sometimes b->y() is so large that it wraps around and becomes positive // FIXME: sometimes b->y() is so large that it wraps around and becomes positive
if (b->y()+b->h() > y()+h()) { int scrollto=0;
int scrollto = scrollbar.value() + (b->y()+b->h()-y()-h())+1; if (b->y()+b->h() > y()+h())
EDEBUG(DBG"by: %d bh: %d y: %d h: %d sv: %d\n", b->y(), b->h(), y(), h(), scrollbar.value()); scrollto = s->value() + (b->y()+b->h()-y()-h())+1;
((Fl_Valuator*)&scrollbar)->value(scrollto); else if (b->y() < y())
scrollto = s->value() - (y()-b->y());
if (scrollto) {
EDEBUG(DBG"by: %d bh: %d y: %d h: %d sv: %d\n", b->y(), b->h(), y(), h(), s->value());
#ifdef USE_FLU_WRAP_GROUP
((Fl_Valuator*)s)->value(scrollto);
redraw(); redraw();
draw(); // we need to relayout the group so that b->y() value is updated for next call draw(); // we need to relayout the group so that b->y() value is updated for next call
}
if (b->y() < y())
scroll_to(b);
#else #else
// ExpandableGroup scrolling - not tested and probably broken scrolly(scrollto); // ExpandableGroup method
Fl_Scrollbar* s = get_scroll();
if (b->y() > s->value()+h()) {
// Widget is below current view
scrolly(b->y()+b->h()-h());
} else if (b->y() < s->value()) {
// Widget is above current view
scrolly(b->y());
}
// else { widget is visible, do nothing }
#endif #endif
}
} }
@ -300,6 +456,54 @@ int FileIconView::handle(int e) {
if (b2==child(i)) set_focus(i+1); if (b2==child(i)) set_focus(i+1);
return 1; return 1;
} }
#else
// edelib::ExpandableGroup - Full keyboard navigation
if (e==FL_KEYDOWN) {
int x = get_focus();
// Wrap around
if ((k==FL_Up || k==FL_Left) && x==1)
set_focus(children());
else if ((k==FL_Down || k==FL_Right) && x==children())
set_focus(1);
// Left/right use item ordering
else if (k==FL_Left)
set_focus(x-1);
else if (k==FL_Right)
set_focus(x+1);
// Use widget x() && y() to find item above/below
// This isn't very elegant, but with ExpandableGroup there is no other way...
else {
Fl_Widget* w = child(x-1);
Fl_Widget* w2 = 0;
int dest=0;
for (int i=0; i<children(); i++) {
Fl_Widget* t=child(i);
if (k==FL_Up && t->x()==w->x() && t->y()<w->y())
if (!w2 || w2->y()<t->y()) {
w2=t;
dest=i+1;
}
if (k==FL_Down && t->x()==w->x() && t->y()>w->y())
if (!w2 || w2->y()>t->y()) {
w2=t;
dest=i+1;
}
}
if (w2)
set_focus(dest);
else { // nothing found
if (k==FL_Up)
set_focus(1);
else
set_focus(children());
}
}
return 1;
}
#endif #endif
// Remember focus for restoring later // Remember focus for restoring later
@ -318,7 +522,7 @@ int FileIconView::handle(int e) {
} }
// Tab key should always navigate outside group // Tab key should always navigate outside group
// NOTE: This is code is ugly! I am ashamed... // NOTE: This code is ugly! I am ashamed...
if (e!=FL_NO_EVENT && e!=FL_KEYUP && k==FL_Tab) { // FL_NO_EVENT happens a lot if (e!=FL_NO_EVENT && e!=FL_KEYUP && k==FL_Tab) { // FL_NO_EVENT happens a lot
EDEBUG(DBG"TAB %d - focused: (%s)\n",e,Fl::focus()->label()); EDEBUG(DBG"TAB %d - focused: (%s)\n",e,Fl::focus()->label());
// Try to find another widget to give focus to. // Try to find another widget to give focus to.
@ -365,6 +569,65 @@ EDEBUG(DBG"[X]\n");
/* ------------------------------
Rename support
--------------------------------- */
// If rename_callback_ isn't set, we don't support renaming
if (rename_callback_) {
// hide editbox when user clicks outside of it
if (e==FL_PUSH && editbox_->visible() && !Fl::event_inside(editbox_))
hide_editbox();
// hide editbox when scrolling mouse
if (e==FL_MOUSEWHEEL && editbox_->visible())
hide_editbox();
static bool renaming=false;
// this variable is used because we want to select item on FL_PUSH, but
// actually start editing on FL_RELEASE (otherwise it would be impossible
// to doubleclick)
if (e==FL_PUSH) { renaming=false;
EDEBUG(DBG"FL_PUSH\n");
}
// Click once on item that is already selected AND focused to rename it
if (e==FL_PUSH && !editbox_->visible() && Fl::event_clicks()==0 && Fl::event_button()==1) {
EDEBUG(DBG"start rename\n");
// allow to click for focusing
if (!Fl::focus()->inside(this)) return 1;
// Is click inside a label?
int clicked=0;
for (int i=0; i<children(); i++) {
Fl_Widget* w = child(i);
int X=Fl::event_x(); int Y=Fl::event_y();
if (X>w->x() && X<w->x()+w->w() && Y>w->y()+edelib::ICON_SIZE_MEDIUM && Y<w->y()+w->h())
{ clicked=i+1; break; }
}
// Is clicked item selected and focused?
if (clicked && get_focus()==clicked && selected(clicked)) {
renaming=true; // On next event, we will check if it's doubleclick
} // otherwise, let the event become select/focus event
EDEBUG(DBG"clicked: %d \n",clicked);
if (renaming) EDEBUG(DBG"renaming!\n");
}
if (renaming && (e==FL_RELEASE || e==FL_MOVE) && Fl::event_is_click()!=0 && Fl::event_clicks()==0) {
EDEBUG(DBG"stop rename\n");
// Fl::event_is_click() will be ==0 on drag
// Fl::event_clicks() will be >0 on doubleclick
show_editbox(get_focus());
renaming=false;
// don't pass mouse event, otherwise item will become reselected which is a bit ugly
return 1;
}
}
// ------------------------------------------------ // ------------------------------------------------
// Make Fl_Group behave like proper widget // Make Fl_Group behave like proper widget
// ------------------------------------------------ // ------------------------------------------------

View File

@ -15,14 +15,12 @@
#define EDE_FileIconView_H #define EDE_FileIconView_H
#include <FL/Fl_Button.H>
#include <edelib/String.h> #include <edelib/String.h>
//#include "EDE_FileView.h" //#include "EDE_FileView.h"
// uncomment this to use edelib::ExpandableGroup // comment this to use edelib::ExpandableGroup
#define USE_FLU_WRAP_GROUP #define USE_FLU_WRAP_GROUP
#ifdef USE_FLU_WRAP_GROUP #ifdef USE_FLU_WRAP_GROUP
@ -33,22 +31,6 @@
// Dimensions
#define ICONW 70
#define ICONH 80
// Spacing to use between icons
#define ICON_SPACING 5
// Used to make edges of icons less sensitive to selection box, dnd and such
// (e.g. if selection laso only touches a widget with <5px, it will not be selected)
#define SELECTION_EDGE 5
// Sometimes I accidentaly "drag" an icon - don't want dnd to trigger
#define MIN_DISTANCE_FOR_DND 10
#ifdef USE_FLU_WRAP_GROUP #ifdef USE_FLU_WRAP_GROUP
class FileIconView : public Flu_Wrap_Group { class FileIconView : public Flu_Wrap_Group {
#else #else
@ -69,16 +51,33 @@ private:
// selection box // selection box
int select_x1,select_y1,select_x2,select_y2; int select_x1,select_y1,select_x2,select_y2;
// Find the Fl_Button corresponding to real path (encoded in user_data()) // Find the widget corresponding to real path (encoded in user_data())
Fl_Button* find_button(edelib::String realpath) { Fl_Widget* find_icon(edelib::String realpath) {
for (int i=0; i<children(); i++) { for (int i=0; i<children(); i++) {
Fl_Button* b = (Fl_Button*)child(i); Fl_Widget* w = child(i);
char *tmp = (char*)b->user_data(); char *tmp = (char*)w->user_data();
if (realpath==tmp) return b; if (realpath==tmp) return w;
} }
return 0; return 0;
} }
// EditBox is displayed when renaming a file
// We subclass Fl_Input so we can handle keyboard events
class EditBox : public Fl_Input {
public:
EditBox(int x, int y, int w, int h, const char* label = 0) : Fl_Input(x,y,w,h,label) {}
int handle (int e);
}* editbox_;
int editbox_row;
// show editbox at specified row and make the row "invisible" (bgcolor same as fgcolor)
void show_editbox(int row);
void hide_editbox();
// This is called to actually rename file (when user presses Enter in editbox)
void finish_rename();
public: public:
FileIconView(int X, int Y, int W, int H, char*label=0); FileIconView(int X, int Y, int W, int H, char*label=0);

View File

@ -3,3 +3,5 @@
- Add support for fd.o Trash protocol - Add support for fd.o Trash protocol
- Altnernate line color in browser (add to EDE_Browser) - Altnernate line color in browser (add to EDE_Browser)
- Vertical lines delineating columns (add to EDE_Browser) - Vertical lines delineating columns (add to EDE_Browser)
- Nicer edit box for FileIconView (centered, wrapped, possibly multiline - see
Konqueror)

View File

@ -386,7 +386,6 @@ void do_paste(const char* t) {
fprintf (stderr, "PASTE from '%s', to '%s', type=%d\n",(char*)Fl::event_text(),to,operation); fprintf (stderr, "PASTE from '%s', to '%s', type=%d\n",(char*)Fl::event_text(),to,operation);
if (!strchr(Fl::event_text(), '/')) if (!strchr(Fl::event_text(), '/'))
return; // User is pasting something that isn't files return; // User is pasting something that isn't files
// TODO: create a text file? // TODO: create a text file?
@ -468,7 +467,6 @@ fprintf (stderr, "from[%d]='%s'\n", k, from[k]);
else else
c = ede_choice_alert(tsprintf(_("Copy or move these %d files to directory\n\t%s ?"), count, to), _("C&ancel"), _("&Copy"), _("&Move")); c = ede_choice_alert(tsprintf(_("Copy or move these %d files to directory\n\t%s ?"), count, to), _("C&ancel"), _("&Copy"), _("&Move"));
fprintf(stderr, "Exited choice_alert\n");
if (c==0) goto FINISH; if (c==0) goto FINISH;
if (c==1) operation=COPY; else operation=CUT; if (c==1) operation=COPY; else operation=CUT;
} }