Ticket #2021 (MarkFileDown/MarkFileUp)
[free-mc.git] / src / panelize.c
blobc24bef3cae3a48ca742a9a7362365de161b109a1
1 /* External panelize
2 Copyright (C) 1995, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2007, 2009 Free Software Foundation, Inc.
5 Written by: 1995 Janne Kukonlehto
6 1995 Jakub Jelinek
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 /** \file panelize.c
24 * \brief Source: External panelization module
27 #include <config.h>
29 #include <errno.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <unistd.h>
36 #include "lib/global.h"
38 #include "lib/skin.h"
39 #include "lib/vfs/mc-vfs/vfs.h"
40 #include "lib/mcconfig.h" /* Load/save directories panelize */
41 #include "lib/strutil.h"
43 #include "dialog.h"
44 #include "widget.h"
45 #include "wtools.h" /* For common_dialog_repaint() */
46 #include "setup.h" /* For profile_bname */
47 #include "dir.h"
48 #include "panel.h" /* current_panel */
49 #include "layout.h" /* repaint_screen() */
50 #include "main.h"
51 #include "panelize.h"
52 #include "history.h"
54 #define UX 5
55 #define UY 2
57 #define BX 5
58 #define BY 18
60 #define BUTTONS 4
61 #define LABELS 3
62 #define B_ADD B_USER
63 #define B_REMOVE (B_USER + 1)
65 static WListbox *l_panelize;
66 static Dlg_head *panelize_dlg;
67 static int last_listitem;
68 static WInput *pname;
70 static struct
72 int ret_cmd, flags, y, x;
73 const char *text;
74 } panelize_but[BUTTONS] =
76 /* *INDENT-OFF* */
77 { B_CANCEL, NORMAL_BUTTON, 0, 53, N_("&Cancel") },
78 { B_ADD, NORMAL_BUTTON, 0, 28, N_("&Add new") },
79 { B_REMOVE, NORMAL_BUTTON, 0, 16, N_("&Remove") },
80 { B_ENTER, DEFPUSH_BUTTON, 0, 0, N_("Pane&lize") }
81 /* *INDENT-ON* */
84 static const char *panelize_section = "Panelize";
85 static void do_external_panelize (char *command);
87 /* Directory panelize */
88 static struct panelize
90 char *command;
91 char *label;
92 struct panelize *next;
93 } *panelize = NULL;
95 static void
96 update_command (void)
98 if (l_panelize->pos != last_listitem)
100 struct panelize *data = NULL;
102 last_listitem = l_panelize->pos;
103 listbox_get_current (l_panelize, NULL, (void **) &data);
104 assign_text (pname, data->command);
105 pname->point = 0;
106 update_input (pname, 1);
110 static cb_ret_t
111 panelize_callback (Dlg_head * h, Widget * sender, dlg_msg_t msg, int parm, void *data)
113 switch (msg)
115 case DLG_INIT:
116 case DLG_POST_KEY:
117 tty_setcolor (MENU_ENTRY_COLOR);
118 update_command ();
119 return MSG_HANDLED;
121 case DLG_DRAW:
122 common_dialog_repaint (h);
123 tty_setcolor (COLOR_NORMAL);
124 draw_box (h, UY, UX, h->lines - 10, h->cols - 10, TRUE);
125 return MSG_HANDLED;
127 default:
128 return default_dlg_callback (h, sender, msg, parm, data);
132 static void
133 init_panelize (void)
135 int i, panelize_cols = COLS - 6;
136 struct panelize *current = panelize;
138 #ifdef ENABLE_NLS
139 static int i18n_flag = 0;
140 static int maxlen = 0;
142 if (!i18n_flag)
144 i = sizeof (panelize_but) / sizeof (panelize_but[0]);
145 while (i--)
147 panelize_but[i].text = _(panelize_but[i].text);
148 maxlen += str_term_width1 (panelize_but[i].text) + 5;
150 maxlen += 10;
152 i18n_flag = 1;
154 panelize_cols = max (panelize_cols, maxlen);
156 panelize_but[2].x = panelize_but[3].x + str_term_width1 (panelize_but[3].text) + 7;
157 panelize_but[1].x = panelize_but[2].x + str_term_width1 (panelize_but[2].text) + 5;
158 panelize_but[0].x = panelize_cols - str_term_width1 (panelize_but[0].text) - 8 - BX;
160 #endif /* ENABLE_NLS */
162 last_listitem = 0;
164 do_refresh ();
166 panelize_dlg =
167 create_dlg (0, 0, 22, panelize_cols, dialog_colors,
168 panelize_callback, "[External panelize]",
169 _("External panelize"), DLG_CENTER | DLG_REVERSE);
171 for (i = 0; i < BUTTONS; i++)
172 add_widget (panelize_dlg,
173 button_new (BY + panelize_but[i].y,
174 BX + panelize_but[i].x,
175 panelize_but[i].ret_cmd,
176 panelize_but[i].flags, panelize_but[i].text, 0));
178 pname =
179 input_new (UY + 14, UX, INPUT_COLOR, panelize_dlg->cols - 10, "",
180 "in", INPUT_COMPLETE_DEFAULT);
181 add_widget (panelize_dlg, pname);
183 add_widget (panelize_dlg, label_new (UY + 13, UX, _("Command")));
185 /* get new listbox */
186 l_panelize = listbox_new (UY + 1, UX + 1, 10, panelize_dlg->cols - 12, FALSE, NULL);
188 while (current)
190 listbox_add_item (l_panelize, LISTBOX_APPEND_AT_END, 0, current->label, current);
191 current = current->next;
194 /* add listbox to the dialogs */
195 add_widget (panelize_dlg, l_panelize);
197 listbox_select_entry (l_panelize, listbox_search_text (l_panelize, _("Other command")));
200 static void
201 panelize_done (void)
203 destroy_dlg (panelize_dlg);
204 repaint_screen ();
207 static void
208 add2panelize (char *label, char *command)
210 struct panelize *current, *old;
212 old = NULL;
213 current = panelize;
214 while (current && strcmp (current->label, label) <= 0)
216 old = current;
217 current = current->next;
220 if (old == NULL)
222 panelize = g_new (struct panelize, 1);
223 panelize->label = label;
224 panelize->command = command;
225 panelize->next = current;
227 else
229 struct panelize *new;
230 new = g_new (struct panelize, 1);
231 new->label = label;
232 new->command = command;
233 old->next = new;
234 new->next = current;
238 static void
239 add2panelize_cmd (void)
241 char *label;
243 if (pname->buffer && (*pname->buffer))
245 label = input_dialog (_(" Add to external panelize "),
246 _(" Enter command label: "), MC_HISTORY_FM_PANELIZE_ADD, "");
247 if (!label)
248 return;
249 if (!*label)
251 g_free (label);
252 return;
255 add2panelize (label, g_strdup (pname->buffer));
259 static void
260 remove_from_panelize (struct panelize *entry)
262 if (strcmp (entry->label, _("Other command")) != 0)
264 if (entry == panelize)
266 panelize = panelize->next;
268 else
270 struct panelize *current = panelize;
271 while (current && current->next != entry)
272 current = current->next;
273 if (current)
275 current->next = entry->next;
279 g_free (entry->label);
280 g_free (entry->command);
281 g_free (entry);
285 void
286 external_panelize (void)
288 char *target = NULL;
290 if (!vfs_current_is_local ())
292 message (D_ERROR, MSG_ERROR, _(" Cannot run external panelize in a non-local directory "));
293 return;
296 init_panelize ();
298 /* display file info */
299 tty_setcolor (SELECTED_COLOR);
301 run_dlg (panelize_dlg);
303 switch (panelize_dlg->ret_value)
305 case B_CANCEL:
306 break;
308 case B_ADD:
309 add2panelize_cmd ();
310 break;
312 case B_REMOVE:
314 struct panelize *entry;
316 listbox_get_current (l_panelize, NULL, (void **) &entry);
317 remove_from_panelize (entry);
318 break;
321 case B_ENTER:
322 target = pname->buffer;
323 if (target != NULL && *target)
325 char *cmd = g_strdup (target);
326 destroy_dlg (panelize_dlg);
327 do_external_panelize (cmd);
328 g_free (cmd);
329 repaint_screen ();
330 return;
332 break;
335 panelize_done ();
338 void
339 load_panelize (void)
341 gchar **profile_keys, **keys;
342 gsize len;
343 GIConv conv;
344 GString *buffer;
346 conv = str_crt_conv_from ("UTF-8");
348 profile_keys = keys = mc_config_get_keys (mc_main_config, panelize_section, &len);
350 add2panelize (g_strdup (_("Other command")), g_strdup (""));
352 if (!profile_keys || *profile_keys == NULL)
354 add2panelize (g_strdup (_("Find rejects after patching")),
355 g_strdup ("find . -name \\*.rej -print"));
356 add2panelize (g_strdup (_("Find *.orig after patching")),
357 g_strdup ("find . -name \\*.orig -print"));
358 add2panelize (g_strdup (_("Find SUID and SGID programs")),
359 g_strdup
360 ("find . \\( \\( -perm -04000 -a -perm +011 \\) -o \\( -perm -02000 -a -perm +01 \\) \\) -print"));
361 return;
364 while (*profile_keys)
367 if (utf8_display || conv == INVALID_CONV)
369 buffer = g_string_new (*profile_keys);
371 else
373 buffer = g_string_new ("");
374 if (str_convert (conv, *profile_keys, buffer) == ESTR_FAILURE)
376 g_string_free (buffer, TRUE);
377 buffer = g_string_new (*profile_keys);
381 add2panelize (g_string_free (buffer, FALSE),
382 mc_config_get_string (mc_main_config, panelize_section, *profile_keys, ""));
383 profile_keys++;
385 g_strfreev (keys);
386 str_close_conv (conv);
389 void
390 save_panelize (void)
392 struct panelize *current = panelize;
394 mc_config_del_group (mc_main_config, panelize_section);
395 for (; current; current = current->next)
397 if (strcmp (current->label, _("Other command")))
398 mc_config_set_string (mc_main_config,
399 panelize_section, current->label, current->command);
401 mc_config_save_file (mc_main_config, NULL);
404 void
405 done_panelize (void)
407 struct panelize *current = panelize;
408 struct panelize *next;
410 for (; current; current = next)
412 next = current->next;
413 g_free (current->label);
414 g_free (current->command);
415 g_free (current);
419 static void
420 do_external_panelize (char *command)
422 int status, link_to_dir, stale_link;
423 int next_free = 0;
424 struct stat st;
425 dir_list *list = &current_panel->dir;
426 char line[MC_MAXPATHLEN];
427 char *name;
428 FILE *external;
430 open_error_pipe ();
431 external = popen (command, "r");
432 if (!external)
434 close_error_pipe (D_ERROR, _("Cannot invoke command."));
435 return;
437 /* Clear the counters and the directory list */
438 panel_clean_dir (current_panel);
440 while (1)
442 clearerr (external);
443 if (fgets (line, MC_MAXPATHLEN, external) == NULL)
445 if (ferror (external) && errno == EINTR)
446 continue;
447 else
448 break;
450 if (line[strlen (line) - 1] == '\n')
451 line[strlen (line) - 1] = 0;
452 if (strlen (line) < 1)
453 continue;
454 if (line[0] == '.' && line[1] == PATH_SEP)
455 name = line + 2;
456 else
457 name = line;
458 status = handle_path (list, name, &st, next_free, &link_to_dir, &stale_link);
459 if (status == 0)
460 continue;
461 if (status == -1)
462 break;
463 list->list[next_free].fnamelen = strlen (name);
464 list->list[next_free].fname = g_strdup (name);
465 file_mark (current_panel, next_free, 0);
466 list->list[next_free].f.link_to_dir = link_to_dir;
467 list->list[next_free].f.stale_link = stale_link;
468 list->list[next_free].f.dir_size_computed = 0;
469 list->list[next_free].st = st;
470 list->list[next_free].sort_key = NULL;
471 list->list[next_free].second_sort_key = NULL;
472 next_free++;
473 if (!(next_free & 32))
474 rotate_dash ();
477 current_panel->is_panelized = 1;
478 if (next_free)
480 current_panel->count = next_free;
481 if (list->list[0].fname[0] == PATH_SEP)
483 int ret;
484 strcpy (current_panel->cwd, PATH_SEP_STR);
485 ret = chdir (PATH_SEP_STR);
488 else
490 current_panel->count = set_zero_dir (list) ? 1 : 0;
492 if (pclose (external) < 0)
493 message (D_NORMAL, _("External panelize"), _("Pipe close failed"));
494 close_error_pipe (D_NORMAL, NULL);
495 try_to_select (current_panel, NULL);
496 panel_re_sort (current_panel);