This source file includes following definitions.
- update_command
- panelize_callback
- init_panelize
- panelize_done
- add2panelize
- add2panelize_cmd
- remove_from_panelize
- do_external_panelize
- do_panelize_cd
- panelize_change_root
- panelize_save_panel
- panelize_absolutize_if_needed
- cd_panelize_cmd
- external_panelize
- load_panelize
- save_panelize
- done_panelize
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 #include <config.h>
32
33 #include <errno.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <unistd.h>
39
40 #include "lib/global.h"
41
42 #include "lib/skin.h"
43 #include "lib/vfs/vfs.h"
44 #include "lib/mcconfig.h"
45 #include "lib/strutil.h"
46 #include "lib/util.h"
47 #include "lib/widget.h"
48
49 #include "src/setup.h"
50 #include "src/history.h"
51
52 #include "dir.h"
53 #include "filemanager.h"
54 #include "layout.h"
55 #include "panel.h"
56
57 #include "panelize.h"
58
59
60
61
62
63 #define UX 3
64 #define UY 2
65
66 #define B_ADD B_USER
67 #define B_REMOVE (B_USER + 1)
68
69
70
71
72
73 static WListbox *l_panelize;
74 static WDialog *panelize_dlg;
75 static int last_listitem;
76 static WInput *pname;
77
78 static const char *panelize_section = "Panelize";
79
80
81 static struct panelize
82 {
83 char *command;
84 char *label;
85 struct panelize *next;
86 } *panelize = NULL;
87
88
89
90
91
92 static void
93 update_command (void)
94 {
95 if (l_panelize->pos != last_listitem)
96 {
97 struct panelize *data = NULL;
98
99 last_listitem = l_panelize->pos;
100 listbox_get_current (l_panelize, NULL, (void **) &data);
101 input_assign_text (pname, data->command);
102 pname->point = 0;
103 input_update (pname, TRUE);
104 }
105 }
106
107
108
109 static cb_ret_t
110 panelize_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
111 {
112 switch (msg)
113 {
114 case MSG_INIT:
115 group_default_callback (w, NULL, MSG_INIT, 0, NULL);
116 MC_FALLTHROUGH;
117
118 case MSG_NOTIFY:
119 update_command ();
120 return MSG_HANDLED;
121
122 default:
123 return dlg_default_callback (w, sender, msg, parm, data);
124 }
125 }
126
127
128
129 static void
130 init_panelize (void)
131 {
132 struct
133 {
134 int ret_cmd;
135 button_flags_t flags;
136 const char *text;
137 } panelize_but[] =
138 {
139
140 { B_ENTER, DEFPUSH_BUTTON, N_("Pane&lize") },
141 { B_REMOVE, NORMAL_BUTTON, N_("&Remove") },
142 { B_ADD, NORMAL_BUTTON, N_("&Add new") },
143 { B_CANCEL, NORMAL_BUTTON, N_("&Cancel") }
144
145 };
146
147 WGroup *g;
148
149 size_t i;
150 int blen;
151 int panelize_cols;
152 struct panelize *current;
153 int x, y;
154
155 last_listitem = 0;
156
157 do_refresh ();
158
159 i = G_N_ELEMENTS (panelize_but);
160 blen = i - 1;
161 while (i-- != 0)
162 {
163 #ifdef ENABLE_NLS
164 panelize_but[i].text = _(panelize_but[i].text);
165 #endif
166 blen += str_term_width1 (panelize_but[i].text) + 3 + 1;
167 if (panelize_but[i].flags == DEFPUSH_BUTTON)
168 blen += 2;
169 }
170
171 panelize_cols = COLS - 6;
172 panelize_cols = MAX (panelize_cols, blen + 4);
173
174 panelize_dlg =
175 dlg_create (TRUE, 0, 0, 20, panelize_cols, WPOS_CENTER, FALSE, dialog_colors,
176 panelize_callback, NULL, "[External panelize]", _("External panelize"));
177 g = GROUP (panelize_dlg);
178
179
180 y = UY;
181 group_add_widget (g, groupbox_new (y++, UX, 12, panelize_cols - UX * 2, ""));
182
183 l_panelize = listbox_new (y, UX + 1, 10, panelize_cols - UX * 2 - 2, FALSE, NULL);
184 for (current = panelize; current != NULL; current = current->next)
185 listbox_add_item (l_panelize, LISTBOX_APPEND_AT_END, 0, current->label, current, FALSE);
186 listbox_select_entry (l_panelize, listbox_search_text (l_panelize, _("Other command")));
187 group_add_widget (g, l_panelize);
188
189 y += WIDGET (l_panelize)->lines + 1;
190 group_add_widget (g, label_new (y++, UX, _("Command")));
191 pname =
192 input_new (y++, UX, input_colors, panelize_cols - UX * 2, "", "in",
193 INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_HOSTNAMES | INPUT_COMPLETE_COMMANDS |
194 INPUT_COMPLETE_VARIABLES | INPUT_COMPLETE_USERNAMES | INPUT_COMPLETE_CD |
195 INPUT_COMPLETE_SHELL_ESC);
196 group_add_widget (g, pname);
197
198 group_add_widget (g, hline_new (y++, -1, -1));
199
200 x = (panelize_cols - blen) / 2;
201 for (i = 0; i < G_N_ELEMENTS (panelize_but); i++)
202 {
203 WButton *b;
204
205 b = button_new (y, x,
206 panelize_but[i].ret_cmd, panelize_but[i].flags, panelize_but[i].text, NULL);
207 group_add_widget (g, b);
208
209 x += button_get_len (b) + 1;
210 }
211
212 widget_select (WIDGET (l_panelize));
213 }
214
215
216
217 static void
218 panelize_done (void)
219 {
220 dlg_destroy (panelize_dlg);
221 repaint_screen ();
222 }
223
224
225
226 static void
227 add2panelize (char *label, char *command)
228 {
229 struct panelize *current;
230 struct panelize *old = NULL;
231
232 current = panelize;
233 while (current != NULL && strcmp (current->label, label) <= 0)
234 {
235 old = current;
236 current = current->next;
237 }
238
239 if (old == NULL)
240 {
241 panelize = g_new (struct panelize, 1);
242 panelize->label = label;
243 panelize->command = command;
244 panelize->next = current;
245 }
246 else
247 {
248 struct panelize *new;
249
250 new = g_new (struct panelize, 1);
251 new->label = label;
252 new->command = command;
253 old->next = new;
254 new->next = current;
255 }
256 }
257
258
259
260 static void
261 add2panelize_cmd (void)
262 {
263 if (!input_is_empty (pname))
264 {
265 char *label;
266
267 label = input_dialog (_("Add to external panelize"),
268 _("Enter command label:"), MC_HISTORY_FM_PANELIZE_ADD, "",
269 INPUT_COMPLETE_NONE);
270 if (label == NULL || *label == '\0')
271 g_free (label);
272 else
273 add2panelize (label, g_strdup (pname->buffer));
274 }
275 }
276
277
278
279 static void
280 remove_from_panelize (struct panelize *entry)
281 {
282 if (strcmp (entry->label, _("Other command")) != 0)
283 {
284 if (entry == panelize)
285 panelize = panelize->next;
286 else
287 {
288 struct panelize *current = panelize;
289
290 while (current != NULL && current->next != entry)
291 current = current->next;
292
293 if (current != NULL)
294 current->next = entry->next;
295 }
296
297 g_free (entry->label);
298 g_free (entry->command);
299 g_free (entry);
300 }
301 }
302
303
304
305 static void
306 do_external_panelize (char *command)
307 {
308 dir_list *list = ¤t_panel->dir;
309 FILE *external;
310
311 open_error_pipe ();
312 external = popen (command, "r");
313 if (external == NULL)
314 {
315 close_error_pipe (D_ERROR, _("Cannot invoke command."));
316 return;
317 }
318
319 panel_clean_dir (current_panel);
320
321 panelize_change_root (current_panel->cwd_vpath);
322
323 dir_list_init (list);
324
325 while (TRUE)
326 {
327 char line[MC_MAXPATHLEN];
328 size_t len;
329 char *name;
330 gboolean link_to_dir, stale_link;
331 struct stat st;
332
333 clearerr (external);
334 if (fgets (line, sizeof (line), external) == NULL)
335 {
336 if (ferror (external) != 0 && errno == EINTR)
337 continue;
338 break;
339 }
340
341 len = strlen (line);
342 if (line[len - 1] == '\n')
343 line[len - 1] = '\0';
344 if (line[0] == '\0')
345 continue;
346
347 name = line;
348 if (line[0] == '.' && IS_PATH_SEP (line[1]))
349 name += 2;
350
351 if (!handle_path (name, &st, &link_to_dir, &stale_link))
352 continue;
353
354 if (!dir_list_append (list, name, &st, link_to_dir, stale_link))
355 break;
356
357 file_mark (current_panel, list->len - 1, 0);
358
359 if ((list->len & 31) == 0)
360 rotate_dash (TRUE);
361 }
362
363 current_panel->is_panelized = TRUE;
364 panelize_absolutize_if_needed (current_panel);
365
366 if (pclose (external) < 0)
367 message (D_NORMAL, _("External panelize"), _("Pipe close failed"));
368 close_error_pipe (D_NORMAL, NULL);
369 try_to_select (current_panel, NULL);
370 panel_re_sort (current_panel);
371 rotate_dash (FALSE);
372 }
373
374
375
376 static void
377 do_panelize_cd (WPanel * panel)
378 {
379 int i;
380 dir_list *list;
381 gboolean panelized_same;
382
383 dir_list_clean (&panel->dir);
384 if (panelized_panel.root_vpath == NULL)
385 panelize_change_root (current_panel->cwd_vpath);
386
387 if (panelized_panel.list.len < 1)
388 dir_list_init (&panelized_panel.list);
389 else if (panelized_panel.list.len > panel->dir.size)
390 dir_list_grow (&panel->dir, panelized_panel.list.len - panel->dir.size);
391
392 list = &panel->dir;
393 list->len = panelized_panel.list.len;
394
395 panelized_same = vfs_path_equal (panelized_panel.root_vpath, panel->cwd_vpath);
396
397 for (i = 0; i < panelized_panel.list.len; i++)
398 {
399 if (panelized_same || DIR_IS_DOTDOT (panelized_panel.list.list[i].fname))
400 {
401 list->list[i].fnamelen = panelized_panel.list.list[i].fnamelen;
402 list->list[i].fname = g_strndup (panelized_panel.list.list[i].fname,
403 panelized_panel.list.list[i].fnamelen);
404 }
405 else
406 {
407 vfs_path_t *tmp_vpath;
408 const char *fname;
409
410 tmp_vpath =
411 vfs_path_append_new (panelized_panel.root_vpath, panelized_panel.list.list[i].fname,
412 (char *) NULL);
413 fname = vfs_path_as_str (tmp_vpath);
414 list->list[i].fnamelen = strlen (fname);
415 list->list[i].fname = g_strndup (fname, list->list[i].fnamelen);
416 vfs_path_free (tmp_vpath);
417 }
418 list->list[i].f.link_to_dir = panelized_panel.list.list[i].f.link_to_dir;
419 list->list[i].f.stale_link = panelized_panel.list.list[i].f.stale_link;
420 list->list[i].f.dir_size_computed = panelized_panel.list.list[i].f.dir_size_computed;
421 list->list[i].f.marked = panelized_panel.list.list[i].f.marked;
422 list->list[i].st = panelized_panel.list.list[i].st;
423 list->list[i].sort_key = panelized_panel.list.list[i].sort_key;
424 list->list[i].second_sort_key = panelized_panel.list.list[i].second_sort_key;
425 }
426
427 panel->is_panelized = TRUE;
428 panelize_absolutize_if_needed (panel);
429
430 try_to_select (panel, NULL);
431 }
432
433
434
435
436
437
438
439
440
441 void
442 panelize_change_root (const vfs_path_t * new_root)
443 {
444 vfs_path_free (panelized_panel.root_vpath);
445 panelized_panel.root_vpath = vfs_path_clone (new_root);
446 }
447
448
449
450 void
451 panelize_save_panel (WPanel * panel)
452 {
453 int i;
454 dir_list *list = &panel->dir;
455
456 panelize_change_root (current_panel->cwd_vpath);
457
458 if (panelized_panel.list.len > 0)
459 dir_list_clean (&panelized_panel.list);
460 if (panel->dir.len == 0)
461 return;
462
463 if (panel->dir.len > panelized_panel.list.size)
464 dir_list_grow (&panelized_panel.list, panel->dir.len - panelized_panel.list.size);
465 panelized_panel.list.len = panel->dir.len;
466
467 for (i = 0; i < panel->dir.len; i++)
468 {
469 panelized_panel.list.list[i].fnamelen = list->list[i].fnamelen;
470 panelized_panel.list.list[i].fname =
471 g_strndup (list->list[i].fname, list->list[i].fnamelen);
472 panelized_panel.list.list[i].f.link_to_dir = list->list[i].f.link_to_dir;
473 panelized_panel.list.list[i].f.stale_link = list->list[i].f.stale_link;
474 panelized_panel.list.list[i].f.dir_size_computed = list->list[i].f.dir_size_computed;
475 panelized_panel.list.list[i].f.marked = list->list[i].f.marked;
476 panelized_panel.list.list[i].st = list->list[i].st;
477 panelized_panel.list.list[i].sort_key = list->list[i].sort_key;
478 panelized_panel.list.list[i].second_sort_key = list->list[i].second_sort_key;
479 }
480 }
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501 void
502 panelize_absolutize_if_needed (WPanel * panel)
503 {
504 const dir_list *const list = &panel->dir;
505
506
507
508 if (list->len > 1 && g_path_is_absolute (list->list[1].fname))
509 {
510 vfs_path_t *root;
511
512 root = vfs_path_from_str (PATH_SEP_STR);
513 panel_set_cwd (panel, root);
514 if (panel == current_panel)
515 mc_chdir (root);
516 vfs_path_free (root);
517 }
518 }
519
520
521
522 void
523 cd_panelize_cmd (void)
524 {
525 if (!SELECTED_IS_PANEL)
526 create_panel (MENU_PANEL_IDX, view_listing);
527
528 do_panelize_cd (PANEL (get_panel_widget (MENU_PANEL_IDX)));
529 }
530
531
532
533 void
534 external_panelize (void)
535 {
536 if (!vfs_current_is_local ())
537 {
538 message (D_ERROR, MSG_ERROR, _("Cannot run external panelize in a non-local directory"));
539 return;
540 }
541
542 init_panelize ();
543
544
545 tty_setcolor (SELECTED_COLOR);
546
547 switch (dlg_run (panelize_dlg))
548 {
549 case B_CANCEL:
550 break;
551
552 case B_ADD:
553 add2panelize_cmd ();
554 break;
555
556 case B_REMOVE:
557 {
558 struct panelize *entry;
559
560 listbox_get_current (l_panelize, NULL, (void **) &entry);
561 remove_from_panelize (entry);
562 break;
563 }
564
565 case B_ENTER:
566 if (!input_is_empty (pname))
567 {
568 char *cmd;
569
570 cmd = g_strdup (pname->buffer);
571 dlg_destroy (panelize_dlg);
572 do_external_panelize (cmd);
573 g_free (cmd);
574 repaint_screen ();
575 return;
576 }
577 break;
578
579 default:
580 break;
581 }
582
583 panelize_done ();
584 }
585
586
587
588 void
589 load_panelize (void)
590 {
591 char **keys;
592
593 keys = mc_config_get_keys (mc_global.main_config, panelize_section, NULL);
594
595 add2panelize (g_strdup (_("Other command")), g_strdup (""));
596
597 if (*keys == NULL)
598 {
599 add2panelize (g_strdup (_("Modified git files")), g_strdup ("git ls-files --modified"));
600 add2panelize (g_strdup (_("Find rejects after patching")),
601 g_strdup ("find . -name \\*.rej -print"));
602 add2panelize (g_strdup (_("Find *.orig after patching")),
603 g_strdup ("find . -name \\*.orig -print"));
604 add2panelize (g_strdup (_("Find SUID and SGID programs")),
605 g_strdup
606 ("find . \\( \\( -perm -04000 -a -perm /011 \\) -o \\( -perm -02000 -a -perm /01 \\) \\) -print"));
607 }
608 else
609 {
610 GIConv conv;
611 char **profile_keys;
612
613 conv = str_crt_conv_from ("UTF-8");
614
615 for (profile_keys = keys; *profile_keys != NULL; profile_keys++)
616 {
617 GString *buffer;
618
619 if (mc_global.utf8_display || conv == INVALID_CONV)
620 buffer = g_string_new (*profile_keys);
621 else
622 {
623 buffer = g_string_new ("");
624 if (str_convert (conv, *profile_keys, buffer) == ESTR_FAILURE)
625 g_string_assign (buffer, *profile_keys);
626 }
627
628 add2panelize (g_string_free (buffer, FALSE),
629 mc_config_get_string (mc_global.main_config, panelize_section,
630 *profile_keys, ""));
631 }
632
633 str_close_conv (conv);
634 }
635
636 g_strfreev (keys);
637 }
638
639
640
641 void
642 save_panelize (void)
643 {
644 struct panelize *current;
645
646 mc_config_del_group (mc_global.main_config, panelize_section);
647
648 for (current = panelize; current != NULL; current = current->next)
649 if (strcmp (current->label, _("Other command")) != 0)
650 mc_config_set_string (mc_global.main_config,
651 panelize_section, current->label, current->command);
652 }
653
654
655
656 void
657 done_panelize (void)
658 {
659 struct panelize *current, *next;
660
661 for (current = panelize; current != NULL; current = next)
662 {
663 next = current->next;
664 g_free (current->label);
665 g_free (current->command);
666 g_free (current);
667 }
668 }
669
670