This source file includes following definitions.
- max
- check_split
- update_split
- b_left_right_cback
- bplus_cback
- bminus_cback
- layout_bg_callback
- layout_callback
- layout_dlg_create
- panel_do_cols
- restore_into_right_dir_panel
- layout_save
- layout_restore
- layout_change
- layout_box
- panel_update_cols
- setup_panels
- panels_split_equal
- panels_split_more
- panels_split_less
- setup_cmdline
- use_dash
- set_hintbar
- rotate_dash
- get_nth_panel_name
- create_panel
- swap_panels
- get_panel_type
- get_panel_widget
- get_current_index
- get_other_index
- get_other_panel
- get_current_type
- get_other_type
- save_panel_dir
- get_panel_dir_for
- do_load_prompt
- load_prompt
- title_path_prepare
- update_xterm_title_path
- update_terminal_cwd
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
34 #include <config.h>
35
36 #include <pwd.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42
43 #include "lib/global.h"
44 #include "lib/terminal.h"
45 #include "lib/tty/tty.h"
46 #include "lib/skin.h"
47 #include "lib/tty/key.h"
48 #include "lib/tty/mouse.h"
49 #include "lib/mcconfig.h"
50 #include "lib/vfs/vfs.h"
51 #include "lib/strutil.h"
52 #include "lib/widget.h"
53 #include "lib/util.h"
54
55 #include "src/consaver/cons.saver.h"
56 #include "src/viewer/mcviewer.h"
57 #include "src/setup.h"
58 #ifdef ENABLE_SUBSHELL
59 #include "src/subshell/subshell.h"
60 #endif
61
62 #include "command.h"
63 #include "filemanager.h"
64 #include "tree.h"
65
66 #include "dir.h"
67 #include "layout.h"
68 #include "info.h"
69
70
71
72 panels_layout_t panels_layout = {
73
74 .horizontal_split = FALSE,
75
76
77 .vertical_equal = TRUE,
78 .left_panel_size = 0,
79
80
81 .horizontal_equal = TRUE,
82 .top_panel_size = 0
83 };
84
85
86 gboolean nice_rotating_dash = TRUE;
87
88
89 int output_lines = 0;
90
91
92 gboolean command_prompt = TRUE;
93
94
95 gboolean menubar_visible = TRUE;
96
97
98 gboolean xterm_title = TRUE;
99
100
101 gboolean free_space = TRUE;
102
103
104 int output_start_y = 0;
105
106 int ok_to_refresh = 1;
107
108
109
110
111
112
113 #define MAX_VIEWS 2
114
115
116 #define MINWIDTH 12
117 #define MINHEIGHT 5
118
119 #define B_2LEFT B_USER
120 #define B_2RIGHT (B_USER + 1)
121 #define B_PLUS (B_USER + 2)
122 #define B_MINUS (B_USER + 3)
123
124 #define LAYOUT_OPTIONS_COUNT G_N_ELEMENTS (check_options)
125
126
127
128 typedef struct
129 {
130 gboolean menubar_visible;
131 gboolean command_prompt;
132 gboolean keybar_visible;
133 gboolean message_visible;
134 gboolean xterm_title;
135 gboolean free_space;
136 int output_lines;
137 } layout_t;
138
139
140
141
142
143 static struct
144 {
145 panel_view_mode_t type;
146 Widget *widget;
147 char *last_saved_dir;
148 } panels[MAX_VIEWS] = {
149
150 { view_listing, NULL, NULL },
151 { view_listing, NULL, NULL },
152 };
153
154 static layout_t old_layout;
155 static panels_layout_t old_panels_layout;
156
157 static gboolean equal_split;
158 static int _output_lines;
159
160 static int height;
161
162 static WRadio *radio_widget;
163
164 static struct
165 {
166 const char *text;
167 gboolean *variable;
168 WCheck *widget;
169 } check_options[] = {
170 { N_ ("&Equal split"), &equal_split, NULL },
171 { N_ ("&Menubar visible"), &menubar_visible, NULL },
172 { N_ ("Command &prompt"), &command_prompt, NULL },
173 { N_ ("&Keybar visible"), &mc_global.keybar_visible, NULL },
174 { N_ ("H&intbar visible"), &mc_global.message_visible, NULL },
175 { N_ ("&XTerm window title"), &xterm_title, NULL },
176 { N_ ("&Show free space"), &free_space, NULL },
177 };
178
179 static const char *output_lines_label = NULL;
180 static int output_lines_label_len;
181
182 static WButton *bleft_widget, *bright_widget;
183
184
185
186
187
188
189 #undef max
190
191 static int
192 max (int a, int b)
193 {
194 return a > b ? a : b;
195 }
196
197
198
199 static void
200 check_split (panels_layout_t *layout)
201 {
202 if (layout->horizontal_split)
203 {
204 if (layout->horizontal_equal)
205 layout->top_panel_size = height / 2;
206 else if (layout->top_panel_size < MINHEIGHT)
207 layout->top_panel_size = MINHEIGHT;
208 else if (layout->top_panel_size > height - MINHEIGHT)
209 layout->top_panel_size = height - MINHEIGHT;
210 }
211 else
212 {
213 int md_cols = CONST_WIDGET (filemanager)->rect.cols;
214
215 if (layout->vertical_equal)
216 layout->left_panel_size = md_cols / 2;
217 else if (layout->left_panel_size < MINWIDTH)
218 layout->left_panel_size = MINWIDTH;
219 else if (layout->left_panel_size > md_cols - MINWIDTH)
220 layout->left_panel_size = md_cols - MINWIDTH;
221 }
222 }
223
224
225
226 static void
227 update_split (const WDialog *h)
228 {
229
230
231 check_split (&panels_layout);
232
233 if (panels_layout.horizontal_split)
234 check_options[0].widget->state = panels_layout.horizontal_equal;
235 else
236 check_options[0].widget->state = panels_layout.vertical_equal;
237 widget_draw (WIDGET (check_options[0].widget));
238
239 tty_setcolor (check_options[0].widget->state ? CORE_DISABLED_COLOR : DIALOG_NORMAL_COLOR);
240
241 widget_gotoyx (h, 6, 5);
242 if (panels_layout.horizontal_split)
243 tty_printf ("%03d", panels_layout.top_panel_size);
244 else
245 tty_printf ("%03d", panels_layout.left_panel_size);
246
247 widget_gotoyx (h, 6, 17);
248 if (panels_layout.horizontal_split)
249 tty_printf ("%03d", height - panels_layout.top_panel_size);
250 else
251 tty_printf ("%03d", CONST_WIDGET (filemanager)->rect.cols - panels_layout.left_panel_size);
252
253 widget_gotoyx (h, 6, 12);
254 tty_print_char ('=');
255 }
256
257
258
259 static int
260 b_left_right_cback (WButton *button, int action)
261 {
262 (void) action;
263
264 if (button == bright_widget)
265 {
266 if (panels_layout.horizontal_split)
267 panels_layout.top_panel_size++;
268 else
269 panels_layout.left_panel_size++;
270 }
271 else
272 {
273 if (panels_layout.horizontal_split)
274 panels_layout.top_panel_size--;
275 else
276 panels_layout.left_panel_size--;
277 }
278
279 update_split (DIALOG (WIDGET (button)->owner));
280 layout_change ();
281 do_refresh ();
282 return 0;
283 }
284
285
286
287 static int
288 bplus_cback (WButton *button, int action)
289 {
290 (void) button;
291 (void) action;
292
293 if (_output_lines < 99)
294 _output_lines++;
295 return 0;
296 }
297
298
299
300 static int
301 bminus_cback (WButton *button, int action)
302 {
303 (void) button;
304 (void) action;
305
306 if (_output_lines > 0)
307 _output_lines--;
308 return 0;
309 }
310
311
312
313 static cb_ret_t
314 layout_bg_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
315 {
316 switch (msg)
317 {
318 case MSG_DRAW:
319 frame_callback (w, NULL, MSG_DRAW, 0, NULL);
320
321 old_layout.output_lines = -1;
322
323 update_split (DIALOG (w->owner));
324
325 if (old_layout.output_lines != _output_lines)
326 {
327 old_layout.output_lines = _output_lines;
328 tty_setcolor (mc_global.tty.console_flag != '\0' ? DIALOG_NORMAL_COLOR
329 : CORE_DISABLED_COLOR);
330 widget_gotoyx (w, 9, 5);
331 tty_print_string (output_lines_label);
332 widget_gotoyx (w, 9, 5 + 3 + output_lines_label_len);
333 tty_printf ("%02d", _output_lines);
334 }
335 return MSG_HANDLED;
336
337 default:
338 return frame_callback (w, sender, msg, parm, data);
339 }
340 }
341
342
343
344 static cb_ret_t
345 layout_callback (Widget *w, Widget *sender, widget_msg_t msg, int parm, void *data)
346 {
347 WDialog *h = DIALOG (w);
348
349 switch (msg)
350 {
351 case MSG_POST_KEY:
352 {
353 const Widget *mw = CONST_WIDGET (filemanager);
354 gboolean _menubar_visible, _command_prompt, _keybar_visible, _message_visible;
355
356 _menubar_visible = check_options[1].widget->state;
357 _command_prompt = check_options[2].widget->state;
358 _keybar_visible = check_options[3].widget->state;
359 _message_visible = check_options[4].widget->state;
360
361 if (mc_global.tty.console_flag == '\0')
362 height = mw->rect.lines - (_keybar_visible ? 1 : 0) - (_command_prompt ? 1 : 0)
363 - (_menubar_visible ? 1 : 0) - _output_lines - (_message_visible ? 1 : 0);
364 else
365 {
366 int minimum;
367
368 if (_output_lines < 0)
369 _output_lines = 0;
370 height = mw->rect.lines - (_keybar_visible ? 1 : 0) - (_command_prompt ? 1 : 0)
371 - (_menubar_visible ? 1 : 0) - _output_lines - (_message_visible ? 1 : 0);
372 minimum = MINHEIGHT * (1 + (panels_layout.horizontal_split ? 1 : 0));
373 if (height < minimum)
374 {
375 _output_lines -= minimum - height;
376 height = minimum;
377 }
378 }
379
380 if (old_layout.output_lines != _output_lines)
381 {
382 old_layout.output_lines = _output_lines;
383 tty_setcolor (mc_global.tty.console_flag != '\0' ? DIALOG_NORMAL_COLOR
384 : CORE_DISABLED_COLOR);
385 widget_gotoyx (h, 9, 5 + 3 + output_lines_label_len);
386 tty_printf ("%02d", _output_lines);
387 }
388 }
389 return MSG_HANDLED;
390
391 case MSG_NOTIFY:
392 if (sender == WIDGET (radio_widget))
393 {
394 if ((panels_layout.horizontal_split ? 1 : 0) == radio_widget->sel)
395 update_split (h);
396 else
397 {
398 int eq;
399
400 panels_layout.horizontal_split = radio_widget->sel != 0;
401
402 if (panels_layout.horizontal_split)
403 {
404 eq = panels_layout.horizontal_equal;
405 if (eq)
406 panels_layout.top_panel_size = height / 2;
407 }
408 else
409 {
410 eq = panels_layout.vertical_equal;
411 if (eq)
412 panels_layout.left_panel_size = CONST_WIDGET (filemanager)->rect.cols / 2;
413 }
414
415 widget_disable (WIDGET (bleft_widget), eq);
416 widget_disable (WIDGET (bright_widget), eq);
417
418 update_split (h);
419 layout_change ();
420 do_refresh ();
421 }
422
423 return MSG_HANDLED;
424 }
425
426 if (sender == WIDGET (check_options[0].widget))
427 {
428 gboolean eq;
429
430 if (panels_layout.horizontal_split)
431 {
432 panels_layout.horizontal_equal = check_options[0].widget->state;
433 eq = panels_layout.horizontal_equal;
434 }
435 else
436 {
437 panels_layout.vertical_equal = check_options[0].widget->state;
438 eq = panels_layout.vertical_equal;
439 }
440
441 widget_disable (WIDGET (bleft_widget), eq);
442 widget_disable (WIDGET (bright_widget), eq);
443
444 update_split (h);
445 layout_change ();
446 do_refresh ();
447
448 return MSG_HANDLED;
449 }
450
451 {
452 gboolean ok = TRUE;
453
454 if (sender == WIDGET (check_options[1].widget))
455 menubar_visible = check_options[1].widget->state;
456 else if (sender == WIDGET (check_options[2].widget))
457 command_prompt = check_options[2].widget->state;
458 else if (sender == WIDGET (check_options[3].widget))
459 mc_global.keybar_visible = check_options[3].widget->state;
460 else if (sender == WIDGET (check_options[4].widget))
461 mc_global.message_visible = check_options[4].widget->state;
462 else if (sender == WIDGET (check_options[5].widget))
463 xterm_title = check_options[5].widget->state;
464 else if (sender == WIDGET (check_options[6].widget))
465 free_space = check_options[6].widget->state;
466 else
467 ok = FALSE;
468
469 if (ok)
470 {
471 update_split (h);
472 layout_change ();
473 do_refresh ();
474 return MSG_HANDLED;
475 }
476 }
477
478 return MSG_NOT_HANDLED;
479
480 default:
481 return dlg_default_callback (w, sender, msg, parm, data);
482 }
483 }
484
485
486
487 static WDialog *
488 layout_dlg_create (void)
489 {
490 WDialog *layout_dlg;
491 WGroup *g;
492 int l1 = 0, width;
493 int b1, b2, b;
494 size_t i;
495
496 const char *title1 = _ ("Panel split");
497 const char *title2 = _ ("Console output");
498 const char *title3 = _ ("Other options");
499
500 const char *s_split_direction[2] = {
501 _ ("&Vertical"),
502 _ ("&Horizontal"),
503 };
504
505 const char *ok_button = _ ("&OK");
506 const char *cancel_button = _ ("&Cancel");
507
508 output_lines_label = _ ("Output lines:");
509
510 #ifdef ENABLE_NLS
511 {
512 static gboolean i18n = FALSE;
513
514 if (!i18n)
515 {
516 for (i = 0; i < (size_t) LAYOUT_OPTIONS_COUNT; i++)
517 check_options[i].text = _ (check_options[i].text);
518 i18n = TRUE;
519 }
520 }
521 #endif
522
523
524 i = G_N_ELEMENTS (s_split_direction);
525 while (i-- != 0)
526 l1 = max (l1, str_term_width1 (s_split_direction[i]) + 7);
527
528 for (i = 0; i < (size_t) LAYOUT_OPTIONS_COUNT; i++)
529 l1 = max (l1, str_term_width1 (check_options[i].text) + 7);
530
531 l1 = max (l1, str_term_width1 (title1) + 4);
532 l1 = max (l1, str_term_width1 (title2) + 4);
533 l1 = max (l1, str_term_width1 (title3) + 4);
534
535 output_lines_label_len = str_term_width1 (output_lines_label);
536 l1 = max (l1, output_lines_label_len + 12);
537
538 b1 = str_term_width1 (ok_button) + 5;
539 b2 = str_term_width1 (cancel_button) + 3;
540 b = b1 + b2 + 1;
541
542 width = max (l1 * 2 + 7, b);
543
544 layout_dlg = dlg_create (TRUE, 0, 0, 15, width, WPOS_CENTER, FALSE, dialog_colors,
545 layout_callback, NULL, "[Layout]", _ ("Layout"));
546 g = GROUP (layout_dlg);
547
548
549 layout_dlg->bg->callback = layout_bg_callback;
550
551 #define XTRACT(i) (*check_options[i].variable != 0), check_options[i].text
552
553
554 group_add_widget (g, groupbox_new (2, 3, 6, l1, title1));
555
556 radio_widget = radio_new (3, 5, 2, s_split_direction);
557 radio_widget->sel = panels_layout.horizontal_split ? 1 : 0;
558 group_add_widget (g, radio_widget);
559
560 check_options[0].widget = check_new (5, 5, XTRACT (0));
561 group_add_widget (g, check_options[0].widget);
562
563 equal_split = panels_layout.horizontal_split ? panels_layout.horizontal_equal
564 : panels_layout.vertical_equal;
565
566 bleft_widget = button_new (6, 8, B_2LEFT, NARROW_BUTTON, "&<", b_left_right_cback);
567 widget_disable (WIDGET (bleft_widget), equal_split);
568 group_add_widget (g, bleft_widget);
569
570 bright_widget = button_new (6, 14, B_2RIGHT, NARROW_BUTTON, "&>", b_left_right_cback);
571 widget_disable (WIDGET (bright_widget), equal_split);
572 group_add_widget (g, bright_widget);
573
574
575 {
576 widget_state_t disabled;
577 Widget *w;
578
579 disabled = mc_global.tty.console_flag != '\0' ? 0 : WST_DISABLED;
580
581 w = WIDGET (groupbox_new (8, 3, 3, l1, title2));
582 w->state |= disabled;
583 group_add_widget (g, w);
584
585 w = WIDGET (
586 button_new (9, output_lines_label_len + 5, B_PLUS, NARROW_BUTTON, "&+", bplus_cback));
587 w->state |= disabled;
588 group_add_widget (g, w);
589
590 w = WIDGET (button_new (9, output_lines_label_len + 5 + 5, B_MINUS, NARROW_BUTTON, "&-",
591 bminus_cback));
592 w->state |= disabled;
593 group_add_widget (g, w);
594 }
595
596
597 group_add_widget (g, groupbox_new (2, 4 + l1, 9, l1, title3));
598
599 for (i = 1; i < (size_t) LAYOUT_OPTIONS_COUNT; i++)
600 {
601 check_options[i].widget = check_new (i + 2, 6 + l1, XTRACT (i));
602 group_add_widget (g, check_options[i].widget);
603 }
604
605 #undef XTRACT
606
607 group_add_widget (g, hline_new (11, -1, -1));
608
609 group_add_widget (g, button_new (12, (width - b) / 2, B_ENTER, DEFPUSH_BUTTON, ok_button, 0));
610 group_add_widget (
611 g, button_new (12, (width - b) / 2 + b1 + 1, B_CANCEL, NORMAL_BUTTON, cancel_button, 0));
612
613 widget_select (WIDGET (radio_widget));
614
615 return layout_dlg;
616 }
617
618
619
620 static void
621 panel_do_cols (int idx)
622 {
623 if (get_panel_type (idx) == view_listing)
624 set_panel_formats (PANEL (panels[idx].widget));
625 else
626 panel_update_cols (panels[idx].widget, frame_half);
627 }
628
629
630
631
632 static Widget *
633 restore_into_right_dir_panel (int idx, gboolean last_was_panel, const WRect *r)
634 {
635 WPanel *new_widget;
636 const char *p_name;
637
638 p_name = get_nth_panel_name (idx);
639
640 if (last_was_panel)
641 {
642 vfs_path_t *saved_dir_vpath;
643
644 saved_dir_vpath = vfs_path_from_str (panels[idx].last_saved_dir);
645 new_widget = panel_sized_with_dir_new (p_name, r, saved_dir_vpath);
646 vfs_path_free (saved_dir_vpath, TRUE);
647 }
648 else
649 new_widget = panel_sized_new (p_name, r);
650
651 return WIDGET (new_widget);
652 }
653
654
655
656 static void
657 layout_save (void)
658 {
659 old_layout.menubar_visible = menubar_visible;
660 old_layout.command_prompt = command_prompt;
661 old_layout.keybar_visible = mc_global.keybar_visible;
662 old_layout.message_visible = mc_global.message_visible;
663 old_layout.xterm_title = xterm_title;
664 old_layout.free_space = free_space;
665 old_layout.output_lines = -1;
666
667 _output_lines = output_lines;
668
669 old_panels_layout = panels_layout;
670 }
671
672
673
674 static void
675 layout_restore (void)
676 {
677 menubar_visible = old_layout.menubar_visible;
678 command_prompt = old_layout.command_prompt;
679 mc_global.keybar_visible = old_layout.keybar_visible;
680 mc_global.message_visible = old_layout.message_visible;
681 xterm_title = old_layout.xterm_title;
682 free_space = old_layout.free_space;
683 output_lines = old_layout.output_lines;
684
685 panels_layout = old_panels_layout;
686 }
687
688
689
690
691
692 void
693 layout_change (void)
694 {
695 setup_panels ();
696
697
698
699 update_menu ();
700 load_hint (TRUE);
701 }
702
703
704
705 void
706 layout_box (void)
707 {
708 WDialog *layout_dlg;
709
710 layout_save ();
711
712 layout_dlg = layout_dlg_create ();
713
714 if (dlg_run (layout_dlg) == B_ENTER)
715 {
716 size_t i;
717
718 for (i = 0; i < (size_t) LAYOUT_OPTIONS_COUNT; i++)
719 if (check_options[i].widget != NULL)
720 *check_options[i].variable = check_options[i].widget->state;
721
722 output_lines = _output_lines;
723 }
724 else
725 layout_restore ();
726
727 widget_destroy (WIDGET (layout_dlg));
728 layout_change ();
729 do_refresh ();
730 }
731
732
733
734 void
735 panel_update_cols (Widget *widget, panel_display_t frame_size)
736 {
737 const Widget *mw = CONST_WIDGET (filemanager);
738 int cols, x;
739
740
741
742
743 if (widget->owner == NULL)
744 return;
745
746 if (panels_layout.horizontal_split)
747 {
748 widget->rect.cols = mw->rect.cols;
749 return;
750 }
751
752 if (frame_size == frame_full)
753 {
754 cols = mw->rect.cols;
755 x = mw->rect.x;
756 }
757 else if (widget == get_panel_widget (0))
758 {
759 cols = panels_layout.left_panel_size;
760 x = mw->rect.x;
761 }
762 else
763 {
764 cols = mw->rect.cols - panels_layout.left_panel_size;
765 x = mw->rect.x + panels_layout.left_panel_size;
766 }
767
768 widget->rect.cols = cols;
769 widget->rect.x = x;
770 }
771
772
773
774 void
775 setup_panels (void)
776 {
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803 Widget *mw = WIDGET (filemanager);
804 const WRect *r = &CONST_WIDGET (mw)->rect;
805 int start_y;
806 gboolean active;
807 WRect rb;
808
809 active = widget_get_state (mw, WST_ACTIVE);
810
811
812 if (active)
813 widget_set_state (mw, WST_SUSPENDED, TRUE);
814
815
816 height = r->lines - (menubar_visible ? 1 : 0) - (mc_global.message_visible ? 1 : 0)
817 - (command_prompt ? 1 : 0) - (mc_global.keybar_visible ? 1 : 0);
818
819 if (mc_global.tty.console_flag != '\0')
820 {
821 int minimum;
822
823 if (output_lines < 0)
824 output_lines = 0;
825 else
826 height -= output_lines;
827 minimum = MINHEIGHT * (1 + (panels_layout.horizontal_split ? 1 : 0));
828 if (height < minimum)
829 {
830 output_lines -= minimum - height;
831 height = minimum;
832 }
833 }
834
835 rb = *r;
836 rb.lines = 1;
837 widget_set_size_rect (WIDGET (the_menubar), &rb);
838 widget_set_visibility (WIDGET (the_menubar), menubar_visible);
839
840 check_split (&panels_layout);
841 start_y = r->y + (menubar_visible ? 1 : 0);
842
843
844 panel_do_cols (0);
845 panel_do_cols (1);
846
847
848 if (panels_layout.horizontal_split)
849 {
850 widget_set_size (panels[0].widget, start_y, r->x, panels_layout.top_panel_size,
851 panels[0].widget->rect.cols);
852 widget_set_size (panels[1].widget, start_y + panels_layout.top_panel_size, r->x,
853 height - panels_layout.top_panel_size, panels[1].widget->rect.cols);
854 }
855 else
856 {
857 widget_set_size (panels[0].widget, start_y, r->x, height, panels[0].widget->rect.cols);
858 widget_set_size (panels[1].widget, start_y, panels[1].widget->rect.x, height,
859 panels[1].widget->rect.cols);
860 }
861
862 widget_set_size (WIDGET (the_hint), height + start_y, r->x, 1, r->cols);
863 widget_set_visibility (WIDGET (the_hint), mc_global.message_visible);
864
865
866 if (mc_global.tty.console_flag != '\0' && output_lines != 0)
867 {
868 unsigned char end_line;
869
870 end_line = r->lines - (mc_global.keybar_visible ? 1 : 0) - 1;
871 output_start_y = end_line - (command_prompt ? 1 : 0) - output_lines + 1;
872 show_console_contents (output_start_y, end_line - output_lines, end_line);
873 }
874
875 if (command_prompt)
876 {
877 #ifdef ENABLE_SUBSHELL
878 if (!mc_global.tty.use_subshell || !do_load_prompt ())
879 #endif
880 setup_cmdline ();
881 }
882 else
883 {
884
885 widget_hide (WIDGET (cmdline));
886 widget_hide (WIDGET (the_prompt));
887 }
888
889 rb = *r;
890 rb.y = r->lines - 1;
891 rb.lines = 1;
892 widget_set_size_rect (WIDGET (the_bar), &rb);
893 widget_set_visibility (WIDGET (the_bar), mc_global.keybar_visible);
894
895 update_xterm_title_path ();
896 update_terminal_cwd ();
897
898
899 if (active)
900 {
901 widget_set_state (mw, WST_ACTIVE, TRUE);
902 widget_draw (mw);
903 }
904 }
905
906
907
908 void
909 panels_split_equal (void)
910 {
911 if (panels_layout.horizontal_split)
912 panels_layout.horizontal_equal = TRUE;
913 else
914 panels_layout.vertical_equal = TRUE;
915
916 layout_change ();
917 do_refresh ();
918 }
919
920
921
922 void
923 panels_split_more (void)
924 {
925 if (panels_layout.horizontal_split)
926 {
927 panels_layout.horizontal_equal = FALSE;
928 panels_layout.top_panel_size++;
929 }
930 else
931 {
932 panels_layout.vertical_equal = FALSE;
933 panels_layout.left_panel_size++;
934 }
935
936 layout_change ();
937 }
938
939
940
941 void
942 panels_split_less (void)
943 {
944 if (panels_layout.horizontal_split)
945 {
946 panels_layout.horizontal_equal = FALSE;
947 panels_layout.top_panel_size--;
948 }
949 else
950 {
951 panels_layout.vertical_equal = FALSE;
952 panels_layout.left_panel_size--;
953 }
954
955 layout_change ();
956 }
957
958
959
960 void
961 setup_cmdline (void)
962 {
963 const Widget *mw = CONST_WIDGET (filemanager);
964 const WRect *r = &mw->rect;
965 int prompt_width;
966 int y;
967
968 if (!command_prompt)
969 return;
970
971 #ifdef ENABLE_SUBSHELL
972 if (mc_global.tty.use_subshell)
973 {
974
975 if (subshell_prompt != NULL)
976 {
977 g_free (mc_prompt);
978 mc_prompt = g_strndup (subshell_prompt->str, subshell_prompt->len);
979 }
980
981 (void) strip_ctrl_codes (mc_prompt);
982 }
983 #endif
984
985 prompt_width = str_term_width1 (mc_prompt);
986
987
988 if (r->cols > 8 && prompt_width > r->cols - 8)
989 {
990 int prompt_len;
991
992 prompt_width = r->cols - 8;
993 prompt_len = str_offset_to_pos (mc_prompt, prompt_width);
994 mc_prompt[prompt_len] = '\0';
995 }
996
997 y = r->lines - 1 - (mc_global.keybar_visible ? 1 : 0);
998
999 widget_set_size (WIDGET (the_prompt), y, r->x, 1, prompt_width);
1000 label_set_text (the_prompt, mc_prompt);
1001 widget_set_size (WIDGET (cmdline), y, r->x + prompt_width, 1, r->cols - prompt_width);
1002
1003 widget_show (WIDGET (the_prompt));
1004 widget_show (WIDGET (cmdline));
1005 }
1006
1007
1008
1009 void
1010 use_dash (gboolean flag)
1011 {
1012 if (flag)
1013 ok_to_refresh++;
1014 else
1015 ok_to_refresh--;
1016 }
1017
1018
1019
1020 void
1021 set_hintbar (const char *str)
1022 {
1023 label_set_text (the_hint, str);
1024 if (ok_to_refresh > 0)
1025 mc_refresh ();
1026 }
1027
1028
1029
1030 void
1031 rotate_dash (gboolean show)
1032 {
1033 static gint64 timestamp = 0;
1034
1035 static const gint64 delay = G_USEC_PER_SEC / 10;
1036
1037 const Widget *w = CONST_WIDGET (filemanager);
1038
1039 if (!nice_rotating_dash || (ok_to_refresh <= 0))
1040 return;
1041
1042 if (show && !mc_time_elapsed (×tamp, delay))
1043 return;
1044
1045 widget_gotoyx (w, menubar_visible ? 1 : 0, w->rect.cols - 1);
1046 tty_setcolor (CORE_NORMAL_COLOR);
1047
1048 if (!show)
1049 tty_print_char (mc_tty_frm[MC_TTY_FRM_DRIGHTTOP]);
1050 else
1051 {
1052 static const char rotating_dash[4] MC_NONSTRING = "|/-\\";
1053 static size_t pos = 0;
1054
1055 tty_print_char (rotating_dash[pos]);
1056 pos = (pos + 1) % sizeof (rotating_dash);
1057 }
1058
1059 mc_refresh ();
1060 }
1061
1062
1063
1064 const char *
1065 get_nth_panel_name (int num)
1066 {
1067 if (num == 0)
1068 return "New Left Panel";
1069
1070 if (num == 1)
1071 return "New Right Panel";
1072
1073 {
1074 static char buffer[BUF_SMALL];
1075
1076 g_snprintf (buffer, sizeof (buffer), "%ith Panel", num);
1077 return buffer;
1078 }
1079 }
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 void
1095 create_panel (int num, panel_view_mode_t type)
1096 {
1097 WRect r = { 0, 0, 0, 0 };
1098 unsigned int the_other = 0;
1099 Widget *new_widget = NULL, *old_widget = NULL;
1100 panel_view_mode_t old_type = view_listing;
1101
1102 if (num >= MAX_VIEWS)
1103 {
1104 fprintf (stderr, "Cannot allocate more that %d views\n", MAX_VIEWS);
1105 abort ();
1106 }
1107
1108 if (type != view_listing)
1109 {
1110 the_other = num == 0 ? 1 : 0;
1111
1112 if (panels[the_other].type != view_listing)
1113 return;
1114 }
1115
1116
1117 if (panels[num].widget != NULL)
1118 {
1119 Widget *w = panels[num].widget;
1120 WPanel *panel = PANEL (w);
1121
1122 r = w->rect;
1123 old_widget = w;
1124 old_type = panels[num].type;
1125
1126 if (old_type == view_listing && panel->frame_size == frame_full && type != view_listing)
1127 {
1128 int md_cols = CONST_WIDGET (filemanager)->rect.cols;
1129
1130 if (panels_layout.horizontal_split)
1131 {
1132 r.cols = md_cols;
1133 r.x = 0;
1134 }
1135 else
1136 {
1137 r.cols = md_cols - panels_layout.left_panel_size;
1138 if (num == 1)
1139 r.x = panels_layout.left_panel_size;
1140 }
1141 }
1142 }
1143
1144
1145
1146 if (old_widget == NULL && type != view_listing)
1147 panels[num].last_saved_dir = vfs_get_cwd ();
1148
1149 switch (type)
1150 {
1151 case view_nothing:
1152 case view_listing:
1153 {
1154 gboolean last_was_panel;
1155
1156 last_was_panel = old_widget != NULL && get_panel_type (num) != view_listing;
1157 new_widget = restore_into_right_dir_panel (num, last_was_panel, &r);
1158 break;
1159 }
1160
1161 case view_info:
1162 new_widget = WIDGET (info_new (&r));
1163 break;
1164
1165 case view_tree:
1166 new_widget = WIDGET (tree_new (&r, TRUE));
1167 break;
1168
1169 case view_quick:
1170 {
1171 WPanel *the_other_panel;
1172 const char *file_name = "";
1173
1174 new_widget = WIDGET (mcview_new (&r, TRUE));
1175 the_other_panel = PANEL (panels[the_other].widget);
1176 if (the_other_panel != NULL)
1177 {
1178 const file_entry_t *fe;
1179
1180 fe = panel_current_entry (the_other_panel);
1181 if (fe != NULL)
1182 file_name = fe->fname->str;
1183 }
1184
1185 mcview_load ((WView *) new_widget, 0, file_name, 0, 0, 0);
1186 break;
1187 }
1188
1189 default:
1190 break;
1191 }
1192
1193 if (type != view_listing)
1194
1195
1196 save_panel_dir (num);
1197
1198 panels[num].type = type;
1199 panels[num].widget = new_widget;
1200
1201
1202
1203 if (old_widget != NULL)
1204 {
1205
1206 if (old_type == view_listing)
1207 history_save (filemanager, old_widget);
1208
1209 widget_replace (old_widget, new_widget);
1210 }
1211
1212 if (type == view_listing)
1213 {
1214 WPanel *panel = PANEL (new_widget);
1215
1216
1217 if (old_widget != NULL)
1218 history_load (filemanager, new_widget);
1219
1220 if (num == 0)
1221 left_panel = panel;
1222 else
1223 right_panel = panel;
1224
1225
1226 set_panel_formats (panel);
1227 }
1228
1229 if (type == view_tree)
1230 the_tree = (WTree *) new_widget;
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240 if ((type != view_listing) && (current_panel == PANEL (old_widget)))
1241 current_panel = num == 0 ? right_panel : left_panel;
1242
1243 g_free (old_widget);
1244 }
1245
1246
1247
1248
1249
1250
1251 void
1252 swap_panels (void)
1253 {
1254 WPanel *panel1, *panel2;
1255 Widget *tmp_widget;
1256
1257 panel1 = PANEL (panels[0].widget);
1258 panel2 = PANEL (panels[1].widget);
1259
1260 if (panels[0].type == view_listing && panels[1].type == view_listing
1261 && !mc_config_get_bool (mc_global.main_config, CONFIG_PANELS_SECTION, "simple_swap", FALSE))
1262 {
1263 WPanel panel;
1264
1265 #define panelswap(x) \
1266 panel.x = panel1->x; \
1267 panel1->x = panel2->x; \
1268 panel2->x = panel.x;
1269
1270 panelswap (dir);
1271 panelswap (active);
1272 panelswap (cwd_vpath);
1273 panelswap (lwd_vpath);
1274 panelswap (marked);
1275 panelswap (dirs_marked);
1276 panelswap (total);
1277 panelswap (top);
1278 panelswap (current);
1279 panelswap (is_panelized);
1280 panelswap (panelized_descr);
1281 panelswap (dir_stat);
1282 #undef panelswap
1283
1284 panel1->quick_search.active = FALSE;
1285 panel2->quick_search.active = FALSE;
1286
1287 if (current_panel == panel1)
1288 current_panel = panel2;
1289 else
1290 current_panel = panel1;
1291
1292
1293 if (memcmp (&panel1->sort_info, &panel2->sort_info, sizeof (dir_sort_options_t)) != 0)
1294 {
1295 panel_re_sort (other_panel);
1296 panel_re_sort (current_panel);
1297 }
1298
1299 if (widget_is_active (panels[0].widget))
1300 widget_select (panels[1].widget);
1301 else if (widget_is_active (panels[1].widget))
1302 widget_select (panels[0].widget);
1303 }
1304 else
1305 {
1306 WPanel *tmp_panel;
1307 WRect r;
1308 int tmp_type;
1309
1310 tmp_panel = right_panel;
1311 right_panel = left_panel;
1312 left_panel = tmp_panel;
1313
1314 if (panels[0].type == view_listing)
1315 {
1316 if (strcmp (panel1->name, get_nth_panel_name (0)) == 0)
1317 {
1318 g_free (panel1->name);
1319 panel1->name = g_strdup (get_nth_panel_name (1));
1320 }
1321 }
1322 if (panels[1].type == view_listing)
1323 {
1324 if (strcmp (panel2->name, get_nth_panel_name (1)) == 0)
1325 {
1326 g_free (panel2->name);
1327 panel2->name = g_strdup (get_nth_panel_name (0));
1328 }
1329 }
1330
1331 r = panels[0].widget->rect;
1332 panels[0].widget->rect = panels[1].widget->rect;
1333 panels[1].widget->rect = r;
1334
1335 tmp_widget = panels[0].widget;
1336 panels[0].widget = panels[1].widget;
1337 panels[1].widget = tmp_widget;
1338 tmp_type = panels[0].type;
1339 panels[0].type = panels[1].type;
1340 panels[1].type = tmp_type;
1341
1342
1343 if (panels[0].type == view_listing)
1344 set_panel_formats (PANEL (panels[0].widget));
1345 if (panels[1].type == view_listing)
1346 set_panel_formats (PANEL (panels[1].widget));
1347 }
1348 }
1349
1350
1351
1352 panel_view_mode_t
1353 get_panel_type (int idx)
1354 {
1355 return panels[idx].type;
1356 }
1357
1358
1359
1360 Widget *
1361 get_panel_widget (int idx)
1362 {
1363 return panels[idx].widget;
1364 }
1365
1366
1367
1368 int
1369 get_current_index (void)
1370 {
1371 return (panels[0].widget == WIDGET (current_panel) ? 0 : 1);
1372 }
1373
1374
1375
1376 int
1377 get_other_index (void)
1378 {
1379 return (get_current_index () == 0 ? 1 : 0);
1380 }
1381
1382
1383
1384 WPanel *
1385 get_other_panel (void)
1386 {
1387 return PANEL (get_panel_widget (get_other_index ()));
1388 }
1389
1390
1391
1392
1393 panel_view_mode_t
1394 get_current_type (void)
1395 {
1396 return (panels[0].widget == WIDGET (current_panel) ? panels[0].type : panels[1].type);
1397 }
1398
1399
1400
1401
1402 panel_view_mode_t
1403 get_other_type (void)
1404 {
1405 return (panels[0].widget == WIDGET (current_panel) ? panels[1].type : panels[0].type);
1406 }
1407
1408
1409
1410
1411 void
1412 save_panel_dir (int idx)
1413 {
1414 panel_view_mode_t type;
1415
1416 type = get_panel_type (idx);
1417 if (type == view_listing)
1418 {
1419 WPanel *p;
1420
1421 p = PANEL (get_panel_widget (idx));
1422 if (p != NULL)
1423 {
1424 g_free (panels[idx].last_saved_dir);
1425
1426 panels[idx].last_saved_dir = g_strdup (vfs_path_as_str (p->cwd_vpath));
1427 }
1428 }
1429 }
1430
1431
1432
1433
1434
1435 char *
1436 get_panel_dir_for (const WPanel *widget)
1437 {
1438 int i;
1439
1440 for (i = 0; i < MAX_VIEWS; i++)
1441 if (PANEL (get_panel_widget (i)) == widget)
1442 break;
1443
1444 if (i >= MAX_VIEWS)
1445 return g_strdup (".");
1446
1447 if (get_panel_type (i) == view_listing)
1448 {
1449 vfs_path_t *cwd_vpath;
1450
1451 cwd_vpath = PANEL (get_panel_widget (i))->cwd_vpath;
1452 return g_strdup (vfs_path_as_str (cwd_vpath));
1453 }
1454
1455 return g_strdup (panels[i].last_saved_dir);
1456 }
1457
1458
1459
1460 #ifdef ENABLE_SUBSHELL
1461 gboolean
1462 do_load_prompt (void)
1463 {
1464 gboolean ret = FALSE;
1465
1466 if (!read_subshell_prompt ())
1467 return ret;
1468
1469
1470 if (top_dlg != NULL && DIALOG (top_dlg->data) == filemanager && command_prompt)
1471 {
1472 setup_cmdline ();
1473
1474
1475
1476
1477
1478 widget_update_cursor (WIDGET (filemanager));
1479 mc_refresh ();
1480 ret = TRUE;
1481 }
1482 update_subshell_prompt = TRUE;
1483 return ret;
1484 }
1485
1486
1487
1488 int
1489 load_prompt (int fd, void *unused)
1490 {
1491 (void) fd;
1492 (void) unused;
1493
1494 if (should_read_new_subshell_prompt)
1495 do_load_prompt ();
1496 else
1497 flush_subshell (0, QUIETLY);
1498
1499 return 0;
1500 }
1501 #endif
1502
1503
1504
1505 void
1506 title_path_prepare (char **path, char **login)
1507 {
1508 char host[BUF_TINY];
1509 struct passwd *pw = NULL;
1510 int res = 0;
1511
1512 *path =
1513 vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_STRIP_HOME | VPF_STRIP_PASSWORD);
1514
1515 res = gethostname (host, sizeof (host));
1516 if (res != 0)
1517 host[0] = '\0';
1518 else
1519 host[sizeof (host) - 1] = '\0';
1520
1521 pw = getpwuid (getuid ());
1522 if (pw != NULL)
1523 *login = g_strdup_printf ("%s@%s", pw->pw_name, host);
1524 else
1525 *login = g_strdup (host);
1526 }
1527
1528
1529
1530
1531 void
1532 update_xterm_title_path (void)
1533 {
1534 if (mc_global.tty.xterm_flag && xterm_title)
1535 {
1536 char *p;
1537 char *path;
1538 char *login;
1539
1540 title_path_prepare (&path, &login);
1541
1542 p = g_strdup_printf ("mc [%s]:%s", login, path);
1543 g_free (login);
1544 g_free (path);
1545
1546 fprintf (stdout, ESC_STR "]0;%s" ESC_STR "\\", str_term_form (p));
1547 g_free (p);
1548
1549 if (!mc_global.tty.alternate_plus_minus)
1550 numeric_keypad_mode ();
1551 (void) fflush (stdout);
1552 }
1553 }
1554
1555
1556
1557
1558 void
1559 update_terminal_cwd (void)
1560 {
1561 if (mc_global.tty.xterm_flag && vfs_current_is_local ())
1562 {
1563 const gchar *host;
1564 char *path, *path_uri;
1565
1566 host = g_get_host_name ();
1567 path = vfs_path_to_str_flags (current_panel->cwd_vpath, 0, VPF_NONE);
1568 path_uri = g_uri_escape_string (path, "/", FALSE);
1569
1570 fprintf (stdout, ESC_STR "]7;file://%s%s" ESC_STR "\\", host, path_uri);
1571 (void) fflush (stdout);
1572
1573 g_free (path_uri);
1574 g_free (path);
1575 }
1576 }
1577
1578