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