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 widget_destroy (WIDGET (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 mc_pipe_t *external;
310 GError *error = NULL;
311 GString *remain_file_name = NULL;
312
313 external = mc_popen (command, TRUE, TRUE, &error);
314 if (external == NULL)
315 {
316 message (D_ERROR, _("External panelize"), "%s", error->message);
317 g_error_free (error);
318 return;
319 }
320
321
322 panel_clean_dir (current_panel);
323
324 panelize_change_root (current_panel->cwd_vpath);
325
326 dir_list_init (list);
327
328 while (TRUE)
329 {
330 GString *line;
331 gboolean ok;
332
333
334 external->out.len = MC_PIPE_BUFSIZE;
335 external->err.len = MC_PIPE_BUFSIZE;
336
337 mc_pread (external, &error);
338
339 if (error != NULL)
340 {
341 message (D_ERROR, MSG_ERROR, _("External panelize:\n%s"), error->message);
342 g_error_free (error);
343 break;
344 }
345
346 if (external->err.len > 0)
347 message (D_ERROR, MSG_ERROR, _("External panelize:\n%s"), external->err.buf);
348
349 if (external->out.len == MC_PIPE_STREAM_EOF)
350 break;
351
352 if (external->out.len == 0)
353 continue;
354
355 if (external->out.len == MC_PIPE_ERROR_READ)
356 {
357 message (D_ERROR, MSG_ERROR,
358 _("External panelize:\nfailed to read data from child stdout:\n%s"),
359 unix_error_string (external->out.error));
360 break;
361 }
362
363 ok = TRUE;
364
365 while (ok && (line = mc_pstream_get_string (&external->out)) != NULL)
366 {
367 char *name;
368 gboolean link_to_dir, stale_link;
369 struct stat st;
370
371
372
373 if (line->str[line->len - 1] == '\n')
374 {
375
376
377 g_string_truncate (line, line->len - 1);
378
379
380 if (remain_file_name != NULL)
381 {
382 g_string_append_len (remain_file_name, line->str, line->len);
383 g_string_free (line, TRUE);
384 line = remain_file_name;
385 remain_file_name = NULL;
386 }
387 }
388 else
389 {
390
391
392 if (remain_file_name == NULL)
393 remain_file_name = line;
394 else
395 {
396 g_string_append_len (remain_file_name, line->str, line->len);
397 g_string_free (line, TRUE);
398 }
399
400 continue;
401 }
402
403 name = line->str;
404
405 if (name[0] == '.' && IS_PATH_SEP (name[1]))
406 name += 2;
407
408 if (handle_path (name, &st, &link_to_dir, &stale_link))
409 {
410 ok = dir_list_append (list, name, &st, link_to_dir, stale_link);
411
412 if (ok)
413 {
414 file_mark (current_panel, list->len - 1, 0);
415
416 if ((list->len & 31) == 0)
417 rotate_dash (TRUE);
418 }
419 }
420
421 g_string_free (line, TRUE);
422 }
423 }
424
425 if (remain_file_name != NULL)
426 g_string_free (remain_file_name, TRUE);
427
428 mc_pclose (external, NULL);
429
430 current_panel->is_panelized = TRUE;
431 panelize_absolutize_if_needed (current_panel);
432
433 try_to_select (current_panel, NULL);
434 panel_re_sort (current_panel);
435 rotate_dash (FALSE);
436 }
437
438
439
440 static void
441 do_panelize_cd (WPanel * panel)
442 {
443 int i;
444 dir_list *list;
445 gboolean panelized_same;
446
447 dir_list_clean (&panel->dir);
448 if (panelized_panel.root_vpath == NULL)
449 panelize_change_root (current_panel->cwd_vpath);
450
451 if (panelized_panel.list.len < 1)
452 dir_list_init (&panelized_panel.list);
453 else if (panelized_panel.list.len > panel->dir.size)
454 dir_list_grow (&panel->dir, panelized_panel.list.len - panel->dir.size);
455
456 list = &panel->dir;
457 list->len = panelized_panel.list.len;
458
459 panelized_same = vfs_path_equal (panelized_panel.root_vpath, panel->cwd_vpath);
460
461 for (i = 0; i < panelized_panel.list.len; i++)
462 {
463 if (panelized_same || DIR_IS_DOTDOT (panelized_panel.list.list[i].fname->str))
464 list->list[i].fname = mc_g_string_dup (panelized_panel.list.list[i].fname);
465 else
466 {
467 vfs_path_t *tmp_vpath;
468
469 tmp_vpath =
470 vfs_path_append_new (panelized_panel.root_vpath,
471 panelized_panel.list.list[i].fname->str, (char *) NULL);
472 list->list[i].fname = g_string_new (vfs_path_as_str (tmp_vpath));
473 vfs_path_free (tmp_vpath, TRUE);
474 }
475 list->list[i].f.link_to_dir = panelized_panel.list.list[i].f.link_to_dir;
476 list->list[i].f.stale_link = panelized_panel.list.list[i].f.stale_link;
477 list->list[i].f.dir_size_computed = panelized_panel.list.list[i].f.dir_size_computed;
478 list->list[i].f.marked = panelized_panel.list.list[i].f.marked;
479 list->list[i].st = panelized_panel.list.list[i].st;
480 list->list[i].sort_key = panelized_panel.list.list[i].sort_key;
481 list->list[i].second_sort_key = panelized_panel.list.list[i].second_sort_key;
482 }
483
484 panel->is_panelized = TRUE;
485 panelize_absolutize_if_needed (panel);
486
487 try_to_select (panel, NULL);
488 }
489
490
491
492
493
494
495
496
497
498 void
499 panelize_change_root (const vfs_path_t * new_root)
500 {
501 vfs_path_free (panelized_panel.root_vpath, TRUE);
502 panelized_panel.root_vpath = vfs_path_clone (new_root);
503 }
504
505
506
507 void
508 panelize_save_panel (WPanel * panel)
509 {
510 int i;
511 dir_list *list = &panel->dir;
512
513 panelize_change_root (current_panel->cwd_vpath);
514
515 if (panelized_panel.list.len > 0)
516 dir_list_clean (&panelized_panel.list);
517 if (panel->dir.len == 0)
518 return;
519
520 if (panel->dir.len > panelized_panel.list.size)
521 dir_list_grow (&panelized_panel.list, panel->dir.len - panelized_panel.list.size);
522 panelized_panel.list.len = panel->dir.len;
523
524 for (i = 0; i < panel->dir.len; i++)
525 {
526 panelized_panel.list.list[i].fname = mc_g_string_dup (list->list[i].fname);
527 panelized_panel.list.list[i].f.link_to_dir = list->list[i].f.link_to_dir;
528 panelized_panel.list.list[i].f.stale_link = list->list[i].f.stale_link;
529 panelized_panel.list.list[i].f.dir_size_computed = list->list[i].f.dir_size_computed;
530 panelized_panel.list.list[i].f.marked = list->list[i].f.marked;
531 panelized_panel.list.list[i].st = list->list[i].st;
532 panelized_panel.list.list[i].sort_key = list->list[i].sort_key;
533 panelized_panel.list.list[i].second_sort_key = list->list[i].second_sort_key;
534 }
535 }
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556 void
557 panelize_absolutize_if_needed (WPanel * panel)
558 {
559 const dir_list *const list = &panel->dir;
560
561
562
563 if (list->len > 1 && g_path_is_absolute (list->list[1].fname->str))
564 {
565 vfs_path_t *root;
566
567 root = vfs_path_from_str (PATH_SEP_STR);
568 panel_set_cwd (panel, root);
569 if (panel == current_panel)
570 mc_chdir (root);
571 vfs_path_free (root, TRUE);
572 }
573 }
574
575
576
577 void
578 cd_panelize_cmd (void)
579 {
580 if (!SELECTED_IS_PANEL)
581 create_panel (MENU_PANEL_IDX, view_listing);
582
583 do_panelize_cd (PANEL (get_panel_widget (MENU_PANEL_IDX)));
584 }
585
586
587
588 void
589 external_panelize (void)
590 {
591 if (!vfs_current_is_local ())
592 {
593 message (D_ERROR, MSG_ERROR, _("Cannot run external panelize in a non-local directory"));
594 return;
595 }
596
597 init_panelize ();
598
599
600 tty_setcolor (SELECTED_COLOR);
601
602 switch (dlg_run (panelize_dlg))
603 {
604 case B_CANCEL:
605 break;
606
607 case B_ADD:
608 add2panelize_cmd ();
609 break;
610
611 case B_REMOVE:
612 {
613 struct panelize *entry;
614
615 listbox_get_current (l_panelize, NULL, (void **) &entry);
616 remove_from_panelize (entry);
617 break;
618 }
619
620 case B_ENTER:
621 if (!input_is_empty (pname))
622 {
623 char *cmd;
624
625 cmd = g_strdup (pname->buffer);
626 widget_destroy (WIDGET (panelize_dlg));
627 do_external_panelize (cmd);
628 g_free (cmd);
629 repaint_screen ();
630 return;
631 }
632 break;
633
634 default:
635 break;
636 }
637
638 panelize_done ();
639 }
640
641
642
643 void
644 load_panelize (void)
645 {
646 char **keys;
647
648 keys = mc_config_get_keys (mc_global.main_config, panelize_section, NULL);
649
650 add2panelize (g_strdup (_("Other command")), g_strdup (""));
651
652 if (*keys == NULL)
653 {
654 add2panelize (g_strdup (_("Modified git files")), g_strdup ("git ls-files --modified"));
655 add2panelize (g_strdup (_("Find rejects after patching")),
656 g_strdup ("find . -name \\*.rej -print"));
657 add2panelize (g_strdup (_("Find *.orig after patching")),
658 g_strdup ("find . -name \\*.orig -print"));
659 add2panelize (g_strdup (_("Find SUID and SGID programs")),
660 g_strdup
661 ("find . \\( \\( -perm -04000 -a -perm /011 \\) -o \\( -perm -02000 -a -perm /01 \\) \\) -print"));
662 }
663 else
664 {
665 GIConv conv;
666 char **profile_keys;
667
668 conv = str_crt_conv_from ("UTF-8");
669
670 for (profile_keys = keys; *profile_keys != NULL; profile_keys++)
671 {
672 GString *buffer;
673
674 if (mc_global.utf8_display || conv == INVALID_CONV)
675 buffer = g_string_new (*profile_keys);
676 else
677 {
678 buffer = g_string_new ("");
679 if (str_convert (conv, *profile_keys, buffer) == ESTR_FAILURE)
680 g_string_assign (buffer, *profile_keys);
681 }
682
683 add2panelize (g_string_free (buffer, FALSE),
684 mc_config_get_string (mc_global.main_config, panelize_section,
685 *profile_keys, ""));
686 }
687
688 str_close_conv (conv);
689 }
690
691 g_strfreev (keys);
692 }
693
694
695
696 void
697 save_panelize (void)
698 {
699 struct panelize *current;
700
701 mc_config_del_group (mc_global.main_config, panelize_section);
702
703 for (current = panelize; current != NULL; current = current->next)
704 if (strcmp (current->label, _("Other command")) != 0)
705 mc_config_set_string (mc_global.main_config,
706 panelize_section, current->label, current->command);
707 }
708
709
710
711 void
712 done_panelize (void)
713 {
714 struct panelize *current, *next;
715
716 for (current = panelize; current != NULL; current = next)
717 {
718 next = current->next;
719 g_free (current->label);
720 g_free (current->command);
721 g_free (current);
722 }
723 }
724
725