This source file includes following definitions.
- panelized_descr_new
- panelized_descr_free
- set_colors
- format_item_free
- panel_lines
- add_permission_string
- string_file_name
- ilog10
- format_device_number
- string_file_size
- string_file_size_brief
- string_file_type
- string_file_mtime
- string_file_atime
- string_file_ctime
- string_file_permission
- string_file_perm_octal
- string_file_nlinks
- string_inode
- string_file_nuid
- string_file_ngid
- string_file_owner
- string_file_group
- string_marked
- string_space
- string_dot
- file_compute_color
- panel_items
- format_file
- repaint_file
- repaint_status
- display_mini_info
- paint_dir
- display_total_marked_size
- mini_info_separator
- show_free_space
- panel_correct_path_to_show
- panel_get_encoding_info_str
- show_dir
- adjust_top_file
- panel_save_name
- directory_history_add
- panel_load_history
- panel_save_history
- panel_destroy
- panel_paint_sort_info
- panel_get_title_without_hotkey
- panel_print_header
- parse_panel_size
- parse_display_format
- use_display_format
- panel_format
- mini_status_format
- cd_up_dir
- maybe_cd
- force_maybe_cd
- unselect_item
- panel_select_ext_cmd
- panel_set_current
- panel_current_at_half
- move_down
- move_up
- panel_move_current
- move_left
- move_right
- prev_page
- goto_parent_dir
- next_page
- goto_child_dir
- goto_top_file
- goto_middle_file
- goto_bottom_file
- move_home
- move_end
- do_mark_file
- mark_file
- mark_file_up
- mark_file_down
- mark_file_right
- mark_file_left
- panel_select_unselect_files_dialog
- panel_select_unselect_files
- panel_select_files
- panel_unselect_files
- panel_select_invert_files
- panel_do_set_filter
- do_search
- start_search
- stop_search
- do_enter_on_file_entry
- do_enter
- panel_cycle_listing_format
- chdir_other_panel
- panel_sync_other
- chdir_to_readlink
- panel_get_format_field_index_by_name
- panel_get_sortable_field_by_format
- panel_toggle_sort_order_prev
- panel_toggle_sort_order_next
- panel_select_sort_order
- panel_content_scroll_left
- panel_content_scroll_right
- panel_set_sort_type_by_id
- get_parent_dir_name
- panel_do_cd_int
- directory_history_next
- directory_history_prev
- directory_history_list
- panel_execute_cmd
- panel_key
- panel_callback
- mouse_toggle_mark
- mouse_set_mark
- mark_if_marking
- mouse_sort_col
- panel_mouse_is_on_item
- panel_mouse_callback
- reload_panelized
- update_one_panel_widget
- update_one_panel
- event_update_panels
- panel_save_current_file_to_clip_file
- panel_recursive_cd_to_parent
- panel_dir_list_callback
- panel_current_entry
- panel_set_current_by_name
- panel_clean_dir
- panel_set_cwd
- panel_set_lwd
- panel_sized_empty_new
- panel_sized_with_dir_new
- panel_reload
- set_panel_formats
- panel_set_filter
- select_item
- unmark_files
- recalculate_panel_summary
- do_file_mark
- panel_do_cd
- file_mark
- panel_find_marked_file
- panel_get_marked_file
- panel_re_sort
- panel_set_sort_order
- panel_change_encoding
- remove_encoding_from_path
- update_panels
- panel_get_num_of_sortable_fields
- panel_get_sortable_fields
- panel_get_field_by_id
- panel_get_field_by_title_hotkey
- panel_get_field_by_title
- panel_get_num_of_user_possible_fields
- panel_get_user_possible_fields
- panel_panelize_cd
- panel_panelize_change_root
- panel_panelize_absolutize_if_needed
- panel_panelize_save
- panel_init
- panel_deinit
- panel_cd
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
32
33 #include <config.h>
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 #include "lib/global.h"
40
41 #include "lib/tty/tty.h"
42 #include "lib/tty/key.h"
43 #include "lib/skin.h"
44 #include "lib/strutil.h"
45 #include "lib/mcconfig.h"
46 #include "lib/vfs/vfs.h"
47 #include "lib/unixcompat.h"
48 #include "lib/search.h"
49 #include "lib/timefmt.h"
50 #include "lib/util.h"
51 #include "lib/widget.h"
52 #ifdef HAVE_CHARSET
53 #include "lib/charsets.h"
54 #endif
55 #include "lib/event.h"
56
57 #include "src/setup.h"
58 #include "src/execute.h"
59 #ifdef HAVE_CHARSET
60 #include "src/selcodepage.h"
61 #endif
62 #include "src/keymap.h"
63 #include "src/history.h"
64 #ifdef ENABLE_SUBSHELL
65 #include "src/subshell/subshell.h"
66 #endif
67
68 #include "src/usermenu.h"
69
70 #include "dir.h"
71 #include "boxes.h"
72 #include "tree.h"
73 #include "ext.h"
74 #include "layout.h"
75 #include "cmd.h"
76 #include "command.h"
77 #include "filemanager.h"
78 #include "mountlist.h"
79 #include "cd.h"
80
81 #include "panel.h"
82
83
84
85
86 hook_t *select_file_hook = NULL;
87
88 mc_fhl_t *mc_filehighlight = NULL;
89
90
91
92 typedef enum
93 {
94 FATTR_NORMAL = 0,
95 FATTR_CURRENT,
96 FATTR_MARKED,
97 FATTR_MARKED_CURRENT,
98 FATTR_STATUS
99 } file_attr_t;
100
101 #define DEFAULT_USER_FORMAT "half type name | size | perm"
102
103
104 #define SELECT_RESET ((mc_search_t *)(-1))
105 #define SELECT_ERROR ((mc_search_t *)(-2))
106
107
108 #define MOUSE_UPPER_FILE_LIST (-1)
109 #define MOUSE_BELOW_FILE_LIST (-2)
110 #define MOUSE_AFTER_LAST_FILE (-3)
111
112
113
114 typedef enum
115 {
116 MARK_DONT_MOVE = 0,
117 MARK_DOWN = 1,
118 MARK_FORCE_DOWN = 2,
119 MARK_FORCE_UP = 3
120 } mark_act_t;
121
122
123
124
125
126 typedef struct format_item_t
127 {
128 int requested_field_len;
129 int field_len;
130 align_crt_t just_mode;
131 gboolean expand;
132 const char *(*string_fn) (const file_entry_t * fe, int len);
133 char *title;
134 const char *id;
135 } format_item_t;
136
137
138 typedef enum
139 {
140 FILENAME_NOSCROLL = 1,
141 FILENAME_SCROLL_LEFT = 2,
142 FILENAME_SCROLL_RIGHT = 4
143 } filename_scroll_flag_t;
144
145
146
147 static const char *string_file_name (const file_entry_t * fe, int len);
148 static const char *string_file_size (const file_entry_t * fe, int len);
149 static const char *string_file_size_brief (const file_entry_t * fe, int len);
150 static const char *string_file_type (const file_entry_t * fe, int len);
151 static const char *string_file_mtime (const file_entry_t * fe, int len);
152 static const char *string_file_atime (const file_entry_t * fe, int len);
153 static const char *string_file_ctime (const file_entry_t * fe, int len);
154 static const char *string_file_permission (const file_entry_t * fe, int len);
155 static const char *string_file_perm_octal (const file_entry_t * fe, int len);
156 static const char *string_file_nlinks (const file_entry_t * fe, int len);
157 static const char *string_inode (const file_entry_t * fe, int len);
158 static const char *string_file_nuid (const file_entry_t * fe, int len);
159 static const char *string_file_ngid (const file_entry_t * fe, int len);
160 static const char *string_file_owner (const file_entry_t * fe, int len);
161 static const char *string_file_group (const file_entry_t * fe, int len);
162 static const char *string_marked (const file_entry_t * fe, int len);
163 static const char *string_space (const file_entry_t * fe, int len);
164 static const char *string_dot (const file_entry_t * fe, int len);
165
166
167
168
169 static panel_field_t panel_fields[] = {
170 {
171 "unsorted", 12, TRUE, J_LEFT_FIT,
172
173
174 N_("sort|u"),
175 N_("&Unsorted"), TRUE, FALSE,
176 string_file_name,
177 (GCompareFunc) unsorted
178 }
179 ,
180 {
181 "name", 12, TRUE, J_LEFT_FIT,
182
183
184 N_("sort|n"),
185 N_("&Name"), TRUE, TRUE,
186 string_file_name,
187 (GCompareFunc) sort_name
188 }
189 ,
190 {
191 "version", 12, TRUE, J_LEFT_FIT,
192
193
194 N_("sort|v"),
195 N_("&Version"), TRUE, FALSE,
196 string_file_name,
197 (GCompareFunc) sort_vers
198 }
199 ,
200 {
201 "extension", 12, TRUE, J_LEFT_FIT,
202
203
204 N_("sort|e"),
205 N_("E&xtension"), TRUE, FALSE,
206 string_file_name,
207 (GCompareFunc) sort_ext
208 }
209 ,
210 {
211 "size", 7, FALSE, J_RIGHT,
212
213
214 N_("sort|s"),
215 N_("&Size"), TRUE, TRUE,
216 string_file_size,
217 (GCompareFunc) sort_size
218 }
219 ,
220 {
221 "bsize", 7, FALSE, J_RIGHT,
222 "",
223 N_("Block Size"), FALSE, FALSE,
224 string_file_size_brief,
225 (GCompareFunc) sort_size
226 }
227 ,
228 {
229 "type", 1, FALSE, J_LEFT,
230 "",
231 "", FALSE, TRUE,
232 string_file_type,
233 NULL
234 }
235 ,
236 {
237 "mtime", 12, FALSE, J_RIGHT,
238
239
240 N_("sort|m"),
241 N_("&Modify time"), TRUE, TRUE,
242 string_file_mtime,
243 (GCompareFunc) sort_time
244 }
245 ,
246 {
247 "atime", 12, FALSE, J_RIGHT,
248
249
250 N_("sort|a"),
251 N_("&Access time"), TRUE, TRUE,
252 string_file_atime,
253 (GCompareFunc) sort_atime
254 }
255 ,
256 {
257 "ctime", 12, FALSE, J_RIGHT,
258
259
260 N_("sort|h"),
261 N_("C&hange time"), TRUE, TRUE,
262 string_file_ctime,
263 (GCompareFunc) sort_ctime
264 }
265 ,
266 {
267 "perm", 10, FALSE, J_LEFT,
268 "",
269 N_("Permission"), FALSE, TRUE,
270 string_file_permission,
271 NULL
272 }
273 ,
274 {
275 "mode", 6, FALSE, J_RIGHT,
276 "",
277 N_("Perm"), FALSE, TRUE,
278 string_file_perm_octal,
279 NULL
280 }
281 ,
282 {
283 "nlink", 2, FALSE, J_RIGHT,
284 "",
285 N_("Nl"), FALSE, TRUE,
286 string_file_nlinks, NULL
287 }
288 ,
289 {
290 "inode", 5, FALSE, J_RIGHT,
291
292
293 N_("sort|i"),
294 N_("&Inode"), TRUE, TRUE,
295 string_inode,
296 (GCompareFunc) sort_inode
297 }
298 ,
299 {
300 "nuid", 5, FALSE, J_RIGHT,
301 "",
302 N_("UID"), FALSE, FALSE,
303 string_file_nuid,
304 NULL
305 }
306 ,
307 {
308 "ngid", 5, FALSE, J_RIGHT,
309 "",
310 N_("GID"), FALSE, FALSE,
311 string_file_ngid,
312 NULL
313 }
314 ,
315 {
316 "owner", 8, FALSE, J_LEFT_FIT,
317 "",
318 N_("Owner"), FALSE, TRUE,
319 string_file_owner,
320 NULL
321 }
322 ,
323 {
324 "group", 8, FALSE, J_LEFT_FIT,
325 "",
326 N_("Group"), FALSE, TRUE,
327 string_file_group,
328 NULL
329 }
330 ,
331 {
332 "mark", 1, FALSE, J_RIGHT,
333 "",
334 " ", FALSE, TRUE,
335 string_marked,
336 NULL
337 }
338 ,
339 {
340 "|", 1, FALSE, J_RIGHT,
341 "",
342 " ", FALSE, TRUE,
343 NULL,
344 NULL
345 }
346 ,
347 {
348 "space", 1, FALSE, J_RIGHT,
349 "",
350 " ", FALSE, TRUE,
351 string_space,
352 NULL
353 }
354 ,
355 {
356 "dot", 1, FALSE, J_RIGHT,
357 "",
358 " ", FALSE, FALSE,
359 string_dot,
360 NULL
361 }
362 ,
363 {
364 NULL, 0, FALSE, J_RIGHT, NULL, NULL, FALSE, FALSE, NULL, NULL
365 }
366 };
367
368
369 static char *panel_sort_up_char = NULL;
370 static char *panel_sort_down_char = NULL;
371
372 static char *panel_hiddenfiles_show_char = NULL;
373 static char *panel_hiddenfiles_hide_char = NULL;
374 static char *panel_history_prev_item_char = NULL;
375 static char *panel_history_next_item_char = NULL;
376 static char *panel_history_show_list_char = NULL;
377 static char *panel_filename_scroll_left_char = NULL;
378 static char *panel_filename_scroll_right_char = NULL;
379
380
381 static WPanel *mouse_mark_panel = NULL;
382
383 static gboolean mouse_marking = FALSE;
384 static int state_mark = 0;
385
386 static GString *string_file_name_buffer;
387
388
389
390
391
392 static panelized_descr_t *
393 panelized_descr_new (void)
394 {
395 panelized_descr_t *p;
396
397 p = g_new0 (panelized_descr_t, 1);
398 p->list.len = -1;
399
400 return p;
401 }
402
403
404
405 static void
406 panelized_descr_free (panelized_descr_t *p)
407 {
408 if (p != NULL)
409 {
410 dir_list_free_list (&p->list);
411 vfs_path_free (p->root_vpath, TRUE);
412 g_free (p);
413 }
414 }
415
416
417
418 static void
419 set_colors (const WPanel *panel)
420 {
421 (void) panel;
422
423 tty_set_normal_attrs ();
424 tty_setcolor (NORMAL_COLOR);
425 }
426
427
428
429
430 static void
431 format_item_free (format_item_t *format)
432 {
433 g_free (format->title);
434 g_free (format);
435 }
436
437
438
439
440 static int
441 panel_lines (const WPanel *p)
442 {
443
444 return (CONST_WIDGET (p)->rect.lines - 3 - (panels_options.show_mini_info ? 2 : 0));
445 }
446
447
448
449
450 static void
451 add_permission_string (const char *dest, int width, file_entry_t *fe, file_attr_t attr, int color,
452 gboolean is_octal)
453 {
454 int i, r, l;
455
456 l = get_user_permissions (&fe->st);
457
458 if (is_octal)
459 {
460
461 l = width + l - 3;
462 r = l + 1;
463 }
464 else
465 {
466
467 l = l * 3 + 1;
468 r = l + 3;
469 }
470
471 for (i = 0; i < width; i++)
472 {
473 if (i >= l && i < r)
474 {
475 if (attr == FATTR_CURRENT || attr == FATTR_MARKED_CURRENT)
476 tty_setcolor (MARKED_SELECTED_COLOR);
477 else
478 tty_setcolor (MARKED_COLOR);
479 }
480 else if (color >= 0)
481 tty_setcolor (color);
482 else
483 tty_lowlevel_setcolor (-color);
484
485 tty_print_char (dest[i]);
486 }
487 }
488
489
490
491
492 static const char *
493 string_file_name (const file_entry_t *fe, int len)
494 {
495 (void) len;
496
497 mc_g_string_copy (string_file_name_buffer, fe->fname);
498
499 return string_file_name_buffer->str;
500 }
501
502
503
504 static unsigned int
505 ilog10 (dev_t n)
506 {
507 unsigned int digits = 0;
508
509 do
510 {
511 digits++;
512 n /= 10;
513 }
514 while (n != 0);
515
516 return digits;
517 }
518
519
520
521 static void
522 format_device_number (char *buf, size_t bufsize, dev_t dev)
523 {
524 dev_t major_dev, minor_dev;
525 unsigned int major_digits, minor_digits;
526
527 major_dev = major (dev);
528 major_digits = ilog10 (major_dev);
529
530 minor_dev = minor (dev);
531 minor_digits = ilog10 (minor_dev);
532
533 g_assert (bufsize >= 1);
534
535 if (major_digits + 1 + minor_digits + 1 <= bufsize)
536 g_snprintf (buf, bufsize, "%lu,%lu", (unsigned long) major_dev, (unsigned long) minor_dev);
537 else
538 g_strlcpy (buf, _("[dev]"), bufsize);
539 }
540
541
542
543
544 static const char *
545 string_file_size (const file_entry_t *fe, int len)
546 {
547 static char buffer[BUF_TINY];
548
549
550 if (DIR_IS_DOTDOT (fe->fname->str))
551 return _("UP--DIR");
552
553 #ifdef HAVE_STRUCT_STAT_ST_RDEV
554 if (S_ISBLK (fe->st.st_mode) || S_ISCHR (fe->st.st_mode))
555 format_device_number (buffer, len + 1, fe->st.st_rdev);
556 else
557 #endif
558 size_trunc_len (buffer, (unsigned int) len, fe->st.st_size, 0, panels_options.kilobyte_si);
559
560 return buffer;
561 }
562
563
564
565
566 static const char *
567 string_file_size_brief (const file_entry_t *fe, int len)
568 {
569 if (S_ISLNK (fe->st.st_mode) && !link_isdir (fe))
570 return _("SYMLINK");
571
572 if ((S_ISDIR (fe->st.st_mode) || link_isdir (fe)) && !DIR_IS_DOTDOT (fe->fname->str))
573 return _("SUB-DIR");
574
575 return string_file_size (fe, len);
576 }
577
578
579
580
581 static const char *
582 string_file_type (const file_entry_t *fe, int len)
583 {
584 static char buffer[2];
585
586 (void) len;
587
588 if (S_ISDIR (fe->st.st_mode))
589 buffer[0] = PATH_SEP;
590 else if (S_ISLNK (fe->st.st_mode))
591 {
592 if (link_isdir (fe))
593 buffer[0] = '~';
594 else if (fe->f.stale_link != 0)
595 buffer[0] = '!';
596 else
597 buffer[0] = '@';
598 }
599 else if (S_ISCHR (fe->st.st_mode))
600 buffer[0] = '-';
601 else if (S_ISSOCK (fe->st.st_mode))
602 buffer[0] = '=';
603 else if (S_ISDOOR (fe->st.st_mode))
604 buffer[0] = '>';
605 else if (S_ISBLK (fe->st.st_mode))
606 buffer[0] = '+';
607 else if (S_ISFIFO (fe->st.st_mode))
608 buffer[0] = '|';
609 else if (S_ISNAM (fe->st.st_mode))
610 buffer[0] = '#';
611 else if (!S_ISREG (fe->st.st_mode))
612 buffer[0] = '?';
613 else if (is_exe (fe->st.st_mode))
614 buffer[0] = '*';
615 else
616 buffer[0] = ' ';
617 buffer[1] = '\0';
618 return buffer;
619 }
620
621
622
623
624 static const char *
625 string_file_mtime (const file_entry_t *fe, int len)
626 {
627 (void) len;
628
629 return file_date (fe->st.st_mtime);
630 }
631
632
633
634
635 static const char *
636 string_file_atime (const file_entry_t *fe, int len)
637 {
638 (void) len;
639
640 return file_date (fe->st.st_atime);
641 }
642
643
644
645
646 static const char *
647 string_file_ctime (const file_entry_t *fe, int len)
648 {
649 (void) len;
650
651 return file_date (fe->st.st_ctime);
652 }
653
654
655
656
657 static const char *
658 string_file_permission (const file_entry_t *fe, int len)
659 {
660 (void) len;
661
662 return string_perm (fe->st.st_mode);
663 }
664
665
666
667
668 static const char *
669 string_file_perm_octal (const file_entry_t *fe, int len)
670 {
671 static char buffer[10];
672
673 (void) len;
674
675 g_snprintf (buffer, sizeof (buffer), "0%06lo", (unsigned long) fe->st.st_mode);
676 return buffer;
677 }
678
679
680
681
682 static const char *
683 string_file_nlinks (const file_entry_t *fe, int len)
684 {
685 static char buffer[BUF_TINY];
686
687 (void) len;
688
689 g_snprintf (buffer, sizeof (buffer), "%16d", (int) fe->st.st_nlink);
690 return buffer;
691 }
692
693
694
695
696 static const char *
697 string_inode (const file_entry_t *fe, int len)
698 {
699 static char buffer[10];
700
701 (void) len;
702
703 g_snprintf (buffer, sizeof (buffer), "%lu", (unsigned long) fe->st.st_ino);
704 return buffer;
705 }
706
707
708
709
710 static const char *
711 string_file_nuid (const file_entry_t *fe, int len)
712 {
713 static char buffer[10];
714
715 (void) len;
716
717 g_snprintf (buffer, sizeof (buffer), "%lu", (unsigned long) fe->st.st_uid);
718 return buffer;
719 }
720
721
722
723
724 static const char *
725 string_file_ngid (const file_entry_t *fe, int len)
726 {
727 static char buffer[10];
728
729 (void) len;
730
731 g_snprintf (buffer, sizeof (buffer), "%lu", (unsigned long) fe->st.st_gid);
732 return buffer;
733 }
734
735
736
737
738 static const char *
739 string_file_owner (const file_entry_t *fe, int len)
740 {
741 (void) len;
742
743 return get_owner (fe->st.st_uid);
744 }
745
746
747
748
749 static const char *
750 string_file_group (const file_entry_t *fe, int len)
751 {
752 (void) len;
753
754 return get_group (fe->st.st_gid);
755 }
756
757
758
759
760 static const char *
761 string_marked (const file_entry_t *fe, int len)
762 {
763 (void) len;
764
765 return fe->f.marked != 0 ? "*" : " ";
766 }
767
768
769
770
771 static const char *
772 string_space (const file_entry_t *fe, int len)
773 {
774 (void) fe;
775 (void) len;
776
777 return " ";
778 }
779
780
781
782
783 static const char *
784 string_dot (const file_entry_t *fe, int len)
785 {
786 (void) fe;
787 (void) len;
788
789 return ".";
790 }
791
792
793
794 static int
795 file_compute_color (const file_attr_t attr, file_entry_t *fe)
796 {
797 switch (attr)
798 {
799 case FATTR_CURRENT:
800 return (SELECTED_COLOR);
801 case FATTR_MARKED:
802 return (MARKED_COLOR);
803 case FATTR_MARKED_CURRENT:
804 return (MARKED_SELECTED_COLOR);
805 case FATTR_STATUS:
806 return (NORMAL_COLOR);
807 case FATTR_NORMAL:
808 default:
809 if (!panels_options.filetype_mode)
810 return (NORMAL_COLOR);
811 }
812
813 return mc_fhl_get_color (mc_filehighlight, fe);
814 }
815
816
817
818
819 static int
820 panel_items (const WPanel *p)
821 {
822 return panel_lines (p) * p->list_cols;
823 }
824
825
826
827
828 static filename_scroll_flag_t
829 format_file (WPanel *panel, int file_index, int width, file_attr_t attr, gboolean isstatus,
830 int *field_length)
831 {
832 int color = NORMAL_COLOR;
833 int length = 0;
834 GSList *format, *home;
835 file_entry_t *fe = NULL;
836 filename_scroll_flag_t res = FILENAME_NOSCROLL;
837
838 *field_length = 0;
839
840 if (panel->dir.len != 0 && file_index < panel->dir.len)
841 {
842 fe = &panel->dir.list[file_index];
843 color = file_compute_color (attr, fe);
844 }
845
846 home = isstatus ? panel->status_format : panel->format;
847
848 for (format = home; format != NULL && length != width; format = g_slist_next (format))
849 {
850 format_item_t *fi = (format_item_t *) format->data;
851
852 if (fi->string_fn != NULL)
853 {
854 const char *txt = " ";
855 int len, perm = 0;
856 const char *prepared_text;
857 int name_offset = 0;
858
859 if (fe != NULL)
860 txt = fi->string_fn (fe, fi->field_len);
861
862 len = fi->field_len;
863 if (len + length > width)
864 len = width - length;
865 if (len <= 0)
866 break;
867
868 if (!isstatus && panel->content_shift > -1 && strcmp (fi->id, "name") == 0)
869 {
870 int str_len;
871 int i;
872
873 *field_length = len + 1;
874
875 str_len = str_length (txt);
876 i = MAX (0, str_len - len);
877 panel->max_shift = MAX (panel->max_shift, i);
878 i = MIN (panel->content_shift, i);
879
880 if (i > -1)
881 {
882 name_offset = str_offset_to_pos (txt, i);
883 if (str_len > len)
884 {
885 res = FILENAME_SCROLL_LEFT;
886 if (str_length (txt + name_offset) > len)
887 res |= FILENAME_SCROLL_RIGHT;
888 }
889 }
890 }
891
892 if (panels_options.permission_mode)
893 {
894 if (strcmp (fi->id, "perm") == 0)
895 perm = 1;
896 else if (strcmp (fi->id, "mode") == 0)
897 perm = 2;
898 }
899
900 if (color >= 0)
901 tty_setcolor (color);
902 else
903 tty_lowlevel_setcolor (-color);
904
905 if (!isstatus && panel->content_shift > -1)
906 prepared_text = str_fit_to_term (txt + name_offset, len, HIDE_FIT (fi->just_mode));
907 else
908 prepared_text = str_fit_to_term (txt, len, fi->just_mode);
909
910 if (perm != 0 && fe != NULL)
911 add_permission_string (prepared_text, fi->field_len, fe, attr, color, perm != 1);
912 else
913 tty_print_string (prepared_text);
914
915 length += len;
916 }
917 else
918 {
919 if (attr == FATTR_CURRENT || attr == FATTR_MARKED_CURRENT)
920 tty_setcolor (SELECTED_COLOR);
921 else
922 tty_setcolor (NORMAL_COLOR);
923 tty_print_one_vline (TRUE);
924 length++;
925 }
926 }
927
928 if (length < width)
929 {
930 int y, x;
931
932 tty_getyx (&y, &x);
933 tty_draw_hline (y, x, ' ', width - length);
934 }
935
936 return res;
937 }
938
939
940
941 static void
942 repaint_file (WPanel *panel, int file_index, file_attr_t attr)
943 {
944 Widget *w = WIDGET (panel);
945
946 int nth_column = 0;
947 int width;
948 int offset = 0;
949 filename_scroll_flag_t ret_frm;
950 int ypos = 0;
951 gboolean panel_is_split;
952 int fln = 0;
953
954 panel_is_split = panel->list_cols > 1;
955 width = w->rect.cols - 2;
956
957 if (panel_is_split)
958 {
959 nth_column = (file_index - panel->top) / panel_lines (panel);
960 width /= panel->list_cols;
961
962 offset = width * nth_column;
963
964 if (nth_column + 1 >= panel->list_cols)
965 width = w->rect.cols - offset - 2;
966 }
967
968
969 if (width <= 0)
970 return;
971
972 ypos = file_index - panel->top;
973
974 if (panel_is_split)
975 ypos %= panel_lines (panel);
976
977 ypos += 2;
978 widget_gotoyx (w, ypos, offset + 1);
979
980 ret_frm = format_file (panel, file_index, width, attr, FALSE, &fln);
981
982 if (panel_is_split && nth_column + 1 < panel->list_cols)
983 {
984 tty_setcolor (NORMAL_COLOR);
985 tty_print_one_vline (TRUE);
986 }
987
988 if (ret_frm != FILENAME_NOSCROLL)
989 {
990 if (!panel_is_split && fln > 0)
991 {
992 if (panel->list_format != list_long)
993 width = fln;
994 else
995 {
996 offset = width - fln + 1;
997 width = fln - 1;
998 }
999 }
1000
1001 widget_gotoyx (w, ypos, offset);
1002 tty_setcolor (NORMAL_COLOR);
1003 tty_print_string (panel_filename_scroll_left_char);
1004
1005 if ((ret_frm & FILENAME_SCROLL_RIGHT) != 0)
1006 {
1007 offset += width;
1008 if (nth_column + 1 >= panel->list_cols)
1009 offset++;
1010
1011 widget_gotoyx (w, ypos, offset);
1012 tty_setcolor (NORMAL_COLOR);
1013 tty_print_string (panel_filename_scroll_right_char);
1014 }
1015 }
1016 }
1017
1018
1019
1020 static void
1021 repaint_status (WPanel *panel)
1022 {
1023 int width;
1024
1025 width = WIDGET (panel)->rect.cols - 2;
1026 if (width > 0)
1027 {
1028 int fln = 0;
1029
1030 (void) format_file (panel, panel->current, width, FATTR_STATUS, TRUE, &fln);
1031 }
1032 }
1033
1034
1035
1036 static void
1037 display_mini_info (WPanel *panel)
1038 {
1039 Widget *w = WIDGET (panel);
1040 const file_entry_t *fe;
1041
1042 if (!panels_options.show_mini_info)
1043 return;
1044
1045 widget_gotoyx (w, panel_lines (panel) + 3, 1);
1046
1047 if (panel->quick_search.active)
1048 {
1049 tty_setcolor (INPUT_COLOR);
1050 tty_print_char ('/');
1051 tty_print_string (str_fit_to_term
1052 (panel->quick_search.buffer->str, w->rect.cols - 3, J_LEFT));
1053 return;
1054 }
1055
1056
1057 set_colors (panel);
1058
1059 fe = panel_current_entry (panel);
1060
1061 if (fe == NULL)
1062
1063 repaint_status (panel);
1064 else if (S_ISLNK (fe->st.st_mode))
1065 {
1066 char link_target[MC_MAXPATHLEN];
1067 vfs_path_t *lc_link_vpath;
1068 int len;
1069
1070 lc_link_vpath = vfs_path_append_new (panel->cwd_vpath, fe->fname->str, (char *) NULL);
1071 len = mc_readlink (lc_link_vpath, link_target, MC_MAXPATHLEN - 1);
1072 vfs_path_free (lc_link_vpath, TRUE);
1073 if (len > 0)
1074 {
1075 link_target[len] = 0;
1076 tty_print_string ("-> ");
1077 tty_print_string (str_fit_to_term (link_target, w->rect.cols - 5, J_LEFT_FIT));
1078 }
1079 else
1080 tty_print_string (str_fit_to_term (_("<readlink failed>"), w->rect.cols - 2, J_LEFT));
1081 }
1082 else if (DIR_IS_DOTDOT (fe->fname->str))
1083 {
1084
1085
1086
1087
1088 tty_print_string (str_fit_to_term (_("UP--DIR"), w->rect.cols - 2, J_LEFT));
1089 }
1090 else
1091
1092 repaint_status (panel);
1093 }
1094
1095
1096
1097 static void
1098 paint_dir (WPanel *panel)
1099 {
1100 int i;
1101 int items;
1102
1103 items = panel_items (panel);
1104
1105 panel->max_shift = -1;
1106
1107 for (i = 0; i < items; i++)
1108 {
1109 file_attr_t attr = FATTR_NORMAL;
1110 int n;
1111 gboolean marked;
1112
1113 n = i + panel->top;
1114 marked = (panel->dir.list[n].f.marked != 0);
1115
1116 if (n < panel->dir.len)
1117 {
1118 if (panel->current == n && panel->active)
1119 attr = marked ? FATTR_MARKED_CURRENT : FATTR_CURRENT;
1120 else if (marked)
1121 attr = FATTR_MARKED;
1122 }
1123
1124 repaint_file (panel, n, attr);
1125 }
1126
1127 tty_set_normal_attrs ();
1128 }
1129
1130
1131
1132 static void
1133 display_total_marked_size (const WPanel *panel, int y, int x, gboolean size_only)
1134 {
1135 const Widget *w = CONST_WIDGET (panel);
1136
1137 char buffer[BUF_SMALL], b_bytes[BUF_SMALL];
1138 const char *buf;
1139 int cols;
1140
1141 if (panel->marked <= 0)
1142 return;
1143
1144 buf = size_only ? b_bytes : buffer;
1145 cols = w->rect.cols - 2;
1146
1147 g_strlcpy (b_bytes, size_trunc_sep (panel->total, panels_options.kilobyte_si),
1148 sizeof (b_bytes));
1149
1150 if (!size_only)
1151 g_snprintf (buffer, sizeof (buffer),
1152 ngettext ("%s in %d file", "%s in %d files", panel->marked),
1153 b_bytes, panel->marked);
1154
1155
1156 buf = str_trunc (buf, cols - 4);
1157
1158 if (x < 0)
1159
1160 x = (w->rect.cols - str_term_width1 (buf)) / 2 - 1;
1161
1162
1163
1164
1165
1166 widget_gotoyx (w, y, x);
1167 tty_setcolor (MARKED_COLOR);
1168 tty_printf (" %s ", buf);
1169 }
1170
1171
1172
1173 static void
1174 mini_info_separator (const WPanel *panel)
1175 {
1176 if (panels_options.show_mini_info)
1177 {
1178 const Widget *w = CONST_WIDGET (panel);
1179 int y;
1180
1181 y = panel_lines (panel) + 2;
1182
1183 tty_setcolor (NORMAL_COLOR);
1184 tty_draw_hline (w->rect.y + y, w->rect.x + 1, ACS_HLINE, w->rect.cols - 2);
1185
1186
1187 display_total_marked_size (panel, y, -1, FALSE);
1188 }
1189 }
1190
1191
1192
1193 static void
1194 show_free_space (const WPanel *panel)
1195 {
1196
1197 static struct my_statfs myfs_stats;
1198
1199 static char *old_cwd = NULL;
1200
1201
1202 if (!vfs_file_is_local (panel->cwd_vpath) || !free_space)
1203 return;
1204
1205 if (old_cwd == NULL || strcmp (old_cwd, vfs_path_as_str (panel->cwd_vpath)) != 0)
1206 {
1207 char rpath[PATH_MAX];
1208
1209 init_my_statfs ();
1210 g_free (old_cwd);
1211 old_cwd = g_strdup (vfs_path_as_str (panel->cwd_vpath));
1212
1213 if (mc_realpath (old_cwd, rpath) == NULL)
1214 return;
1215
1216 my_statfs (&myfs_stats, rpath);
1217 }
1218
1219 if (myfs_stats.avail != 0 || myfs_stats.total != 0)
1220 {
1221 const Widget *w = CONST_WIDGET (panel);
1222 char buffer1[6], buffer2[6], tmp[BUF_SMALL];
1223
1224 size_trunc_len (buffer1, sizeof (buffer1) - 1, myfs_stats.avail, 1,
1225 panels_options.kilobyte_si);
1226 size_trunc_len (buffer2, sizeof (buffer2) - 1, myfs_stats.total, 1,
1227 panels_options.kilobyte_si);
1228 g_snprintf (tmp, sizeof (tmp), " %s / %s (%d%%) ", buffer1, buffer2,
1229 myfs_stats.total == 0 ? 0 :
1230 (int) (100 * (long double) myfs_stats.avail / myfs_stats.total));
1231 widget_gotoyx (w, w->rect.lines - 1, w->rect.cols - 2 - (int) strlen (tmp));
1232 tty_setcolor (NORMAL_COLOR);
1233 tty_print_string (tmp);
1234 }
1235 }
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247 static char *
1248 panel_correct_path_to_show (const WPanel *panel)
1249 {
1250 vfs_path_t *last_vpath;
1251 const vfs_path_element_t *path_element;
1252 char *return_path;
1253 int elements_count;
1254
1255 elements_count = vfs_path_elements_count (panel->cwd_vpath);
1256
1257
1258 path_element = vfs_path_element_clone (vfs_path_get_by_index (panel->cwd_vpath, -1));
1259
1260 if (elements_count > 1 && (strcmp (path_element->class->name, "cpiofs") == 0 ||
1261 strcmp (path_element->class->name, "extfs") == 0 ||
1262 strcmp (path_element->class->name, "tarfs") == 0))
1263 {
1264 const char *archive_name;
1265 const vfs_path_element_t *prev_path_element;
1266
1267
1268 prev_path_element = vfs_path_get_by_index (panel->cwd_vpath, -2);
1269 archive_name = strrchr (prev_path_element->path, PATH_SEP);
1270 if (archive_name != NULL)
1271 last_vpath = vfs_path_from_str_flags (archive_name + 1, VPF_NO_CANON);
1272 else
1273 {
1274 last_vpath = vfs_path_from_str_flags (prev_path_element->path, VPF_NO_CANON);
1275 last_vpath->relative = TRUE;
1276 }
1277 }
1278 else
1279 last_vpath = vfs_path_new (TRUE);
1280
1281 vfs_path_add_element (last_vpath, path_element);
1282 return_path =
1283 vfs_path_to_str_flags (last_vpath, 0,
1284 VPF_STRIP_HOME | VPF_STRIP_PASSWORD | VPF_HIDE_CHARSET);
1285 vfs_path_free (last_vpath, TRUE);
1286
1287 return return_path;
1288 }
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299 #ifdef HAVE_CHARSET
1300 static char *
1301 panel_get_encoding_info_str (const WPanel *panel)
1302 {
1303 char *ret_str = NULL;
1304 const vfs_path_element_t *path_element;
1305
1306 path_element = vfs_path_get_by_index (panel->cwd_vpath, -1);
1307 if (path_element->encoding != NULL)
1308 ret_str = g_strdup_printf ("[%s]", path_element->encoding);
1309
1310 return ret_str;
1311 }
1312 #endif
1313
1314
1315
1316 static void
1317 show_dir (const WPanel *panel)
1318 {
1319 const Widget *w = CONST_WIDGET (panel);
1320 gchar *tmp;
1321
1322 set_colors (panel);
1323 tty_draw_box (w->rect.y, w->rect.x, w->rect.lines, w->rect.cols, FALSE);
1324
1325 if (panels_options.show_mini_info)
1326 {
1327 int y;
1328
1329 y = panel_lines (panel) + 2;
1330
1331 widget_gotoyx (w, y, 0);
1332 tty_print_alt_char (ACS_LTEE, FALSE);
1333 widget_gotoyx (w, y, w->rect.cols - 1);
1334 tty_print_alt_char (ACS_RTEE, FALSE);
1335 }
1336
1337 widget_gotoyx (w, 0, 1);
1338 tty_print_string (panel_history_prev_item_char);
1339
1340 tmp = panels_options.show_dot_files ? panel_hiddenfiles_show_char : panel_hiddenfiles_hide_char;
1341 tmp = g_strdup_printf ("%s[%s]%s", tmp, panel_history_show_list_char,
1342 panel_history_next_item_char);
1343
1344 widget_gotoyx (w, 0, w->rect.cols - 6);
1345 tty_print_string (tmp);
1346
1347 g_free (tmp);
1348
1349 widget_gotoyx (w, 0, 3);
1350
1351 if (panel->is_panelized)
1352 tty_printf (" %s ", _("Panelize"));
1353 #ifdef HAVE_CHARSET
1354 else
1355 {
1356 tmp = panel_get_encoding_info_str (panel);
1357 if (tmp != NULL)
1358 {
1359 tty_printf ("%s", tmp);
1360 widget_gotoyx (w, 0, 3 + strlen (tmp));
1361 g_free (tmp);
1362 }
1363 }
1364 #endif
1365
1366 if (panel->active)
1367 tty_setcolor (REVERSE_COLOR);
1368
1369 tmp = panel_correct_path_to_show (panel);
1370 tty_printf (" %s ", str_term_trim (tmp, MIN (MAX (w->rect.cols - 12, 0), w->rect.cols)));
1371 g_free (tmp);
1372
1373 if (!panels_options.show_mini_info)
1374 {
1375 if (panel->marked == 0)
1376 {
1377 const file_entry_t *fe;
1378
1379 fe = panel_current_entry (panel);
1380
1381
1382 if (fe != NULL && S_ISREG (fe->st.st_mode))
1383 {
1384 char buffer[BUF_SMALL];
1385
1386 g_snprintf (buffer, sizeof (buffer), " %s ",
1387 size_trunc_sep (fe->st.st_size, panels_options.kilobyte_si));
1388 tty_setcolor (NORMAL_COLOR);
1389 widget_gotoyx (w, w->rect.lines - 1, 4);
1390 tty_print_string (buffer);
1391 }
1392 }
1393 else
1394 {
1395
1396
1397 display_total_marked_size (panel, w->rect.lines - 1, 2, TRUE);
1398 }
1399 }
1400
1401 show_free_space (panel);
1402
1403 if (panel->active)
1404 tty_set_normal_attrs ();
1405 }
1406
1407
1408
1409 static void
1410 adjust_top_file (WPanel *panel)
1411 {
1412 int items;
1413
1414 items = panel_items (panel);
1415
1416 if (panel->dir.len <= items || panel->current < 0)
1417 {
1418
1419
1420 panel->top = 0;
1421 }
1422 else
1423 {
1424 int i;
1425
1426
1427 panel->current = CLAMP (panel->current, 0, panel->dir.len - 1);
1428
1429
1430
1431
1432
1433
1434
1435 if (panel->top < 0)
1436 panel->top = 0;
1437
1438 i = panel->current - items + 1;
1439 if (panel->top < i)
1440 panel->top = i;
1441
1442 i = panel->dir.len - items;
1443 if (panel->top > i)
1444 panel->top = i;
1445
1446 if (panel->top > panel->current)
1447 panel->top = panel->current;
1448 }
1449 }
1450
1451
1452
1453
1454
1455
1456
1457
1458 static char *
1459 panel_save_name (WPanel *panel)
1460 {
1461
1462 if ((mc_global.midnight_shutdown && auto_save_setup) || saving_setup)
1463 return g_strdup (panel->name);
1464
1465 return g_strconcat ("Temporal:", panel->name, (char *) NULL);
1466 }
1467
1468
1469
1470 static void
1471 directory_history_add (WPanel *panel, const vfs_path_t *vpath)
1472 {
1473 char *tmp;
1474
1475 tmp = vfs_path_to_str_flags (vpath, 0, VPF_STRIP_PASSWORD);
1476 panel->dir_history.list = list_append_unique (panel->dir_history.list, tmp);
1477 panel->dir_history.current = panel->dir_history.list;
1478 }
1479
1480
1481
1482
1483 static gboolean
1484 panel_load_history (const gchar *event_group_name, const gchar *event_name,
1485 gpointer init_data, gpointer data)
1486 {
1487 WPanel *p = PANEL (init_data);
1488 ev_history_load_save_t *ev = (ev_history_load_save_t *) data;
1489
1490 (void) event_group_name;
1491 (void) event_name;
1492
1493 if (ev->receiver == NULL || ev->receiver == WIDGET (p))
1494 {
1495 if (ev->cfg != NULL)
1496 p->dir_history.list = mc_config_history_load (ev->cfg, p->dir_history.name);
1497 else
1498 p->dir_history.list = mc_config_history_get (p->dir_history.name);
1499
1500 directory_history_add (p, p->cwd_vpath);
1501 }
1502
1503 return TRUE;
1504 }
1505
1506
1507
1508
1509 static gboolean
1510 panel_save_history (const gchar *event_group_name, const gchar *event_name,
1511 gpointer init_data, gpointer data)
1512 {
1513 WPanel *p = PANEL (init_data);
1514
1515 (void) event_group_name;
1516 (void) event_name;
1517
1518 if (p->dir_history.list != NULL)
1519 {
1520 ev_history_load_save_t *ev = (ev_history_load_save_t *) data;
1521
1522 mc_config_history_save (ev->cfg, p->dir_history.name, p->dir_history.list);
1523 }
1524
1525 return TRUE;
1526 }
1527
1528
1529
1530 static void
1531 panel_destroy (WPanel *p)
1532 {
1533 size_t i;
1534
1535 if (panels_options.auto_save_setup)
1536 {
1537 char *name;
1538
1539 name = panel_save_name (p);
1540 panel_save_setup (p, name);
1541 g_free (name);
1542 }
1543
1544 panel_clean_dir (p);
1545
1546
1547 if (p->dir_history.list != NULL)
1548 {
1549
1550 p->dir_history.list = g_list_first (p->dir_history.list);
1551 g_list_free_full (p->dir_history.list, g_free);
1552 }
1553 g_free (p->dir_history.name);
1554
1555 file_filter_clear (&p->filter);
1556
1557 g_slist_free_full (p->format, (GDestroyNotify) format_item_free);
1558 g_slist_free_full (p->status_format, (GDestroyNotify) format_item_free);
1559
1560 g_free (p->user_format);
1561 for (i = 0; i < LIST_FORMATS; i++)
1562 g_free (p->user_status_format[i]);
1563
1564 g_free (p->name);
1565
1566 panelized_descr_free (p->panelized_descr);
1567
1568 g_string_free (p->quick_search.buffer, TRUE);
1569 g_string_free (p->quick_search.prev_buffer, TRUE);
1570
1571 vfs_path_free (p->lwd_vpath, TRUE);
1572 vfs_path_free (p->cwd_vpath, TRUE);
1573 }
1574
1575
1576
1577 static void
1578 panel_paint_sort_info (const WPanel *panel)
1579 {
1580 if (*panel->sort_field->hotkey != '\0')
1581 {
1582 const char *sort_sign =
1583 panel->sort_info.reverse ? panel_sort_up_char : panel_sort_down_char;
1584 char *str;
1585
1586 str = g_strdup_printf ("%s%s", sort_sign, Q_ (panel->sort_field->hotkey));
1587 widget_gotoyx (panel, 1, 1);
1588 tty_print_string (str);
1589 g_free (str);
1590 }
1591 }
1592
1593
1594
1595 static const char *
1596 panel_get_title_without_hotkey (const char *title)
1597 {
1598 static char translated_title[BUF_TINY];
1599
1600 if (title == NULL || title[0] == '\0')
1601 translated_title[0] = '\0';
1602 else
1603 {
1604 char *hkey;
1605
1606 g_snprintf (translated_title, sizeof (translated_title), "%s", _(title));
1607
1608 hkey = strchr (translated_title, '&');
1609 if (hkey != NULL && hkey[1] != '\0')
1610 memmove (hkey, hkey + 1, strlen (hkey));
1611 }
1612
1613 return translated_title;
1614 }
1615
1616
1617
1618 static void
1619 panel_print_header (const WPanel *panel)
1620 {
1621 const Widget *w = CONST_WIDGET (panel);
1622
1623 int y, x;
1624 int i;
1625 GString *format_txt;
1626
1627 widget_gotoyx (w, 1, 1);
1628 tty_getyx (&y, &x);
1629 tty_setcolor (NORMAL_COLOR);
1630 tty_draw_hline (y, x, ' ', w->rect.cols - 2);
1631
1632 format_txt = g_string_new ("");
1633
1634 for (i = 0; i < panel->list_cols; i++)
1635 {
1636 GSList *format;
1637
1638 for (format = panel->format; format != NULL; format = g_slist_next (format))
1639 {
1640 format_item_t *fi = (format_item_t *) format->data;
1641
1642 if (fi->string_fn != NULL)
1643 {
1644 g_string_set_size (format_txt, 0);
1645
1646 if (panel->list_format == list_long && strcmp (fi->id, panel->sort_field->id) == 0)
1647 g_string_append (format_txt,
1648 panel->sort_info.reverse
1649 ? panel_sort_up_char : panel_sort_down_char);
1650
1651 g_string_append (format_txt, fi->title);
1652
1653 if (panel->filter.handler != NULL && strcmp (fi->id, "name") == 0)
1654 {
1655 g_string_append (format_txt, " [");
1656 g_string_append (format_txt, panel->filter.value);
1657 g_string_append (format_txt, "]");
1658 }
1659
1660 tty_setcolor (HEADER_COLOR);
1661 tty_print_string (str_fit_to_term (format_txt->str, fi->field_len, J_CENTER_LEFT));
1662 }
1663 else
1664 {
1665 tty_setcolor (NORMAL_COLOR);
1666 tty_print_one_vline (TRUE);
1667 }
1668 }
1669
1670 if (i < panel->list_cols - 1)
1671 {
1672 tty_setcolor (NORMAL_COLOR);
1673 tty_print_one_vline (TRUE);
1674 }
1675 }
1676
1677 g_string_free (format_txt, TRUE);
1678
1679 if (panel->list_format != list_long)
1680 panel_paint_sort_info (panel);
1681 }
1682
1683
1684
1685 static const char *
1686 parse_panel_size (WPanel *panel, const char *format, gboolean isstatus)
1687 {
1688 panel_display_t frame = frame_half;
1689
1690 format = skip_separators (format);
1691
1692 if (strncmp (format, "full", 4) == 0)
1693 {
1694 frame = frame_full;
1695 format += 4;
1696 }
1697 else if (strncmp (format, "half", 4) == 0)
1698 {
1699 frame = frame_half;
1700 format += 4;
1701 }
1702
1703 if (!isstatus)
1704 {
1705 panel->frame_size = frame;
1706 panel->list_cols = 1;
1707 }
1708
1709
1710 format = skip_separators (format);
1711
1712 if (g_ascii_isdigit (*format))
1713 {
1714 if (!isstatus)
1715 {
1716 panel->list_cols = g_ascii_digit_value (*format);
1717 if (panel->list_cols < 1)
1718 panel->list_cols = 1;
1719 }
1720
1721 format++;
1722 }
1723
1724 if (!isstatus)
1725 panel_update_cols (WIDGET (panel), panel->frame_size);
1726
1727 return skip_separators (format);
1728 }
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749 static GSList *
1750 parse_display_format (WPanel *panel, const char *format, char **error, gboolean isstatus,
1751 int *res_total_cols)
1752 {
1753 GSList *home = NULL;
1754 int total_cols = 0;
1755 size_t i;
1756
1757 static size_t i18n_timelength = 0;
1758
1759 *error = NULL;
1760
1761 if (i18n_timelength == 0)
1762 {
1763 i18n_timelength = i18n_checktimelength ();
1764
1765 for (i = 0; panel_fields[i].id != NULL; i++)
1766 if (strcmp ("time", panel_fields[i].id + 1) == 0)
1767 panel_fields[i].min_size = i18n_timelength;
1768 }
1769
1770
1771
1772
1773
1774 format = parse_panel_size (panel, format, isstatus);
1775
1776 while (*format != '\0')
1777 {
1778 format_item_t *darr;
1779 align_crt_t justify;
1780 gboolean set_justify = TRUE;
1781 gboolean found = FALSE;
1782 size_t klen = 0;
1783
1784 darr = g_new0 (format_item_t, 1);
1785 home = g_slist_append (home, darr);
1786
1787 format = skip_separators (format);
1788
1789 switch (*format)
1790 {
1791 case '<':
1792 justify = J_LEFT;
1793 format = skip_separators (format + 1);
1794 break;
1795 case '=':
1796 justify = J_CENTER;
1797 format = skip_separators (format + 1);
1798 break;
1799 case '>':
1800 justify = J_RIGHT;
1801 format = skip_separators (format + 1);
1802 break;
1803 default:
1804 justify = J_LEFT;
1805 set_justify = FALSE;
1806 break;
1807 }
1808
1809 for (i = 0; !found && panel_fields[i].id != NULL; i++)
1810 {
1811 klen = strlen (panel_fields[i].id);
1812 found = strncmp (format, panel_fields[i].id, klen) == 0;
1813 }
1814
1815 if (found)
1816 {
1817 i--;
1818 format += klen;
1819
1820 darr->requested_field_len = panel_fields[i].min_size;
1821 darr->string_fn = panel_fields[i].string_fn;
1822 darr->title = g_strdup (panel_get_title_without_hotkey (panel_fields[i].title_hotkey));
1823 darr->id = panel_fields[i].id;
1824 darr->expand = panel_fields[i].expands;
1825 darr->just_mode = panel_fields[i].default_just;
1826
1827 if (set_justify)
1828 {
1829 if (IS_FIT (darr->just_mode))
1830 darr->just_mode = MAKE_FIT (justify);
1831 else
1832 darr->just_mode = justify;
1833 }
1834
1835 format = skip_separators (format);
1836
1837
1838 if (*format == ':')
1839 {
1840 int req_length;
1841
1842
1843
1844
1845 darr->expand = FALSE;
1846 format++;
1847 req_length = atoi (format);
1848 darr->requested_field_len = req_length;
1849
1850 format = skip_numbers (format);
1851
1852
1853 if (*format == '+')
1854 {
1855 darr->expand = TRUE;
1856 format++;
1857 }
1858 }
1859 }
1860 else
1861 {
1862 size_t pos;
1863 char *tmp_format;
1864
1865 pos = strlen (format);
1866 if (pos > 8)
1867 pos = 8;
1868
1869 tmp_format = g_strndup (format, pos);
1870 g_slist_free_full (home, (GDestroyNotify) format_item_free);
1871 *error =
1872 g_strconcat (_("Unknown tag on display format:"), " ", tmp_format, (char *) NULL);
1873 g_free (tmp_format);
1874
1875 return NULL;
1876 }
1877
1878 total_cols += darr->requested_field_len;
1879 }
1880
1881 *res_total_cols = total_cols;
1882 return home;
1883 }
1884
1885
1886
1887 static GSList *
1888 use_display_format (WPanel *panel, const char *format, char **error, gboolean isstatus)
1889 {
1890 #define MAX_EXPAND 4
1891 int expand_top = 0;
1892 int usable_columns;
1893 int total_cols = 0;
1894 GSList *darr, *home;
1895
1896 if (format == NULL)
1897 format = DEFAULT_USER_FORMAT;
1898
1899 home = parse_display_format (panel, format, error, isstatus, &total_cols);
1900
1901 if (*error != NULL)
1902 return NULL;
1903
1904 panel->dirty = TRUE;
1905
1906 usable_columns = WIDGET (panel)->rect.cols - 2;
1907
1908 if (!isstatus)
1909 {
1910 usable_columns /= panel->list_cols;
1911 if (panel->list_cols > 1)
1912 usable_columns--;
1913 }
1914
1915
1916 for (darr = home; darr != NULL && expand_top < MAX_EXPAND; darr = g_slist_next (darr))
1917 {
1918 format_item_t *fi = (format_item_t *) darr->data;
1919
1920 fi->field_len = fi->requested_field_len;
1921 if (fi->expand)
1922 expand_top++;
1923 }
1924
1925
1926 if (total_cols > usable_columns)
1927 {
1928 int dif;
1929 int pdif = 0;
1930
1931 dif = total_cols - usable_columns;
1932
1933 while (dif != 0 && pdif != dif)
1934 {
1935 pdif = dif;
1936
1937 for (darr = home; darr != NULL; darr = g_slist_next (darr))
1938 {
1939 format_item_t *fi = (format_item_t *) darr->data;
1940
1941 if (dif != 0 && fi->field_len != 1)
1942 {
1943 fi->field_len--;
1944 dif--;
1945 }
1946 }
1947 }
1948
1949 total_cols = usable_columns;
1950 }
1951
1952
1953 if (usable_columns > total_cols && expand_top != 0)
1954 {
1955 int i;
1956 int spaces;
1957
1958 spaces = (usable_columns - total_cols) / expand_top;
1959
1960 for (i = 0, darr = home; darr != NULL && i < expand_top; darr = g_slist_next (darr))
1961 {
1962 format_item_t *fi = (format_item_t *) darr->data;
1963
1964 if (fi->expand)
1965 {
1966 fi->field_len += spaces;
1967 if (i == 0)
1968 fi->field_len += (usable_columns - total_cols) % expand_top;
1969 i++;
1970 }
1971 }
1972 }
1973
1974 return home;
1975 }
1976
1977
1978
1979
1980 static const char *
1981 panel_format (WPanel *panel)
1982 {
1983 switch (panel->list_format)
1984 {
1985 case list_long:
1986 return "full perm space nlink space owner space group space size space mtime space name";
1987
1988 case list_brief:
1989 {
1990 static char format[BUF_TINY];
1991 int brief_cols = panel->brief_cols;
1992
1993 if (brief_cols < 1)
1994 brief_cols = 2;
1995
1996 if (brief_cols > 9)
1997 brief_cols = 9;
1998
1999 g_snprintf (format, sizeof (format), "half %d type name", brief_cols);
2000 return format;
2001 }
2002
2003 case list_user:
2004 return panel->user_format;
2005
2006 default:
2007 case list_full:
2008 return "half type name | size | mtime";
2009 }
2010 }
2011
2012
2013
2014 static const char *
2015 mini_status_format (WPanel *panel)
2016 {
2017 if (panel->user_mini_status)
2018 return panel->user_status_format[panel->list_format];
2019
2020 switch (panel->list_format)
2021 {
2022 case list_long:
2023 return "full perm space nlink space owner space group space size space mtime space name";
2024
2025 case list_brief:
2026 return "half type name space bsize space perm space";
2027
2028 case list_full:
2029 return "half type name";
2030
2031 default:
2032 case list_user:
2033 return panel->user_format;
2034 }
2035 }
2036
2037
2038
2039
2040
2041
2042
2043 static void
2044 cd_up_dir (WPanel *panel)
2045 {
2046 vfs_path_t *up_dir;
2047
2048 up_dir = vfs_path_from_str ("..");
2049 panel_cd (panel, up_dir, cd_exact);
2050 vfs_path_free (up_dir, TRUE);
2051 }
2052
2053
2054
2055
2056 static cb_ret_t
2057 maybe_cd (WPanel *panel, gboolean move_up_dir)
2058 {
2059 if (panels_options.navigate_with_arrows && input_is_empty (cmdline))
2060 {
2061 const file_entry_t *fe;
2062
2063 if (move_up_dir)
2064 {
2065 cd_up_dir (panel);
2066 return MSG_HANDLED;
2067 }
2068
2069 fe = panel_current_entry (panel);
2070
2071 if (fe != NULL && (S_ISDIR (fe->st.st_mode) || link_isdir (fe)))
2072 {
2073 vfs_path_t *vpath;
2074
2075 vpath = vfs_path_from_str (fe->fname->str);
2076 panel_cd (panel, vpath, cd_exact);
2077 vfs_path_free (vpath, TRUE);
2078 return MSG_HANDLED;
2079 }
2080 }
2081
2082 return MSG_NOT_HANDLED;
2083 }
2084
2085
2086
2087
2088 static cb_ret_t
2089 force_maybe_cd (WPanel *panel)
2090 {
2091 if (input_is_empty (cmdline))
2092 {
2093 cd_up_dir (panel);
2094 return MSG_HANDLED;
2095 }
2096
2097 return MSG_NOT_HANDLED;
2098 }
2099
2100
2101
2102 static void
2103 unselect_item (WPanel *panel)
2104 {
2105 const file_entry_t *fe;
2106
2107 fe = panel_current_entry (panel);
2108 repaint_file (panel, panel->current,
2109 fe != NULL && fe->f.marked != 0 ? FATTR_MARKED : FATTR_NORMAL);
2110 }
2111
2112
2113
2114
2115 static void
2116 panel_select_ext_cmd (WPanel *panel)
2117 {
2118 const file_entry_t *fe;
2119 gboolean do_select;
2120 char *reg_exp, *cur_file_ext;
2121 mc_search_t *search;
2122 int i;
2123
2124 fe = panel_current_entry (panel);
2125 if (fe == NULL)
2126 return;
2127
2128 do_select = (fe->f.marked == 0);
2129
2130 cur_file_ext = str_regex_escape (extension (fe->fname->str));
2131 if (cur_file_ext[0] != '\0')
2132 reg_exp = g_strconcat ("^.*\\.", cur_file_ext, "$", (char *) NULL);
2133 else
2134 reg_exp = g_strdup ("^[^\\.]+$");
2135
2136 g_free (cur_file_ext);
2137
2138 search = mc_search_new (reg_exp, NULL);
2139 search->search_type = MC_SEARCH_T_REGEX;
2140 search->is_case_sensitive = FALSE;
2141
2142 for (i = 0; i < panel->dir.len; i++)
2143 {
2144 fe = &panel->dir.list[i];
2145
2146 if (DIR_IS_DOTDOT (fe->fname->str) || S_ISDIR (fe->st.st_mode))
2147 continue;
2148
2149 if (!mc_search_run (search, fe->fname->str, 0, fe->fname->len, NULL))
2150 continue;
2151
2152 do_file_mark (panel, i, do_select ? 1 : 0);
2153 }
2154
2155 mc_search_free (search);
2156 g_free (reg_exp);
2157 }
2158
2159
2160
2161 static void
2162 panel_set_current (WPanel *panel, int i)
2163 {
2164 if (i != panel->current)
2165 {
2166 panel->dirty = TRUE;
2167 panel->current = i;
2168 panel->top = panel->current - (WIDGET (panel)->rect.lines - 2) / 2;
2169 if (panel->top < 0)
2170 panel->top = 0;
2171 }
2172 }
2173
2174
2175
2176 static int
2177 panel_current_at_half (const WPanel *panel)
2178 {
2179 int lines, top;
2180
2181 lines = panel_lines (panel);
2182
2183
2184 top = panel->top;
2185 if (panel->list_cols > 1)
2186 top += lines * ((panel->current - top) / lines);
2187
2188 return (panel->current - top - lines / 2);
2189 }
2190
2191
2192
2193 static void
2194 move_down (WPanel *panel)
2195 {
2196 int items;
2197
2198 if (panel->dir.len == 0 || panel->current + 1 == panel->dir.len)
2199 return;
2200
2201 unselect_item (panel);
2202 panel->current++;
2203
2204 items = panel_items (panel);
2205
2206 if (panels_options.scroll_pages && panel->current - panel->top == items)
2207 {
2208
2209 panel->top += items / 2;
2210 if (panel->top > panel->dir.len - items)
2211 panel->top = panel->dir.len - items;
2212 paint_dir (panel);
2213 }
2214 else if (panels_options.scroll_center && panel_current_at_half (panel) > 0)
2215 {
2216
2217 panel->top++;
2218 if (panel->top > panel->dir.len - items)
2219 panel->top = panel->dir.len - items;
2220 }
2221 select_item (panel);
2222 }
2223
2224
2225
2226 static void
2227 move_up (WPanel *panel)
2228 {
2229 if (panel->dir.len == 0 || panel->current <= 0)
2230 return;
2231
2232 unselect_item (panel);
2233 panel->current--;
2234
2235 if (panels_options.scroll_pages && panel->current < panel->top)
2236 {
2237
2238 panel->top -= panel_items (panel) / 2;
2239 if (panel->top < 0)
2240 panel->top = 0;
2241 paint_dir (panel);
2242 }
2243 else if (panels_options.scroll_center && panel_current_at_half (panel) < 0)
2244 {
2245
2246 panel->top--;
2247 if (panel->top < 0)
2248 panel->top = 0;
2249 }
2250 select_item (panel);
2251 }
2252
2253
2254
2255
2256 static void
2257 panel_move_current (WPanel *panel, int lines)
2258 {
2259 int new_pos;
2260 gboolean adjust = FALSE;
2261
2262 if (panel->dir.len == 0 || panel->current < 0)
2263 return;
2264
2265 new_pos = panel->current + lines;
2266 if (new_pos >= panel->dir.len)
2267 new_pos = panel->dir.len - 1;
2268
2269 if (new_pos < 0)
2270 new_pos = 0;
2271
2272 unselect_item (panel);
2273 panel->current = new_pos;
2274
2275 if (panel->current - panel->top >= panel_items (panel))
2276 {
2277 panel->top += lines;
2278 adjust = TRUE;
2279 }
2280
2281 if (panel->current - panel->top < 0)
2282 {
2283 panel->top += lines;
2284 adjust = TRUE;
2285 }
2286
2287 if (adjust)
2288 {
2289 if (panel->top > panel->current)
2290 panel->top = panel->current;
2291 if (panel->top < 0)
2292 panel->top = 0;
2293 paint_dir (panel);
2294 }
2295 select_item (panel);
2296 }
2297
2298
2299
2300 static cb_ret_t
2301 move_left (WPanel *panel)
2302 {
2303 if (panel->list_cols > 1)
2304 {
2305 panel_move_current (panel, -panel_lines (panel));
2306 return MSG_HANDLED;
2307 }
2308
2309 return maybe_cd (panel, TRUE);
2310 }
2311
2312
2313
2314 static cb_ret_t
2315 move_right (WPanel *panel)
2316 {
2317 if (panel->list_cols > 1)
2318 {
2319 panel_move_current (panel, panel_lines (panel));
2320 return MSG_HANDLED;
2321 }
2322
2323 return maybe_cd (panel, FALSE);
2324 }
2325
2326
2327
2328 static void
2329 prev_page (WPanel *panel)
2330 {
2331 int items;
2332
2333 if (panel->dir.len == 0 || panel->current < 0 || (panel->current == 0 && panel->top == 0))
2334 return;
2335
2336 unselect_item (panel);
2337 items = panel_items (panel);
2338 if (panel->top < items)
2339 items = panel->top;
2340 if (items == 0)
2341 panel->current = 0;
2342 else
2343 panel->current -= items;
2344 panel->top -= items;
2345
2346 select_item (panel);
2347 paint_dir (panel);
2348 }
2349
2350
2351
2352 static void
2353 goto_parent_dir (WPanel *panel)
2354 {
2355 if (!panel->is_panelized)
2356 cd_up_dir (panel);
2357 else
2358 {
2359 const file_entry_t *fe;
2360 GString *fname;
2361 const char *bname;
2362 vfs_path_t *dname_vpath;
2363
2364 fe = panel_current_entry (panel);
2365 if (fe == NULL)
2366 return;
2367
2368 fname = fe->fname;
2369
2370 if (g_path_is_absolute (fname->str))
2371 fname = mc_g_string_dup (fname);
2372 else
2373 {
2374 char *fname2;
2375
2376 fname2 =
2377 mc_build_filename (vfs_path_as_str (panel->panelized_descr->root_vpath), fname->str,
2378 (char *) NULL);
2379
2380 fname = g_string_new_take (fname2);
2381 }
2382
2383 bname = x_basename (fname->str);
2384
2385 if (bname == fname->str)
2386 dname_vpath = vfs_path_from_str (".");
2387 else
2388 {
2389 g_string_truncate (fname, bname - fname->str);
2390 dname_vpath = vfs_path_from_str (fname->str);
2391 }
2392
2393 panel_cd (panel, dname_vpath, cd_exact);
2394 panel_set_current_by_name (panel, bname);
2395
2396 vfs_path_free (dname_vpath, TRUE);
2397 g_string_free (fname, TRUE);
2398 }
2399 }
2400
2401
2402
2403 static void
2404 next_page (WPanel *panel)
2405 {
2406 int items;
2407
2408 if (panel->dir.len == 0 || panel->current < 0 || panel->current == panel->dir.len - 1)
2409 return;
2410
2411 unselect_item (panel);
2412 items = panel_items (panel);
2413 if (panel->top > panel->dir.len - 2 * items)
2414 items = panel->dir.len - items - panel->top;
2415 if (panel->top + items < 0)
2416 items = -panel->top;
2417 if (items == 0)
2418 panel->current = panel->dir.len - 1;
2419 else
2420 panel->current += items;
2421 panel->top += items;
2422
2423 select_item (panel);
2424 paint_dir (panel);
2425 }
2426
2427
2428
2429 static void
2430 goto_child_dir (WPanel *panel)
2431 {
2432 const file_entry_t *fe;
2433
2434 fe = panel_current_entry (panel);
2435
2436 if (fe != NULL && (S_ISDIR (fe->st.st_mode) || link_isdir (fe)))
2437 {
2438 vfs_path_t *vpath;
2439
2440 vpath = vfs_path_from_str (fe->fname->str);
2441 panel_cd (panel, vpath, cd_exact);
2442 vfs_path_free (vpath, TRUE);
2443 }
2444 }
2445
2446
2447
2448 static void
2449 goto_top_file (WPanel *panel)
2450 {
2451 if (panel->dir.len == 0 || panel->current < 0)
2452 return;
2453
2454 unselect_item (panel);
2455 panel->current = panel->top;
2456 select_item (panel);
2457 }
2458
2459
2460
2461 static void
2462 goto_middle_file (WPanel *panel)
2463 {
2464 if (panel->dir.len == 0 || panel->current < 0)
2465 return;
2466
2467 unselect_item (panel);
2468 panel->current = panel->top + panel_items (panel) / 2;
2469 select_item (panel);
2470 }
2471
2472
2473
2474 static void
2475 goto_bottom_file (WPanel *panel)
2476 {
2477 if (panel->dir.len == 0 || panel->current < 0)
2478 return;
2479
2480 unselect_item (panel);
2481 panel->current = panel->top + panel_items (panel) - 1;
2482 select_item (panel);
2483 }
2484
2485
2486
2487 static void
2488 move_home (WPanel *panel)
2489 {
2490 if (panel->dir.len == 0 || panel->current <= 0)
2491 return;
2492
2493 unselect_item (panel);
2494
2495 if (panels_options.torben_fj_mode)
2496 {
2497 int middle_pos;
2498
2499 middle_pos = panel->top + panel_items (panel) / 2;
2500
2501 if (panel->current > middle_pos)
2502 {
2503 goto_middle_file (panel);
2504 return;
2505 }
2506 if (panel->current != panel->top)
2507 {
2508 goto_top_file (panel);
2509 return;
2510 }
2511 }
2512
2513 panel->top = 0;
2514 panel->current = 0;
2515
2516 paint_dir (panel);
2517 select_item (panel);
2518 }
2519
2520
2521
2522 static void
2523 move_end (WPanel *panel)
2524 {
2525 if (panel->dir.len == 0 || panel->current < 0 || panel->current == panel->dir.len - 1)
2526 return;
2527
2528 unselect_item (panel);
2529
2530 if (panels_options.torben_fj_mode)
2531 {
2532 int items, middle_pos;
2533
2534 items = panel_items (panel);
2535 middle_pos = panel->top + items / 2;
2536
2537 if (panel->current < middle_pos)
2538 {
2539 goto_middle_file (panel);
2540 return;
2541 }
2542 if (panel->current != panel->top + items - 1)
2543 {
2544 goto_bottom_file (panel);
2545 return;
2546 }
2547 }
2548
2549 panel->current = panel->dir.len - 1;
2550 paint_dir (panel);
2551 select_item (panel);
2552 }
2553
2554
2555
2556 static void
2557 do_mark_file (WPanel *panel, mark_act_t do_move)
2558 {
2559 const file_entry_t *fe;
2560
2561 fe = panel_current_entry (panel);
2562 if (fe == NULL)
2563 return;
2564
2565 do_file_mark (panel, panel->current, fe->f.marked ? 0 : 1);
2566
2567 if ((panels_options.mark_moves_down && do_move == MARK_DOWN) || do_move == MARK_FORCE_DOWN)
2568 move_down (panel);
2569 else if (do_move == MARK_FORCE_UP)
2570 move_up (panel);
2571 }
2572
2573
2574
2575 static inline void
2576 mark_file (WPanel *panel)
2577 {
2578 do_mark_file (panel, MARK_DOWN);
2579 }
2580
2581
2582
2583 static inline void
2584 mark_file_up (WPanel *panel)
2585 {
2586 do_mark_file (panel, MARK_FORCE_UP);
2587 }
2588
2589
2590
2591 static inline void
2592 mark_file_down (WPanel *panel)
2593 {
2594 do_mark_file (panel, MARK_FORCE_DOWN);
2595 }
2596
2597
2598
2599 static void
2600 mark_file_right (WPanel *panel)
2601 {
2602 int lines;
2603
2604 if (state_mark < 0)
2605 {
2606 const file_entry_t *fe;
2607
2608 fe = panel_current_entry (panel);
2609 if (fe == NULL)
2610 return;
2611
2612 state_mark = fe->f.marked ? 0 : 1;
2613 }
2614
2615 lines = panel_lines (panel);
2616 lines = MIN (lines, panel->dir.len - panel->current - 1);
2617 for (; lines != 0; lines--)
2618 {
2619 do_file_mark (panel, panel->current, state_mark);
2620 move_down (panel);
2621 }
2622 do_file_mark (panel, panel->current, state_mark);
2623 }
2624
2625
2626
2627 static void
2628 mark_file_left (WPanel *panel)
2629 {
2630 int lines;
2631
2632 if (state_mark < 0)
2633 {
2634 const file_entry_t *fe;
2635
2636 fe = panel_current_entry (panel);
2637 if (fe == NULL)
2638 return;
2639
2640 state_mark = fe->f.marked ? 0 : 1;
2641 }
2642
2643 lines = panel_lines (panel);
2644 lines = MIN (lines, panel->current + 1);
2645 for (; lines != 0; lines--)
2646 {
2647 do_file_mark (panel, panel->current, state_mark);
2648 move_up (panel);
2649 }
2650 do_file_mark (panel, panel->current, state_mark);
2651 }
2652
2653
2654
2655 static mc_search_t *
2656 panel_select_unselect_files_dialog (select_flags_t *flags, const char *title,
2657 const char *history_name, const char *help_section, char **str)
2658 {
2659 gboolean files_only = (*flags & SELECT_FILES_ONLY) != 0;
2660 gboolean case_sens = (*flags & SELECT_MATCH_CASE) != 0;
2661 gboolean shell_patterns = (*flags & SELECT_SHELL_PATTERNS) != 0;
2662
2663 char *reg_exp;
2664 mc_search_t *search;
2665
2666 quick_widget_t quick_widgets[] = {
2667
2668 QUICK_INPUT (INPUT_LAST_TEXT, history_name, ®_exp, NULL,
2669 FALSE, FALSE, INPUT_COMPLETE_FILENAMES),
2670 QUICK_START_COLUMNS,
2671 QUICK_CHECKBOX (N_("&Files only"), &files_only, NULL),
2672 QUICK_CHECKBOX (N_("&Using shell patterns"), &shell_patterns, NULL),
2673 QUICK_NEXT_COLUMN,
2674 QUICK_CHECKBOX (N_("&Case sensitive"), &case_sens, NULL),
2675 QUICK_STOP_COLUMNS,
2676 QUICK_END
2677
2678 };
2679
2680 WRect r = { -1, -1, 0, 50 };
2681
2682 quick_dialog_t qdlg = {
2683 r, title, help_section,
2684 quick_widgets, NULL, NULL
2685 };
2686
2687 if (quick_dialog (&qdlg) == B_CANCEL)
2688 return NULL;
2689
2690 if (*reg_exp == '\0')
2691 {
2692 g_free (reg_exp);
2693 if (str != NULL)
2694 *str = NULL;
2695 return SELECT_RESET;
2696 }
2697
2698 search = mc_search_new (reg_exp, NULL);
2699 search->search_type = shell_patterns ? MC_SEARCH_T_GLOB : MC_SEARCH_T_REGEX;
2700 search->is_entire_line = TRUE;
2701 search->is_case_sensitive = case_sens;
2702
2703 if (str != NULL)
2704 *str = reg_exp;
2705 else
2706 g_free (reg_exp);
2707
2708 if (!mc_search_prepare (search))
2709 {
2710 message (D_ERROR, MSG_ERROR, _("Malformed regular expression"));
2711 mc_search_free (search);
2712 return SELECT_ERROR;
2713 }
2714
2715
2716 *flags = 0;
2717 if (case_sens)
2718 *flags |= SELECT_MATCH_CASE;
2719 if (files_only)
2720 *flags |= SELECT_FILES_ONLY;
2721 if (shell_patterns)
2722 *flags |= SELECT_SHELL_PATTERNS;
2723
2724 return search;
2725 }
2726
2727
2728
2729 static void
2730 panel_select_unselect_files (WPanel *panel, const char *title, const char *history_name,
2731 const char *help_section, gboolean do_select)
2732 {
2733 mc_search_t *search;
2734 gboolean files_only;
2735 int i;
2736
2737 search = panel_select_unselect_files_dialog (&panels_options.select_flags, title, history_name,
2738 help_section, NULL);
2739 if (search == NULL || search == SELECT_RESET || search == SELECT_ERROR)
2740 return;
2741
2742 files_only = (panels_options.select_flags & SELECT_FILES_ONLY) != 0;
2743
2744 for (i = 0; i < panel->dir.len; i++)
2745 {
2746 if (DIR_IS_DOTDOT (panel->dir.list[i].fname->str))
2747 continue;
2748 if (S_ISDIR (panel->dir.list[i].st.st_mode) && files_only)
2749 continue;
2750
2751 if (mc_search_run
2752 (search, panel->dir.list[i].fname->str, 0, panel->dir.list[i].fname->len, NULL))
2753 do_file_mark (panel, i, do_select ? 1 : 0);
2754 }
2755
2756 mc_search_free (search);
2757 }
2758
2759
2760
2761 static void
2762 panel_select_files (WPanel *panel)
2763 {
2764 panel_select_unselect_files (panel, _("Select"), MC_HISTORY_FM_PANEL_SELECT,
2765 "[Select/Unselect Files]", TRUE);
2766 }
2767
2768
2769
2770 static void
2771 panel_unselect_files (WPanel *panel)
2772 {
2773 panel_select_unselect_files (panel, _("Unselect"), MC_HISTORY_FM_PANEL_UNSELECT,
2774 "[Select/Unselect Files]", FALSE);
2775 }
2776
2777
2778
2779 static void
2780 panel_select_invert_files (WPanel *panel)
2781 {
2782 int i;
2783
2784 for (i = 0; i < panel->dir.len; i++)
2785 {
2786 file_entry_t *file = &panel->dir.list[i];
2787
2788 if (!panels_options.reverse_files_only || !S_ISDIR (file->st.st_mode))
2789 do_file_mark (panel, i, file->f.marked ? 0 : 1);
2790 }
2791 }
2792
2793
2794
2795 static void
2796 panel_do_set_filter (WPanel *panel)
2797 {
2798
2799 file_filter_t ff = { .value = NULL, .handler = NULL, .flags = panel->filter.flags };
2800
2801
2802 ff.handler =
2803 panel_select_unselect_files_dialog (&ff.flags, _("Filter"), MC_HISTORY_FM_PANEL_FILTER,
2804 "[Filter...]", &ff.value);
2805
2806 if (ff.handler == NULL || ff.handler == SELECT_ERROR)
2807 return;
2808
2809 if (ff.handler == SELECT_RESET)
2810 ff.handler = NULL;
2811
2812 panel_set_filter (panel, &ff);
2813 }
2814
2815
2816
2817
2818
2819
2820
2821 static void
2822 do_search (WPanel *panel, int c_code)
2823 {
2824 int curr;
2825 int i;
2826 gboolean wrapped = FALSE;
2827 char *act;
2828 mc_search_t *search;
2829 char *reg_exp, *esc_str;
2830 gboolean is_found = FALSE;
2831
2832 if (c_code == KEY_BACKSPACE)
2833 {
2834 if (panel->quick_search.buffer->len != 0)
2835 {
2836 act = panel->quick_search.buffer->str + panel->quick_search.buffer->len;
2837 str_prev_noncomb_char (&act, panel->quick_search.buffer->str);
2838 g_string_set_size (panel->quick_search.buffer, act - panel->quick_search.buffer->str);
2839 }
2840 panel->quick_search.chpoint = 0;
2841 }
2842 else
2843 {
2844 if (c_code != 0 && (gsize) panel->quick_search.chpoint < sizeof (panel->quick_search.ch))
2845 {
2846 panel->quick_search.ch[panel->quick_search.chpoint] = c_code;
2847 panel->quick_search.chpoint++;
2848 }
2849
2850 if (panel->quick_search.chpoint > 0)
2851 {
2852 switch (str_is_valid_char (panel->quick_search.ch, panel->quick_search.chpoint))
2853 {
2854 case -2:
2855 return;
2856 case -1:
2857 panel->quick_search.chpoint = 0;
2858 return;
2859 default:
2860 g_string_append_len (panel->quick_search.buffer, panel->quick_search.ch,
2861 panel->quick_search.chpoint);
2862 panel->quick_search.chpoint = 0;
2863 }
2864 }
2865 }
2866
2867 reg_exp = g_strdup_printf ("%s*", panel->quick_search.buffer->str);
2868 esc_str = str_escape (reg_exp, -1, ",|\\{}[]", TRUE);
2869 search = mc_search_new (esc_str, NULL);
2870 search->search_type = MC_SEARCH_T_GLOB;
2871 search->is_entire_line = TRUE;
2872
2873 switch (panels_options.qsearch_mode)
2874 {
2875 case QSEARCH_CASE_SENSITIVE:
2876 search->is_case_sensitive = TRUE;
2877 break;
2878 case QSEARCH_CASE_INSENSITIVE:
2879 search->is_case_sensitive = FALSE;
2880 break;
2881 default:
2882 search->is_case_sensitive = panel->sort_info.case_sensitive;
2883 break;
2884 }
2885
2886 curr = panel->current;
2887
2888 for (i = panel->current; !wrapped || i != panel->current; i++)
2889 {
2890 if (i >= panel->dir.len)
2891 {
2892 i = 0;
2893 if (wrapped)
2894 break;
2895 wrapped = TRUE;
2896 }
2897 if (mc_search_run
2898 (search, panel->dir.list[i].fname->str, 0, panel->dir.list[i].fname->len, NULL))
2899 {
2900 curr = i;
2901 is_found = TRUE;
2902 break;
2903 }
2904 }
2905 if (is_found)
2906 {
2907 unselect_item (panel);
2908 panel->current = curr;
2909 select_item (panel);
2910 widget_draw (WIDGET (panel));
2911 }
2912 else if (c_code != KEY_BACKSPACE)
2913 {
2914 act = panel->quick_search.buffer->str + panel->quick_search.buffer->len;
2915 str_prev_noncomb_char (&act, panel->quick_search.buffer->str);
2916 g_string_set_size (panel->quick_search.buffer, act - panel->quick_search.buffer->str);
2917 }
2918 mc_search_free (search);
2919 g_free (reg_exp);
2920 g_free (esc_str);
2921 }
2922
2923
2924
2925
2926
2927
2928 static void
2929 start_search (WPanel *panel)
2930 {
2931 if (panel->quick_search.active)
2932 {
2933 if (panel->current == panel->dir.len - 1)
2934 panel->current = 0;
2935 else
2936 move_down (panel);
2937
2938
2939
2940 if (panel->quick_search.buffer->len == 0)
2941 mc_g_string_copy (panel->quick_search.buffer, panel->quick_search.prev_buffer);
2942
2943 do_search (panel, 0);
2944 }
2945 else if (panel->dir.len != 0)
2946 {
2947 panel->quick_search.active = TRUE;
2948 g_string_set_size (panel->quick_search.buffer, 0);
2949 panel->quick_search.ch[0] = '\0';
2950 panel->quick_search.chpoint = 0;
2951 display_mini_info (panel);
2952 }
2953 }
2954
2955
2956
2957 static void
2958 stop_search (WPanel *panel)
2959 {
2960 if (!panel->quick_search.active)
2961 return;
2962
2963 panel->quick_search.active = FALSE;
2964
2965
2966
2967 if (panel->quick_search.buffer->len != 0)
2968 mc_g_string_copy (panel->quick_search.prev_buffer, panel->quick_search.buffer);
2969
2970 display_mini_info (panel);
2971 }
2972
2973
2974
2975
2976 static gboolean
2977 do_enter_on_file_entry (WPanel *panel, const file_entry_t *fe)
2978 {
2979 const char *fname = fe->fname->str;
2980 char *fname_quoted;
2981 vfs_path_t *full_name_vpath;
2982 gboolean ok;
2983
2984
2985
2986
2987
2988 if (S_ISDIR (fe->st.st_mode) || link_isdir (fe) || (fe->st.st_mode == 0))
2989 {
2990 vfs_path_t *fname_vpath;
2991
2992 fname_vpath = vfs_path_from_str (fname);
2993 if (!panel_cd (panel, fname_vpath, cd_exact))
2994 cd_error_message (fname);
2995 vfs_path_free (fname_vpath, TRUE);
2996 return TRUE;
2997 }
2998
2999 full_name_vpath = vfs_path_append_new (panel->cwd_vpath, fname, (char *) NULL);
3000
3001
3002 ok = regex_command (full_name_vpath, "Open") != 0;
3003 vfs_path_free (full_name_vpath, TRUE);
3004 if (ok)
3005 return TRUE;
3006
3007
3008 full_name_vpath = vfs_path_append_new (panel->cwd_vpath, fname, (char *) NULL);
3009 ok = (is_exe (fe->st.st_mode) && if_link_is_exe (full_name_vpath, fe));
3010 vfs_path_free (full_name_vpath, TRUE);
3011 if (!ok)
3012 return FALSE;
3013
3014 if (confirm_execute
3015 && query_dialog (_("The Midnight Commander"), _("Do you really want to execute?"), D_NORMAL,
3016 2, _("&Yes"), _("&No")) != 0)
3017 return TRUE;
3018
3019 if (!vfs_current_is_local ())
3020 {
3021 int ret;
3022 vfs_path_t *tmp_vpath;
3023
3024 tmp_vpath = vfs_path_append_new (vfs_get_raw_current_dir (), fname, (char *) NULL);
3025 ret = mc_setctl (tmp_vpath, VFS_SETCTL_RUN, NULL);
3026 vfs_path_free (tmp_vpath, TRUE);
3027
3028 return confirm_execute || (ret == 0);
3029 }
3030
3031 fname_quoted = name_quote (fname, FALSE);
3032 if (fname_quoted != NULL)
3033 {
3034 char *cmd;
3035
3036 cmd = g_strconcat ("." PATH_SEP_STR, fname_quoted, (char *) NULL);
3037 g_free (fname_quoted);
3038
3039 shell_execute (cmd, 0);
3040 g_free (cmd);
3041 }
3042
3043 #ifdef HAVE_CHARSET
3044 mc_global.source_codepage = default_source_codepage;
3045 #endif
3046
3047 return TRUE;
3048 }
3049
3050
3051
3052 static inline gboolean
3053 do_enter (WPanel *panel)
3054 {
3055 const file_entry_t *fe;
3056
3057 fe = panel_current_entry (panel);
3058
3059 return (fe == NULL ? FALSE : do_enter_on_file_entry (panel, fe));
3060 }
3061
3062
3063
3064 static void
3065 panel_cycle_listing_format (WPanel *panel)
3066 {
3067 panel->list_format = (panel->list_format + 1) % LIST_FORMATS;
3068
3069 if (set_panel_formats (panel) == 0)
3070 do_refresh ();
3071 }
3072
3073
3074
3075 static void
3076 chdir_other_panel (WPanel *panel)
3077 {
3078 const file_entry_t *entry;
3079 vfs_path_t *new_dir_vpath;
3080 char *curr_entry = NULL;
3081 WPanel *p;
3082
3083 entry = panel_current_entry (panel);
3084 if (entry == NULL)
3085 return;
3086
3087 if (get_other_type () != view_listing)
3088 create_panel (get_other_index (), view_listing);
3089
3090 if (S_ISDIR (entry->st.st_mode) || link_isdir (entry))
3091 new_dir_vpath = vfs_path_append_new (panel->cwd_vpath, entry->fname->str, (char *) NULL);
3092 else
3093 {
3094 new_dir_vpath = vfs_path_append_new (panel->cwd_vpath, "..", (char *) NULL);
3095 curr_entry = strrchr (vfs_path_get_last_path_str (panel->cwd_vpath), PATH_SEP);
3096 }
3097
3098 p = change_panel ();
3099 panel_cd (p, new_dir_vpath, cd_exact);
3100 vfs_path_free (new_dir_vpath, TRUE);
3101
3102 if (curr_entry != NULL)
3103 panel_set_current_by_name (p, curr_entry);
3104 (void) change_panel ();
3105
3106 move_down (panel);
3107 }
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117 static void
3118 panel_sync_other (const WPanel *panel)
3119 {
3120 if (get_other_type () != view_listing)
3121 create_panel (get_other_index (), view_listing);
3122
3123 panel_do_cd (other_panel, panel->cwd_vpath, cd_exact);
3124
3125
3126 if (!panel->is_panelized)
3127 {
3128 const file_entry_t *fe;
3129
3130 fe = panel_current_entry (panel);
3131 if (fe != NULL)
3132 panel_set_current_by_name (other_panel, fe->fname->str);
3133 }
3134 }
3135
3136
3137
3138 static void
3139 chdir_to_readlink (WPanel *panel)
3140 {
3141 const file_entry_t *fe;
3142 vfs_path_t *new_dir_vpath;
3143 char buffer[MC_MAXPATHLEN];
3144 int i;
3145 struct stat st;
3146 vfs_path_t *panel_fname_vpath;
3147 gboolean ok;
3148 WPanel *cpanel;
3149
3150 if (get_other_type () != view_listing)
3151 return;
3152
3153 fe = panel_current_entry (panel);
3154
3155 if (fe == NULL || !S_ISLNK (fe->st.st_mode))
3156 return;
3157
3158 i = readlink (fe->fname->str, buffer, MC_MAXPATHLEN - 1);
3159 if (i < 0)
3160 return;
3161
3162 panel_fname_vpath = vfs_path_from_str (fe->fname->str);
3163 ok = (mc_stat (panel_fname_vpath, &st) >= 0);
3164 vfs_path_free (panel_fname_vpath, TRUE);
3165 if (!ok)
3166 return;
3167
3168 buffer[i] = '\0';
3169 if (!S_ISDIR (st.st_mode))
3170 {
3171 char *p;
3172
3173 p = strrchr (buffer, PATH_SEP);
3174 if (p != NULL && p[1] == '\0')
3175 {
3176 *p = '\0';
3177 p = strrchr (buffer, PATH_SEP);
3178 }
3179 if (p == NULL)
3180 return;
3181
3182 p[1] = '\0';
3183 }
3184 if (IS_PATH_SEP (*buffer))
3185 new_dir_vpath = vfs_path_from_str (buffer);
3186 else
3187 new_dir_vpath = vfs_path_append_new (panel->cwd_vpath, buffer, (char *) NULL);
3188
3189 cpanel = change_panel ();
3190 panel_cd (cpanel, new_dir_vpath, cd_exact);
3191 vfs_path_free (new_dir_vpath, TRUE);
3192 (void) change_panel ();
3193
3194 move_down (panel);
3195 }
3196
3197
3198
3199
3200
3201
3202 static gsize
3203 panel_get_format_field_index_by_name (const WPanel *panel, const char *name)
3204 {
3205 GSList *format;
3206 gsize lc_index;
3207
3208 for (lc_index = 1, format = panel->format;
3209 format != NULL && strcmp (((format_item_t *) format->data)->title, name) != 0;
3210 format = g_slist_next (format), lc_index++)
3211 ;
3212
3213 if (format == NULL)
3214 lc_index = 0;
3215
3216 return lc_index;
3217 }
3218
3219
3220
3221 static const panel_field_t *
3222 panel_get_sortable_field_by_format (const WPanel *panel, gsize lc_index)
3223 {
3224 const panel_field_t *pfield;
3225 const format_item_t *format;
3226
3227 format = (const format_item_t *) g_slist_nth_data (panel->format, lc_index);
3228 if (format == NULL)
3229 return NULL;
3230
3231 pfield = panel_get_field_by_title (format->title);
3232 if (pfield == NULL)
3233 return NULL;
3234 if (pfield->sort_routine == NULL)
3235 return NULL;
3236 return pfield;
3237 }
3238
3239
3240
3241 static void
3242 panel_toggle_sort_order_prev (WPanel *panel)
3243 {
3244 gsize lc_index, i;
3245 const char *title;
3246 const panel_field_t *pfield = NULL;
3247
3248 title = panel_get_title_without_hotkey (panel->sort_field->title_hotkey);
3249 lc_index = panel_get_format_field_index_by_name (panel, title);
3250
3251 if (lc_index > 1)
3252 {
3253
3254 for (i = lc_index - 1;
3255 i != 0 && (pfield = panel_get_sortable_field_by_format (panel, i - 1)) == NULL; i--)
3256 ;
3257 }
3258
3259 if (pfield == NULL)
3260 {
3261
3262 for (i = g_slist_length (panel->format);
3263 i != 0 && (pfield = panel_get_sortable_field_by_format (panel, i - 1)) == NULL; i--)
3264 ;
3265 }
3266
3267 if (pfield != NULL)
3268 {
3269 panel->sort_field = pfield;
3270 panel_set_sort_order (panel, pfield);
3271 }
3272 }
3273
3274
3275
3276 static void
3277 panel_toggle_sort_order_next (WPanel *panel)
3278 {
3279 gsize lc_index, i;
3280 const panel_field_t *pfield = NULL;
3281 gsize format_field_count;
3282 const char *title;
3283
3284 format_field_count = g_slist_length (panel->format);
3285 title = panel_get_title_without_hotkey (panel->sort_field->title_hotkey);
3286 lc_index = panel_get_format_field_index_by_name (panel, title);
3287
3288 if (lc_index != 0 && lc_index != format_field_count)
3289 {
3290
3291 for (i = lc_index;
3292 i != format_field_count
3293 && (pfield = panel_get_sortable_field_by_format (panel, i)) == NULL; i++)
3294 ;
3295 }
3296
3297 if (pfield == NULL)
3298 {
3299
3300 for (i = 0;
3301 i != format_field_count
3302 && (pfield = panel_get_sortable_field_by_format (panel, i)) == NULL; i++)
3303 ;
3304 }
3305
3306 if (pfield != NULL)
3307 {
3308 panel->sort_field = pfield;
3309 panel_set_sort_order (panel, pfield);
3310 }
3311 }
3312
3313
3314
3315 static void
3316 panel_select_sort_order (WPanel *panel)
3317 {
3318 const panel_field_t *sort_order;
3319
3320 sort_order = sort_box (&panel->sort_info, panel->sort_field);
3321 if (sort_order != NULL)
3322 {
3323 panel->sort_field = sort_order;
3324 panel_set_sort_order (panel, sort_order);
3325 }
3326 }
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338 static void
3339 panel_content_scroll_left (WPanel *panel)
3340 {
3341 if (panel->content_shift > -1)
3342 {
3343 if (panel->content_shift > panel->max_shift)
3344 panel->content_shift = panel->max_shift;
3345
3346 panel->content_shift--;
3347 show_dir (panel);
3348 paint_dir (panel);
3349 }
3350 }
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361 static void
3362 panel_content_scroll_right (WPanel *panel)
3363 {
3364 if (panel->content_shift < 0 || panel->content_shift < panel->max_shift)
3365 {
3366 panel->content_shift++;
3367 show_dir (panel);
3368 paint_dir (panel);
3369 }
3370 }
3371
3372
3373
3374 static void
3375 panel_set_sort_type_by_id (WPanel *panel, const char *name)
3376 {
3377 if (strcmp (panel->sort_field->id, name) == 0)
3378 panel->sort_info.reverse = !panel->sort_info.reverse;
3379 else
3380 {
3381 const panel_field_t *sort_order;
3382
3383 sort_order = panel_get_field_by_id (name);
3384 if (sort_order == NULL)
3385 return;
3386
3387 panel->sort_field = sort_order;
3388 }
3389
3390 panel_set_sort_order (panel, panel->sort_field);
3391 }
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401 static const char *
3402 get_parent_dir_name (const vfs_path_t *cwd_vpath, const vfs_path_t *lwd_vpath)
3403 {
3404 size_t llen, clen;
3405 const char *p, *lwd;
3406
3407 llen = vfs_path_len (lwd_vpath);
3408 clen = vfs_path_len (cwd_vpath);
3409
3410 if (llen <= clen)
3411 return NULL;
3412
3413 lwd = vfs_path_as_str (lwd_vpath);
3414
3415 p = g_strrstr (lwd, VFS_PATH_URL_DELIMITER);
3416
3417 if (p == NULL)
3418 {
3419 const char *cwd;
3420
3421 cwd = vfs_path_as_str (cwd_vpath);
3422
3423 p = strrchr (lwd, PATH_SEP);
3424
3425 if (p != NULL && strncmp (cwd, lwd, (size_t) (p - lwd)) == 0
3426 && (clen == (size_t) (p - lwd) || (p == lwd && IS_PATH_SEP (cwd[0]) && cwd[1] == '\0')))
3427 return (p + 1);
3428
3429 return NULL;
3430 }
3431
3432
3433 while (--p > lwd && !IS_PATH_SEP (*p))
3434 ;
3435
3436 while (--p > lwd && !IS_PATH_SEP (*p))
3437 ;
3438
3439
3440 return (p != lwd || IS_PATH_SEP (*p)) ? p + 1 : p;
3441 }
3442
3443
3444
3445
3446
3447
3448
3449 static gboolean
3450 panel_do_cd_int (WPanel *panel, const vfs_path_t *new_dir_vpath, enum cd_enum cd_type)
3451 {
3452 vfs_path_t *olddir_vpath;
3453
3454
3455 if (cd_type == cd_parse_command)
3456 {
3457 const vfs_path_element_t *element;
3458
3459 element = vfs_path_get_by_index (new_dir_vpath, 0);
3460 if (strcmp (element->path, "-") == 0)
3461 new_dir_vpath = panel->lwd_vpath;
3462 }
3463
3464 if (mc_chdir (new_dir_vpath) == -1)
3465 return FALSE;
3466
3467
3468 olddir_vpath = vfs_path_clone (panel->cwd_vpath);
3469 panel_set_lwd (panel, panel->cwd_vpath);
3470 input_complete_free (cmdline);
3471
3472 vfs_path_free (panel->cwd_vpath, TRUE);
3473 vfs_setup_cwd ();
3474 panel->cwd_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
3475
3476 vfs_release_path (olddir_vpath);
3477
3478 #ifdef ENABLE_SUBSHELL
3479 subshell_chdir (panel->cwd_vpath);
3480 #endif
3481
3482
3483 panel_clean_dir (panel);
3484
3485 if (!dir_list_load (&panel->dir, panel->cwd_vpath, panel->sort_field->sort_routine,
3486 &panel->sort_info, &panel->filter))
3487 message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
3488
3489 if (panel->dir.len == 0)
3490 panel_set_current (panel, -1);
3491
3492 panel_set_current_by_name (panel, get_parent_dir_name (panel->cwd_vpath, olddir_vpath));
3493
3494 load_hint (FALSE);
3495 panel->dirty = TRUE;
3496 update_xterm_title_path ();
3497 update_terminal_cwd ();
3498
3499 vfs_path_free (olddir_vpath, TRUE);
3500
3501 return TRUE;
3502 }
3503
3504
3505
3506 static void
3507 directory_history_next (WPanel *panel)
3508 {
3509 gboolean ok;
3510
3511 do
3512 {
3513 GList *next;
3514
3515 ok = TRUE;
3516 next = g_list_next (panel->dir_history.current);
3517 if (next != NULL)
3518 {
3519 vfs_path_t *data_vpath;
3520
3521 data_vpath = vfs_path_from_str ((char *) next->data);
3522 ok = panel_do_cd_int (panel, data_vpath, cd_exact);
3523 vfs_path_free (data_vpath, TRUE);
3524 panel->dir_history.current = next;
3525 }
3526
3527 }
3528 while (!ok);
3529 }
3530
3531
3532
3533 static void
3534 directory_history_prev (WPanel *panel)
3535 {
3536 gboolean ok;
3537
3538 do
3539 {
3540 GList *prev;
3541
3542 ok = TRUE;
3543 prev = g_list_previous (panel->dir_history.current);
3544 if (prev != NULL)
3545 {
3546 vfs_path_t *data_vpath;
3547
3548 data_vpath = vfs_path_from_str ((char *) prev->data);
3549 ok = panel_do_cd_int (panel, data_vpath, cd_exact);
3550 vfs_path_free (data_vpath, TRUE);
3551 panel->dir_history.current = prev;
3552 }
3553
3554 }
3555 while (!ok);
3556 }
3557
3558
3559
3560 static void
3561 directory_history_list (WPanel *panel)
3562 {
3563 history_descriptor_t hd;
3564 gboolean ok = FALSE;
3565 size_t pos;
3566
3567 pos = g_list_position (panel->dir_history.current, panel->dir_history.list);
3568
3569 history_descriptor_init (&hd, WIDGET (panel)->rect.y, WIDGET (panel)->rect.x,
3570 panel->dir_history.list, (int) pos);
3571 history_show (&hd);
3572
3573 panel->dir_history.list = hd.list;
3574 if (hd.text != NULL)
3575 {
3576 vfs_path_t *s_vpath;
3577
3578 s_vpath = vfs_path_from_str (hd.text);
3579 ok = panel_do_cd_int (panel, s_vpath, cd_exact);
3580 if (ok)
3581 directory_history_add (panel, panel->cwd_vpath);
3582 else
3583 cd_error_message (hd.text);
3584 vfs_path_free (s_vpath, TRUE);
3585 g_free (hd.text);
3586 }
3587
3588 if (!ok)
3589 {
3590
3591
3592
3593 size_t i;
3594
3595 panel->dir_history.current = panel->dir_history.list;
3596
3597 for (i = 0; i <= pos; i++)
3598 {
3599 GList *prev;
3600
3601 prev = g_list_previous (panel->dir_history.current);
3602 if (prev == NULL)
3603 break;
3604
3605 panel->dir_history.current = prev;
3606 }
3607 }
3608 }
3609
3610
3611
3612 static cb_ret_t
3613 panel_execute_cmd (WPanel *panel, long command)
3614 {
3615 int res = MSG_HANDLED;
3616
3617 if (command != CK_Search)
3618 stop_search (panel);
3619
3620 switch (command)
3621 {
3622 case CK_Up:
3623 case CK_Down:
3624 case CK_Left:
3625 case CK_Right:
3626 case CK_Bottom:
3627 case CK_Top:
3628 case CK_PageDown:
3629 case CK_PageUp:
3630
3631 state_mark = -1;
3632 break;
3633 default:
3634 break;
3635 }
3636
3637 switch (command)
3638 {
3639 case CK_CycleListingFormat:
3640 panel_cycle_listing_format (panel);
3641 break;
3642 case CK_PanelOtherCd:
3643 chdir_other_panel (panel);
3644 break;
3645 case CK_PanelOtherCdLink:
3646 chdir_to_readlink (panel);
3647 break;
3648 case CK_CopySingle:
3649 copy_cmd_local (panel);
3650 break;
3651 case CK_DeleteSingle:
3652 delete_cmd_local (panel);
3653 break;
3654 case CK_Enter:
3655 do_enter (panel);
3656 break;
3657 case CK_ViewRaw:
3658 view_raw_cmd (panel);
3659 break;
3660 case CK_EditNew:
3661 edit_cmd_new ();
3662 break;
3663 case CK_MoveSingle:
3664 rename_cmd_local (panel);
3665 break;
3666 case CK_SelectInvert:
3667 panel_select_invert_files (panel);
3668 break;
3669 case CK_Select:
3670 panel_select_files (panel);
3671 break;
3672 case CK_SelectExt:
3673 panel_select_ext_cmd (panel);
3674 break;
3675 case CK_Unselect:
3676 panel_unselect_files (panel);
3677 break;
3678 case CK_Filter:
3679 panel_do_set_filter (panel);
3680 break;
3681 case CK_PageDown:
3682 next_page (panel);
3683 break;
3684 case CK_PageUp:
3685 prev_page (panel);
3686 break;
3687 case CK_CdChild:
3688 goto_child_dir (panel);
3689 break;
3690 case CK_CdParent:
3691 goto_parent_dir (panel);
3692 break;
3693 case CK_History:
3694 directory_history_list (panel);
3695 break;
3696 case CK_HistoryNext:
3697 directory_history_next (panel);
3698 break;
3699 case CK_HistoryPrev:
3700 directory_history_prev (panel);
3701 break;
3702 case CK_BottomOnScreen:
3703 goto_bottom_file (panel);
3704 break;
3705 case CK_MiddleOnScreen:
3706 goto_middle_file (panel);
3707 break;
3708 case CK_TopOnScreen:
3709 goto_top_file (panel);
3710 break;
3711 case CK_Mark:
3712 mark_file (panel);
3713 break;
3714 case CK_MarkUp:
3715 mark_file_up (panel);
3716 break;
3717 case CK_MarkDown:
3718 mark_file_down (panel);
3719 break;
3720 case CK_MarkLeft:
3721 mark_file_left (panel);
3722 break;
3723 case CK_MarkRight:
3724 mark_file_right (panel);
3725 break;
3726 case CK_CdParentSmart:
3727 res = force_maybe_cd (panel);
3728 break;
3729 case CK_Up:
3730 move_up (panel);
3731 break;
3732 case CK_Down:
3733 move_down (panel);
3734 break;
3735 case CK_Left:
3736 res = move_left (panel);
3737 break;
3738 case CK_Right:
3739 res = move_right (panel);
3740 break;
3741 case CK_Bottom:
3742 move_end (panel);
3743 break;
3744 case CK_Top:
3745 move_home (panel);
3746 break;
3747 #ifdef HAVE_CHARSET
3748 case CK_SelectCodepage:
3749 panel_change_encoding (panel);
3750 break;
3751 #endif
3752 case CK_ScrollLeft:
3753 panel_content_scroll_left (panel);
3754 break;
3755 case CK_ScrollRight:
3756 panel_content_scroll_right (panel);
3757 break;
3758 case CK_Search:
3759 start_search (panel);
3760 break;
3761 case CK_SearchStop:
3762 break;
3763 case CK_PanelOtherSync:
3764 panel_sync_other (panel);
3765 break;
3766 case CK_Sort:
3767 panel_select_sort_order (panel);
3768 break;
3769 case CK_SortPrev:
3770 panel_toggle_sort_order_prev (panel);
3771 break;
3772 case CK_SortNext:
3773 panel_toggle_sort_order_next (panel);
3774 break;
3775 case CK_SortReverse:
3776 panel->sort_info.reverse = !panel->sort_info.reverse;
3777 panel_set_sort_order (panel, panel->sort_field);
3778 break;
3779 case CK_SortByName:
3780 panel_set_sort_type_by_id (panel, "name");
3781 break;
3782 case CK_SortByExt:
3783 panel_set_sort_type_by_id (panel, "extension");
3784 break;
3785 case CK_SortBySize:
3786 panel_set_sort_type_by_id (panel, "size");
3787 break;
3788 case CK_SortByMTime:
3789 panel_set_sort_type_by_id (panel, "mtime");
3790 break;
3791 default:
3792 res = MSG_NOT_HANDLED;
3793 break;
3794 }
3795
3796 return res;
3797 }
3798
3799
3800
3801 static cb_ret_t
3802 panel_key (WPanel *panel, int key)
3803 {
3804 long command;
3805
3806 if (is_abort_char (key))
3807 {
3808 stop_search (panel);
3809 return MSG_HANDLED;
3810 }
3811
3812 if (panel->quick_search.active && ((key >= ' ' && key <= 255) || key == KEY_BACKSPACE))
3813 {
3814 do_search (panel, key);
3815 return MSG_HANDLED;
3816 }
3817
3818 command = widget_lookup_key (WIDGET (panel), key);
3819 if (command != CK_IgnoreKey)
3820 return panel_execute_cmd (panel, command);
3821
3822 if (panels_options.torben_fj_mode && key == ALT ('h'))
3823 {
3824 goto_middle_file (panel);
3825 return MSG_HANDLED;
3826 }
3827
3828 if (!command_prompt && ((key >= ' ' && key <= 255) || key == KEY_BACKSPACE))
3829 {
3830 start_search (panel);
3831 do_search (panel, key);
3832 return MSG_HANDLED;
3833 }
3834
3835 return MSG_NOT_HANDLED;
3836 }
3837
3838
3839
3840 static cb_ret_t
3841 panel_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
3842 {
3843 WPanel *panel = PANEL (w);
3844 WDialog *h = DIALOG (w->owner);
3845 WButtonBar *bb;
3846
3847 switch (msg)
3848 {
3849 case MSG_INIT:
3850
3851 mc_event_add (h->event_group, MCEVENT_HISTORY_LOAD, panel_load_history, w, NULL);
3852
3853 mc_event_add (h->event_group, MCEVENT_HISTORY_SAVE, panel_save_history, w, NULL);
3854 return MSG_HANDLED;
3855
3856 case MSG_DRAW:
3857
3858 widget_erase (w);
3859 show_dir (panel);
3860 panel_print_header (panel);
3861 adjust_top_file (panel);
3862 paint_dir (panel);
3863 mini_info_separator (panel);
3864 display_mini_info (panel);
3865 panel->dirty = FALSE;
3866 return MSG_HANDLED;
3867
3868 case MSG_FOCUS:
3869 state_mark = -1;
3870 current_panel = panel;
3871 panel->active = TRUE;
3872
3873 if (mc_chdir (panel->cwd_vpath) != 0)
3874 {
3875 char *cwd;
3876
3877 cwd = vfs_path_to_str_flags (panel->cwd_vpath, 0, VPF_STRIP_PASSWORD);
3878 cd_error_message (cwd);
3879 g_free (cwd);
3880 }
3881 #ifdef ENABLE_SUBSHELL
3882 else
3883 subshell_chdir (panel->cwd_vpath);
3884 #endif
3885
3886 update_xterm_title_path ();
3887 update_terminal_cwd ();
3888 select_item (panel);
3889
3890 bb = buttonbar_find (h);
3891 midnight_set_buttonbar (bb);
3892 return MSG_HANDLED;
3893
3894 case MSG_UNFOCUS:
3895
3896 stop_search (panel);
3897 panel->active = FALSE;
3898 unselect_item (panel);
3899 return MSG_HANDLED;
3900
3901 case MSG_KEY:
3902 return panel_key (panel, parm);
3903
3904 case MSG_ACTION:
3905 return panel_execute_cmd (panel, parm);
3906
3907 case MSG_DESTROY:
3908 vfs_stamp_path (panel->cwd_vpath);
3909
3910 mc_event_del (h->event_group, MCEVENT_HISTORY_LOAD, panel_load_history, w);
3911
3912 mc_event_del (h->event_group, MCEVENT_HISTORY_SAVE, panel_save_history, w);
3913 panel_destroy (panel);
3914 free_my_statfs ();
3915 return MSG_HANDLED;
3916
3917 default:
3918 return widget_default_callback (w, sender, msg, parm, data);
3919 }
3920 }
3921
3922
3923
3924
3925
3926
3927 static void
3928 mouse_toggle_mark (WPanel *panel)
3929 {
3930 const file_entry_t *fe;
3931
3932 fe = panel_current_entry (panel);
3933 if (fe != NULL)
3934 {
3935 do_mark_file (panel, MARK_DONT_MOVE);
3936 mouse_marking = fe->f.marked != 0;
3937 mouse_mark_panel = current_panel;
3938 }
3939 }
3940
3941
3942
3943 static void
3944 mouse_set_mark (WPanel *panel)
3945 {
3946 if (mouse_mark_panel == panel)
3947 {
3948 const file_entry_t *fe;
3949
3950 fe = panel_current_entry (panel);
3951 if (fe != NULL)
3952 {
3953 if (mouse_marking && fe->f.marked == 0)
3954 do_mark_file (panel, MARK_DONT_MOVE);
3955 else if (!mouse_marking && fe->f.marked != 0)
3956 do_mark_file (panel, MARK_DONT_MOVE);
3957 }
3958 }
3959 }
3960
3961
3962
3963 static void
3964 mark_if_marking (WPanel *panel, const mouse_event_t *event, int previous_current)
3965 {
3966 if ((event->buttons & GPM_B_RIGHT) == 0)
3967 return;
3968
3969 if (event->msg == MSG_MOUSE_DOWN)
3970 mouse_toggle_mark (panel);
3971 else
3972 {
3973 int pcurr, curr1, curr2;
3974
3975 pcurr = panel->current;
3976 curr1 = MIN (previous_current, panel->current);
3977 curr2 = MAX (previous_current, panel->current);
3978
3979 for (; curr1 <= curr2; curr1++)
3980 {
3981 panel->current = curr1;
3982 mouse_set_mark (panel);
3983 }
3984
3985 panel->current = pcurr;
3986 }
3987 }
3988
3989
3990
3991
3992
3993
3994
3995 static void
3996 mouse_sort_col (WPanel *panel, int x)
3997 {
3998 int i = 0;
3999 GSList *format;
4000 const char *lc_sort_name = NULL;
4001 panel_field_t *col_sort_format = NULL;
4002
4003 for (format = panel->format; format != NULL; format = g_slist_next (format))
4004 {
4005 format_item_t *fi = (format_item_t *) format->data;
4006
4007 i += fi->field_len;
4008 if (x < i + 1)
4009 {
4010
4011 lc_sort_name = fi->title;
4012 break;
4013 }
4014 }
4015
4016 if (lc_sort_name == NULL)
4017 return;
4018
4019 for (i = 0; panel_fields[i].id != NULL; i++)
4020 {
4021 const char *title;
4022
4023 title = panel_get_title_without_hotkey (panel_fields[i].title_hotkey);
4024 if (panel_fields[i].sort_routine != NULL && strcmp (title, lc_sort_name) == 0)
4025 {
4026 col_sort_format = &panel_fields[i];
4027 break;
4028 }
4029 }
4030
4031 if (col_sort_format != NULL)
4032 {
4033 if (panel->sort_field == col_sort_format)
4034
4035 panel->sort_info.reverse = !panel->sort_info.reverse;
4036 else
4037
4038 panel->sort_info.reverse = FALSE;
4039
4040 panel_set_sort_order (panel, col_sort_format);
4041 }
4042 }
4043
4044
4045
4046 static int
4047 panel_mouse_is_on_item (const WPanel *panel, int y, int x)
4048 {
4049 int lines, col_width, col;
4050
4051 if (y < 0)
4052 return MOUSE_UPPER_FILE_LIST;
4053
4054 lines = panel_lines (panel);
4055 if (y >= lines)
4056 return MOUSE_BELOW_FILE_LIST;
4057
4058 col_width = (CONST_WIDGET (panel)->rect.cols - 2) / panel->list_cols;
4059
4060 col = x / col_width;
4061
4062 y += panel->top + lines * col;
4063
4064
4065 if (y > panel->dir.len)
4066 return MOUSE_AFTER_LAST_FILE;
4067
4068
4069 return y;
4070 }
4071
4072
4073
4074 static void
4075 panel_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
4076 {
4077 WPanel *panel = PANEL (w);
4078 gboolean is_active;
4079
4080 is_active = widget_is_active (w);
4081
4082 switch (msg)
4083 {
4084 case MSG_MOUSE_DOWN:
4085 if (event->y == 0)
4086 {
4087
4088 if (event->x == 1)
4089
4090 directory_history_prev (panel);
4091 else if (event->x == w->rect.cols - 2)
4092
4093 directory_history_next (panel);
4094 else if (event->x >= w->rect.cols - 5 && event->x <= w->rect.cols - 3)
4095
4096 directory_history_list (panel);
4097 else if (event->x == w->rect.cols - 6)
4098
4099 send_message (filemanager, NULL, MSG_ACTION, CK_ShowHidden, NULL);
4100 else
4101 {
4102
4103 event->result.abort = TRUE;
4104
4105 panel->dirty = FALSE;
4106 }
4107 break;
4108 }
4109
4110 if (event->y == 1)
4111 {
4112
4113 mouse_sort_col (panel, event->x + 1);
4114 break;
4115 }
4116
4117 if (!is_active)
4118 (void) change_panel ();
4119 MC_FALLTHROUGH;
4120
4121 case MSG_MOUSE_DRAG:
4122 {
4123 int my_index;
4124 int previous_current;
4125
4126 my_index = panel_mouse_is_on_item (panel, event->y - 2, event->x);
4127 previous_current = panel->current;
4128
4129 switch (my_index)
4130 {
4131 case MOUSE_UPPER_FILE_LIST:
4132 move_up (panel);
4133 mark_if_marking (panel, event, previous_current);
4134 break;
4135
4136 case MOUSE_BELOW_FILE_LIST:
4137 move_down (panel);
4138 mark_if_marking (panel, event, previous_current);
4139 break;
4140
4141 case MOUSE_AFTER_LAST_FILE:
4142 break;
4143
4144 default:
4145 if (my_index != panel->current)
4146 {
4147 unselect_item (panel);
4148 panel->current = my_index;
4149 select_item (panel);
4150 }
4151
4152 mark_if_marking (panel, event, previous_current);
4153 break;
4154 }
4155 }
4156 break;
4157
4158 case MSG_MOUSE_UP:
4159 break;
4160
4161 case MSG_MOUSE_CLICK:
4162 if ((event->count & GPM_DOUBLE) != 0 && (event->buttons & GPM_B_LEFT) != 0 &&
4163 panel_mouse_is_on_item (panel, event->y - 2, event->x) >= 0)
4164 do_enter (panel);
4165 break;
4166
4167 case MSG_MOUSE_MOVE:
4168 break;
4169
4170 case MSG_MOUSE_SCROLL_UP:
4171 if (is_active)
4172 {
4173 if (panels_options.mouse_move_pages && panel->top > 0)
4174 prev_page (panel);
4175 else
4176 move_up (panel);
4177 }
4178 break;
4179
4180 case MSG_MOUSE_SCROLL_DOWN:
4181 if (is_active)
4182 {
4183 if (panels_options.mouse_move_pages
4184 && panel->top + panel_items (panel) < panel->dir.len)
4185 next_page (panel);
4186 else
4187 move_down (panel);
4188 }
4189 break;
4190
4191 default:
4192 break;
4193 }
4194
4195 if (panel->dirty)
4196 widget_draw (w);
4197 }
4198
4199
4200
4201 static void
4202 reload_panelized (WPanel *panel)
4203 {
4204 int i, j;
4205 dir_list *list = &panel->dir;
4206
4207
4208 (void) mc_chdir (panel->cwd_vpath);
4209
4210 for (i = 0, j = 0; i < list->len; i++)
4211 {
4212 vfs_path_t *vpath;
4213
4214 vpath = vfs_path_from_str (list->list[i].fname->str);
4215 if (mc_lstat (vpath, &list->list[i].st) != 0)
4216 g_string_free (list->list[i].fname, TRUE);
4217 else
4218 {
4219 if (j != i)
4220 list->list[j] = list->list[i];
4221 j++;
4222 }
4223 vfs_path_free (vpath, TRUE);
4224 }
4225 if (j == 0)
4226 dir_list_init (list);
4227 else
4228 list->len = j;
4229
4230 recalculate_panel_summary (panel);
4231
4232 if (panel != current_panel)
4233 (void) mc_chdir (current_panel->cwd_vpath);
4234 }
4235
4236
4237
4238 static void
4239 update_one_panel_widget (WPanel *panel, panel_update_flags_t flags, const char *current_file)
4240 {
4241 gboolean free_pointer;
4242 char *my_current_file = NULL;
4243
4244 if ((flags & UP_RELOAD) != 0)
4245 {
4246 panel->is_panelized = FALSE;
4247 mc_setctl (panel->cwd_vpath, VFS_SETCTL_FLUSH, NULL);
4248 memset (&(panel->dir_stat), 0, sizeof (panel->dir_stat));
4249 }
4250
4251
4252 free_pointer = current_file == UP_KEEPSEL;
4253
4254 if (free_pointer)
4255 {
4256 const file_entry_t *fe;
4257
4258 fe = panel_current_entry (panel);
4259 if (fe != NULL)
4260 my_current_file = g_strndup (fe->fname->str, fe->fname->len);
4261 current_file = my_current_file;
4262 }
4263
4264 if (panel->is_panelized)
4265 reload_panelized (panel);
4266 else
4267 panel_reload (panel);
4268
4269 panel_set_current_by_name (panel, current_file);
4270 panel->dirty = TRUE;
4271
4272 if (free_pointer)
4273 g_free (my_current_file);
4274 }
4275
4276
4277
4278 static void
4279 update_one_panel (int which, panel_update_flags_t flags, const char *current_file)
4280 {
4281 if (get_panel_type (which) == view_listing)
4282 {
4283 WPanel *panel;
4284
4285 panel = PANEL (get_panel_widget (which));
4286 if (panel->is_panelized)
4287 flags &= ~UP_RELOAD;
4288 update_one_panel_widget (panel, flags, current_file);
4289 }
4290 }
4291
4292
4293
4294
4295 static gboolean
4296 event_update_panels (const gchar *event_group_name, const gchar *event_name,
4297 gpointer init_data, gpointer data)
4298 {
4299 (void) event_group_name;
4300 (void) event_name;
4301 (void) init_data;
4302 (void) data;
4303
4304 update_panels (UP_RELOAD, UP_KEEPSEL);
4305
4306 return TRUE;
4307 }
4308
4309
4310
4311
4312 static gboolean
4313 panel_save_current_file_to_clip_file (const gchar *event_group_name, const gchar *event_name,
4314 gpointer init_data, gpointer data)
4315 {
4316 (void) event_group_name;
4317 (void) event_name;
4318 (void) init_data;
4319 (void) data;
4320
4321 if (current_panel->marked == 0)
4322 {
4323 const file_entry_t *fe;
4324
4325 fe = panel_current_entry (current_panel);
4326 if (fe != NULL)
4327 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_text_to_file", (gpointer) fe->fname->str);
4328 }
4329 else
4330 {
4331 int i;
4332 gboolean first = TRUE;
4333 char *flist = NULL;
4334
4335 for (i = 0; i < current_panel->dir.len; i++)
4336 {
4337 const file_entry_t *fe = ¤t_panel->dir.list[i];
4338
4339 if (fe->f.marked != 0)
4340 {
4341 if (first)
4342 {
4343 flist = g_strndup (fe->fname->str, fe->fname->len);
4344 first = FALSE;
4345 }
4346 else
4347 {
4348
4349 char *tmp;
4350
4351 tmp = g_strconcat (flist, "\n", fe->fname->str, (char *) NULL);
4352 g_free (flist);
4353 flist = tmp;
4354 }
4355 }
4356 }
4357
4358 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_text_to_file", (gpointer) flist);
4359 g_free (flist);
4360 }
4361 return TRUE;
4362 }
4363
4364
4365
4366 static vfs_path_t *
4367 panel_recursive_cd_to_parent (const vfs_path_t *vpath)
4368 {
4369 vfs_path_t *cwd_vpath;
4370
4371 cwd_vpath = vfs_path_clone (vpath);
4372
4373 while (mc_chdir (cwd_vpath) < 0)
4374 {
4375 const char *panel_cwd_path;
4376 vfs_path_t *tmp_vpath;
4377
4378
4379 panel_cwd_path = vfs_path_as_str (cwd_vpath);
4380 if (panel_cwd_path != NULL && IS_PATH_SEP (panel_cwd_path[0]) && panel_cwd_path[1] == '\0')
4381 {
4382 vfs_path_free (cwd_vpath, TRUE);
4383 return NULL;
4384 }
4385
4386 tmp_vpath = vfs_path_vtokens_get (cwd_vpath, 0, -1);
4387 vfs_path_free (cwd_vpath, TRUE);
4388 cwd_vpath =
4389 vfs_path_build_filename (PATH_SEP_STR, vfs_path_as_str (tmp_vpath), (char *) NULL);
4390 vfs_path_free (tmp_vpath, TRUE);
4391 }
4392
4393 return cwd_vpath;
4394 }
4395
4396
4397
4398 static void
4399 panel_dir_list_callback (dir_list_cb_state_t state, void *data)
4400 {
4401 static int count = 0;
4402
4403 (void) data;
4404
4405 switch (state)
4406 {
4407 case DIR_OPEN:
4408 count = 0;
4409 break;
4410
4411 case DIR_READ:
4412 count++;
4413 if ((count & 15) == 0)
4414 rotate_dash (TRUE);
4415 break;
4416
4417 case DIR_CLOSE:
4418 rotate_dash (FALSE);
4419 break;
4420
4421 default:
4422 g_assert_not_reached ();
4423 }
4424 }
4425
4426
4427
4428
4429
4430 file_entry_t *
4431 panel_current_entry (const WPanel *panel)
4432 {
4433 file_entry_t *fe;
4434
4435 if (panel->dir.len == 0 || panel->current < 0 || panel->current >= panel->dir.len)
4436 return NULL;
4437
4438 fe = &(panel->dir.list[panel->current]);
4439
4440 return fe->fname == NULL ? NULL : fe;
4441 }
4442
4443
4444
4445 void
4446 panel_set_current_by_name (WPanel *panel, const char *name)
4447 {
4448 int i;
4449 char *subdir;
4450
4451 if (panel->dir.len == 0)
4452 {
4453 panel_set_current (panel, -1);
4454 return;
4455 }
4456
4457 if (name == NULL)
4458 {
4459 panel_set_current (panel, 0);
4460 return;
4461 }
4462
4463
4464
4465
4466 if (panel->is_panelized)
4467 subdir = vfs_strip_suffix_from_filename (name);
4468 else
4469 subdir = vfs_strip_suffix_from_filename (x_basename (name));
4470
4471
4472
4473 for (i = 0; i < panel->dir.len; i++)
4474 if (strcmp (subdir, panel->dir.list[i].fname->str) == 0)
4475 {
4476 panel_set_current (panel, i);
4477 g_free (subdir);
4478 return;
4479 }
4480
4481
4482 if (panel->current >= panel->dir.len)
4483 panel_set_current (panel, panel->dir.len - 1);
4484 g_free (subdir);
4485
4486 select_item (panel);
4487 }
4488
4489
4490
4491 void
4492 panel_clean_dir (WPanel *panel)
4493 {
4494 panel->top = 0;
4495 panel->current = 0;
4496 panel->marked = 0;
4497 panel->dirs_marked = 0;
4498 panel->total = 0;
4499 panel->quick_search.active = FALSE;
4500 panel->is_panelized = FALSE;
4501 panel->dirty = TRUE;
4502 panel->content_shift = -1;
4503 panel->max_shift = -1;
4504
4505 dir_list_free_list (&panel->dir);
4506 }
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516 void
4517 panel_set_cwd (WPanel *panel, const vfs_path_t *vpath)
4518 {
4519 if (vpath != panel->cwd_vpath)
4520 {
4521 vfs_path_free (panel->cwd_vpath, TRUE);
4522 panel->cwd_vpath = vfs_path_clone (vpath);
4523 }
4524 }
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534 void
4535 panel_set_lwd (WPanel *panel, const vfs_path_t *vpath)
4536 {
4537 if (vpath != panel->lwd_vpath)
4538 {
4539 vfs_path_free (panel->lwd_vpath, TRUE);
4540 panel->lwd_vpath = vfs_path_clone (vpath);
4541 }
4542 }
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554 WPanel *
4555 panel_sized_empty_new (const char *panel_name, const WRect *r)
4556 {
4557 WPanel *panel;
4558 Widget *w;
4559 char *section;
4560 int i, err;
4561
4562 panel = g_new0 (WPanel, 1);
4563 w = WIDGET (panel);
4564 widget_init (w, r, panel_callback, panel_mouse_callback);
4565 w->options |= WOP_SELECTABLE | WOP_TOP_SELECT;
4566 w->keymap = panel_map;
4567
4568 panel->dir.size = DIR_LIST_MIN_SIZE;
4569 panel->dir.list = g_new (file_entry_t, panel->dir.size);
4570 panel->dir.len = 0;
4571 panel->dir.callback = panel_dir_list_callback;
4572
4573 panel->list_cols = 1;
4574 panel->brief_cols = 2;
4575 panel->dirty = TRUE;
4576 panel->content_shift = -1;
4577 panel->max_shift = -1;
4578
4579 panel->list_format = list_full;
4580 panel->user_format = g_strdup (DEFAULT_USER_FORMAT);
4581
4582 panel->filter.flags = FILE_FILTER_DEFAULT_FLAGS;
4583
4584 for (i = 0; i < LIST_FORMATS; i++)
4585 panel->user_status_format[i] = g_strdup (DEFAULT_USER_FORMAT);
4586
4587 #ifdef HAVE_CHARSET
4588 panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
4589 #endif
4590
4591 panel->frame_size = frame_half;
4592
4593 panel->quick_search.buffer = g_string_sized_new (MC_MAXFILENAMELEN);
4594 panel->quick_search.prev_buffer = g_string_sized_new (MC_MAXFILENAMELEN);
4595
4596 panel->name = g_strdup (panel_name);
4597 panel->dir_history.name = g_strconcat ("Dir Hist ", panel->name, (char *) NULL);
4598
4599
4600 section = g_strconcat ("Temporal:", panel->name, (char *) NULL);
4601 if (!mc_config_has_group (mc_global.main_config, section))
4602 {
4603 g_free (section);
4604 section = g_strdup (panel->name);
4605 }
4606 panel_load_setup (panel, section);
4607 g_free (section);
4608
4609 if (panel->filter.value != NULL)
4610 {
4611 gboolean case_sens = (panel->filter.flags & SELECT_MATCH_CASE) != 0;
4612 gboolean shell_patterns = (panel->filter.flags & SELECT_SHELL_PATTERNS) != 0;
4613
4614 panel->filter.handler = mc_search_new (panel->filter.value, NULL);
4615 panel->filter.handler->search_type = shell_patterns ? MC_SEARCH_T_GLOB : MC_SEARCH_T_REGEX;
4616 panel->filter.handler->is_entire_line = TRUE;
4617 panel->filter.handler->is_case_sensitive = case_sens;
4618
4619
4620 if (!mc_search_prepare (panel->filter.handler))
4621 file_filter_clear (&panel->filter);
4622 }
4623
4624
4625 err = set_panel_formats (panel);
4626 if (err != 0)
4627 set_panel_formats (panel);
4628
4629 return panel;
4630 }
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643 WPanel *
4644 panel_sized_with_dir_new (const char *panel_name, const WRect *r, const vfs_path_t *vpath)
4645 {
4646 WPanel *panel;
4647 char *curdir = NULL;
4648 #ifdef HAVE_CHARSET
4649 const vfs_path_element_t *path_element;
4650 #endif
4651
4652 panel = panel_sized_empty_new (panel_name, r);
4653
4654 if (vpath != NULL)
4655 {
4656 curdir = vfs_get_cwd ();
4657 panel_set_cwd (panel, vpath);
4658 }
4659 else
4660 {
4661 vfs_setup_cwd ();
4662 panel->cwd_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
4663 }
4664
4665 panel_set_lwd (panel, vfs_get_raw_current_dir ());
4666
4667 #ifdef HAVE_CHARSET
4668 path_element = vfs_path_get_by_index (panel->cwd_vpath, -1);
4669 if (path_element->encoding != NULL)
4670 panel->codepage = get_codepage_index (path_element->encoding);
4671 #endif
4672
4673 if (mc_chdir (panel->cwd_vpath) != 0)
4674 {
4675 #ifdef HAVE_CHARSET
4676 panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
4677 #endif
4678 vfs_setup_cwd ();
4679 vfs_path_free (panel->cwd_vpath, TRUE);
4680 panel->cwd_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
4681 }
4682
4683
4684 if (!dir_list_load (&panel->dir, panel->cwd_vpath, panel->sort_field->sort_routine,
4685 &panel->sort_info, &panel->filter))
4686 message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
4687
4688 if (panel->dir.len == 0)
4689 panel_set_current (panel, -1);
4690
4691
4692 if (curdir != NULL)
4693 {
4694 vfs_path_t *tmp_vpath;
4695 int err;
4696
4697 tmp_vpath = vfs_path_from_str (curdir);
4698 mc_chdir (tmp_vpath);
4699 vfs_path_free (tmp_vpath, TRUE);
4700 (void) err;
4701 }
4702 g_free (curdir);
4703
4704 return panel;
4705 }
4706
4707
4708
4709 void
4710 panel_reload (WPanel *panel)
4711 {
4712 struct stat current_stat;
4713 vfs_path_t *cwd_vpath;
4714
4715 if (panels_options.fast_reload && stat (vfs_path_as_str (panel->cwd_vpath), ¤t_stat) == 0
4716 && current_stat.st_ctime == panel->dir_stat.st_ctime
4717 && current_stat.st_mtime == panel->dir_stat.st_mtime)
4718 return;
4719
4720 cwd_vpath = panel_recursive_cd_to_parent (panel->cwd_vpath);
4721 vfs_path_free (panel->cwd_vpath, TRUE);
4722
4723 if (cwd_vpath == NULL)
4724 {
4725 panel->cwd_vpath = vfs_path_from_str (PATH_SEP_STR);
4726 panel_clean_dir (panel);
4727 dir_list_init (&panel->dir);
4728 return;
4729 }
4730
4731 panel->cwd_vpath = cwd_vpath;
4732 memset (&(panel->dir_stat), 0, sizeof (panel->dir_stat));
4733 show_dir (panel);
4734
4735 if (!dir_list_reload (&panel->dir, panel->cwd_vpath, panel->sort_field->sort_routine,
4736 &panel->sort_info, &panel->filter))
4737 message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
4738
4739 panel->dirty = TRUE;
4740
4741 if (panel->dir.len == 0)
4742 panel_set_current (panel, -1);
4743 else if (panel->current >= panel->dir.len)
4744 panel_set_current (panel, panel->dir.len - 1);
4745
4746 recalculate_panel_summary (panel);
4747 }
4748
4749
4750
4751
4752
4753
4754 int
4755 set_panel_formats (WPanel *p)
4756 {
4757 GSList *form;
4758 char *err = NULL;
4759 int retcode = 0;
4760
4761 form = use_display_format (p, panel_format (p), &err, FALSE);
4762
4763 if (err != NULL)
4764 {
4765 g_free (err);
4766 retcode = 1;
4767 }
4768 else
4769 {
4770 g_slist_free_full (p->format, (GDestroyNotify) format_item_free);
4771 p->format = form;
4772 }
4773
4774 if (panels_options.show_mini_info)
4775 {
4776 form = use_display_format (p, mini_status_format (p), &err, TRUE);
4777
4778 if (err != NULL)
4779 {
4780 g_free (err);
4781 retcode += 2;
4782 }
4783 else
4784 {
4785 g_slist_free_full (p->status_format, (GDestroyNotify) format_item_free);
4786 p->status_format = form;
4787 }
4788 }
4789
4790 panel_update_cols (WIDGET (p), p->frame_size);
4791
4792 if (retcode != 0)
4793 message (D_ERROR, _("Warning"),
4794 _("User supplied format looks invalid, reverting to default."));
4795 if ((retcode & 0x01) != 0)
4796 {
4797 g_free (p->user_format);
4798 p->user_format = g_strdup (DEFAULT_USER_FORMAT);
4799 }
4800 if ((retcode & 0x02) != 0)
4801 {
4802 g_free (p->user_status_format[p->list_format]);
4803 p->user_status_format[p->list_format] = g_strdup (DEFAULT_USER_FORMAT);
4804 }
4805
4806 return retcode;
4807 }
4808
4809
4810
4811 void
4812 panel_set_filter (WPanel *panel, const file_filter_t *filter)
4813 {
4814 MC_PTR_FREE (panel->filter.value);
4815 mc_search_free (panel->filter.handler);
4816 panel->filter.handler = NULL;
4817
4818
4819 if (filter != NULL)
4820 panel->filter = *filter;
4821
4822 reread_cmd ();
4823 }
4824
4825
4826
4827
4828 void
4829 select_item (WPanel *panel)
4830 {
4831 adjust_top_file (panel);
4832
4833 panel->dirty = TRUE;
4834
4835 execute_hooks (select_file_hook);
4836 }
4837
4838
4839
4840 void
4841 unmark_files (WPanel *panel)
4842 {
4843 if (panel->marked != 0)
4844 {
4845 int i;
4846
4847 for (i = 0; i < panel->dir.len; i++)
4848 file_mark (panel, i, 0);
4849
4850 panel->dirs_marked = 0;
4851 panel->marked = 0;
4852 panel->total = 0;
4853 }
4854 }
4855
4856
4857
4858
4859
4860 void
4861 recalculate_panel_summary (WPanel *panel)
4862 {
4863 int i;
4864
4865 panel->marked = 0;
4866 panel->dirs_marked = 0;
4867 panel->total = 0;
4868
4869 for (i = 0; i < panel->dir.len; i++)
4870 if (panel->dir.list[i].f.marked != 0)
4871 {
4872
4873
4874
4875 panel->dir.list[i].f.marked = 0;
4876 do_file_mark (panel, i, 1);
4877 }
4878 }
4879
4880
4881
4882
4883 void
4884 do_file_mark (WPanel *panel, int idx, int mark)
4885 {
4886 if (panel->dir.list[idx].f.marked == mark)
4887 return;
4888
4889
4890 if (DIR_IS_DOTDOT (panel->dir.list[idx].fname->str))
4891 return;
4892
4893 file_mark (panel, idx, mark);
4894 if (panel->dir.list[idx].f.marked != 0)
4895 {
4896 panel->marked++;
4897
4898 if (S_ISDIR (panel->dir.list[idx].st.st_mode))
4899 {
4900 if (panel->dir.list[idx].f.dir_size_computed != 0)
4901 panel->total += (uintmax_t) panel->dir.list[idx].st.st_size;
4902 panel->dirs_marked++;
4903 }
4904 else
4905 panel->total += (uintmax_t) panel->dir.list[idx].st.st_size;
4906
4907 set_colors (panel);
4908 }
4909 else
4910 {
4911 if (S_ISDIR (panel->dir.list[idx].st.st_mode))
4912 {
4913 if (panel->dir.list[idx].f.dir_size_computed != 0)
4914 panel->total -= (uintmax_t) panel->dir.list[idx].st.st_size;
4915 panel->dirs_marked--;
4916 }
4917 else
4918 panel->total -= (uintmax_t) panel->dir.list[idx].st.st_size;
4919
4920 panel->marked--;
4921 }
4922 }
4923
4924
4925
4926
4927
4928
4929 gboolean
4930 panel_do_cd (WPanel *panel, const vfs_path_t *new_dir_vpath, enum cd_enum cd_type)
4931 {
4932 gboolean r;
4933
4934 r = panel_do_cd_int (panel, new_dir_vpath, cd_type);
4935 if (r)
4936 directory_history_add (panel, panel->cwd_vpath);
4937 return r;
4938 }
4939
4940
4941
4942 void
4943 file_mark (WPanel *panel, int lc_index, int val)
4944 {
4945 if (panel->dir.list[lc_index].f.marked != val)
4946 {
4947 panel->dir.list[lc_index].f.marked = val;
4948 panel->dirty = TRUE;
4949 }
4950 }
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962 const GString *
4963 panel_find_marked_file (const WPanel *panel, int *current_file)
4964 {
4965 while (panel->dir.list[*current_file].f.marked == 0 && *current_file < panel->dir.len)
4966 (*current_file)++;
4967
4968 return (*current_file >= panel->dir.len ? NULL : panel->dir.list[*current_file].fname);
4969 }
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982 const GString *
4983 panel_get_marked_file (const WPanel *panel, int *current_file)
4984 {
4985 const file_entry_t *fe;
4986
4987 if (panel->marked != 0)
4988 return panel_find_marked_file (panel, current_file);
4989
4990 fe = panel_current_entry (panel);
4991
4992 return (fe == NULL ? NULL : fe->fname);
4993 }
4994
4995
4996
4997 void
4998 panel_re_sort (WPanel *panel)
4999 {
5000 char *filename;
5001 const file_entry_t *fe;
5002 int i;
5003
5004 if (panel == NULL)
5005 return;
5006
5007 fe = panel_current_entry (panel);
5008 if (fe == NULL)
5009 return;
5010
5011 filename = g_strndup (fe->fname->str, fe->fname->len);
5012 unselect_item (panel);
5013 dir_list_sort (&panel->dir, panel->sort_field->sort_routine, &panel->sort_info);
5014 panel->current = -1;
5015
5016 for (i = panel->dir.len; i != 0; i--)
5017 if (strcmp (panel->dir.list[i - 1].fname->str, filename) == 0)
5018 {
5019 panel->current = i - 1;
5020 break;
5021 }
5022
5023 g_free (filename);
5024 panel->top = panel->current - panel_items (panel) / 2;
5025 select_item (panel);
5026 panel->dirty = TRUE;
5027 }
5028
5029
5030
5031 void
5032 panel_set_sort_order (WPanel *panel, const panel_field_t *sort_order)
5033 {
5034 if (sort_order == NULL)
5035 return;
5036
5037 panel->sort_field = sort_order;
5038
5039
5040 if (sort_order->sort_routine == (GCompareFunc) unsorted)
5041 {
5042 const file_entry_t *fe;
5043 char *current_file = NULL;
5044
5045 fe = panel_current_entry (panel);
5046 if (fe != NULL)
5047 current_file = g_strndup (fe->fname->str, fe->fname->len);
5048 panel_reload (panel);
5049 panel_set_current_by_name (panel, current_file);
5050 g_free (current_file);
5051 }
5052 panel_re_sort (panel);
5053 }
5054
5055
5056
5057 #ifdef HAVE_CHARSET
5058
5059
5060
5061
5062
5063
5064 void
5065 panel_change_encoding (WPanel *panel)
5066 {
5067 const char *encoding = NULL;
5068 char *errmsg;
5069 int r;
5070
5071 r = select_charset (-1, -1, panel->codepage, FALSE);
5072
5073 if (r == SELECT_CHARSET_CANCEL)
5074 return;
5075
5076 panel->codepage = r;
5077
5078 if (panel->codepage == SELECT_CHARSET_NO_TRANSLATE)
5079 {
5080
5081 vfs_path_t *cd_path_vpath;
5082
5083 g_free (init_translation_table (mc_global.display_codepage, mc_global.display_codepage));
5084 cd_path_vpath = remove_encoding_from_path (panel->cwd_vpath);
5085 panel_do_cd (panel, cd_path_vpath, cd_parse_command);
5086 show_dir (panel);
5087 vfs_path_free (cd_path_vpath, TRUE);
5088 return;
5089 }
5090
5091 errmsg = init_translation_table (panel->codepage, mc_global.display_codepage);
5092 if (errmsg != NULL)
5093 {
5094 message (D_ERROR, MSG_ERROR, "%s", errmsg);
5095 g_free (errmsg);
5096 return;
5097 }
5098
5099 encoding = get_codepage_id (panel->codepage);
5100 if (encoding != NULL)
5101 {
5102 vfs_path_change_encoding (panel->cwd_vpath, encoding);
5103
5104 if (!panel_do_cd (panel, panel->cwd_vpath, cd_parse_command))
5105 cd_error_message (vfs_path_as_str (panel->cwd_vpath));
5106 }
5107 }
5108
5109
5110
5111
5112
5113
5114
5115 vfs_path_t *
5116 remove_encoding_from_path (const vfs_path_t *vpath)
5117 {
5118 vfs_path_t *ret_vpath;
5119 GString *tmp_conv;
5120 int indx;
5121
5122 ret_vpath = vfs_path_new (FALSE);
5123
5124 tmp_conv = g_string_new ("");
5125
5126 for (indx = 0; indx < vfs_path_elements_count (vpath); indx++)
5127 {
5128 GIConv converter;
5129 vfs_path_element_t *path_element;
5130
5131 path_element = vfs_path_element_clone (vfs_path_get_by_index (vpath, indx));
5132
5133 if (path_element->encoding == NULL)
5134 {
5135 vfs_path_add_element (ret_vpath, path_element);
5136 continue;
5137 }
5138
5139 converter = str_crt_conv_to (path_element->encoding);
5140 if (converter == INVALID_CONV)
5141 {
5142 vfs_path_add_element (ret_vpath, path_element);
5143 continue;
5144 }
5145
5146 MC_PTR_FREE (path_element->encoding);
5147
5148 str_vfs_convert_from (converter, path_element->path, tmp_conv);
5149
5150 g_free (path_element->path);
5151 path_element->path = g_strndup (tmp_conv->str, tmp_conv->len);
5152
5153 g_string_set_size (tmp_conv, 0);
5154
5155 str_close_conv (converter);
5156 str_close_conv (path_element->dir.converter);
5157 path_element->dir.converter = INVALID_CONV;
5158 vfs_path_add_element (ret_vpath, path_element);
5159 }
5160 g_string_free (tmp_conv, TRUE);
5161 return ret_vpath;
5162 }
5163 #endif
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180 void
5181 update_panels (panel_update_flags_t flags, const char *current_file)
5182 {
5183 WPanel *panel;
5184
5185
5186 if ((flags & UP_ONLY_CURRENT) == 0)
5187 update_one_panel (get_other_index (), flags, UP_KEEPSEL);
5188
5189 update_one_panel (get_current_index (), flags, current_file);
5190
5191 if (get_current_type () == view_listing)
5192 panel = PANEL (get_panel_widget (get_current_index ()));
5193 else
5194 panel = PANEL (get_panel_widget (get_other_index ()));
5195
5196 if (!panel->is_panelized)
5197 (void) mc_chdir (panel->cwd_vpath);
5198 }
5199
5200
5201
5202 gsize
5203 panel_get_num_of_sortable_fields (void)
5204 {
5205 gsize ret = 0, lc_index;
5206
5207 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5208 if (panel_fields[lc_index].is_user_choice)
5209 ret++;
5210 return ret;
5211 }
5212
5213
5214
5215 char **
5216 panel_get_sortable_fields (gsize *array_size)
5217 {
5218 char **ret;
5219 gsize lc_index, i;
5220
5221 lc_index = panel_get_num_of_sortable_fields ();
5222
5223 ret = g_try_new0 (char *, lc_index + 1);
5224 if (ret == NULL)
5225 return NULL;
5226
5227 if (array_size != NULL)
5228 *array_size = lc_index;
5229
5230 lc_index = 0;
5231
5232 for (i = 0; panel_fields[i].id != NULL; i++)
5233 if (panel_fields[i].is_user_choice)
5234 ret[lc_index++] = g_strdup (_(panel_fields[i].title_hotkey));
5235
5236 return ret;
5237 }
5238
5239
5240
5241 const panel_field_t *
5242 panel_get_field_by_id (const char *name)
5243 {
5244 gsize lc_index;
5245
5246 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5247 if (panel_fields[lc_index].id != NULL && strcmp (name, panel_fields[lc_index].id) == 0)
5248 return &panel_fields[lc_index];
5249
5250 return NULL;
5251 }
5252
5253
5254
5255 const panel_field_t *
5256 panel_get_field_by_title_hotkey (const char *name)
5257 {
5258 gsize lc_index;
5259
5260 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5261 if (panel_fields[lc_index].title_hotkey != NULL &&
5262 strcmp (name, _(panel_fields[lc_index].title_hotkey)) == 0)
5263 return &panel_fields[lc_index];
5264
5265 return NULL;
5266 }
5267
5268
5269
5270 const panel_field_t *
5271 panel_get_field_by_title (const char *name)
5272 {
5273 gsize lc_index;
5274
5275 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5276 {
5277 const char *title;
5278
5279 title = panel_get_title_without_hotkey (panel_fields[lc_index].title_hotkey);
5280 if (strcmp (title, name) == 0)
5281 return &panel_fields[lc_index];
5282 }
5283
5284 return NULL;
5285 }
5286
5287
5288
5289 gsize
5290 panel_get_num_of_user_possible_fields (void)
5291 {
5292 gsize ret = 0, lc_index;
5293
5294 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5295 if (panel_fields[lc_index].use_in_user_format)
5296 ret++;
5297
5298 return ret;
5299 }
5300
5301
5302
5303 char **
5304 panel_get_user_possible_fields (gsize *array_size)
5305 {
5306 char **ret;
5307 gsize lc_index, i;
5308
5309 lc_index = panel_get_num_of_user_possible_fields ();
5310
5311 ret = g_try_new0 (char *, lc_index + 1);
5312 if (ret == NULL)
5313 return NULL;
5314
5315 if (array_size != NULL)
5316 *array_size = lc_index;
5317
5318 lc_index = 0;
5319
5320 for (i = 0; panel_fields[i].id != NULL; i++)
5321 if (panel_fields[i].use_in_user_format)
5322 ret[lc_index++] = g_strdup (_(panel_fields[i].title_hotkey));
5323
5324 return ret;
5325 }
5326
5327
5328
5329 void
5330 panel_panelize_cd (void)
5331 {
5332 WPanel *panel;
5333 int i;
5334 dir_list *list;
5335 panelized_descr_t *pdescr;
5336 dir_list *plist;
5337 gboolean panelized_same;
5338
5339 if (!SELECTED_IS_PANEL)
5340 create_panel (MENU_PANEL_IDX, view_listing);
5341
5342 panel = PANEL (get_panel_widget (MENU_PANEL_IDX));
5343
5344 dir_list_clean (&panel->dir);
5345
5346 if (panel->panelized_descr == NULL)
5347 panel->panelized_descr = panelized_descr_new ();
5348
5349 pdescr = panel->panelized_descr;
5350 plist = &pdescr->list;
5351
5352 if (pdescr->root_vpath == NULL)
5353 panel_panelize_change_root (panel, panel->cwd_vpath);
5354
5355 if (plist->len < 1)
5356 dir_list_init (plist);
5357 else if (plist->len > panel->dir.size)
5358 dir_list_grow (&panel->dir, plist->len - panel->dir.size);
5359
5360 list = &panel->dir;
5361 list->len = plist->len;
5362
5363 panelized_same = vfs_path_equal (pdescr->root_vpath, panel->cwd_vpath);
5364
5365 for (i = 0; i < plist->len; i++)
5366 {
5367 if (panelized_same || DIR_IS_DOTDOT (plist->list[i].fname->str))
5368 list->list[i].fname = mc_g_string_dup (plist->list[i].fname);
5369 else
5370 {
5371 vfs_path_t *tmp_vpath;
5372
5373 tmp_vpath =
5374 vfs_path_append_new (pdescr->root_vpath, plist->list[i].fname->str, (char *) NULL);
5375 list->list[i].fname = g_string_new_take (vfs_path_free (tmp_vpath, FALSE));
5376 }
5377 list->list[i].f.link_to_dir = plist->list[i].f.link_to_dir;
5378 list->list[i].f.stale_link = plist->list[i].f.stale_link;
5379 list->list[i].f.dir_size_computed = plist->list[i].f.dir_size_computed;
5380 list->list[i].f.marked = plist->list[i].f.marked;
5381 list->list[i].st = plist->list[i].st;
5382 list->list[i].name_sort_key = plist->list[i].name_sort_key;
5383 list->list[i].extension_sort_key = plist->list[i].extension_sort_key;
5384 }
5385
5386 panel->is_panelized = TRUE;
5387 panel_panelize_absolutize_if_needed (panel);
5388
5389 panel_set_current_by_name (panel, NULL);
5390 }
5391
5392
5393
5394
5395
5396
5397
5398
5399 void
5400 panel_panelize_change_root (WPanel *panel, const vfs_path_t *new_root)
5401 {
5402 if (panel->panelized_descr == NULL)
5403 panel->panelized_descr = panelized_descr_new ();
5404 else
5405 vfs_path_free (panel->panelized_descr->root_vpath, TRUE);
5406
5407 panel->panelized_descr->root_vpath = vfs_path_clone (new_root);
5408 }
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429 void
5430 panel_panelize_absolutize_if_needed (WPanel *panel)
5431 {
5432 const dir_list *const list = &panel->dir;
5433
5434
5435
5436 if (list->len > 1 && g_path_is_absolute (list->list[1].fname->str))
5437 {
5438 vfs_path_t *root;
5439
5440 root = vfs_path_from_str (PATH_SEP_STR);
5441 panel_set_cwd (panel, root);
5442 if (panel == current_panel)
5443 mc_chdir (root);
5444 vfs_path_free (root, TRUE);
5445 }
5446 }
5447
5448
5449
5450 void
5451 panel_panelize_save (WPanel *panel)
5452 {
5453 int i;
5454 dir_list *list = &panel->dir;
5455 dir_list *plist;
5456
5457 panel_panelize_change_root (panel, panel->cwd_vpath);
5458
5459 plist = &panel->panelized_descr->list;
5460
5461 if (plist->len > 0)
5462 dir_list_clean (plist);
5463 if (panel->dir.len == 0)
5464 return;
5465
5466 if (panel->dir.len > plist->size)
5467 dir_list_grow (plist, panel->dir.len - plist->size);
5468 plist->len = panel->dir.len;
5469
5470 for (i = 0; i < panel->dir.len; i++)
5471 {
5472 plist->list[i].fname = mc_g_string_dup (list->list[i].fname);
5473 plist->list[i].f.link_to_dir = list->list[i].f.link_to_dir;
5474 plist->list[i].f.stale_link = list->list[i].f.stale_link;
5475 plist->list[i].f.dir_size_computed = list->list[i].f.dir_size_computed;
5476 plist->list[i].f.marked = list->list[i].f.marked;
5477 plist->list[i].st = list->list[i].st;
5478 plist->list[i].name_sort_key = list->list[i].name_sort_key;
5479 plist->list[i].extension_sort_key = list->list[i].extension_sort_key;
5480 }
5481 }
5482
5483
5484
5485 void
5486 panel_init (void)
5487 {
5488 panel_sort_up_char = mc_skin_get ("widget-panel", "sort-up-char", "'");
5489 panel_sort_down_char = mc_skin_get ("widget-panel", "sort-down-char", ".");
5490 panel_hiddenfiles_show_char = mc_skin_get ("widget-panel", "hiddenfiles-show-char", ".");
5491 panel_hiddenfiles_hide_char = mc_skin_get ("widget-panel", "hiddenfiles-hide-char", ".");
5492 panel_history_prev_item_char = mc_skin_get ("widget-panel", "history-prev-item-char", "<");
5493 panel_history_next_item_char = mc_skin_get ("widget-panel", "history-next-item-char", ">");
5494 panel_history_show_list_char = mc_skin_get ("widget-panel", "history-show-list-char", "^");
5495 panel_filename_scroll_left_char =
5496 mc_skin_get ("widget-panel", "filename-scroll-left-char", "{");
5497 panel_filename_scroll_right_char =
5498 mc_skin_get ("widget-panel", "filename-scroll-right-char", "}");
5499
5500 string_file_name_buffer = g_string_sized_new (MC_MAXFILENAMELEN);
5501
5502 mc_event_add (MCEVENT_GROUP_FILEMANAGER, "update_panels", event_update_panels, NULL, NULL);
5503 mc_event_add (MCEVENT_GROUP_FILEMANAGER, "panel_save_current_file_to_clip_file",
5504 panel_save_current_file_to_clip_file, NULL, NULL);
5505 }
5506
5507
5508
5509 void
5510 panel_deinit (void)
5511 {
5512 g_free (panel_sort_up_char);
5513 g_free (panel_sort_down_char);
5514 g_free (panel_hiddenfiles_show_char);
5515 g_free (panel_hiddenfiles_hide_char);
5516 g_free (panel_history_prev_item_char);
5517 g_free (panel_history_next_item_char);
5518 g_free (panel_history_show_list_char);
5519 g_free (panel_filename_scroll_left_char);
5520 g_free (panel_filename_scroll_right_char);
5521 g_string_free (string_file_name_buffer, TRUE);
5522 }
5523
5524
5525
5526 gboolean
5527 panel_cd (WPanel *panel, const vfs_path_t *new_dir_vpath, enum cd_enum exact)
5528 {
5529 gboolean res;
5530 const vfs_path_t *_new_dir_vpath = new_dir_vpath;
5531
5532 if (panel->is_panelized)
5533 {
5534 size_t new_vpath_len;
5535
5536 new_vpath_len = vfs_path_len (new_dir_vpath);
5537 if (vfs_path_equal_len (new_dir_vpath, panel->panelized_descr->root_vpath, new_vpath_len))
5538 _new_dir_vpath = panel->panelized_descr->root_vpath;
5539 }
5540
5541 res = panel_do_cd (panel, _new_dir_vpath, exact);
5542
5543 #ifdef HAVE_CHARSET
5544 if (res)
5545 {
5546 const vfs_path_element_t *path_element;
5547
5548 path_element = vfs_path_get_by_index (panel->cwd_vpath, -1);
5549 if (path_element->encoding != NULL)
5550 panel->codepage = get_codepage_index (path_element->encoding);
5551 else
5552 panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
5553 }
5554 #endif
5555
5556 return res;
5557 }
5558
5559