Added new fnction for manipulate vpath objects:
[midnight-commander.git] / src / filemanager / panelize.c
bloba9bc1cba982424f9c7d3278cf564b846f335e11b
1 /*
2 External panelize
4 Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5 2007, 2009, 2011
6 The Free Software Foundation, Inc.
8 Written by:
9 Janne Kukonlehto, 1995
10 Jakub Jelinek, 1995
12 This file is part of the Midnight Commander.
14 The Midnight Commander is free software: you can redistribute it
15 and/or modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation, either version 3 of the License,
17 or (at your option) any later version.
19 The Midnight Commander is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 /** \file panelize.c
29 * \brief Source: External panelization module
32 #include <config.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
41 #include "lib/global.h"
43 #include "lib/skin.h"
44 #include "lib/vfs/vfs.h"
45 #include "lib/mcconfig.h" /* Load/save directories panelize */
46 #include "lib/strutil.h"
47 #include "lib/util.h"
48 #include "lib/widget.h"
50 #include "src/setup.h" /* For profile_bname */
51 #include "src/history.h"
53 #include "dir.h"
54 #include "midnight.h" /* current_panel */
55 #include "panel.h" /* WPanel */
57 #include "panelize.h"
59 /*** global variables ****************************************************************************/
61 /*** file scope macro definitions ****************************************************************/
63 #define UX 5
64 #define UY 2
66 #define BX 5
67 #define BY 18
69 #define BUTTONS 4
70 #define LABELS 3
71 #define B_ADD B_USER
72 #define B_REMOVE (B_USER + 1)
74 /*** file scope type declarations ****************************************************************/
76 /*** file scope variables ************************************************************************/
78 static WListbox *l_panelize;
79 static Dlg_head *panelize_dlg;
80 static int last_listitem;
81 static WInput *pname;
83 static struct
85 int ret_cmd;
86 button_flags_t flags;
87 int y, x;
88 const char *text;
89 } panelize_but[BUTTONS] =
91 /* *INDENT-OFF* */
92 { B_CANCEL, NORMAL_BUTTON, 0, 53, N_("&Cancel") },
93 { B_ADD, NORMAL_BUTTON, 0, 28, N_("&Add new") },
94 { B_REMOVE, NORMAL_BUTTON, 0, 16, N_("&Remove") },
95 { B_ENTER, DEFPUSH_BUTTON, 0, 0, N_("Pane&lize") }
96 /* *INDENT-ON* */
99 static const char *panelize_section = "Panelize";
101 /* Directory panelize */
102 static struct panelize
104 char *command;
105 char *label;
106 struct panelize *next;
107 } *panelize = NULL;
109 /*** file scope functions ************************************************************************/
110 /* --------------------------------------------------------------------------------------------- */
112 static void do_external_panelize (char *command);
114 /* --------------------------------------------------------------------------------------------- */
116 static void
117 update_command (void)
119 if (l_panelize->pos != last_listitem)
121 struct panelize *data = NULL;
123 last_listitem = l_panelize->pos;
124 listbox_get_current (l_panelize, NULL, (void **) &data);
125 input_assign_text (pname, data->command);
126 pname->point = 0;
127 input_update (pname, TRUE);
131 /* --------------------------------------------------------------------------------------------- */
133 static cb_ret_t
134 panelize_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, void *data)
136 switch (msg)
138 case DLG_INIT:
139 case DLG_POST_KEY:
140 tty_setcolor (MENU_ENTRY_COLOR);
141 update_command ();
142 return MSG_HANDLED;
144 case DLG_DRAW:
145 common_dialog_repaint (h);
146 tty_setcolor (COLOR_NORMAL);
147 draw_box (h, UY, UX, h->lines - 10, h->cols - 10, TRUE);
148 return MSG_HANDLED;
150 default:
151 return default_dlg_callback (h, sender, msg, parm, data);
155 /* --------------------------------------------------------------------------------------------- */
157 static void
158 init_panelize (void)
160 int i, panelize_cols = COLS - 6;
161 struct panelize *current = panelize;
163 #ifdef ENABLE_NLS
164 static int i18n_flag = 0;
165 static int maxlen = 0;
167 if (!i18n_flag)
169 i = sizeof (panelize_but) / sizeof (panelize_but[0]);
170 while (i--)
172 panelize_but[i].text = _(panelize_but[i].text);
173 maxlen += str_term_width1 (panelize_but[i].text) + 5;
175 maxlen += 10;
177 i18n_flag = 1;
179 panelize_cols = max (panelize_cols, maxlen);
181 panelize_but[2].x = panelize_but[3].x + str_term_width1 (panelize_but[3].text) + 7;
182 panelize_but[1].x = panelize_but[2].x + str_term_width1 (panelize_but[2].text) + 5;
183 panelize_but[0].x = panelize_cols - str_term_width1 (panelize_but[0].text) - 8 - BX;
185 #endif /* ENABLE_NLS */
187 last_listitem = 0;
189 do_refresh ();
191 panelize_dlg =
192 create_dlg (TRUE, 0, 0, 22, panelize_cols, dialog_colors,
193 panelize_callback, "[External panelize]",
194 _("External panelize"), DLG_CENTER | DLG_REVERSE);
196 for (i = 0; i < BUTTONS; i++)
197 add_widget (panelize_dlg,
198 button_new (BY + panelize_but[i].y,
199 BX + panelize_but[i].x,
200 panelize_but[i].ret_cmd,
201 panelize_but[i].flags, panelize_but[i].text, 0));
203 pname =
204 input_new (UY + 14, UX, input_get_default_colors (),
205 panelize_dlg->cols - 10, "", "in", INPUT_COMPLETE_DEFAULT);
206 add_widget (panelize_dlg, pname);
208 add_widget (panelize_dlg, label_new (UY + 13, UX, _("Command")));
210 /* get new listbox */
211 l_panelize = listbox_new (UY + 1, UX + 1, 10, panelize_dlg->cols - 12, FALSE, NULL);
213 while (current)
215 listbox_add_item (l_panelize, LISTBOX_APPEND_AT_END, 0, current->label, current);
216 current = current->next;
219 /* add listbox to the dialogs */
220 add_widget (panelize_dlg, l_panelize);
222 listbox_select_entry (l_panelize, listbox_search_text (l_panelize, _("Other command")));
225 /* --------------------------------------------------------------------------------------------- */
227 static void
228 panelize_done (void)
230 destroy_dlg (panelize_dlg);
231 repaint_screen ();
234 /* --------------------------------------------------------------------------------------------- */
236 static void
237 add2panelize (char *label, char *command)
239 struct panelize *current, *old;
241 old = NULL;
242 current = panelize;
243 while (current && strcmp (current->label, label) <= 0)
245 old = current;
246 current = current->next;
249 if (old == NULL)
251 panelize = g_new (struct panelize, 1);
252 panelize->label = label;
253 panelize->command = command;
254 panelize->next = current;
256 else
258 struct panelize *new;
259 new = g_new (struct panelize, 1);
260 new->label = label;
261 new->command = command;
262 old->next = new;
263 new->next = current;
267 /* --------------------------------------------------------------------------------------------- */
269 static void
270 add2panelize_cmd (void)
272 char *label;
274 if (pname->buffer && (*pname->buffer))
276 label = input_dialog (_("Add to external panelize"),
277 _("Enter command label:"), MC_HISTORY_FM_PANELIZE_ADD, "");
278 if (!label)
279 return;
280 if (!*label)
282 g_free (label);
283 return;
286 add2panelize (label, g_strdup (pname->buffer));
290 /* --------------------------------------------------------------------------------------------- */
292 static void
293 remove_from_panelize (struct panelize *entry)
295 if (strcmp (entry->label, _("Other command")) != 0)
297 if (entry == panelize)
299 panelize = panelize->next;
301 else
303 struct panelize *current = panelize;
304 while (current && current->next != entry)
305 current = current->next;
306 if (current)
308 current->next = entry->next;
312 g_free (entry->label);
313 g_free (entry->command);
314 g_free (entry);
318 /* --------------------------------------------------------------------------------------------- */
320 static void
321 do_external_panelize (char *command)
323 int status, link_to_dir, stale_link;
324 int next_free = 0;
325 struct stat st;
326 dir_list *list = &current_panel->dir;
327 char line[MC_MAXPATHLEN];
328 char *name;
329 FILE *external;
331 open_error_pipe ();
332 external = popen (command, "r");
333 if (!external)
335 close_error_pipe (D_ERROR, _("Cannot invoke command."));
336 return;
338 /* Clear the counters and the directory list */
339 panel_clean_dir (current_panel);
341 g_strlcpy (panelized_panel.root, current_panel->cwd, MC_MAXPATHLEN);
343 if (set_zero_dir (list))
344 next_free++;
346 while (1)
348 clearerr (external);
349 if (fgets (line, MC_MAXPATHLEN, external) == NULL)
351 if (ferror (external) && errno == EINTR)
352 continue;
353 else
354 break;
356 if (line[strlen (line) - 1] == '\n')
357 line[strlen (line) - 1] = 0;
358 if (strlen (line) < 1)
359 continue;
360 if (line[0] == '.' && line[1] == PATH_SEP)
361 name = line + 2;
362 else
363 name = line;
364 status = handle_path (list, name, &st, next_free, &link_to_dir, &stale_link);
365 if (status == 0)
366 continue;
367 if (status == -1)
368 break;
369 list->list[next_free].fnamelen = strlen (name);
370 list->list[next_free].fname = g_strndup (name, list->list[next_free].fnamelen);
371 file_mark (current_panel, next_free, 0);
372 list->list[next_free].f.link_to_dir = link_to_dir;
373 list->list[next_free].f.stale_link = stale_link;
374 list->list[next_free].f.dir_size_computed = 0;
375 list->list[next_free].st = st;
376 list->list[next_free].sort_key = NULL;
377 list->list[next_free].second_sort_key = NULL;
378 next_free++;
379 if (!(next_free & 32))
380 rotate_dash ();
383 current_panel->is_panelized = TRUE;
384 if (next_free)
386 current_panel->count = next_free;
387 if (list->list[0].fname[0] == PATH_SEP)
389 int ret;
390 strcpy (current_panel->cwd, PATH_SEP_STR);
391 ret = chdir (PATH_SEP_STR);
394 else
396 current_panel->count = set_zero_dir (list) ? 1 : 0;
398 if (pclose (external) < 0)
399 message (D_NORMAL, _("External panelize"), _("Pipe close failed"));
400 close_error_pipe (D_NORMAL, NULL);
401 try_to_select (current_panel, NULL);
402 panel_re_sort (current_panel);
405 /* --------------------------------------------------------------------------------------------- */
407 static void
408 do_panelize_cd (struct WPanel *panel)
410 int i;
411 dir_list *list = &panel->dir;
412 gboolean panelized_same;
414 clean_dir (list, panel->count);
415 if (panelized_panel.root[0] == '\0')
416 g_strlcpy (panelized_panel.root, panel->cwd, MC_MAXPATHLEN);
418 if (panelized_panel.count < 1)
420 if (set_zero_dir (&panelized_panel.list))
421 panelized_panel.count = 1;
423 else if (panelized_panel.count >= list->size)
425 list->list = g_try_realloc (list->list, sizeof (file_entry) * panelized_panel.count);
426 list->size = panelized_panel.count;
428 panel->count = panelized_panel.count;
429 panel->is_panelized = TRUE;
431 panelized_same = (strcmp (panelized_panel.root, panel->cwd) == 0);
433 for (i = 0; i < panelized_panel.count; i++)
435 if (panelized_same
436 || (panelized_panel.list.list[i].fname[0] == '.'
437 && panelized_panel.list.list[i].fname[1] == '.'
438 && panelized_panel.list.list[i].fname[2] == '\0'))
440 list->list[i].fnamelen = panelized_panel.list.list[i].fnamelen;
441 list->list[i].fname = g_strndup (panelized_panel.list.list[i].fname,
442 panelized_panel.list.list[i].fnamelen);
444 else
446 list->list[i].fname = mc_build_filename (panelized_panel.root,
447 panelized_panel.list.list[i].fname,
448 (char *) NULL);
449 list->list[i].fnamelen = strlen (list->list[i].fname);
451 list->list[i].f.link_to_dir = panelized_panel.list.list[i].f.link_to_dir;
452 list->list[i].f.stale_link = panelized_panel.list.list[i].f.stale_link;
453 list->list[i].f.dir_size_computed = panelized_panel.list.list[i].f.dir_size_computed;
454 list->list[i].f.marked = panelized_panel.list.list[i].f.marked;
455 list->list[i].st = panelized_panel.list.list[i].st;
456 list->list[i].sort_key = panelized_panel.list.list[i].sort_key;
457 list->list[i].second_sort_key = panelized_panel.list.list[i].second_sort_key;
459 try_to_select (panel, NULL);
462 /* --------------------------------------------------------------------------------------------- */
463 /*** public functions ****************************************************************************/
464 /* --------------------------------------------------------------------------------------------- */
466 void
467 panelize_save_panel (struct WPanel *panel)
469 int i;
470 dir_list *list = &panel->dir;
472 g_strlcpy (panelized_panel.root, panel->cwd, MC_MAXPATHLEN);
474 if (panelized_panel.count > 0)
475 clean_dir (&panelized_panel.list, panelized_panel.count);
476 if (panel->count < 1)
477 return;
479 panelized_panel.count = panel->count;
480 if (panel->count >= panelized_panel.list.size)
482 panelized_panel.list.list = g_try_realloc (panelized_panel.list.list,
483 sizeof (file_entry) * panel->count);
484 panelized_panel.list.size = panel->count;
486 for (i = 0; i < panel->count; i++)
488 panelized_panel.list.list[i].fnamelen = list->list[i].fnamelen;
489 panelized_panel.list.list[i].fname = g_strndup (list->list[i].fname, list->list[i].fnamelen);
490 panelized_panel.list.list[i].f.link_to_dir = list->list[i].f.link_to_dir;
491 panelized_panel.list.list[i].f.stale_link = list->list[i].f.stale_link;
492 panelized_panel.list.list[i].f.dir_size_computed = list->list[i].f.dir_size_computed;
493 panelized_panel.list.list[i].f.marked = list->list[i].f.marked;
494 panelized_panel.list.list[i].st = list->list[i].st;
495 panelized_panel.list.list[i].sort_key = list->list[i].sort_key;
496 panelized_panel.list.list[i].second_sort_key = list->list[i].second_sort_key;
500 /* --------------------------------------------------------------------------------------------- */
502 void
503 cd_panelize_cmd (void)
505 if (get_display_type (MENU_PANEL_IDX) != view_listing)
506 set_display_type (MENU_PANEL_IDX, view_listing);
508 do_panelize_cd ((struct WPanel *) get_panel_widget (MENU_PANEL_IDX));
511 /* --------------------------------------------------------------------------------------------- */
513 void
514 external_panelize (void)
516 char *target = NULL;
518 if (!vfs_current_is_local ())
520 message (D_ERROR, MSG_ERROR, _("Cannot run external panelize in a non-local directory"));
521 return;
524 init_panelize ();
526 /* display file info */
527 tty_setcolor (SELECTED_COLOR);
529 run_dlg (panelize_dlg);
531 switch (panelize_dlg->ret_value)
533 case B_CANCEL:
534 break;
536 case B_ADD:
537 add2panelize_cmd ();
538 break;
540 case B_REMOVE:
542 struct panelize *entry;
544 listbox_get_current (l_panelize, NULL, (void **) &entry);
545 remove_from_panelize (entry);
546 break;
549 case B_ENTER:
550 target = pname->buffer;
551 if (target != NULL && *target)
553 char *cmd = g_strdup (target);
554 destroy_dlg (panelize_dlg);
555 do_external_panelize (cmd);
556 g_free (cmd);
557 repaint_screen ();
558 return;
560 break;
563 panelize_done ();
566 /* --------------------------------------------------------------------------------------------- */
568 void
569 load_panelize (void)
571 gchar **profile_keys, **keys;
572 gsize len;
573 GIConv conv;
575 conv = str_crt_conv_from ("UTF-8");
577 profile_keys = keys = mc_config_get_keys (mc_main_config, panelize_section, &len);
579 add2panelize (g_strdup (_("Other command")), g_strdup (""));
581 if (!profile_keys || *profile_keys == NULL)
583 add2panelize (g_strdup (_("Find rejects after patching")),
584 g_strdup ("find . -name \\*.rej -print"));
585 add2panelize (g_strdup (_("Find *.orig after patching")),
586 g_strdup ("find . -name \\*.orig -print"));
587 add2panelize (g_strdup (_("Find SUID and SGID programs")),
588 g_strdup
589 ("find . \\( \\( -perm -04000 -a -perm +011 \\) -o \\( -perm -02000 -a -perm +01 \\) \\) -print"));
590 return;
593 while (*profile_keys)
595 GString *buffer;
597 if (mc_global.utf8_display || conv == INVALID_CONV)
598 buffer = g_string_new (*profile_keys);
599 else
601 buffer = g_string_new ("");
602 if (str_convert (conv, *profile_keys, buffer) == ESTR_FAILURE)
603 g_string_assign (buffer, *profile_keys);
606 add2panelize (g_string_free (buffer, FALSE),
607 mc_config_get_string (mc_main_config, panelize_section, *profile_keys, ""));
608 profile_keys++;
611 g_strfreev (keys);
612 str_close_conv (conv);
615 /* --------------------------------------------------------------------------------------------- */
617 void
618 save_panelize (void)
620 struct panelize *current = panelize;
622 mc_config_del_group (mc_main_config, panelize_section);
623 for (; current; current = current->next)
625 if (strcmp (current->label, _("Other command")))
626 mc_config_set_string (mc_main_config,
627 panelize_section, current->label, current->command);
631 /* --------------------------------------------------------------------------------------------- */
633 void
634 done_panelize (void)
636 struct panelize *current = panelize;
637 struct panelize *next;
639 for (; current; current = next)
641 next = current->next;
642 g_free (current->label);
643 g_free (current->command);
644 g_free (current);
648 /* --------------------------------------------------------------------------------------------- */