Defuzzied one entry
[midnight-commander.git] / gnome / gdialogs.c
blob223023451998fcd1a5982893ea49312b37728e77
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
2 /* New dialogs... */
3 #include <config.h>
4 #include "panel.h"
5 #include "x.h"
6 #include "dialog.h"
7 #include "global.h"
8 #include "file.h"
9 #include "filegui.h"
10 #include "fileopctx.h"
11 #include "eregex.h"
12 #include "main.h"
13 #include "../vfs/vfs.h"
15 enum {
16 REPLACE_PROMPT,
17 REPLACE_ALWAYS,
18 REPLACE_UPDATE,
19 REPLACE_NEVER,
20 REPLACE_ABORT,
21 REPLACE_SIZE,
22 REPLACE_OPTION_MENU
23 } FileReplaceCode;
25 /* This structure describes the UI and internal data required by a file
26 * operation context.
28 typedef struct {
29 /* The progress window */
30 GtkWidget *op_win;
32 /* Set to FALSE in file_op_context_create_ui, set on the cancel_cb if
33 * user click on Cancel.
35 gboolean aborting;
37 /* Source file label */
38 GtkWidget *op_source_label;
40 /* Target file label */
41 GtkWidget *op_target_label;
43 /* File number label */
44 GtkObject *count_label;
46 /* Current file label */
47 GtkWidget *file_label;
49 /* Bytes progress bar */
50 GtkObject *byte_prog;
52 /* Copy status in query replace dialog */
53 int copy_status;
54 int minor_copy_status;
56 /* Overwrite toggle */
57 GtkWidget *op_radio;
58 } FileOpContextUI;
60 static char *gdialog_to_string = N_("To: ");
61 static char *gdialog_from_string = N_("Copying from: ");
62 static char *gdialog_deleting_string = N_("Deleting file: ");
64 #define GDIALOG_PROGRESS_WIDTH 350
66 /* Callbacks go here... */
67 static void
68 fmd_check_box_callback (GtkWidget *widget, gpointer data)
70 if (data)
71 *((gint*)data) = GTK_TOGGLE_BUTTON (widget)->active;
74 static gchar *
75 trim_file_name (FileOpContextUI *ui, gchar *path, gint length, gint cur_length)
77 static gint dotdotdot = 0;
78 gchar *path_copy = NULL;
79 gint len;
81 if (!dotdotdot)
82 dotdotdot = gdk_string_width (ui->op_source_label->style->font, "...");
83 /* Cut the font length of path to length. */
85 length -= dotdotdot;
86 len = (gint) ((1.0 - (gfloat) length / (gfloat) cur_length) * strlen (path));
88 /* we guess a starting point */
89 if (gdk_string_width (ui->op_source_label->style->font, path + len) < length) {
90 while (gdk_string_width (ui->op_source_label->style->font, path + len) < length)
91 len--;
92 len++;
93 } else {
94 while (gdk_string_width (ui->op_source_label->style->font, path + len) > length)
95 len++;
98 path_copy = g_strdup_printf ("...%s", path + len);
99 return path_copy;
102 FileProgressStatus
103 file_progress_show_source (FileOpContext *ctx, char *path)
105 static gint from_width = 0;
106 FileOpContextUI *ui;
107 gint path_width;
108 gchar *path_copy = NULL;
110 g_return_val_if_fail (ctx != NULL, FILE_CONT);
112 /* ctx->ui might be NULL for background processes */
113 if (ctx->ui == NULL)
114 return FILE_CONT;
116 ui = ctx->ui;
118 g_return_val_if_fail (ui->op_source_label != NULL, FILE_CONT);
120 if (ui->aborting)
121 return FILE_ABORT;
123 if (path == NULL){
124 gtk_label_set_text (GTK_LABEL (ui->op_source_label), "");
125 return FILE_CONT;
128 if (!from_width){
129 from_width = gdk_string_width (ui->op_source_label->style->font,
130 _(gdialog_from_string));
132 path_width = gdk_string_width (ui->op_source_label->style->font, path);
133 if (from_width + path_width < GDIALOG_PROGRESS_WIDTH)
134 gtk_label_set_text (GTK_LABEL (ui->op_source_label), path);
135 else {
136 path_copy = trim_file_name (ui, path, GDIALOG_PROGRESS_WIDTH - from_width,
137 path_width);
139 gtk_label_set_text (GTK_LABEL (ui->op_source_label), path_copy);
140 g_free (path_copy);
143 return FILE_CONT;
146 FileProgressStatus
147 file_progress_show_target (FileOpContext *ctx, char *path)
149 static gint to_width = 0;
150 FileOpContextUI *ui;
151 gint path_width;
152 gchar *path_copy = NULL;
154 g_return_val_if_fail (ctx != NULL, FILE_CONT);
155 /* ctx->ui might be NULL for background processes */
156 if (ctx->ui == NULL)
157 return FILE_CONT;
159 ui = ctx->ui;
161 g_return_val_if_fail (ui->op_target_label != NULL, FILE_CONT);
163 if (ui->aborting)
164 return FILE_ABORT;
166 if (path == NULL){
167 gtk_label_set_text (GTK_LABEL (ui->op_target_label), "");
168 return FILE_CONT;
171 if (!to_width)
172 to_width = gdk_string_width (ui->op_target_label->style->font,
173 _(gdialog_to_string));
174 path_width = gdk_string_width (ui->op_target_label->style->font, path);
175 if (to_width + path_width < GDIALOG_PROGRESS_WIDTH)
176 gtk_label_set_text (GTK_LABEL (ui->op_target_label), path);
177 else {
178 path_copy = trim_file_name (ui, path, GDIALOG_PROGRESS_WIDTH - to_width, path_width);
179 gtk_label_set_text (GTK_LABEL (ui->op_target_label), path_copy);
180 g_free (path_copy);
183 return FILE_CONT;
186 FileProgressStatus
187 file_progress_show_deleting (FileOpContext *ctx, char *path)
189 static gint deleting_width = 0;
190 FileOpContextUI *ui;
191 gint path_width;
192 gchar *path_copy = NULL;
194 g_return_val_if_fail (ctx != NULL, FILE_CONT);
196 /* ctx->ui might be NULL for background processes */
197 if (ctx->ui == NULL)
198 return FILE_CONT;
200 ui = ctx->ui;
202 if (ui->aborting)
203 return FILE_ABORT;
205 if (path == NULL){
206 gtk_label_set_text (GTK_LABEL (ui->op_source_label), "");
207 return FILE_CONT;
210 if (!deleting_width){
211 deleting_width = gdk_string_width (ui->op_source_label->style->font,
212 _(gdialog_deleting_string));
214 path_width = gdk_string_width (ui->op_source_label->style->font, path);
215 if (deleting_width + path_width < GDIALOG_PROGRESS_WIDTH)
216 gtk_label_set_text (GTK_LABEL (ui->op_source_label), path);
217 else {
218 path_copy = trim_file_name (ui, path, GDIALOG_PROGRESS_WIDTH - deleting_width,
219 path_width);
221 gtk_label_set_text (GTK_LABEL (ui->op_source_label), path_copy);
222 g_free (path_copy);
224 return FILE_CONT;
227 FileProgressStatus
228 file_progress_show (FileOpContext *ctx, long done, long total)
230 static gchar count[20];
231 FileOpContextUI *ui;
232 double perc;
234 g_return_val_if_fail (ctx != NULL, FILE_CONT);
236 /* ctx->ui might be NULL for background processes */
237 if (ctx->ui == NULL)
238 return FILE_CONT;
240 ui = ctx->ui;
242 if (ui->aborting)
243 return FILE_ABORT;
245 if (total > 0) {
246 perc = (double) done / (double) total;
247 g_snprintf (count, 9, "%3d%% ", (gint) (100.0 * perc));
248 gtk_label_set_text (GTK_LABEL (ui->file_label), count);
250 while (gtk_events_pending ())
251 gtk_main_iteration ();
252 return FILE_CONT;
255 FileProgressStatus
256 file_progress_show_count (FileOpContext *ctx, long done, long total)
258 static gchar count[100];
259 FileOpContextUI *ui;
261 g_return_val_if_fail (ctx != NULL, FILE_CONT);
263 /* ctx->ui might be NULL for background processes */
264 if (ctx->ui == NULL)
265 return FILE_CONT;
267 ui = ctx->ui;
269 if (ui->aborting)
270 return FILE_ABORT;
272 g_snprintf (count, 100, "%ld/%ld ", done, total);
273 gtk_label_set_text (GTK_LABEL (ui->count_label), count);
274 while (gtk_events_pending ())
275 gtk_main_iteration ();
276 return FILE_CONT;
279 FileProgressStatus
280 file_progress_show_bytes (FileOpContext *ctx, double done, double total)
282 FileOpContextUI *ui;
283 double perc;
285 g_return_val_if_fail (ctx != NULL, FILE_CONT);
287 /* ctx->ui might be NULL for background processes */
288 if (ctx->ui == NULL)
289 return FILE_CONT;
291 ui = ctx->ui;
293 if (ui->aborting)
294 return FILE_ABORT;
296 if (total == 0.0)
297 perc = 1.0;
298 else
299 perc = done / total;
301 gtk_progress_bar_update (GTK_PROGRESS_BAR (ui->byte_prog), CLAMP (perc, 0.0, 1.0));
303 while (gtk_events_pending ())
304 gtk_main_iteration ();
305 return FILE_CONT;
308 static void
309 option_menu_policy_callback (GtkWidget *item, gpointer data)
311 FileOpContextUI *ui;
312 int status;
314 ui = data;
315 status = GPOINTER_TO_INT (gtk_object_get_user_data (GTK_OBJECT (item)));
317 ui->minor_copy_status = status;
318 ui->copy_status = status;
319 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui->op_radio), TRUE);
322 static void
323 policy_callback (GtkWidget *button, gpointer data)
325 FileOpContextUI *ui;
326 int status;
328 ui = data;
329 status = GPOINTER_TO_INT (gtk_object_get_user_data (GTK_OBJECT (button)));
331 if (GTK_TOGGLE_BUTTON (button)->active) {
332 if (status == REPLACE_OPTION_MENU) {
333 ui->copy_status = ui->minor_copy_status;
334 } else
335 ui->copy_status = status;
339 FileProgressStatus
340 file_progress_query_replace_policy (FileOpContext *ctx, gboolean dialog_needed)
342 FileOpContextUI *ui;
343 GtkWidget *qrp_dlg;
344 GtkWidget *radio;
345 GtkWidget *vbox;
346 GtkWidget *vbox2;
347 GtkWidget *hbox;
348 GtkWidget *icon;
349 GtkWidget *label;
350 GtkWidget *hrbox;
351 GSList *group = NULL;
352 GtkWidget *omenu;
353 GtkWidget *menu;
354 GtkWidget *menu_item;
356 g_return_val_if_fail (ctx != NULL, FILE_CONT);
358 /* ctx->ui might be NULL for background processes */
359 if (ctx->ui == NULL)
360 return FILE_CONT;
362 ui = ctx->ui;
364 if (ui->aborting)
365 return FILE_ABORT;
367 ui->copy_status = REPLACE_PROMPT;
368 if (dialog_needed == FALSE)
369 return FILE_CONT;
370 ui->minor_copy_status = REPLACE_ALWAYS;
371 qrp_dlg = gnome_dialog_new (_("Files Exist"),
372 GNOME_STOCK_BUTTON_OK,
373 GNOME_STOCK_BUTTON_CANCEL,
374 NULL);
375 gtk_window_set_position (GTK_WINDOW (qrp_dlg), GTK_WIN_POS_MOUSE);
377 hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
378 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (qrp_dlg)->vbox), hbox, FALSE, FALSE, 0);
380 icon = gnome_stock_pixmap_widget (hbox, GNOME_STOCK_PIXMAP_HELP);
381 gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
383 vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
384 gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, GNOME_PAD_SMALL);
386 label = gtk_label_new (_("Some of the files you are trying to copy already "
387 "exist in the destination folder. Please select "
388 "the action to be performed."));
389 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
390 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
391 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
393 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
394 gtk_box_pack_start (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
396 vbox2 = gtk_vbox_new (TRUE, 0);
397 gtk_box_pack_start (GTK_BOX (vbox), vbox2, FALSE, FALSE, 0);
399 radio = gtk_radio_button_new_with_label (group, _("Prompt me before overwriting any file."));
400 gtk_object_set_user_data (GTK_OBJECT (radio), GINT_TO_POINTER (REPLACE_PROMPT));
401 gtk_signal_connect (GTK_OBJECT (radio), "toggled",
402 GTK_SIGNAL_FUNC (policy_callback), ui);
403 gtk_box_pack_start (GTK_BOX (vbox2), radio, FALSE, FALSE, 0);
404 group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio));
406 radio = gtk_radio_button_new_with_label (group, _("Don't overwrite any files."));
407 gtk_object_set_user_data (GTK_OBJECT (radio), GINT_TO_POINTER (REPLACE_NEVER));
408 gtk_signal_connect (GTK_OBJECT (radio), "toggled",
409 GTK_SIGNAL_FUNC (policy_callback), ui);
410 gtk_box_pack_start (GTK_BOX (vbox2), radio, FALSE, FALSE, 0);
411 group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio));
413 ui->op_radio = gtk_radio_button_new (group);
414 gtk_object_set_user_data (GTK_OBJECT (ui->op_radio), GINT_TO_POINTER (REPLACE_OPTION_MENU));
415 gtk_signal_connect (GTK_OBJECT (ui->op_radio), "toggled",
416 GTK_SIGNAL_FUNC (policy_callback), ui);
417 gtk_box_pack_start (GTK_BOX (vbox2), ui->op_radio, FALSE, FALSE, 0);
419 hrbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
420 gtk_container_add (GTK_CONTAINER (ui->op_radio), hrbox);
422 gtk_box_pack_start (GTK_BOX (hrbox), gtk_label_new (_("Overwrite:")), FALSE, FALSE, 0);
424 /* we set up the option menu. */
425 omenu = gtk_option_menu_new ();
426 gtk_box_pack_start (GTK_BOX (hrbox), omenu, FALSE, FALSE, 0);
427 menu = gtk_menu_new ();
429 menu_item = gtk_menu_item_new_with_label ( _("Older files."));
430 gtk_menu_append (GTK_MENU (menu), menu_item);
431 gtk_object_set_user_data (GTK_OBJECT (menu_item), GINT_TO_POINTER (REPLACE_UPDATE));
432 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
433 GTK_SIGNAL_FUNC (option_menu_policy_callback), ui);
435 menu_item = gtk_menu_item_new_with_label ( _("Files only if size differs."));
436 gtk_menu_append (GTK_MENU (menu), menu_item);
437 gtk_object_set_user_data (GTK_OBJECT (menu_item), GINT_TO_POINTER (REPLACE_SIZE));
438 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
439 GTK_SIGNAL_FUNC (option_menu_policy_callback), ui);
441 menu_item = gtk_menu_item_new_with_label ( _("All files."));
442 gtk_menu_append (GTK_MENU (menu), menu_item);
443 gtk_object_set_user_data (GTK_OBJECT (menu_item), GINT_TO_POINTER (REPLACE_ALWAYS));
444 gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
445 GTK_SIGNAL_FUNC (option_menu_policy_callback), ui);
447 gtk_widget_show_all (menu);
448 gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu);
450 gtk_widget_show_all (GTK_WIDGET (GNOME_DIALOG (qrp_dlg)->vbox));
451 switch (gnome_dialog_run_and_close (GNOME_DIALOG (qrp_dlg))) {
452 case 0:
453 break;
454 case -1:
455 default:
456 ui->copy_status = REPLACE_ABORT;
457 return FILE_ABORT;
459 return FILE_CONT;
462 FileProgressStatus
463 file_progress_real_query_replace (FileOpContext *ctx, enum OperationMode mode, char *destname,
464 struct stat *_s_stat, struct stat *_d_stat)
466 FileOpContextUI *ui;
467 GtkWidget *qr_dlg;
468 gchar msg[128];
469 GtkWidget *label;
471 g_return_val_if_fail (ctx != NULL, FILE_CONT);
472 g_return_val_if_fail (ctx->ui != NULL, FILE_CONT);
474 ui = ctx->ui;
476 if (ui->aborting)
477 return FILE_ABORT;
479 /* so what's the situation? Do we prompt or don't we prompt. */
480 if (ui->copy_status == REPLACE_PROMPT){
481 qr_dlg = gnome_dialog_new (_("File Exists"),
482 GNOME_STOCK_BUTTON_YES,
483 GNOME_STOCK_BUTTON_NO,
484 GNOME_STOCK_BUTTON_CANCEL, NULL);
486 gtk_window_set_position (GTK_WINDOW (qr_dlg), GTK_WIN_POS_MOUSE);
487 g_snprintf (msg, sizeof (msg)-1, _("The target file already exists: %s"), destname);
488 label = gtk_label_new (msg);
489 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
490 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
491 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
492 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (qr_dlg)->vbox),
493 label, FALSE, FALSE, 0);
494 label = gtk_label_new (_("Replace it?"));
495 gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
496 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
497 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (qr_dlg)->vbox),
498 label, FALSE, FALSE, 0);
499 gtk_widget_show_all (GNOME_DIALOG (qr_dlg)->vbox);
500 switch (gnome_dialog_run_and_close (GNOME_DIALOG (qr_dlg))) {
501 case 0:
502 return FILE_CONT;
503 case 1:
504 return FILE_SKIP;
505 default:
506 return FILE_ABORT;
510 switch (ui->copy_status){
511 case REPLACE_UPDATE:
512 if (_s_stat->st_mtime > _d_stat->st_mtime)
513 return FILE_CONT;
514 else
515 return FILE_SKIP;
516 case REPLACE_SIZE:
517 if (_s_stat->st_size == _d_stat->st_size)
518 return FILE_SKIP;
519 else
520 return FILE_CONT;
521 case REPLACE_ALWAYS:
522 return FILE_CONT;
523 case REPLACE_NEVER:
524 return FILE_SKIP;
525 case REPLACE_ABORT:
526 default:
527 return FILE_ABORT;
531 void
532 file_progress_set_stalled_label (FileOpContext *ctx, char *stalled_msg)
534 g_return_if_fail (ctx != NULL);
536 if (ctx->ui == NULL)
537 return;
539 if (!stalled_msg || !*stalled_msg)
540 return;
541 /* FIXME */
542 g_warning ("FIXME: file_progress_set_stalled_label!\nmsg\t%s\n",stalled_msg);
545 char *
546 file_mask_dialog (FileOpContext *ctx, FileOperation operation, char *text, char *def_text,
547 int only_one, int *do_background)
549 GtkWidget *fmd_win;
550 GtkWidget *notebook;
551 GtkWidget *hbox;
552 GtkWidget *vbox, *label;
553 GtkWidget *fentry;
554 GtkWidget *cbox;
555 GtkWidget *icon;
556 int source_easy_patterns = easy_patterns;
557 char *source_mask, *orig_mask, *dest_dir;
558 const char *error;
559 struct stat buf;
560 int run;
562 g_return_val_if_fail (ctx != NULL, NULL);
564 ctx->stable_symlinks = 0;
566 /* Basic window */
567 switch (operation) {
568 case OP_COPY:
569 fmd_win = gnome_dialog_new (_("Copy"), GNOME_STOCK_BUTTON_OK,
570 GNOME_STOCK_BUTTON_CANCEL, NULL);
571 break;
572 case OP_MOVE:
573 fmd_win = gnome_dialog_new (_("Move"), GNOME_STOCK_BUTTON_OK,
574 GNOME_STOCK_BUTTON_CANCEL, NULL);
575 break;
576 default:
577 g_assert_not_reached ();
578 return NULL; /* keep -Wall happy */
581 gtk_window_set_position (GTK_WINDOW (fmd_win), GTK_WIN_POS_MOUSE);
583 notebook = gtk_notebook_new ();
584 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (fmd_win)->vbox),
585 notebook, FALSE, FALSE, 0);
587 hbox = gtk_hbox_new (FALSE, GNOME_PAD);
588 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
589 hbox,
590 gtk_label_new (_("Destination")));
592 /* FIXME: I want a bigger, badder, better Icon here... */
593 icon = gnome_stock_pixmap_widget (hbox, GNOME_STOCK_PIXMAP_HELP);
594 gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
596 vbox = gtk_vbox_new (FALSE, GNOME_PAD);
597 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
598 gtk_container_set_border_width (GTK_CONTAINER (vbox), GNOME_PAD);
600 label = gtk_label_new (text);
601 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
602 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
604 fentry = gnome_file_entry_new ("gmc-copy-file", _("Find Destination Folder"));
605 gnome_file_entry_set_directory (GNOME_FILE_ENTRY (fentry), TRUE);
606 gtk_entry_set_text (GTK_ENTRY (gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (fentry))),
607 def_text);
608 gnome_file_entry_set_default_path (GNOME_FILE_ENTRY (fentry), def_text);
609 gnome_file_entry_set_modal (GNOME_FILE_ENTRY (fentry), TRUE);
610 gtk_box_pack_start (GTK_BOX (vbox), fentry, FALSE, FALSE, 0);
612 /* Background operations are completely hosed, so we olympically disable
613 * them. How's that for foolproof bugfixing.
616 *do_background = FALSE;
617 #if 0
618 cbox = gtk_check_button_new_with_label (_("Copy as a background process"));
619 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox), *do_background);
620 gtk_signal_connect (GTK_OBJECT (cbox), "toggled",
621 (GtkSignalFunc) fmd_check_box_callback, do_background);
622 #if 0
623 gnome_widget_add_help (cbox, "Selecting this will run the copying in the background. "
624 "This is useful for transfers over networks that might take a long "
625 "time to complete.");
626 #endif
627 gtk_box_pack_end (GTK_BOX (vbox), cbox, FALSE, FALSE, 0);
628 gtk_box_pack_end (GTK_BOX (vbox), gtk_hseparator_new (), FALSE, FALSE, 0);
629 #endif
631 /* Advanced Options */
632 hbox = gtk_hbox_new (FALSE, GNOME_PAD_SMALL);
633 vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
634 gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
635 hbox,
636 gtk_label_new (_("Advanced Options")));
637 gtk_container_set_border_width (GTK_CONTAINER (hbox), GNOME_PAD);
638 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
640 cbox = gtk_check_button_new_with_label (_("Preserve symlinks"));
641 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox), ctx->stable_symlinks);
642 gtk_signal_connect (GTK_OBJECT (cbox), "toggled",
643 (GtkSignalFunc) fmd_check_box_callback, &ctx->stable_symlinks);
644 #if 0
645 gnome_widget_add_help (cbox, "FIXME: Add something here Miguel");
646 #endif
647 gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, FALSE, 0);
649 if (operation == OP_COPY) {
650 cbox = gtk_check_button_new_with_label (_("Follow links."));
651 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox), ctx->follow_links);
652 gtk_signal_connect (GTK_OBJECT (cbox), "toggled",
653 (GtkSignalFunc) fmd_check_box_callback, &ctx->follow_links);
654 #if 0
655 gnome_widget_add_help (cbox,
656 _("Selecting this will copy the files that symlinks point "
657 "to instead of just copying the link."));
658 #endif
659 gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, FALSE, 0);
661 cbox = gtk_check_button_new_with_label (_("Preserve file attributes."));
662 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox), ctx->op_preserve);
663 gtk_signal_connect (GTK_OBJECT (cbox), "toggled",
664 (GtkSignalFunc) fmd_check_box_callback, &ctx->op_preserve);
665 #if 0
666 gnome_widget_add_help (cbox,
667 _("Preserves the permissions and the UID/GID if possible"));
668 #endif
669 gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, FALSE, 0);
671 vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
672 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
673 cbox = gtk_check_button_new_with_label (_("Recursively copy subdirectories."));
674 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cbox), ctx->dive_into_subdirs);
675 gtk_signal_connect (GTK_OBJECT (cbox), "toggled",
676 (GtkSignalFunc) fmd_check_box_callback,
677 &ctx->dive_into_subdirs);
678 #if 0
679 gnome_widget_add_help (cbox,
680 _("If set, this will copy the directories recursively"));
681 #endif
682 gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, FALSE, 0);
685 gtk_widget_show_all (GNOME_DIALOG (fmd_win)->vbox);
686 gnome_dialog_set_close (GNOME_DIALOG (fmd_win), TRUE);
687 gnome_dialog_close_hides (GNOME_DIALOG (fmd_win), TRUE);
689 /* Off to the races!!! */
690 run = gnome_dialog_run (GNOME_DIALOG (fmd_win));
692 if (run == 1 || run == -1) {
693 gtk_widget_destroy (fmd_win);
694 return NULL;
697 dest_dir = gnome_file_entry_get_full_path (GNOME_FILE_ENTRY (fentry), FALSE);
698 gtk_widget_destroy (fmd_win);
700 easy_patterns = 1;
701 if (!dest_dir || !*dest_dir)
702 return NULL;
704 if (ctx->follow_links && operation != OP_MOVE)
705 ctx->stat_func = mc_stat;
706 else
707 ctx->stat_func = mc_lstat;
709 if (ctx->op_preserve || operation == OP_MOVE){
710 ctx->preserve = 1;
711 ctx->umask_kill = 0777777;
712 ctx->preserve_uidgid = (geteuid () == 0) ? 1 : 0;
713 } else {
714 int i;
715 ctx->preserve = ctx->preserve_uidgid = 0;
716 i = umask (0);
717 umask (i);
718 ctx->umask_kill = i ^ 0777777;
720 source_mask = g_strdup ("*");
721 orig_mask = source_mask;
722 if (!dest_dir || !*dest_dir){
723 if (source_mask)
724 g_free (source_mask);
725 return dest_dir;
728 if (!dest_dir)
729 return NULL;
731 if (!*dest_dir) {
732 g_free (dest_dir);
733 return NULL;
736 if (source_easy_patterns) {
737 source_easy_patterns = easy_patterns;
738 easy_patterns = 1;
739 source_mask = convert_pattern (source_mask, match_file, 1);
740 easy_patterns = source_easy_patterns;
741 error = re_compile_pattern (source_mask, strlen (source_mask), &ctx->rx);
742 g_free (source_mask);
743 } else
744 error = re_compile_pattern (source_mask, strlen (source_mask), &ctx->rx);
746 if (error)
747 g_warning ("%s\n",error);
749 if (orig_mask)
750 g_free (orig_mask);
751 ctx->dest_mask = strrchr (dest_dir, PATH_SEP);
752 if (ctx->dest_mask == NULL)
753 ctx->dest_mask = dest_dir;
754 else
755 ctx->dest_mask++;
756 orig_mask = ctx->dest_mask;
757 if (!*ctx->dest_mask
758 || (!ctx->dive_into_subdirs && !is_wildcarded (ctx->dest_mask)
759 && (!only_one || (!mc_stat (dest_dir, &buf)
760 && S_ISDIR (buf.st_mode))))
761 || (ctx->dive_into_subdirs && ((!only_one && !is_wildcarded (ctx->dest_mask))
762 || (only_one && !mc_stat (dest_dir, &buf)
763 && S_ISDIR (buf.st_mode)))))
764 ctx->dest_mask = g_strdup ("*");
765 else {
766 ctx->dest_mask = g_strdup (ctx->dest_mask);
767 *orig_mask = 0;
769 if (!*dest_dir){
770 g_free (dest_dir);
771 dest_dir = g_strdup ("./");
773 return dest_dir;
777 file_delete_query_recursive (FileOpContext *ctx, enum OperationMode mode, gchar *s)
779 GtkWidget *dialog;
780 GtkWidget *togglebutton;
781 gchar *title;
782 gchar *msg;
783 gint button;
784 gboolean rest_same;
786 if (ctx->recursive_result < RECURSIVE_ALWAYS) {
787 msg = g_strdup_printf (_("%s\n\nDirectory not empty. Delete it recursively?"),
788 name_trunc (s, 80));
789 dialog = gnome_message_box_new (msg,
790 GNOME_MESSAGE_BOX_QUESTION,
791 GNOME_STOCK_BUTTON_YES,
792 GNOME_STOCK_BUTTON_NO,
793 GNOME_STOCK_BUTTON_CANCEL,
794 NULL);
795 g_free (msg);
797 title = g_strconcat (_(" Delete: "), name_trunc (s, 30), " ", NULL);
798 gtk_window_set_title (GTK_WINDOW (dialog), title);
799 g_free (title);
801 togglebutton = gtk_check_button_new_with_label (_("Do the same for the rest"));
802 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox),
803 togglebutton, FALSE, FALSE, 0);
804 gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
806 gnome_dialog_close_hides (GNOME_DIALOG (dialog), TRUE);
808 button = gnome_dialog_run (GNOME_DIALOG (dialog));
809 rest_same = GTK_TOGGLE_BUTTON (togglebutton)->active;
811 gtk_widget_destroy (dialog);
813 switch (button) {
814 case 0:
815 ctx->recursive_result = rest_same ? RECURSIVE_ALWAYS : RECURSIVE_YES;
816 break;
817 case 1:
818 ctx->recursive_result = rest_same ? RECURSIVE_NEVER : RECURSIVE_NO;
819 break;
820 case 2:
821 ctx->recursive_result = RECURSIVE_ABORT;
822 break;
823 default:
824 break;
827 if (ctx->recursive_result != RECURSIVE_ABORT)
828 do_refresh ();
831 switch (ctx->recursive_result){
832 case RECURSIVE_YES:
833 case RECURSIVE_ALWAYS:
834 return FILE_CONT;
836 case RECURSIVE_NO:
837 case RECURSIVE_NEVER:
838 return FILE_SKIP;
840 case RECURSIVE_ABORT:
842 default:
843 return FILE_ABORT;
847 static void
848 cancel_cb (GtkWidget *widget, gpointer data)
850 FileOpContextUI *ui;
852 ui = data;
853 ui->aborting = TRUE;
856 /* Handler for the close signal from the GnomeDialog in the file operation
857 * context UI. We mark the operation as "aborted" and ask GnomeDialog not to
858 * close the window for us.
860 static gboolean
861 close_cb (GtkWidget *widget, gpointer data)
863 FileOpContextUI *ui;
865 ui = data;
866 ui->aborting = TRUE;
867 return TRUE;
870 void
871 file_op_context_create_ui (FileOpContext *ctx, FileOperation op, int with_eta)
873 FileOpContextUI *ui;
874 GtkWidget *alignment;
875 GtkWidget *hbox;
877 g_return_if_fail (ctx != NULL);
878 g_return_if_fail (ctx->ui == NULL);
880 ui = g_new0 (FileOpContextUI, 1);
881 ctx->ui = ui;
883 switch (op) {
884 case OP_MOVE:
885 ui->op_win = gnome_dialog_new (_("Move Progress"), GNOME_STOCK_BUTTON_CANCEL, NULL);
886 break;
887 case OP_COPY:
888 ui->op_win = gnome_dialog_new (_("Copy Progress"), GNOME_STOCK_BUTTON_CANCEL, NULL);
889 break;
890 case OP_DELETE:
891 ui->op_win = gnome_dialog_new (_("Delete Progress"), GNOME_STOCK_BUTTON_CANCEL, NULL);
892 break;
894 gtk_window_set_position (GTK_WINDOW (ui->op_win), GTK_WIN_POS_MOUSE);
896 gnome_dialog_button_connect (GNOME_DIALOG (ui->op_win), 0,
897 GTK_SIGNAL_FUNC (cancel_cb),
898 ui);
900 gtk_signal_connect (GTK_OBJECT (ui->op_win), "close",
901 GTK_SIGNAL_FUNC (close_cb),
902 ui);
904 if (op != OP_DELETE) {
905 alignment = gtk_alignment_new (0.0, 0.5, 0, 0);
906 hbox = gtk_hbox_new (FALSE, 0);
907 gtk_container_add (GTK_CONTAINER (alignment), hbox);
908 gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_(gdialog_from_string)),
909 FALSE, FALSE, 0);
910 ui->op_source_label = gtk_label_new ("");
912 gtk_box_pack_start (GTK_BOX (hbox), ui->op_source_label, FALSE, FALSE, 0);
913 gtk_box_set_spacing (GTK_BOX (GNOME_DIALOG (ui->op_win)->vbox), GNOME_PAD_SMALL);
914 gtk_container_set_border_width (GTK_CONTAINER (GNOME_DIALOG (ui->op_win)->vbox),
915 GNOME_PAD);
916 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui->op_win)->vbox),
917 alignment, FALSE, FALSE, 0);
919 alignment = gtk_alignment_new (0.0, 0.5, 0, 0);
920 hbox = gtk_hbox_new (FALSE, 0);
921 gtk_container_add (GTK_CONTAINER (alignment), hbox);
922 gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_(gdialog_to_string)),
923 FALSE, FALSE, 0);
924 ui->op_target_label = gtk_label_new ("");
925 gtk_box_pack_start (GTK_BOX (hbox), ui->op_target_label, FALSE, FALSE, 0);
926 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui->op_win)->vbox),
927 alignment, FALSE, FALSE, 0);
929 } else {
930 alignment = gtk_alignment_new (0.0, 0.5, 0, 0);
931 hbox = gtk_hbox_new (FALSE, 0);
932 gtk_container_add (GTK_CONTAINER (alignment), hbox);
933 gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_(gdialog_deleting_string)),
934 FALSE, FALSE, 0);
935 ui->op_source_label = gtk_label_new ("");
937 gtk_box_pack_start (GTK_BOX (hbox), ui->op_source_label, FALSE, FALSE, 0);
938 gtk_box_set_spacing (GTK_BOX (GNOME_DIALOG (ui->op_win)->vbox), GNOME_PAD_SMALL);
939 gtk_container_set_border_width (GTK_CONTAINER (GNOME_DIALOG (ui->op_win)->vbox),
940 GNOME_PAD);
941 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui->op_win)->vbox),
942 alignment, FALSE, FALSE, 0);
945 alignment = gtk_alignment_new (0.0, 0.5, 0, 0);
946 hbox = gtk_hbox_new (FALSE, 0);
947 gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("File ")), FALSE, FALSE, 0);
948 ui->count_label = GTK_OBJECT (gtk_label_new (""));
949 gtk_box_pack_start (GTK_BOX (hbox), GTK_WIDGET (ui->count_label), FALSE, FALSE, 0);
951 gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("is ")), FALSE, FALSE, 0);
952 ui->file_label = gtk_label_new ("");
953 gtk_box_pack_start (GTK_BOX (hbox), ui->file_label, FALSE, FALSE, 0);
954 gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("done.")), FALSE, FALSE, 0);
955 gtk_container_add (GTK_CONTAINER (alignment), hbox);
957 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui->op_win)->vbox),
958 alignment, FALSE, FALSE, 0);
960 ui->byte_prog = GTK_OBJECT (gtk_progress_bar_new ());
961 gtk_widget_set_usize (GTK_WIDGET (ui->byte_prog), GDIALOG_PROGRESS_WIDTH, -1);
962 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (ui->op_win)->vbox),
963 GTK_WIDGET (ui->byte_prog), FALSE, FALSE, 0);
965 /* done with things */
966 gtk_widget_show_all (GNOME_DIALOG (ui->op_win)->vbox);
967 gtk_window_set_modal (GTK_WINDOW (ui->op_win), TRUE);
968 gtk_widget_show_now (ui->op_win);
971 void
972 file_op_context_destroy_ui (FileOpContext *ctx)
974 FileOpContextUI *ui;
976 g_return_if_fail (ctx != NULL);
978 if (ctx->ui == NULL)
979 return;
981 ui = ctx->ui;
983 gtk_widget_destroy (ui->op_win);
985 g_free (ui);
986 ctx->ui = NULL;
989 void
990 fmd_init_i18n (int force)
992 /* unneccessary func */
995 /* Callback for the gnome_request_dialog() in the input dialog */
996 static void
997 input_dialog_cb (gchar *string, gpointer data)
999 char **s;
1001 s = data;
1002 *s = string;
1004 gtk_main_quit ();
1007 /* Our implementation of the general-purpose input dialog */
1008 char *
1009 real_input_dialog_help (char *header, char *text, char *help, char *def_text)
1011 int is_password;
1012 GtkWidget *dialog;
1013 char *string;
1015 if (strncmp (text, _("Password:"), strlen (_("Password"))) == 0)
1016 is_password = TRUE;
1017 else
1018 is_password = FALSE;
1020 dialog = gnome_request_dialog (is_password, text, def_text, 0,
1021 input_dialog_cb, &string,
1022 NULL);
1023 gtk_window_set_title (GTK_WINDOW (dialog), header);
1024 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
1025 gtk_main ();
1026 return string;
1029 /* Our implementation of the symlink-to dialog */
1030 void
1031 symlink_dialog (char *existing, char *new, char **ret_existing, char **ret_new)
1033 GtkWidget *dialog;
1034 GtkWidget *vbox;
1035 GtkWidget *w;
1036 GtkWidget *entry1, *entry2;
1037 WPanel *panel;
1038 int ret;
1040 g_return_if_fail (existing != NULL);
1041 g_return_if_fail (new != NULL);
1042 g_return_if_fail (ret_existing != NULL);
1043 g_return_if_fail (ret_new != NULL);
1045 /* Create the dialog */
1047 dialog = gnome_dialog_new (_("Symbolic Link"),
1048 GNOME_STOCK_BUTTON_OK,
1049 GNOME_STOCK_BUTTON_CANCEL,
1050 NULL);
1051 gnome_dialog_close_hides (GNOME_DIALOG (dialog), TRUE);
1052 gnome_dialog_set_default (GNOME_DIALOG (dialog), 0);
1054 panel = cpanel;
1055 if (!is_a_desktop_panel (panel))
1056 gnome_dialog_set_parent (GNOME_DIALOG (dialog), panel->xwindow);
1058 /* File symlink will point to */
1060 vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
1061 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), vbox, FALSE, FALSE, 0);
1063 w = gtk_label_new (_("Existing filename (filename symlink will point to):"));
1064 gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
1065 gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
1067 entry1 = gtk_entry_new ();
1068 gtk_entry_set_text (GTK_ENTRY (entry1), existing);
1069 gtk_box_pack_start (GTK_BOX (vbox), entry1, FALSE, FALSE, 0);
1070 gnome_dialog_editable_enters (GNOME_DIALOG (dialog), GTK_EDITABLE (entry1));
1072 /* Name of symlink */
1074 vbox = gtk_vbox_new (FALSE, GNOME_PAD_SMALL);
1075 gtk_box_pack_start (GTK_BOX (GNOME_DIALOG (dialog)->vbox), vbox, FALSE, FALSE, 0);
1077 w = gtk_label_new (_("Symbolic link filename:"));
1078 gtk_misc_set_alignment (GTK_MISC (w), 0.0, 0.5);
1079 gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 0);
1081 entry2 = gtk_entry_new ();
1082 gtk_entry_set_text (GTK_ENTRY (entry2), new);
1083 gtk_box_pack_start (GTK_BOX (vbox), entry2, FALSE, FALSE, 0);
1084 gnome_dialog_editable_enters (GNOME_DIALOG (dialog), GTK_EDITABLE (entry2));
1085 gtk_widget_grab_focus (entry2);
1087 /* Run */
1089 gtk_widget_show_all (GNOME_DIALOG (dialog)->vbox);
1090 ret = gnome_dialog_run (GNOME_DIALOG (dialog));
1092 if (ret != 0) {
1093 *ret_existing = NULL;
1094 *ret_new = NULL;
1095 } else {
1096 *ret_existing = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry1)));
1097 *ret_new = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry2)));
1100 if (ret != -1)
1101 gtk_widget_destroy (dialog);
1104 #ifdef WITH_SMBFS
1105 struct smb_authinfo *
1106 vfs_smb_get_authinfo (const char *host, const char *share, const char *domain,
1107 const char *user)
1109 struct smb_authinfo *return_value;
1110 GtkWidget *smbauth_dialog;
1111 GtkWidget *domain_entry, *user_entry, *passwd_entry;
1112 GtkWidget *domain_label, *user_label, *passwd_label;
1114 char *title;
1115 static char* labs[] = {N_("Domain:"), N_("Username:"), N_("Password: ")};
1117 if (!domain)
1118 domain = "";
1119 if (!user)
1120 user = "";
1122 title = g_strdup_printf (_("Password for \\\\%s\\%s"), host, share);
1124 /* Create dialog */
1125 smbauth_dialog =
1126 gnome_dialog_new(title, GNOME_STOCK_BUTTON_OK,
1127 GNOME_STOCK_BUTTON_CANCEL, NULL);
1128 g_free (title);
1129 gmc_window_setup_from_panel(GNOME_DIALOG(smbauth_dialog), cpanel);
1131 domain_label = gtk_label_new(_(labs[0]));
1132 gtk_misc_set_alignment(GTK_MISC(domain_label), 0.0, 0.5);
1133 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(smbauth_dialog)->vbox), domain_label, FALSE,
1134 FALSE, 0);
1136 domain_entry = gnome_entry_new("domain");
1137 gnome_entry_load_history(GNOME_ENTRY(domain_entry));
1138 gtk_entry_set_text(GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(domain_entry))),
1139 domain);
1140 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(smbauth_dialog)->vbox), domain_entry, FALSE,
1141 FALSE, 0);
1143 user_label = gtk_label_new(_(labs[1]));
1144 gtk_misc_set_alignment(GTK_MISC(user_label), 0.0, 0.5);
1145 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(smbauth_dialog)->vbox), user_label, FALSE,
1146 FALSE, 0);
1148 user_entry = gnome_entry_new("user");
1149 gnome_entry_load_history(GNOME_ENTRY(user_entry));
1150 gtk_entry_set_text(GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(user_entry))),
1151 user);
1152 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(smbauth_dialog)->vbox), user_entry, FALSE,
1153 FALSE, 0);
1155 passwd_label = gtk_label_new(_(labs[2]));
1156 gtk_misc_set_alignment(GTK_MISC(passwd_label), 0.0, 0.5);
1157 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(smbauth_dialog)->vbox), passwd_label, FALSE,
1158 FALSE, 0);
1160 passwd_entry = gtk_entry_new();
1161 gtk_entry_set_text(GTK_ENTRY(passwd_entry), "");
1162 gtk_entry_set_visibility(GTK_ENTRY(passwd_entry), FALSE);
1163 gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(smbauth_dialog)->vbox), passwd_entry, FALSE,
1164 FALSE, 0);
1166 gtk_widget_grab_focus(passwd_entry);
1167 gnome_dialog_set_default(GNOME_DIALOG(smbauth_dialog), 0);
1169 gtk_widget_show_all(GNOME_DIALOG(smbauth_dialog)->vbox);
1171 switch (gnome_dialog_run(GNOME_DIALOG(smbauth_dialog))) {
1172 case 0:
1173 return_value = g_new (struct smb_authinfo, 1);
1174 if (!return_value)
1175 break;
1177 return_value->host = g_strdup (host);
1178 return_value->share = g_strdup (share);
1179 return_value->domain =
1180 g_strdup(gtk_entry_get_text
1181 (GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(domain_entry)))));
1182 return_value->user =
1183 g_strdup(gtk_entry_get_text
1184 (GTK_ENTRY(gnome_entry_gtk_entry(GNOME_ENTRY(user_entry)))));
1185 return_value->password = g_strdup(gtk_entry_get_text(GTK_ENTRY(passwd_entry)));
1186 break;
1188 case 1:
1189 return_value = 0;
1190 break;
1192 default:
1193 return 0;
1196 gtk_widget_destroy(smbauth_dialog);
1198 return return_value;
1200 #endif /* WITH_SMBFS */