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
- subshell_chdir
- 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 static void
3447 subshell_chdir (const vfs_path_t *vpath)
3448 {
3449 #ifdef ENABLE_SUBSHELL
3450 if (mc_global.tty.use_subshell && vfs_current_is_local ())
3451 do_subshell_chdir (vpath, FALSE);
3452 #else
3453 (void) vpath;
3454 #endif
3455 }
3456
3457
3458
3459
3460
3461
3462
3463 static gboolean
3464 panel_do_cd_int (WPanel *panel, const vfs_path_t *new_dir_vpath, enum cd_enum cd_type)
3465 {
3466 vfs_path_t *olddir_vpath;
3467
3468
3469 if (cd_type == cd_parse_command)
3470 {
3471 const vfs_path_element_t *element;
3472
3473 element = vfs_path_get_by_index (new_dir_vpath, 0);
3474 if (strcmp (element->path, "-") == 0)
3475 new_dir_vpath = panel->lwd_vpath;
3476 }
3477
3478 if (mc_chdir (new_dir_vpath) == -1)
3479 return FALSE;
3480
3481
3482 olddir_vpath = vfs_path_clone (panel->cwd_vpath);
3483 panel_set_lwd (panel, panel->cwd_vpath);
3484 input_complete_free (cmdline);
3485
3486 vfs_path_free (panel->cwd_vpath, TRUE);
3487 vfs_setup_cwd ();
3488 panel->cwd_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
3489
3490 vfs_release_path (olddir_vpath);
3491
3492 subshell_chdir (panel->cwd_vpath);
3493
3494
3495 panel_clean_dir (panel);
3496
3497 if (!dir_list_load (&panel->dir, panel->cwd_vpath, panel->sort_field->sort_routine,
3498 &panel->sort_info, &panel->filter))
3499 message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
3500
3501 if (panel->dir.len == 0)
3502 panel_set_current (panel, -1);
3503
3504 panel_set_current_by_name (panel, get_parent_dir_name (panel->cwd_vpath, olddir_vpath));
3505
3506 load_hint (FALSE);
3507 panel->dirty = TRUE;
3508 update_xterm_title_path ();
3509 update_terminal_cwd ();
3510
3511 vfs_path_free (olddir_vpath, TRUE);
3512
3513 return TRUE;
3514 }
3515
3516
3517
3518 static void
3519 directory_history_next (WPanel *panel)
3520 {
3521 gboolean ok;
3522
3523 do
3524 {
3525 GList *next;
3526
3527 ok = TRUE;
3528 next = g_list_next (panel->dir_history.current);
3529 if (next != NULL)
3530 {
3531 vfs_path_t *data_vpath;
3532
3533 data_vpath = vfs_path_from_str ((char *) next->data);
3534 ok = panel_do_cd_int (panel, data_vpath, cd_exact);
3535 vfs_path_free (data_vpath, TRUE);
3536 panel->dir_history.current = next;
3537 }
3538
3539 }
3540 while (!ok);
3541 }
3542
3543
3544
3545 static void
3546 directory_history_prev (WPanel *panel)
3547 {
3548 gboolean ok;
3549
3550 do
3551 {
3552 GList *prev;
3553
3554 ok = TRUE;
3555 prev = g_list_previous (panel->dir_history.current);
3556 if (prev != NULL)
3557 {
3558 vfs_path_t *data_vpath;
3559
3560 data_vpath = vfs_path_from_str ((char *) prev->data);
3561 ok = panel_do_cd_int (panel, data_vpath, cd_exact);
3562 vfs_path_free (data_vpath, TRUE);
3563 panel->dir_history.current = prev;
3564 }
3565
3566 }
3567 while (!ok);
3568 }
3569
3570
3571
3572 static void
3573 directory_history_list (WPanel *panel)
3574 {
3575 history_descriptor_t hd;
3576 gboolean ok = FALSE;
3577 size_t pos;
3578
3579 pos = g_list_position (panel->dir_history.current, panel->dir_history.list);
3580
3581 history_descriptor_init (&hd, WIDGET (panel)->rect.y, WIDGET (panel)->rect.x,
3582 panel->dir_history.list, (int) pos);
3583 history_show (&hd);
3584
3585 panel->dir_history.list = hd.list;
3586 if (hd.text != NULL)
3587 {
3588 vfs_path_t *s_vpath;
3589
3590 s_vpath = vfs_path_from_str (hd.text);
3591 ok = panel_do_cd_int (panel, s_vpath, cd_exact);
3592 if (ok)
3593 directory_history_add (panel, panel->cwd_vpath);
3594 else
3595 cd_error_message (hd.text);
3596 vfs_path_free (s_vpath, TRUE);
3597 g_free (hd.text);
3598 }
3599
3600 if (!ok)
3601 {
3602
3603
3604
3605 size_t i;
3606
3607 panel->dir_history.current = panel->dir_history.list;
3608
3609 for (i = 0; i <= pos; i++)
3610 {
3611 GList *prev;
3612
3613 prev = g_list_previous (panel->dir_history.current);
3614 if (prev == NULL)
3615 break;
3616
3617 panel->dir_history.current = prev;
3618 }
3619 }
3620 }
3621
3622
3623
3624 static cb_ret_t
3625 panel_execute_cmd (WPanel *panel, long command)
3626 {
3627 int res = MSG_HANDLED;
3628
3629 if (command != CK_Search)
3630 stop_search (panel);
3631
3632 switch (command)
3633 {
3634 case CK_Up:
3635 case CK_Down:
3636 case CK_Left:
3637 case CK_Right:
3638 case CK_Bottom:
3639 case CK_Top:
3640 case CK_PageDown:
3641 case CK_PageUp:
3642
3643 state_mark = -1;
3644 break;
3645 default:
3646 break;
3647 }
3648
3649 switch (command)
3650 {
3651 case CK_CycleListingFormat:
3652 panel_cycle_listing_format (panel);
3653 break;
3654 case CK_PanelOtherCd:
3655 chdir_other_panel (panel);
3656 break;
3657 case CK_PanelOtherCdLink:
3658 chdir_to_readlink (panel);
3659 break;
3660 case CK_CopySingle:
3661 copy_cmd_local (panel);
3662 break;
3663 case CK_DeleteSingle:
3664 delete_cmd_local (panel);
3665 break;
3666 case CK_Enter:
3667 do_enter (panel);
3668 break;
3669 case CK_ViewRaw:
3670 view_raw_cmd (panel);
3671 break;
3672 case CK_EditNew:
3673 edit_cmd_new ();
3674 break;
3675 case CK_MoveSingle:
3676 rename_cmd_local (panel);
3677 break;
3678 case CK_SelectInvert:
3679 panel_select_invert_files (panel);
3680 break;
3681 case CK_Select:
3682 panel_select_files (panel);
3683 break;
3684 case CK_SelectExt:
3685 panel_select_ext_cmd (panel);
3686 break;
3687 case CK_Unselect:
3688 panel_unselect_files (panel);
3689 break;
3690 case CK_Filter:
3691 panel_do_set_filter (panel);
3692 break;
3693 case CK_PageDown:
3694 next_page (panel);
3695 break;
3696 case CK_PageUp:
3697 prev_page (panel);
3698 break;
3699 case CK_CdChild:
3700 goto_child_dir (panel);
3701 break;
3702 case CK_CdParent:
3703 goto_parent_dir (panel);
3704 break;
3705 case CK_History:
3706 directory_history_list (panel);
3707 break;
3708 case CK_HistoryNext:
3709 directory_history_next (panel);
3710 break;
3711 case CK_HistoryPrev:
3712 directory_history_prev (panel);
3713 break;
3714 case CK_BottomOnScreen:
3715 goto_bottom_file (panel);
3716 break;
3717 case CK_MiddleOnScreen:
3718 goto_middle_file (panel);
3719 break;
3720 case CK_TopOnScreen:
3721 goto_top_file (panel);
3722 break;
3723 case CK_Mark:
3724 mark_file (panel);
3725 break;
3726 case CK_MarkUp:
3727 mark_file_up (panel);
3728 break;
3729 case CK_MarkDown:
3730 mark_file_down (panel);
3731 break;
3732 case CK_MarkLeft:
3733 mark_file_left (panel);
3734 break;
3735 case CK_MarkRight:
3736 mark_file_right (panel);
3737 break;
3738 case CK_CdParentSmart:
3739 res = force_maybe_cd (panel);
3740 break;
3741 case CK_Up:
3742 move_up (panel);
3743 break;
3744 case CK_Down:
3745 move_down (panel);
3746 break;
3747 case CK_Left:
3748 res = move_left (panel);
3749 break;
3750 case CK_Right:
3751 res = move_right (panel);
3752 break;
3753 case CK_Bottom:
3754 move_end (panel);
3755 break;
3756 case CK_Top:
3757 move_home (panel);
3758 break;
3759 #ifdef HAVE_CHARSET
3760 case CK_SelectCodepage:
3761 panel_change_encoding (panel);
3762 break;
3763 #endif
3764 case CK_ScrollLeft:
3765 panel_content_scroll_left (panel);
3766 break;
3767 case CK_ScrollRight:
3768 panel_content_scroll_right (panel);
3769 break;
3770 case CK_Search:
3771 start_search (panel);
3772 break;
3773 case CK_SearchStop:
3774 break;
3775 case CK_PanelOtherSync:
3776 panel_sync_other (panel);
3777 break;
3778 case CK_Sort:
3779 panel_select_sort_order (panel);
3780 break;
3781 case CK_SortPrev:
3782 panel_toggle_sort_order_prev (panel);
3783 break;
3784 case CK_SortNext:
3785 panel_toggle_sort_order_next (panel);
3786 break;
3787 case CK_SortReverse:
3788 panel->sort_info.reverse = !panel->sort_info.reverse;
3789 panel_set_sort_order (panel, panel->sort_field);
3790 break;
3791 case CK_SortByName:
3792 panel_set_sort_type_by_id (panel, "name");
3793 break;
3794 case CK_SortByExt:
3795 panel_set_sort_type_by_id (panel, "extension");
3796 break;
3797 case CK_SortBySize:
3798 panel_set_sort_type_by_id (panel, "size");
3799 break;
3800 case CK_SortByMTime:
3801 panel_set_sort_type_by_id (panel, "mtime");
3802 break;
3803 default:
3804 res = MSG_NOT_HANDLED;
3805 break;
3806 }
3807
3808 return res;
3809 }
3810
3811
3812
3813 static cb_ret_t
3814 panel_key (WPanel *panel, int key)
3815 {
3816 long command;
3817
3818 if (is_abort_char (key))
3819 {
3820 stop_search (panel);
3821 return MSG_HANDLED;
3822 }
3823
3824 if (panel->quick_search.active && ((key >= ' ' && key <= 255) || key == KEY_BACKSPACE))
3825 {
3826 do_search (panel, key);
3827 return MSG_HANDLED;
3828 }
3829
3830 command = widget_lookup_key (WIDGET (panel), key);
3831 if (command != CK_IgnoreKey)
3832 return panel_execute_cmd (panel, command);
3833
3834 if (panels_options.torben_fj_mode && key == ALT ('h'))
3835 {
3836 goto_middle_file (panel);
3837 return MSG_HANDLED;
3838 }
3839
3840 if (!command_prompt && ((key >= ' ' && key <= 255) || key == KEY_BACKSPACE))
3841 {
3842 start_search (panel);
3843 do_search (panel, key);
3844 return MSG_HANDLED;
3845 }
3846
3847 return MSG_NOT_HANDLED;
3848 }
3849
3850
3851
3852 static cb_ret_t
3853 panel_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
3854 {
3855 WPanel *panel = PANEL (w);
3856 WDialog *h = DIALOG (w->owner);
3857 WButtonBar *bb;
3858
3859 switch (msg)
3860 {
3861 case MSG_INIT:
3862
3863 mc_event_add (h->event_group, MCEVENT_HISTORY_LOAD, panel_load_history, w, NULL);
3864
3865 mc_event_add (h->event_group, MCEVENT_HISTORY_SAVE, panel_save_history, w, NULL);
3866 return MSG_HANDLED;
3867
3868 case MSG_DRAW:
3869
3870 widget_erase (w);
3871 show_dir (panel);
3872 panel_print_header (panel);
3873 adjust_top_file (panel);
3874 paint_dir (panel);
3875 mini_info_separator (panel);
3876 display_mini_info (panel);
3877 panel->dirty = FALSE;
3878 return MSG_HANDLED;
3879
3880 case MSG_FOCUS:
3881 state_mark = -1;
3882 current_panel = panel;
3883 panel->active = TRUE;
3884
3885 if (mc_chdir (panel->cwd_vpath) != 0)
3886 {
3887 char *cwd;
3888
3889 cwd = vfs_path_to_str_flags (panel->cwd_vpath, 0, VPF_STRIP_PASSWORD);
3890 cd_error_message (cwd);
3891 g_free (cwd);
3892 }
3893 else
3894 subshell_chdir (panel->cwd_vpath);
3895
3896 update_xterm_title_path ();
3897 update_terminal_cwd ();
3898 select_item (panel);
3899
3900 bb = buttonbar_find (h);
3901 midnight_set_buttonbar (bb);
3902 return MSG_HANDLED;
3903
3904 case MSG_UNFOCUS:
3905
3906 stop_search (panel);
3907 panel->active = FALSE;
3908 unselect_item (panel);
3909 return MSG_HANDLED;
3910
3911 case MSG_KEY:
3912 return panel_key (panel, parm);
3913
3914 case MSG_ACTION:
3915 return panel_execute_cmd (panel, parm);
3916
3917 case MSG_DESTROY:
3918 vfs_stamp_path (panel->cwd_vpath);
3919
3920 mc_event_del (h->event_group, MCEVENT_HISTORY_LOAD, panel_load_history, w);
3921
3922 mc_event_del (h->event_group, MCEVENT_HISTORY_SAVE, panel_save_history, w);
3923 panel_destroy (panel);
3924 free_my_statfs ();
3925 return MSG_HANDLED;
3926
3927 default:
3928 return widget_default_callback (w, sender, msg, parm, data);
3929 }
3930 }
3931
3932
3933
3934
3935
3936
3937 static void
3938 mouse_toggle_mark (WPanel *panel)
3939 {
3940 const file_entry_t *fe;
3941
3942 fe = panel_current_entry (panel);
3943 if (fe != NULL)
3944 {
3945 do_mark_file (panel, MARK_DONT_MOVE);
3946 mouse_marking = fe->f.marked != 0;
3947 mouse_mark_panel = current_panel;
3948 }
3949 }
3950
3951
3952
3953 static void
3954 mouse_set_mark (WPanel *panel)
3955 {
3956 if (mouse_mark_panel == panel)
3957 {
3958 const file_entry_t *fe;
3959
3960 fe = panel_current_entry (panel);
3961 if (fe != NULL)
3962 {
3963 if (mouse_marking && fe->f.marked == 0)
3964 do_mark_file (panel, MARK_DONT_MOVE);
3965 else if (!mouse_marking && fe->f.marked != 0)
3966 do_mark_file (panel, MARK_DONT_MOVE);
3967 }
3968 }
3969 }
3970
3971
3972
3973 static void
3974 mark_if_marking (WPanel *panel, const mouse_event_t *event, int previous_current)
3975 {
3976 if ((event->buttons & GPM_B_RIGHT) == 0)
3977 return;
3978
3979 if (event->msg == MSG_MOUSE_DOWN)
3980 mouse_toggle_mark (panel);
3981 else
3982 {
3983 int pcurr, curr1, curr2;
3984
3985 pcurr = panel->current;
3986 curr1 = MIN (previous_current, panel->current);
3987 curr2 = MAX (previous_current, panel->current);
3988
3989 for (; curr1 <= curr2; curr1++)
3990 {
3991 panel->current = curr1;
3992 mouse_set_mark (panel);
3993 }
3994
3995 panel->current = pcurr;
3996 }
3997 }
3998
3999
4000
4001
4002
4003
4004
4005 static void
4006 mouse_sort_col (WPanel *panel, int x)
4007 {
4008 int i = 0;
4009 GSList *format;
4010 const char *lc_sort_name = NULL;
4011 panel_field_t *col_sort_format = NULL;
4012
4013 for (format = panel->format; format != NULL; format = g_slist_next (format))
4014 {
4015 format_item_t *fi = (format_item_t *) format->data;
4016
4017 i += fi->field_len;
4018 if (x < i + 1)
4019 {
4020
4021 lc_sort_name = fi->title;
4022 break;
4023 }
4024 }
4025
4026 if (lc_sort_name == NULL)
4027 return;
4028
4029 for (i = 0; panel_fields[i].id != NULL; i++)
4030 {
4031 const char *title;
4032
4033 title = panel_get_title_without_hotkey (panel_fields[i].title_hotkey);
4034 if (panel_fields[i].sort_routine != NULL && strcmp (title, lc_sort_name) == 0)
4035 {
4036 col_sort_format = &panel_fields[i];
4037 break;
4038 }
4039 }
4040
4041 if (col_sort_format != NULL)
4042 {
4043 if (panel->sort_field == col_sort_format)
4044
4045 panel->sort_info.reverse = !panel->sort_info.reverse;
4046 else
4047
4048 panel->sort_info.reverse = FALSE;
4049
4050 panel_set_sort_order (panel, col_sort_format);
4051 }
4052 }
4053
4054
4055
4056 static int
4057 panel_mouse_is_on_item (const WPanel *panel, int y, int x)
4058 {
4059 int lines, col_width, col;
4060
4061 if (y < 0)
4062 return MOUSE_UPPER_FILE_LIST;
4063
4064 lines = panel_lines (panel);
4065 if (y >= lines)
4066 return MOUSE_BELOW_FILE_LIST;
4067
4068 col_width = (CONST_WIDGET (panel)->rect.cols - 2) / panel->list_cols;
4069
4070 col = x / col_width;
4071
4072 y += panel->top + lines * col;
4073
4074
4075 if (y > panel->dir.len)
4076 return MOUSE_AFTER_LAST_FILE;
4077
4078
4079 return y;
4080 }
4081
4082
4083
4084 static void
4085 panel_mouse_callback (Widget *w, mouse_msg_t msg, mouse_event_t *event)
4086 {
4087 WPanel *panel = PANEL (w);
4088 gboolean is_active;
4089
4090 is_active = widget_is_active (w);
4091
4092 switch (msg)
4093 {
4094 case MSG_MOUSE_DOWN:
4095 if (event->y == 0)
4096 {
4097
4098 if (event->x == 1)
4099
4100 directory_history_prev (panel);
4101 else if (event->x == w->rect.cols - 2)
4102
4103 directory_history_next (panel);
4104 else if (event->x >= w->rect.cols - 5 && event->x <= w->rect.cols - 3)
4105
4106 directory_history_list (panel);
4107 else if (event->x == w->rect.cols - 6)
4108
4109 send_message (filemanager, NULL, MSG_ACTION, CK_ShowHidden, NULL);
4110 else
4111 {
4112
4113 event->result.abort = TRUE;
4114
4115 panel->dirty = FALSE;
4116 }
4117 break;
4118 }
4119
4120 if (event->y == 1)
4121 {
4122
4123 mouse_sort_col (panel, event->x + 1);
4124 break;
4125 }
4126
4127 if (!is_active)
4128 (void) change_panel ();
4129 MC_FALLTHROUGH;
4130
4131 case MSG_MOUSE_DRAG:
4132 {
4133 int my_index;
4134 int previous_current;
4135
4136 my_index = panel_mouse_is_on_item (panel, event->y - 2, event->x);
4137 previous_current = panel->current;
4138
4139 switch (my_index)
4140 {
4141 case MOUSE_UPPER_FILE_LIST:
4142 move_up (panel);
4143 mark_if_marking (panel, event, previous_current);
4144 break;
4145
4146 case MOUSE_BELOW_FILE_LIST:
4147 move_down (panel);
4148 mark_if_marking (panel, event, previous_current);
4149 break;
4150
4151 case MOUSE_AFTER_LAST_FILE:
4152 break;
4153
4154 default:
4155 if (my_index != panel->current)
4156 {
4157 unselect_item (panel);
4158 panel->current = my_index;
4159 select_item (panel);
4160 }
4161
4162 mark_if_marking (panel, event, previous_current);
4163 break;
4164 }
4165 }
4166 break;
4167
4168 case MSG_MOUSE_UP:
4169 break;
4170
4171 case MSG_MOUSE_CLICK:
4172 if ((event->count & GPM_DOUBLE) != 0 && (event->buttons & GPM_B_LEFT) != 0 &&
4173 panel_mouse_is_on_item (panel, event->y - 2, event->x) >= 0)
4174 do_enter (panel);
4175 break;
4176
4177 case MSG_MOUSE_MOVE:
4178 break;
4179
4180 case MSG_MOUSE_SCROLL_UP:
4181 if (is_active)
4182 {
4183 if (panels_options.mouse_move_pages && panel->top > 0)
4184 prev_page (panel);
4185 else
4186 move_up (panel);
4187 }
4188 break;
4189
4190 case MSG_MOUSE_SCROLL_DOWN:
4191 if (is_active)
4192 {
4193 if (panels_options.mouse_move_pages
4194 && panel->top + panel_items (panel) < panel->dir.len)
4195 next_page (panel);
4196 else
4197 move_down (panel);
4198 }
4199 break;
4200
4201 default:
4202 break;
4203 }
4204
4205 if (panel->dirty)
4206 widget_draw (w);
4207 }
4208
4209
4210
4211 static void
4212 reload_panelized (WPanel *panel)
4213 {
4214 int i, j;
4215 dir_list *list = &panel->dir;
4216
4217
4218 (void) mc_chdir (panel->cwd_vpath);
4219
4220 for (i = 0, j = 0; i < list->len; i++)
4221 {
4222 vfs_path_t *vpath;
4223
4224 vpath = vfs_path_from_str (list->list[i].fname->str);
4225 if (mc_lstat (vpath, &list->list[i].st) != 0)
4226 g_string_free (list->list[i].fname, TRUE);
4227 else
4228 {
4229 if (j != i)
4230 list->list[j] = list->list[i];
4231 j++;
4232 }
4233 vfs_path_free (vpath, TRUE);
4234 }
4235 if (j == 0)
4236 dir_list_init (list);
4237 else
4238 list->len = j;
4239
4240 recalculate_panel_summary (panel);
4241
4242 if (panel != current_panel)
4243 (void) mc_chdir (current_panel->cwd_vpath);
4244 }
4245
4246
4247
4248 static void
4249 update_one_panel_widget (WPanel *panel, panel_update_flags_t flags, const char *current_file)
4250 {
4251 gboolean free_pointer;
4252 char *my_current_file = NULL;
4253
4254 if ((flags & UP_RELOAD) != 0)
4255 {
4256 panel->is_panelized = FALSE;
4257 mc_setctl (panel->cwd_vpath, VFS_SETCTL_FLUSH, NULL);
4258 memset (&(panel->dir_stat), 0, sizeof (panel->dir_stat));
4259 }
4260
4261
4262 free_pointer = current_file == UP_KEEPSEL;
4263
4264 if (free_pointer)
4265 {
4266 const file_entry_t *fe;
4267
4268 fe = panel_current_entry (panel);
4269 if (fe != NULL)
4270 my_current_file = g_strndup (fe->fname->str, fe->fname->len);
4271 current_file = my_current_file;
4272 }
4273
4274 if (panel->is_panelized)
4275 reload_panelized (panel);
4276 else
4277 panel_reload (panel);
4278
4279 panel_set_current_by_name (panel, current_file);
4280 panel->dirty = TRUE;
4281
4282 if (free_pointer)
4283 g_free (my_current_file);
4284 }
4285
4286
4287
4288 static void
4289 update_one_panel (int which, panel_update_flags_t flags, const char *current_file)
4290 {
4291 if (get_panel_type (which) == view_listing)
4292 {
4293 WPanel *panel;
4294
4295 panel = PANEL (get_panel_widget (which));
4296 if (panel->is_panelized)
4297 flags &= ~UP_RELOAD;
4298 update_one_panel_widget (panel, flags, current_file);
4299 }
4300 }
4301
4302
4303
4304
4305 static gboolean
4306 event_update_panels (const gchar *event_group_name, const gchar *event_name,
4307 gpointer init_data, gpointer data)
4308 {
4309 (void) event_group_name;
4310 (void) event_name;
4311 (void) init_data;
4312 (void) data;
4313
4314 update_panels (UP_RELOAD, UP_KEEPSEL);
4315
4316 return TRUE;
4317 }
4318
4319
4320
4321
4322 static gboolean
4323 panel_save_current_file_to_clip_file (const gchar *event_group_name, const gchar *event_name,
4324 gpointer init_data, gpointer data)
4325 {
4326 (void) event_group_name;
4327 (void) event_name;
4328 (void) init_data;
4329 (void) data;
4330
4331 if (current_panel->marked == 0)
4332 {
4333 const file_entry_t *fe;
4334
4335 fe = panel_current_entry (current_panel);
4336 if (fe != NULL)
4337 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_text_to_file", (gpointer) fe->fname->str);
4338 }
4339 else
4340 {
4341 int i;
4342 gboolean first = TRUE;
4343 char *flist = NULL;
4344
4345 for (i = 0; i < current_panel->dir.len; i++)
4346 {
4347 const file_entry_t *fe = ¤t_panel->dir.list[i];
4348
4349 if (fe->f.marked != 0)
4350 {
4351 if (first)
4352 {
4353 flist = g_strndup (fe->fname->str, fe->fname->len);
4354 first = FALSE;
4355 }
4356 else
4357 {
4358
4359 char *tmp;
4360
4361 tmp = g_strconcat (flist, "\n", fe->fname->str, (char *) NULL);
4362 g_free (flist);
4363 flist = tmp;
4364 }
4365 }
4366 }
4367
4368 mc_event_raise (MCEVENT_GROUP_CORE, "clipboard_text_to_file", (gpointer) flist);
4369 g_free (flist);
4370 }
4371 return TRUE;
4372 }
4373
4374
4375
4376 static vfs_path_t *
4377 panel_recursive_cd_to_parent (const vfs_path_t *vpath)
4378 {
4379 vfs_path_t *cwd_vpath;
4380
4381 cwd_vpath = vfs_path_clone (vpath);
4382
4383 while (mc_chdir (cwd_vpath) < 0)
4384 {
4385 const char *panel_cwd_path;
4386 vfs_path_t *tmp_vpath;
4387
4388
4389 panel_cwd_path = vfs_path_as_str (cwd_vpath);
4390 if (panel_cwd_path != NULL && IS_PATH_SEP (panel_cwd_path[0]) && panel_cwd_path[1] == '\0')
4391 {
4392 vfs_path_free (cwd_vpath, TRUE);
4393 return NULL;
4394 }
4395
4396 tmp_vpath = vfs_path_vtokens_get (cwd_vpath, 0, -1);
4397 vfs_path_free (cwd_vpath, TRUE);
4398 cwd_vpath =
4399 vfs_path_build_filename (PATH_SEP_STR, vfs_path_as_str (tmp_vpath), (char *) NULL);
4400 vfs_path_free (tmp_vpath, TRUE);
4401 }
4402
4403 return cwd_vpath;
4404 }
4405
4406
4407
4408 static void
4409 panel_dir_list_callback (dir_list_cb_state_t state, void *data)
4410 {
4411 static int count = 0;
4412
4413 (void) data;
4414
4415 switch (state)
4416 {
4417 case DIR_OPEN:
4418 count = 0;
4419 break;
4420
4421 case DIR_READ:
4422 count++;
4423 if ((count & 15) == 0)
4424 rotate_dash (TRUE);
4425 break;
4426
4427 case DIR_CLOSE:
4428 rotate_dash (FALSE);
4429 break;
4430
4431 default:
4432 g_assert_not_reached ();
4433 }
4434 }
4435
4436
4437
4438
4439
4440 file_entry_t *
4441 panel_current_entry (const WPanel *panel)
4442 {
4443 file_entry_t *fe;
4444
4445 if (panel->dir.len == 0 || panel->current < 0 || panel->current >= panel->dir.len)
4446 return NULL;
4447
4448 fe = &(panel->dir.list[panel->current]);
4449
4450 return fe->fname == NULL ? NULL : fe;
4451 }
4452
4453
4454
4455 void
4456 panel_set_current_by_name (WPanel *panel, const char *name)
4457 {
4458 int i;
4459 char *subdir;
4460
4461 if (panel->dir.len == 0)
4462 {
4463 panel_set_current (panel, -1);
4464 return;
4465 }
4466
4467 if (name == NULL)
4468 {
4469 panel_set_current (panel, 0);
4470 return;
4471 }
4472
4473
4474
4475
4476 if (panel->is_panelized)
4477 subdir = vfs_strip_suffix_from_filename (name);
4478 else
4479 subdir = vfs_strip_suffix_from_filename (x_basename (name));
4480
4481
4482
4483 for (i = 0; i < panel->dir.len; i++)
4484 if (strcmp (subdir, panel->dir.list[i].fname->str) == 0)
4485 {
4486 panel_set_current (panel, i);
4487 g_free (subdir);
4488 return;
4489 }
4490
4491
4492 if (panel->current >= panel->dir.len)
4493 panel_set_current (panel, panel->dir.len - 1);
4494 g_free (subdir);
4495
4496 select_item (panel);
4497 }
4498
4499
4500
4501 void
4502 panel_clean_dir (WPanel *panel)
4503 {
4504 panel->top = 0;
4505 panel->current = 0;
4506 panel->marked = 0;
4507 panel->dirs_marked = 0;
4508 panel->total = 0;
4509 panel->quick_search.active = FALSE;
4510 panel->is_panelized = FALSE;
4511 panel->dirty = TRUE;
4512 panel->content_shift = -1;
4513 panel->max_shift = -1;
4514
4515 dir_list_free_list (&panel->dir);
4516 }
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526 void
4527 panel_set_cwd (WPanel *panel, const vfs_path_t *vpath)
4528 {
4529 if (vpath != panel->cwd_vpath)
4530 {
4531 vfs_path_free (panel->cwd_vpath, TRUE);
4532 panel->cwd_vpath = vfs_path_clone (vpath);
4533 }
4534 }
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544 void
4545 panel_set_lwd (WPanel *panel, const vfs_path_t *vpath)
4546 {
4547 if (vpath != panel->lwd_vpath)
4548 {
4549 vfs_path_free (panel->lwd_vpath, TRUE);
4550 panel->lwd_vpath = vfs_path_clone (vpath);
4551 }
4552 }
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564 WPanel *
4565 panel_sized_empty_new (const char *panel_name, const WRect *r)
4566 {
4567 WPanel *panel;
4568 Widget *w;
4569 char *section;
4570 int i, err;
4571
4572 panel = g_new0 (WPanel, 1);
4573 w = WIDGET (panel);
4574 widget_init (w, r, panel_callback, panel_mouse_callback);
4575 w->options |= WOP_SELECTABLE | WOP_TOP_SELECT;
4576 w->keymap = panel_map;
4577
4578 panel->dir.size = DIR_LIST_MIN_SIZE;
4579 panel->dir.list = g_new (file_entry_t, panel->dir.size);
4580 panel->dir.len = 0;
4581 panel->dir.callback = panel_dir_list_callback;
4582
4583 panel->list_cols = 1;
4584 panel->brief_cols = 2;
4585 panel->dirty = TRUE;
4586 panel->content_shift = -1;
4587 panel->max_shift = -1;
4588
4589 panel->list_format = list_full;
4590 panel->user_format = g_strdup (DEFAULT_USER_FORMAT);
4591
4592 panel->filter.flags = FILE_FILTER_DEFAULT_FLAGS;
4593
4594 for (i = 0; i < LIST_FORMATS; i++)
4595 panel->user_status_format[i] = g_strdup (DEFAULT_USER_FORMAT);
4596
4597 #ifdef HAVE_CHARSET
4598 panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
4599 #endif
4600
4601 panel->frame_size = frame_half;
4602
4603 panel->quick_search.buffer = g_string_sized_new (MC_MAXFILENAMELEN);
4604 panel->quick_search.prev_buffer = g_string_sized_new (MC_MAXFILENAMELEN);
4605
4606 panel->name = g_strdup (panel_name);
4607 panel->dir_history.name = g_strconcat ("Dir Hist ", panel->name, (char *) NULL);
4608
4609
4610 section = g_strconcat ("Temporal:", panel->name, (char *) NULL);
4611 if (!mc_config_has_group (mc_global.main_config, section))
4612 {
4613 g_free (section);
4614 section = g_strdup (panel->name);
4615 }
4616 panel_load_setup (panel, section);
4617 g_free (section);
4618
4619 if (panel->filter.value != NULL)
4620 {
4621 gboolean case_sens = (panel->filter.flags & SELECT_MATCH_CASE) != 0;
4622 gboolean shell_patterns = (panel->filter.flags & SELECT_SHELL_PATTERNS) != 0;
4623
4624 panel->filter.handler = mc_search_new (panel->filter.value, NULL);
4625 panel->filter.handler->search_type = shell_patterns ? MC_SEARCH_T_GLOB : MC_SEARCH_T_REGEX;
4626 panel->filter.handler->is_entire_line = TRUE;
4627 panel->filter.handler->is_case_sensitive = case_sens;
4628
4629
4630 if (!mc_search_prepare (panel->filter.handler))
4631 file_filter_clear (&panel->filter);
4632 }
4633
4634
4635 err = set_panel_formats (panel);
4636 if (err != 0)
4637 set_panel_formats (panel);
4638
4639 return panel;
4640 }
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653 WPanel *
4654 panel_sized_with_dir_new (const char *panel_name, const WRect *r, const vfs_path_t *vpath)
4655 {
4656 WPanel *panel;
4657 char *curdir = NULL;
4658 #ifdef HAVE_CHARSET
4659 const vfs_path_element_t *path_element;
4660 #endif
4661
4662 panel = panel_sized_empty_new (panel_name, r);
4663
4664 if (vpath != NULL)
4665 {
4666 curdir = vfs_get_cwd ();
4667 panel_set_cwd (panel, vpath);
4668 }
4669 else
4670 {
4671 vfs_setup_cwd ();
4672 panel->cwd_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
4673 }
4674
4675 panel_set_lwd (panel, vfs_get_raw_current_dir ());
4676
4677 #ifdef HAVE_CHARSET
4678 path_element = vfs_path_get_by_index (panel->cwd_vpath, -1);
4679 if (path_element->encoding != NULL)
4680 panel->codepage = get_codepage_index (path_element->encoding);
4681 #endif
4682
4683 if (mc_chdir (panel->cwd_vpath) != 0)
4684 {
4685 #ifdef HAVE_CHARSET
4686 panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
4687 #endif
4688 vfs_setup_cwd ();
4689 vfs_path_free (panel->cwd_vpath, TRUE);
4690 panel->cwd_vpath = vfs_path_clone (vfs_get_raw_current_dir ());
4691 }
4692
4693
4694 if (!dir_list_load (&panel->dir, panel->cwd_vpath, panel->sort_field->sort_routine,
4695 &panel->sort_info, &panel->filter))
4696 message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
4697
4698 if (panel->dir.len == 0)
4699 panel_set_current (panel, -1);
4700
4701
4702 if (curdir != NULL)
4703 {
4704 vfs_path_t *tmp_vpath;
4705 int err;
4706
4707 tmp_vpath = vfs_path_from_str (curdir);
4708 mc_chdir (tmp_vpath);
4709 vfs_path_free (tmp_vpath, TRUE);
4710 (void) err;
4711 }
4712 g_free (curdir);
4713
4714 return panel;
4715 }
4716
4717
4718
4719 void
4720 panel_reload (WPanel *panel)
4721 {
4722 struct stat current_stat;
4723 vfs_path_t *cwd_vpath;
4724
4725 if (panels_options.fast_reload && stat (vfs_path_as_str (panel->cwd_vpath), ¤t_stat) == 0
4726 && current_stat.st_ctime == panel->dir_stat.st_ctime
4727 && current_stat.st_mtime == panel->dir_stat.st_mtime)
4728 return;
4729
4730 cwd_vpath = panel_recursive_cd_to_parent (panel->cwd_vpath);
4731 vfs_path_free (panel->cwd_vpath, TRUE);
4732
4733 if (cwd_vpath == NULL)
4734 {
4735 panel->cwd_vpath = vfs_path_from_str (PATH_SEP_STR);
4736 panel_clean_dir (panel);
4737 dir_list_init (&panel->dir);
4738 return;
4739 }
4740
4741 panel->cwd_vpath = cwd_vpath;
4742 memset (&(panel->dir_stat), 0, sizeof (panel->dir_stat));
4743 show_dir (panel);
4744
4745 if (!dir_list_reload (&panel->dir, panel->cwd_vpath, panel->sort_field->sort_routine,
4746 &panel->sort_info, &panel->filter))
4747 message (D_ERROR, MSG_ERROR, _("Cannot read directory contents"));
4748
4749 panel->dirty = TRUE;
4750
4751 if (panel->dir.len == 0)
4752 panel_set_current (panel, -1);
4753 else if (panel->current >= panel->dir.len)
4754 panel_set_current (panel, panel->dir.len - 1);
4755
4756 recalculate_panel_summary (panel);
4757 }
4758
4759
4760
4761
4762
4763
4764 int
4765 set_panel_formats (WPanel *p)
4766 {
4767 GSList *form;
4768 char *err = NULL;
4769 int retcode = 0;
4770
4771 form = use_display_format (p, panel_format (p), &err, FALSE);
4772
4773 if (err != NULL)
4774 {
4775 g_free (err);
4776 retcode = 1;
4777 }
4778 else
4779 {
4780 g_slist_free_full (p->format, (GDestroyNotify) format_item_free);
4781 p->format = form;
4782 }
4783
4784 if (panels_options.show_mini_info)
4785 {
4786 form = use_display_format (p, mini_status_format (p), &err, TRUE);
4787
4788 if (err != NULL)
4789 {
4790 g_free (err);
4791 retcode += 2;
4792 }
4793 else
4794 {
4795 g_slist_free_full (p->status_format, (GDestroyNotify) format_item_free);
4796 p->status_format = form;
4797 }
4798 }
4799
4800 panel_update_cols (WIDGET (p), p->frame_size);
4801
4802 if (retcode != 0)
4803 message (D_ERROR, _("Warning"),
4804 _("User supplied format looks invalid, reverting to default."));
4805 if ((retcode & 0x01) != 0)
4806 {
4807 g_free (p->user_format);
4808 p->user_format = g_strdup (DEFAULT_USER_FORMAT);
4809 }
4810 if ((retcode & 0x02) != 0)
4811 {
4812 g_free (p->user_status_format[p->list_format]);
4813 p->user_status_format[p->list_format] = g_strdup (DEFAULT_USER_FORMAT);
4814 }
4815
4816 return retcode;
4817 }
4818
4819
4820
4821 void
4822 panel_set_filter (WPanel *panel, const file_filter_t *filter)
4823 {
4824 MC_PTR_FREE (panel->filter.value);
4825 mc_search_free (panel->filter.handler);
4826 panel->filter.handler = NULL;
4827
4828
4829 if (filter != NULL)
4830 panel->filter = *filter;
4831
4832 reread_cmd ();
4833 }
4834
4835
4836
4837
4838 void
4839 select_item (WPanel *panel)
4840 {
4841 adjust_top_file (panel);
4842
4843 panel->dirty = TRUE;
4844
4845 execute_hooks (select_file_hook);
4846 }
4847
4848
4849
4850 void
4851 unmark_files (WPanel *panel)
4852 {
4853 if (panel->marked != 0)
4854 {
4855 int i;
4856
4857 for (i = 0; i < panel->dir.len; i++)
4858 file_mark (panel, i, 0);
4859
4860 panel->dirs_marked = 0;
4861 panel->marked = 0;
4862 panel->total = 0;
4863 }
4864 }
4865
4866
4867
4868
4869
4870 void
4871 recalculate_panel_summary (WPanel *panel)
4872 {
4873 int i;
4874
4875 panel->marked = 0;
4876 panel->dirs_marked = 0;
4877 panel->total = 0;
4878
4879 for (i = 0; i < panel->dir.len; i++)
4880 if (panel->dir.list[i].f.marked != 0)
4881 {
4882
4883
4884
4885 panel->dir.list[i].f.marked = 0;
4886 do_file_mark (panel, i, 1);
4887 }
4888 }
4889
4890
4891
4892
4893 void
4894 do_file_mark (WPanel *panel, int idx, int mark)
4895 {
4896 if (panel->dir.list[idx].f.marked == mark)
4897 return;
4898
4899
4900 if (DIR_IS_DOTDOT (panel->dir.list[idx].fname->str))
4901 return;
4902
4903 file_mark (panel, idx, mark);
4904 if (panel->dir.list[idx].f.marked != 0)
4905 {
4906 panel->marked++;
4907
4908 if (S_ISDIR (panel->dir.list[idx].st.st_mode))
4909 {
4910 if (panel->dir.list[idx].f.dir_size_computed != 0)
4911 panel->total += (uintmax_t) panel->dir.list[idx].st.st_size;
4912 panel->dirs_marked++;
4913 }
4914 else
4915 panel->total += (uintmax_t) panel->dir.list[idx].st.st_size;
4916
4917 set_colors (panel);
4918 }
4919 else
4920 {
4921 if (S_ISDIR (panel->dir.list[idx].st.st_mode))
4922 {
4923 if (panel->dir.list[idx].f.dir_size_computed != 0)
4924 panel->total -= (uintmax_t) panel->dir.list[idx].st.st_size;
4925 panel->dirs_marked--;
4926 }
4927 else
4928 panel->total -= (uintmax_t) panel->dir.list[idx].st.st_size;
4929
4930 panel->marked--;
4931 }
4932 }
4933
4934
4935
4936
4937
4938
4939 gboolean
4940 panel_do_cd (WPanel *panel, const vfs_path_t *new_dir_vpath, enum cd_enum cd_type)
4941 {
4942 gboolean r;
4943
4944 r = panel_do_cd_int (panel, new_dir_vpath, cd_type);
4945 if (r)
4946 directory_history_add (panel, panel->cwd_vpath);
4947 return r;
4948 }
4949
4950
4951
4952 void
4953 file_mark (WPanel *panel, int lc_index, int val)
4954 {
4955 if (panel->dir.list[lc_index].f.marked != val)
4956 {
4957 panel->dir.list[lc_index].f.marked = val;
4958 panel->dirty = TRUE;
4959 }
4960 }
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972 const GString *
4973 panel_find_marked_file (const WPanel *panel, int *current_file)
4974 {
4975 while (panel->dir.list[*current_file].f.marked == 0 && *current_file < panel->dir.len)
4976 (*current_file)++;
4977
4978 return (*current_file >= panel->dir.len ? NULL : panel->dir.list[*current_file].fname);
4979 }
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992 const GString *
4993 panel_get_marked_file (const WPanel *panel, int *current_file)
4994 {
4995 const file_entry_t *fe;
4996
4997 if (panel->marked != 0)
4998 return panel_find_marked_file (panel, current_file);
4999
5000 fe = panel_current_entry (panel);
5001
5002 return (fe == NULL ? NULL : fe->fname);
5003 }
5004
5005
5006
5007 void
5008 panel_re_sort (WPanel *panel)
5009 {
5010 char *filename;
5011 const file_entry_t *fe;
5012 int i;
5013
5014 if (panel == NULL)
5015 return;
5016
5017 fe = panel_current_entry (panel);
5018 if (fe == NULL)
5019 return;
5020
5021 filename = g_strndup (fe->fname->str, fe->fname->len);
5022 unselect_item (panel);
5023 dir_list_sort (&panel->dir, panel->sort_field->sort_routine, &panel->sort_info);
5024 panel->current = -1;
5025
5026 for (i = panel->dir.len; i != 0; i--)
5027 if (strcmp (panel->dir.list[i - 1].fname->str, filename) == 0)
5028 {
5029 panel->current = i - 1;
5030 break;
5031 }
5032
5033 g_free (filename);
5034 panel->top = panel->current - panel_items (panel) / 2;
5035 select_item (panel);
5036 panel->dirty = TRUE;
5037 }
5038
5039
5040
5041 void
5042 panel_set_sort_order (WPanel *panel, const panel_field_t *sort_order)
5043 {
5044 if (sort_order == NULL)
5045 return;
5046
5047 panel->sort_field = sort_order;
5048
5049
5050 if (sort_order->sort_routine == (GCompareFunc) unsorted)
5051 {
5052 const file_entry_t *fe;
5053 char *current_file = NULL;
5054
5055 fe = panel_current_entry (panel);
5056 if (fe != NULL)
5057 current_file = g_strndup (fe->fname->str, fe->fname->len);
5058 panel_reload (panel);
5059 panel_set_current_by_name (panel, current_file);
5060 g_free (current_file);
5061 }
5062 panel_re_sort (panel);
5063 }
5064
5065
5066
5067 #ifdef HAVE_CHARSET
5068
5069
5070
5071
5072
5073
5074 void
5075 panel_change_encoding (WPanel *panel)
5076 {
5077 const char *encoding = NULL;
5078 char *errmsg;
5079 int r;
5080
5081 r = select_charset (-1, -1, panel->codepage, FALSE);
5082
5083 if (r == SELECT_CHARSET_CANCEL)
5084 return;
5085
5086 panel->codepage = r;
5087
5088 if (panel->codepage == SELECT_CHARSET_NO_TRANSLATE)
5089 {
5090
5091 vfs_path_t *cd_path_vpath;
5092
5093 g_free (init_translation_table (mc_global.display_codepage, mc_global.display_codepage));
5094 cd_path_vpath = remove_encoding_from_path (panel->cwd_vpath);
5095 panel_do_cd (panel, cd_path_vpath, cd_parse_command);
5096 show_dir (panel);
5097 vfs_path_free (cd_path_vpath, TRUE);
5098 return;
5099 }
5100
5101 errmsg = init_translation_table (panel->codepage, mc_global.display_codepage);
5102 if (errmsg != NULL)
5103 {
5104 message (D_ERROR, MSG_ERROR, "%s", errmsg);
5105 g_free (errmsg);
5106 return;
5107 }
5108
5109 encoding = get_codepage_id (panel->codepage);
5110 if (encoding != NULL)
5111 {
5112 vfs_path_change_encoding (panel->cwd_vpath, encoding);
5113
5114 if (!panel_do_cd (panel, panel->cwd_vpath, cd_parse_command))
5115 cd_error_message (vfs_path_as_str (panel->cwd_vpath));
5116 }
5117 }
5118
5119
5120
5121
5122
5123
5124
5125 vfs_path_t *
5126 remove_encoding_from_path (const vfs_path_t *vpath)
5127 {
5128 vfs_path_t *ret_vpath;
5129 GString *tmp_conv;
5130 int indx;
5131
5132 ret_vpath = vfs_path_new (FALSE);
5133
5134 tmp_conv = g_string_new ("");
5135
5136 for (indx = 0; indx < vfs_path_elements_count (vpath); indx++)
5137 {
5138 GIConv converter;
5139 vfs_path_element_t *path_element;
5140
5141 path_element = vfs_path_element_clone (vfs_path_get_by_index (vpath, indx));
5142
5143 if (path_element->encoding == NULL)
5144 {
5145 vfs_path_add_element (ret_vpath, path_element);
5146 continue;
5147 }
5148
5149 converter = str_crt_conv_to (path_element->encoding);
5150 if (converter == INVALID_CONV)
5151 {
5152 vfs_path_add_element (ret_vpath, path_element);
5153 continue;
5154 }
5155
5156 MC_PTR_FREE (path_element->encoding);
5157
5158 str_vfs_convert_from (converter, path_element->path, tmp_conv);
5159
5160 g_free (path_element->path);
5161 path_element->path = g_strndup (tmp_conv->str, tmp_conv->len);
5162
5163 g_string_set_size (tmp_conv, 0);
5164
5165 str_close_conv (converter);
5166 str_close_conv (path_element->dir.converter);
5167 path_element->dir.converter = INVALID_CONV;
5168 vfs_path_add_element (ret_vpath, path_element);
5169 }
5170 g_string_free (tmp_conv, TRUE);
5171 return ret_vpath;
5172 }
5173 #endif
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190 void
5191 update_panels (panel_update_flags_t flags, const char *current_file)
5192 {
5193 WPanel *panel;
5194
5195
5196 if ((flags & UP_ONLY_CURRENT) == 0)
5197 update_one_panel (get_other_index (), flags, UP_KEEPSEL);
5198
5199 update_one_panel (get_current_index (), flags, current_file);
5200
5201 if (get_current_type () == view_listing)
5202 panel = PANEL (get_panel_widget (get_current_index ()));
5203 else
5204 panel = PANEL (get_panel_widget (get_other_index ()));
5205
5206 if (!panel->is_panelized)
5207 (void) mc_chdir (panel->cwd_vpath);
5208 }
5209
5210
5211
5212 gsize
5213 panel_get_num_of_sortable_fields (void)
5214 {
5215 gsize ret = 0, lc_index;
5216
5217 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5218 if (panel_fields[lc_index].is_user_choice)
5219 ret++;
5220 return ret;
5221 }
5222
5223
5224
5225 char **
5226 panel_get_sortable_fields (gsize *array_size)
5227 {
5228 char **ret;
5229 gsize lc_index, i;
5230
5231 lc_index = panel_get_num_of_sortable_fields ();
5232
5233 ret = g_try_new0 (char *, lc_index + 1);
5234 if (ret == NULL)
5235 return NULL;
5236
5237 if (array_size != NULL)
5238 *array_size = lc_index;
5239
5240 lc_index = 0;
5241
5242 for (i = 0; panel_fields[i].id != NULL; i++)
5243 if (panel_fields[i].is_user_choice)
5244 ret[lc_index++] = g_strdup (_(panel_fields[i].title_hotkey));
5245
5246 return ret;
5247 }
5248
5249
5250
5251 const panel_field_t *
5252 panel_get_field_by_id (const char *name)
5253 {
5254 gsize lc_index;
5255
5256 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5257 if (panel_fields[lc_index].id != NULL && strcmp (name, panel_fields[lc_index].id) == 0)
5258 return &panel_fields[lc_index];
5259
5260 return NULL;
5261 }
5262
5263
5264
5265 const panel_field_t *
5266 panel_get_field_by_title_hotkey (const char *name)
5267 {
5268 gsize lc_index;
5269
5270 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5271 if (panel_fields[lc_index].title_hotkey != NULL &&
5272 strcmp (name, _(panel_fields[lc_index].title_hotkey)) == 0)
5273 return &panel_fields[lc_index];
5274
5275 return NULL;
5276 }
5277
5278
5279
5280 const panel_field_t *
5281 panel_get_field_by_title (const char *name)
5282 {
5283 gsize lc_index;
5284
5285 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5286 {
5287 const char *title;
5288
5289 title = panel_get_title_without_hotkey (panel_fields[lc_index].title_hotkey);
5290 if (strcmp (title, name) == 0)
5291 return &panel_fields[lc_index];
5292 }
5293
5294 return NULL;
5295 }
5296
5297
5298
5299 gsize
5300 panel_get_num_of_user_possible_fields (void)
5301 {
5302 gsize ret = 0, lc_index;
5303
5304 for (lc_index = 0; panel_fields[lc_index].id != NULL; lc_index++)
5305 if (panel_fields[lc_index].use_in_user_format)
5306 ret++;
5307
5308 return ret;
5309 }
5310
5311
5312
5313 char **
5314 panel_get_user_possible_fields (gsize *array_size)
5315 {
5316 char **ret;
5317 gsize lc_index, i;
5318
5319 lc_index = panel_get_num_of_user_possible_fields ();
5320
5321 ret = g_try_new0 (char *, lc_index + 1);
5322 if (ret == NULL)
5323 return NULL;
5324
5325 if (array_size != NULL)
5326 *array_size = lc_index;
5327
5328 lc_index = 0;
5329
5330 for (i = 0; panel_fields[i].id != NULL; i++)
5331 if (panel_fields[i].use_in_user_format)
5332 ret[lc_index++] = g_strdup (_(panel_fields[i].title_hotkey));
5333
5334 return ret;
5335 }
5336
5337
5338
5339 void
5340 panel_panelize_cd (void)
5341 {
5342 WPanel *panel;
5343 int i;
5344 dir_list *list;
5345 panelized_descr_t *pdescr;
5346 dir_list *plist;
5347 gboolean panelized_same;
5348
5349 if (!SELECTED_IS_PANEL)
5350 create_panel (MENU_PANEL_IDX, view_listing);
5351
5352 panel = PANEL (get_panel_widget (MENU_PANEL_IDX));
5353
5354 dir_list_clean (&panel->dir);
5355
5356 if (panel->panelized_descr == NULL)
5357 panel->panelized_descr = panelized_descr_new ();
5358
5359 pdescr = panel->panelized_descr;
5360 plist = &pdescr->list;
5361
5362 if (pdescr->root_vpath == NULL)
5363 panel_panelize_change_root (panel, panel->cwd_vpath);
5364
5365 if (plist->len < 1)
5366 dir_list_init (plist);
5367 else if (plist->len > panel->dir.size)
5368 dir_list_grow (&panel->dir, plist->len - panel->dir.size);
5369
5370 list = &panel->dir;
5371 list->len = plist->len;
5372
5373 panelized_same = vfs_path_equal (pdescr->root_vpath, panel->cwd_vpath);
5374
5375 for (i = 0; i < plist->len; i++)
5376 {
5377 if (panelized_same || DIR_IS_DOTDOT (plist->list[i].fname->str))
5378 list->list[i].fname = mc_g_string_dup (plist->list[i].fname);
5379 else
5380 {
5381 vfs_path_t *tmp_vpath;
5382
5383 tmp_vpath =
5384 vfs_path_append_new (pdescr->root_vpath, plist->list[i].fname->str, (char *) NULL);
5385 list->list[i].fname = g_string_new_take (vfs_path_free (tmp_vpath, FALSE));
5386 }
5387 list->list[i].f.link_to_dir = plist->list[i].f.link_to_dir;
5388 list->list[i].f.stale_link = plist->list[i].f.stale_link;
5389 list->list[i].f.dir_size_computed = plist->list[i].f.dir_size_computed;
5390 list->list[i].f.marked = plist->list[i].f.marked;
5391 list->list[i].st = plist->list[i].st;
5392 list->list[i].name_sort_key = plist->list[i].name_sort_key;
5393 list->list[i].extension_sort_key = plist->list[i].extension_sort_key;
5394 }
5395
5396 panel->is_panelized = TRUE;
5397 panel_panelize_absolutize_if_needed (panel);
5398
5399 panel_set_current_by_name (panel, NULL);
5400 }
5401
5402
5403
5404
5405
5406
5407
5408
5409 void
5410 panel_panelize_change_root (WPanel *panel, const vfs_path_t *new_root)
5411 {
5412 if (panel->panelized_descr == NULL)
5413 panel->panelized_descr = panelized_descr_new ();
5414 else
5415 vfs_path_free (panel->panelized_descr->root_vpath, TRUE);
5416
5417 panel->panelized_descr->root_vpath = vfs_path_clone (new_root);
5418 }
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439 void
5440 panel_panelize_absolutize_if_needed (WPanel *panel)
5441 {
5442 const dir_list *const list = &panel->dir;
5443
5444
5445
5446 if (list->len > 1 && g_path_is_absolute (list->list[1].fname->str))
5447 {
5448 vfs_path_t *root;
5449
5450 root = vfs_path_from_str (PATH_SEP_STR);
5451 panel_set_cwd (panel, root);
5452 if (panel == current_panel)
5453 mc_chdir (root);
5454 vfs_path_free (root, TRUE);
5455 }
5456 }
5457
5458
5459
5460 void
5461 panel_panelize_save (WPanel *panel)
5462 {
5463 int i;
5464 dir_list *list = &panel->dir;
5465 dir_list *plist;
5466
5467 panel_panelize_change_root (panel, panel->cwd_vpath);
5468
5469 plist = &panel->panelized_descr->list;
5470
5471 if (plist->len > 0)
5472 dir_list_clean (plist);
5473 if (panel->dir.len == 0)
5474 return;
5475
5476 if (panel->dir.len > plist->size)
5477 dir_list_grow (plist, panel->dir.len - plist->size);
5478 plist->len = panel->dir.len;
5479
5480 for (i = 0; i < panel->dir.len; i++)
5481 {
5482 plist->list[i].fname = mc_g_string_dup (list->list[i].fname);
5483 plist->list[i].f.link_to_dir = list->list[i].f.link_to_dir;
5484 plist->list[i].f.stale_link = list->list[i].f.stale_link;
5485 plist->list[i].f.dir_size_computed = list->list[i].f.dir_size_computed;
5486 plist->list[i].f.marked = list->list[i].f.marked;
5487 plist->list[i].st = list->list[i].st;
5488 plist->list[i].name_sort_key = list->list[i].name_sort_key;
5489 plist->list[i].extension_sort_key = list->list[i].extension_sort_key;
5490 }
5491 }
5492
5493
5494
5495 void
5496 panel_init (void)
5497 {
5498 panel_sort_up_char = mc_skin_get ("widget-panel", "sort-up-char", "'");
5499 panel_sort_down_char = mc_skin_get ("widget-panel", "sort-down-char", ".");
5500 panel_hiddenfiles_show_char = mc_skin_get ("widget-panel", "hiddenfiles-show-char", ".");
5501 panel_hiddenfiles_hide_char = mc_skin_get ("widget-panel", "hiddenfiles-hide-char", ".");
5502 panel_history_prev_item_char = mc_skin_get ("widget-panel", "history-prev-item-char", "<");
5503 panel_history_next_item_char = mc_skin_get ("widget-panel", "history-next-item-char", ">");
5504 panel_history_show_list_char = mc_skin_get ("widget-panel", "history-show-list-char", "^");
5505 panel_filename_scroll_left_char =
5506 mc_skin_get ("widget-panel", "filename-scroll-left-char", "{");
5507 panel_filename_scroll_right_char =
5508 mc_skin_get ("widget-panel", "filename-scroll-right-char", "}");
5509
5510 string_file_name_buffer = g_string_sized_new (MC_MAXFILENAMELEN);
5511
5512 mc_event_add (MCEVENT_GROUP_FILEMANAGER, "update_panels", event_update_panels, NULL, NULL);
5513 mc_event_add (MCEVENT_GROUP_FILEMANAGER, "panel_save_current_file_to_clip_file",
5514 panel_save_current_file_to_clip_file, NULL, NULL);
5515 }
5516
5517
5518
5519 void
5520 panel_deinit (void)
5521 {
5522 g_free (panel_sort_up_char);
5523 g_free (panel_sort_down_char);
5524 g_free (panel_hiddenfiles_show_char);
5525 g_free (panel_hiddenfiles_hide_char);
5526 g_free (panel_history_prev_item_char);
5527 g_free (panel_history_next_item_char);
5528 g_free (panel_history_show_list_char);
5529 g_free (panel_filename_scroll_left_char);
5530 g_free (panel_filename_scroll_right_char);
5531 g_string_free (string_file_name_buffer, TRUE);
5532 }
5533
5534
5535
5536 gboolean
5537 panel_cd (WPanel *panel, const vfs_path_t *new_dir_vpath, enum cd_enum exact)
5538 {
5539 gboolean res;
5540 const vfs_path_t *_new_dir_vpath = new_dir_vpath;
5541
5542 if (panel->is_panelized)
5543 {
5544 size_t new_vpath_len;
5545
5546 new_vpath_len = vfs_path_len (new_dir_vpath);
5547 if (vfs_path_equal_len (new_dir_vpath, panel->panelized_descr->root_vpath, new_vpath_len))
5548 _new_dir_vpath = panel->panelized_descr->root_vpath;
5549 }
5550
5551 res = panel_do_cd (panel, _new_dir_vpath, exact);
5552
5553 #ifdef HAVE_CHARSET
5554 if (res)
5555 {
5556 const vfs_path_element_t *path_element;
5557
5558 path_element = vfs_path_get_by_index (panel->cwd_vpath, -1);
5559 if (path_element->encoding != NULL)
5560 panel->codepage = get_codepage_index (path_element->encoding);
5561 else
5562 panel->codepage = SELECT_CHARSET_NO_TRANSLATE;
5563 }
5564 #endif
5565
5566 return res;
5567 }
5568
5569