This source file includes following definitions.
- update_path_name
- fill_listbox
- unlink_entry
- add_name_to_list
- hotlist_run_cmd
- hotlist_button_callback
- hotlist_handle_key
- hotlist_callback
- hotlist_listbox_callback
- init_i18n_stuff
- init_hotlist
- init_movelist
- hotlist_done
- find_group_section
- add2hotlist
- add_new_entry_input
- add_new_entry_cmd
- add_new_group_input
- add_new_group_cmd
- remove_group
- remove_from_hotlist
- load_group
- hot_skip_blanks
- hot_next_token
- hot_load_group
- hot_load_file
- clean_up_hotlist_groups
- load_hotlist
- hot_save_group
- add_dotdot_to_list
- add2hotlist_cmd
- hotlist_show
- save_hotlist
- done_hotlist
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
35
36
37
38 #include <config.h>
39
40 #include <ctype.h>
41 #include <stdio.h>
42 #include <string.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <unistd.h>
46
47 #include "lib/global.h"
48
49 #include "lib/tty/tty.h"
50 #include "lib/tty/key.h"
51 #include "lib/skin.h"
52 #include "lib/mcconfig.h"
53 #include "lib/fileloc.h"
54 #include "lib/strutil.h"
55 #include "lib/vfs/vfs.h"
56 #include "lib/util.h"
57 #include "lib/widget.h"
58
59 #include "src/setup.h"
60 #include "src/history.h"
61
62 #include "command.h"
63
64 #include "hotlist.h"
65
66
67
68
69
70 #define UX 3
71 #define UY 2
72
73 #define B_ADD_CURRENT B_USER
74 #define B_REMOVE (B_USER + 1)
75 #define B_NEW_GROUP (B_USER + 2)
76 #define B_NEW_ENTRY (B_USER + 3)
77 #define B_ENTER_GROUP (B_USER + 4)
78 #define B_UP_GROUP (B_USER + 5)
79 #define B_INSERT (B_USER + 6)
80 #define B_APPEND (B_USER + 7)
81 #define B_MOVE (B_USER + 8)
82 #ifdef ENABLE_VFS
83 #define B_FREE_ALL_VFS (B_USER + 9)
84 #define B_REFRESH_VFS (B_USER + 10)
85 #endif
86
87 #define TKN_GROUP 0
88 #define TKN_ENTRY 1
89 #define TKN_STRING 2
90 #define TKN_URL 3
91 #define TKN_ENDGROUP 4
92 #define TKN_COMMENT 5
93 #define TKN_EOL 125
94 #define TKN_EOF 126
95 #define TKN_UNKNOWN 127
96
97 #define SKIP_TO_EOL \
98 { \
99 int _tkn; \
100 while ((_tkn = hot_next_token ()) != TKN_EOF && _tkn != TKN_EOL) ; \
101 }
102
103 #define CHECK_TOKEN(_TKN_) \
104 tkn = hot_next_token (); \
105 if (tkn != _TKN_) \
106 { \
107 hotlist_state.readonly = TRUE; \
108 hotlist_state.file_error = TRUE; \
109 while (tkn != TKN_EOL && tkn != TKN_EOF) \
110 tkn = hot_next_token (); \
111 break; \
112 }
113
114
115
116 enum HotListType
117 {
118 HL_TYPE_GROUP,
119 HL_TYPE_ENTRY,
120 HL_TYPE_COMMENT,
121 HL_TYPE_DOTDOT
122 };
123
124 static struct
125 {
126
127
128
129
130 gboolean loaded;
131 gboolean readonly;
132 gboolean file_error;
133 gboolean running;
134
135 gboolean moving;
136 gboolean modified;
137 hotlist_t type;
138 } hotlist_state;
139
140
141 struct hotlist
142 {
143 enum HotListType type;
144 char *directory;
145 char *label;
146 struct hotlist *head;
147 struct hotlist *up;
148 struct hotlist *next;
149 };
150
151
152
153
154
155 static WPanel *our_panel;
156
157 static gboolean hotlist_has_dot_dot = TRUE;
158
159 static WDialog *hotlist_dlg, *movelist_dlg;
160 static WGroupbox *hotlist_group, *movelist_group;
161 static WListbox *l_hotlist, *l_movelist;
162 static WLabel *pname;
163
164 static struct
165 {
166 int ret_cmd, flags, y, x, len;
167 const char *text;
168 int type;
169 widget_pos_flags_t pos_flags;
170 } hotlist_but[] =
171 {
172
173 { B_ENTER, DEFPUSH_BUTTON, 0, 0, 0, N_("Change &to"),
174 LIST_HOTLIST | LIST_VFSLIST | LIST_MOVELIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
175 #ifdef ENABLE_VFS
176 { B_FREE_ALL_VFS, NORMAL_BUTTON, 0, 20, 0, N_("&Free VFSs now"),
177 LIST_VFSLIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
178 { B_REFRESH_VFS, NORMAL_BUTTON, 0, 43, 0, N_("&Refresh"),
179 LIST_VFSLIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
180 #endif
181 { B_ADD_CURRENT, NORMAL_BUTTON, 0, 20, 0, N_("&Add current"),
182 LIST_HOTLIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
183 { B_UP_GROUP, NORMAL_BUTTON, 0, 42, 0, N_("&Up"),
184 LIST_HOTLIST | LIST_MOVELIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
185 { B_CANCEL, NORMAL_BUTTON, 0, 53, 0, N_("&Cancel"),
186 LIST_HOTLIST | LIST_VFSLIST | LIST_MOVELIST, WPOS_KEEP_RIGHT | WPOS_KEEP_BOTTOM },
187 { B_NEW_GROUP, NORMAL_BUTTON, 1, 0, 0, N_("New &group"),
188 LIST_HOTLIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
189 { B_NEW_ENTRY, NORMAL_BUTTON, 1, 15, 0, N_("New &entry"),
190 LIST_HOTLIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
191 { B_INSERT, NORMAL_BUTTON, 1, 0, 0, N_("&Insert"),
192 LIST_MOVELIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
193 { B_APPEND, NORMAL_BUTTON, 1, 15, 0, N_("A&ppend"),
194 LIST_MOVELIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
195 { B_REMOVE, NORMAL_BUTTON, 1, 30, 0, N_("&Remove"),
196 LIST_HOTLIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM },
197 { B_MOVE, NORMAL_BUTTON, 1, 42, 0, N_("&Move"),
198 LIST_HOTLIST, WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM }
199
200 };
201
202 static const size_t hotlist_but_num = G_N_ELEMENTS (hotlist_but);
203
204 static struct hotlist *hotlist = NULL;
205
206 static struct hotlist *current_group;
207
208 static GString *tkn_buf = NULL;
209
210 static char *hotlist_file_name;
211 static FILE *hotlist_file;
212 static time_t hotlist_file_mtime;
213
214 static int list_level = 0;
215
216
217
218
219
220 static void init_movelist (struct hotlist *item);
221 static void add_new_group_cmd (void);
222 static void add_new_entry_cmd (WPanel * panel);
223 static void remove_from_hotlist (struct hotlist *entry);
224 static void load_hotlist (void);
225 static void add_dotdot_to_list (void);
226
227
228
229
230 static void
231 update_path_name (void)
232 {
233 const char *text = "";
234 char *p;
235 WListbox *list = hotlist_state.moving ? l_movelist : l_hotlist;
236 Widget *w = WIDGET (list);
237
238 if (!listbox_is_empty (list))
239 {
240 char *ctext = NULL;
241 void *cdata = NULL;
242
243 listbox_get_current (list, &ctext, &cdata);
244 if (cdata == NULL)
245 text = ctext;
246 else
247 {
248 struct hotlist *hlp = (struct hotlist *) cdata;
249
250 if (hlp->type == HL_TYPE_ENTRY || hlp->type == HL_TYPE_DOTDOT)
251 text = hlp->directory;
252 else if (hlp->type == HL_TYPE_GROUP)
253 text = _("Subgroup - press ENTER to see list");
254 }
255 }
256
257 p = g_strconcat (" ", current_group->label, " ", (char *) NULL);
258 if (hotlist_state.moving)
259 groupbox_set_title (movelist_group, str_trunc (p, w->rect.cols - 2));
260 else
261 {
262 groupbox_set_title (hotlist_group, str_trunc (p, w->rect.cols - 2));
263 label_set_text (pname, str_trunc (text, w->rect.cols));
264 }
265 g_free (p);
266 }
267
268
269
270 static void
271 fill_listbox (WListbox * list)
272 {
273 struct hotlist *current;
274 GString *buff;
275
276 buff = g_string_new ("");
277
278 for (current = current_group->head; current != NULL; current = current->next)
279 switch (current->type)
280 {
281 case HL_TYPE_GROUP:
282 {
283
284 g_string_truncate (buff, 0);
285 g_string_append (buff, "->");
286 g_string_append (buff, current->label);
287 listbox_add_item (list, LISTBOX_APPEND_AT_END, 0, buff->str, current, FALSE);
288 }
289 break;
290 case HL_TYPE_DOTDOT:
291 case HL_TYPE_ENTRY:
292 listbox_add_item (list, LISTBOX_APPEND_AT_END, 0, current->label, current, FALSE);
293 break;
294 default:
295 break;
296 }
297
298 g_string_free (buff, TRUE);
299 }
300
301
302
303 static void
304 unlink_entry (struct hotlist *entry)
305 {
306 struct hotlist *current = current_group->head;
307
308 if (current == entry)
309 current_group->head = entry->next;
310 else
311 {
312 while (current != NULL && current->next != entry)
313 current = current->next;
314 if (current != NULL)
315 current->next = entry->next;
316 }
317 entry->next = entry->up = NULL;
318 }
319
320
321
322 #ifdef ENABLE_VFS
323 static void
324 add_name_to_list (const char *path)
325 {
326 listbox_add_item (l_hotlist, LISTBOX_APPEND_AT_END, 0, path, NULL, FALSE);
327 }
328 #endif
329
330
331
332 static int
333 hotlist_run_cmd (int action)
334 {
335 switch (action)
336 {
337 case B_MOVE:
338 {
339 struct hotlist *saved = current_group;
340 struct hotlist *item = NULL;
341 struct hotlist *moveto_item = NULL;
342 struct hotlist *moveto_group = NULL;
343 int ret;
344
345 if (listbox_is_empty (l_hotlist))
346 return 0;
347
348 listbox_get_current (l_hotlist, NULL, (void **) &item);
349 init_movelist (item);
350 hotlist_state.moving = TRUE;
351 ret = dlg_run (movelist_dlg);
352 hotlist_state.moving = FALSE;
353 listbox_get_current (l_movelist, NULL, (void **) &moveto_item);
354 moveto_group = current_group;
355 widget_destroy (WIDGET (movelist_dlg));
356 current_group = saved;
357 if (ret == B_CANCEL)
358 return 0;
359 if (moveto_item == item)
360 return 0;
361
362 unlink_entry (item);
363 listbox_remove_current (l_hotlist);
364 item->up = moveto_group;
365 if (moveto_group->head == NULL)
366 moveto_group->head = item;
367 else if (moveto_item == NULL)
368 {
369 struct hotlist *p = moveto_group->head;
370
371
372 while (p->next != NULL)
373 p = p->next;
374 p->next = item;
375 }
376 else if (ret == B_ENTER || ret == B_APPEND)
377 {
378 if (moveto_item->next == NULL)
379 moveto_item->next = item;
380 else
381 {
382 item->next = moveto_item->next;
383 moveto_item->next = item;
384 }
385 }
386 else if (moveto_group->head == moveto_item)
387 {
388 moveto_group->head = item;
389 item->next = moveto_item;
390 }
391 else
392 {
393 struct hotlist *p = moveto_group->head;
394
395 while (p->next != moveto_item)
396 p = p->next;
397 item->next = p->next;
398 p->next = item;
399 }
400 listbox_remove_list (l_hotlist);
401 fill_listbox (l_hotlist);
402 repaint_screen ();
403 hotlist_state.modified = TRUE;
404 return 0;
405 }
406 case B_REMOVE:
407 {
408 struct hotlist *entry = NULL;
409
410 listbox_get_current (l_hotlist, NULL, (void **) &entry);
411 remove_from_hotlist (entry);
412 }
413 return 0;
414
415 case B_NEW_GROUP:
416 add_new_group_cmd ();
417 return 0;
418
419 case B_ADD_CURRENT:
420 add2hotlist_cmd (our_panel);
421 return 0;
422
423 case B_NEW_ENTRY:
424 add_new_entry_cmd (our_panel);
425 return 0;
426
427 case B_ENTER:
428 case B_ENTER_GROUP:
429 {
430 WListbox *list;
431 void *data;
432 struct hotlist *hlp;
433
434 list = hotlist_state.moving ? l_movelist : l_hotlist;
435 listbox_get_current (list, NULL, &data);
436
437 if (data == NULL)
438 return 1;
439
440 hlp = (struct hotlist *) data;
441
442 if (hlp->type == HL_TYPE_ENTRY)
443 return (action == B_ENTER ? 1 : 0);
444 if (hlp->type != HL_TYPE_DOTDOT)
445 {
446 listbox_remove_list (list);
447 current_group = hlp;
448 fill_listbox (list);
449 return 0;
450 }
451 }
452 MC_FALLTHROUGH;
453
454 case B_UP_GROUP:
455 {
456 WListbox *list = hotlist_state.moving ? l_movelist : l_hotlist;
457
458 listbox_remove_list (list);
459 current_group = current_group->up;
460 fill_listbox (list);
461 return 0;
462 }
463
464 #ifdef ENABLE_VFS
465 case B_FREE_ALL_VFS:
466 vfs_expire (TRUE);
467 MC_FALLTHROUGH;
468
469 case B_REFRESH_VFS:
470 listbox_remove_list (l_hotlist);
471 listbox_add_item (l_hotlist, LISTBOX_APPEND_AT_END, 0, mc_config_get_home_dir (), NULL,
472 FALSE);
473 vfs_fill_names (add_name_to_list);
474 return 0;
475 #endif
476
477 default:
478 return 1;
479 }
480 }
481
482
483
484 static int
485 hotlist_button_callback (WButton * button, int action)
486 {
487 int ret;
488
489 (void) button;
490 ret = hotlist_run_cmd (action);
491 update_path_name ();
492 return ret;
493 }
494
495
496
497 static inline cb_ret_t
498 hotlist_handle_key (WDialog * h, int key)
499 {
500 switch (key)
501 {
502 case KEY_M_CTRL | '\n':
503 goto l1;
504
505 case '\n':
506 case KEY_ENTER:
507 if (hotlist_button_callback (NULL, B_ENTER) != 0)
508 {
509 h->ret_value = B_ENTER;
510 dlg_close (h);
511 }
512 return MSG_HANDLED;
513
514 case KEY_RIGHT:
515
516 if (hotlist_state.type == LIST_VFSLIST)
517 return MSG_NOT_HANDLED;
518 return hotlist_button_callback (NULL, B_ENTER_GROUP) == 0 ? MSG_HANDLED : MSG_NOT_HANDLED;
519
520 case KEY_LEFT:
521
522 if (hotlist_state.type == LIST_VFSLIST)
523 return MSG_NOT_HANDLED;
524 return hotlist_button_callback (NULL, B_UP_GROUP) == 0 ? MSG_HANDLED : MSG_NOT_HANDLED;
525
526 case KEY_DC:
527 if (hotlist_state.moving)
528 return MSG_NOT_HANDLED;
529 hotlist_button_callback (NULL, B_REMOVE);
530 return MSG_HANDLED;
531
532 l1:
533 case ALT ('\n'):
534 case ALT ('\r'):
535 if (!hotlist_state.moving)
536 {
537 void *ldata = NULL;
538
539 listbox_get_current (l_hotlist, NULL, &ldata);
540
541 if (ldata != NULL)
542 {
543 struct hotlist *hlp = (struct hotlist *) ldata;
544
545 if (hlp->type == HL_TYPE_ENTRY)
546 {
547 char *tmp;
548
549 tmp = g_strconcat ("cd ", hlp->directory, (char *) NULL);
550 input_insert (cmdline, tmp, FALSE);
551 g_free (tmp);
552 h->ret_value = B_CANCEL;
553 dlg_close (h);
554 }
555 }
556 }
557 return MSG_HANDLED;
558
559 default:
560 return MSG_NOT_HANDLED;
561 }
562 }
563
564
565
566 static cb_ret_t
567 hotlist_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data)
568 {
569 WDialog *h = DIALOG (w);
570
571 switch (msg)
572 {
573 case MSG_INIT:
574 case MSG_NOTIFY:
575 update_path_name ();
576 return MSG_HANDLED;
577
578 case MSG_UNHANDLED_KEY:
579 return hotlist_handle_key (h, parm);
580
581 case MSG_POST_KEY:
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597 {
598 Widget *lst;
599
600 lst = WIDGET (h == hotlist_dlg ? l_hotlist : l_movelist);
601
602
603
604
605 if (!widget_get_state (lst, WST_FOCUSED))
606 widget_select (lst);
607 else
608 widget_draw (lst);
609 }
610 return MSG_HANDLED;
611
612 case MSG_RESIZE:
613 {
614 WRect r = w->rect;
615
616 r.lines = LINES - (h == hotlist_dlg ? 2 : 6);
617 r.cols = COLS - 6;
618
619 return dlg_default_callback (w, NULL, MSG_RESIZE, 0, &r);
620 }
621
622 default:
623 return dlg_default_callback (w, sender, msg, parm, data);
624 }
625 }
626
627
628
629 static lcback_ret_t
630 hotlist_listbox_callback (WListbox * list)
631 {
632 WDialog *dlg = DIALOG (WIDGET (list)->owner);
633
634 if (!listbox_is_empty (list))
635 {
636 void *data = NULL;
637
638 listbox_get_current (list, NULL, &data);
639
640 if (data != NULL)
641 {
642 struct hotlist *hlp = (struct hotlist *) data;
643
644 if (hlp->type == HL_TYPE_ENTRY)
645 {
646 dlg->ret_value = B_ENTER;
647 dlg_close (dlg);
648 return LISTBOX_DONE;
649 }
650 else
651 {
652 hotlist_button_callback (NULL, B_ENTER);
653 send_message (dlg, NULL, MSG_POST_KEY, '\n', NULL);
654 return LISTBOX_CONT;
655 }
656 }
657 else
658 {
659 dlg->ret_value = B_ENTER;
660 dlg_close (dlg);
661 return LISTBOX_DONE;
662 }
663 }
664
665 hotlist_button_callback (NULL, B_UP_GROUP);
666 send_message (dlg, NULL, MSG_POST_KEY, 'u', NULL);
667 return LISTBOX_CONT;
668 }
669
670
671
672
673
674
675
676
677
678
679
680 static int
681 init_i18n_stuff (int list_type, int cols)
682 {
683 size_t i;
684
685 static gboolean i18n_flag = FALSE;
686
687 if (!i18n_flag)
688 {
689 for (i = 0; i < hotlist_but_num; i++)
690 {
691 #ifdef ENABLE_NLS
692 hotlist_but[i].text = _(hotlist_but[i].text);
693 #endif
694 hotlist_but[i].len = str_term_width1 (hotlist_but[i].text) + 3;
695 if (hotlist_but[i].flags == DEFPUSH_BUTTON)
696 hotlist_but[i].len += 2;
697 }
698
699 i18n_flag = TRUE;
700 }
701
702
703 {
704 int len[2], count[2];
705 int cur_x[2];
706
707 len[0] = len[1] = 0;
708 count[0] = count[1] = 0;
709 cur_x[0] = cur_x[1] = 0;
710
711
712 for (i = 0; i < hotlist_but_num; i++)
713 if ((hotlist_but[i].type & list_type) != 0)
714 {
715 int row;
716
717 row = hotlist_but[i].y;
718 ++count[row];
719 len[row] += hotlist_but[i].len + 1;
720 }
721
722 (len[0])--;
723 (len[1])--;
724
725 cols = MAX (cols, MAX (len[0], len[1]));
726
727
728 for (i = 0; i < hotlist_but_num; i++)
729 if ((hotlist_but[i].type & list_type) != 0)
730 {
731 int row;
732
733 row = hotlist_but[i].y;
734
735 if (hotlist_but[i].x != 0)
736 {
737
738 if (hotlist_but[i].ret_cmd == B_CANCEL)
739 hotlist_but[i].x = cols - hotlist_but[i].len - 6;
740 else
741 hotlist_but[i].x = cur_x[row];
742 }
743
744 cur_x[row] += hotlist_but[i].len + 1;
745 }
746 }
747
748 return cols;
749 }
750
751
752
753 static void
754 init_hotlist (hotlist_t list_type)
755 {
756 size_t i;
757 const char *title, *help_node;
758 int lines, cols;
759 int y;
760 int dh = 0;
761 WGroup *g;
762 WGroupbox *path_box;
763 Widget *hotlist_widget;
764
765 do_refresh ();
766
767 lines = LINES - 2;
768 cols = init_i18n_stuff (list_type, COLS - 6);
769
770 #ifdef ENABLE_VFS
771 if (list_type == LIST_VFSLIST)
772 {
773 title = _("Active VFS directories");
774 help_node = "[vfshot]";
775 dh = 1;
776 }
777 else
778 #endif
779 {
780 title = _("Directory hotlist");
781 help_node = "[Hotlist]";
782 }
783
784 hotlist_dlg =
785 dlg_create (TRUE, 0, 0, lines, cols, WPOS_CENTER, FALSE, dialog_colors, hotlist_callback,
786 NULL, help_node, title);
787 g = GROUP (hotlist_dlg);
788
789 y = UY;
790 hotlist_group = groupbox_new (y, UX, lines - 10 + dh, cols - 2 * UX, _("Top level group"));
791 hotlist_widget = WIDGET (hotlist_group);
792 group_add_widget_autopos (g, hotlist_widget, WPOS_KEEP_ALL, NULL);
793
794 l_hotlist =
795 listbox_new (y + 1, UX + 1, hotlist_widget->rect.lines - 2, hotlist_widget->rect.cols - 2,
796 FALSE, hotlist_listbox_callback);
797
798
799 #ifdef ENABLE_VFS
800 if (list_type == LIST_VFSLIST)
801 {
802 listbox_add_item (l_hotlist, LISTBOX_APPEND_AT_END, 0, mc_config_get_home_dir (), NULL,
803 FALSE);
804 vfs_fill_names (add_name_to_list);
805 }
806 else
807 #endif
808 fill_listbox (l_hotlist);
809
810
811 group_add_widget_autopos (g, l_hotlist, WPOS_KEEP_ALL, NULL);
812
813 y += hotlist_widget->rect.lines;
814
815 path_box = groupbox_new (y, UX, 3, hotlist_widget->rect.cols, _("Directory path"));
816 group_add_widget_autopos (g, path_box, WPOS_KEEP_BOTTOM | WPOS_KEEP_HORZ, NULL);
817
818 pname = label_new (y + 1, UX + 2, NULL);
819 group_add_widget_autopos (g, pname, WPOS_KEEP_BOTTOM | WPOS_KEEP_LEFT, NULL);
820 y += WIDGET (path_box)->rect.lines;
821
822 group_add_widget_autopos (g, hline_new (y++, -1, -1), WPOS_KEEP_BOTTOM, NULL);
823
824 for (i = 0; i < hotlist_but_num; i++)
825 if ((hotlist_but[i].type & list_type) != 0)
826 group_add_widget_autopos (g,
827 button_new (y + hotlist_but[i].y, UX + hotlist_but[i].x,
828 hotlist_but[i].ret_cmd, hotlist_but[i].flags,
829 hotlist_but[i].text, hotlist_button_callback),
830 hotlist_but[i].pos_flags, NULL);
831
832 widget_select (WIDGET (l_hotlist));
833 }
834
835
836
837 static void
838 init_movelist (struct hotlist *item)
839 {
840 size_t i;
841 char *hdr;
842 int lines, cols;
843 int y;
844 WGroup *g;
845 Widget *movelist_widget;
846
847 do_refresh ();
848
849 lines = LINES - 6;
850 cols = init_i18n_stuff (LIST_MOVELIST, COLS - 6);
851
852 hdr = g_strdup_printf (_("Moving %s"), item->label);
853
854 movelist_dlg =
855 dlg_create (TRUE, 0, 0, lines, cols, WPOS_CENTER, FALSE, dialog_colors, hotlist_callback,
856 NULL, "[Hotlist]", hdr);
857 g = GROUP (movelist_dlg);
858
859 g_free (hdr);
860
861 y = UY;
862 movelist_group = groupbox_new (y, UX, lines - 7, cols - 2 * UX, _("Directory label"));
863 movelist_widget = WIDGET (movelist_group);
864 group_add_widget_autopos (g, movelist_widget, WPOS_KEEP_ALL, NULL);
865
866 l_movelist =
867 listbox_new (y + 1, UX + 1, movelist_widget->rect.lines - 2, movelist_widget->rect.cols - 2,
868 FALSE, hotlist_listbox_callback);
869 fill_listbox (l_movelist);
870
871 group_add_widget_autopos (g, l_movelist, WPOS_KEEP_ALL, NULL);
872
873 y += movelist_widget->rect.lines;
874
875 group_add_widget_autopos (g, hline_new (y++, -1, -1), WPOS_KEEP_BOTTOM, NULL);
876
877 for (i = 0; i < hotlist_but_num; i++)
878 if ((hotlist_but[i].type & LIST_MOVELIST) != 0)
879 group_add_widget_autopos (g,
880 button_new (y + hotlist_but[i].y, UX + hotlist_but[i].x,
881 hotlist_but[i].ret_cmd, hotlist_but[i].flags,
882 hotlist_but[i].text, hotlist_button_callback),
883 hotlist_but[i].pos_flags, NULL);
884
885 widget_select (WIDGET (l_movelist));
886 }
887
888
889
890
891
892
893
894 static void
895 hotlist_done (void)
896 {
897 widget_destroy (WIDGET (hotlist_dlg));
898 l_hotlist = NULL;
899 #if 0
900 update_panels (UP_OPTIMIZE, UP_KEEPSEL);
901 #endif
902 repaint_screen ();
903 }
904
905
906
907 static inline char *
908 find_group_section (struct hotlist *grp)
909 {
910 return g_strconcat (grp->directory, ".Group", (char *) NULL);
911 }
912
913
914
915 static struct hotlist *
916 add2hotlist (char *label, char *directory, enum HotListType type, listbox_append_t pos)
917 {
918 struct hotlist *new;
919 struct hotlist *current = NULL;
920
921
922
923
924
925 if (current_group == NULL)
926 load_hotlist ();
927
928 listbox_get_current (l_hotlist, NULL, (void **) ¤t);
929
930
931 if ((current != NULL) && (current->type == HL_TYPE_DOTDOT))
932 pos = LISTBOX_APPEND_AFTER;
933
934 new = g_new0 (struct hotlist, 1);
935
936 new->type = type;
937 new->label = label;
938 new->directory = directory;
939 new->up = current_group;
940
941 if (type == HL_TYPE_GROUP)
942 {
943 current_group = new;
944 add_dotdot_to_list ();
945 current_group = new->up;
946 }
947
948 if (current_group->head == NULL)
949 {
950
951 current_group->head = new;
952 }
953 else if (pos == LISTBOX_APPEND_AFTER)
954 {
955 new->next = current->next;
956 current->next = new;
957 }
958 else if (pos == LISTBOX_APPEND_BEFORE && current == current_group->head)
959 {
960
961 new->next = current;
962 current_group->head = new;
963 }
964 else if (pos == LISTBOX_APPEND_BEFORE)
965 {
966 struct hotlist *p = current_group->head;
967
968 while (p->next != current)
969 p = p->next;
970
971 new->next = current;
972 p->next = new;
973 }
974 else
975 {
976 struct hotlist *p = current_group->head;
977
978 while (p->next != NULL)
979 p = p->next;
980
981 p->next = new;
982 }
983
984 if (hotlist_state.running && type != HL_TYPE_COMMENT && type != HL_TYPE_DOTDOT)
985 {
986 if (type == HL_TYPE_GROUP)
987 {
988 char *lbl;
989
990 lbl = g_strconcat ("->", new->label, (char *) NULL);
991 listbox_add_item (l_hotlist, pos, 0, lbl, new, FALSE);
992 g_free (lbl);
993 }
994 else
995 listbox_add_item (l_hotlist, pos, 0, new->label, new, FALSE);
996 listbox_set_current (l_hotlist, l_hotlist->current);
997 }
998
999 return new;
1000 }
1001
1002
1003
1004 static int
1005 add_new_entry_input (const char *header, const char *text1, const char *text2,
1006 const char *help, char **r1, char **r2)
1007 {
1008 quick_widget_t quick_widgets[] = {
1009
1010 QUICK_LABELED_INPUT (text1, input_label_above, *r1, "input-lbl", r1, NULL,
1011 FALSE, FALSE, INPUT_COMPLETE_NONE),
1012 QUICK_SEPARATOR (FALSE),
1013 QUICK_LABELED_INPUT (text2, input_label_above, *r2, "input-lbl", r2, NULL,
1014 FALSE, FALSE, INPUT_COMPLETE_FILENAMES | INPUT_COMPLETE_CD),
1015 QUICK_START_BUTTONS (TRUE, TRUE),
1016 QUICK_BUTTON (N_("&Append"), B_APPEND, NULL, NULL),
1017 QUICK_BUTTON (N_("&Insert"), B_INSERT, NULL, NULL),
1018 QUICK_BUTTON (N_("&Cancel"), B_CANCEL, NULL, NULL),
1019 QUICK_END
1020
1021 };
1022
1023 WRect r = { -1, -1, 0, 64 };
1024
1025 quick_dialog_t qdlg = {
1026 r, header, help,
1027 quick_widgets, NULL, NULL
1028 };
1029
1030 int ret;
1031
1032 ret = quick_dialog (&qdlg);
1033
1034 return (ret != B_CANCEL) ? ret : 0;
1035 }
1036
1037
1038
1039 static void
1040 add_new_entry_cmd (WPanel * panel)
1041 {
1042 char *title, *url, *to_free;
1043 int ret;
1044
1045
1046 to_free = title = url = vfs_path_to_str_flags (panel->cwd_vpath, 0, VPF_STRIP_PASSWORD);
1047
1048 ret = add_new_entry_input (_("New hotlist entry"), _("Directory label:"),
1049 _("Directory path:"), "[Hotlist]", &title, &url);
1050 g_free (to_free);
1051
1052 if (ret == 0)
1053 return;
1054 if (title == NULL || *title == '\0' || url == NULL || *url == '\0')
1055 {
1056 g_free (title);
1057 g_free (url);
1058 return;
1059 }
1060
1061 if (ret == B_ENTER || ret == B_APPEND)
1062 add2hotlist (title, url, HL_TYPE_ENTRY, LISTBOX_APPEND_AFTER);
1063 else
1064 add2hotlist (title, url, HL_TYPE_ENTRY, LISTBOX_APPEND_BEFORE);
1065
1066 hotlist_state.modified = TRUE;
1067 }
1068
1069
1070
1071 static int
1072 add_new_group_input (const char *header, const char *label, char **result)
1073 {
1074 quick_widget_t quick_widgets[] = {
1075
1076 QUICK_LABELED_INPUT (label, input_label_above, "", "input", result, NULL,
1077 FALSE, FALSE, INPUT_COMPLETE_NONE),
1078 QUICK_START_BUTTONS (TRUE, TRUE),
1079 QUICK_BUTTON (N_("&Append"), B_APPEND, NULL, NULL),
1080 QUICK_BUTTON (N_("&Insert"), B_INSERT, NULL, NULL),
1081 QUICK_BUTTON (N_("&Cancel"), B_CANCEL, NULL, NULL),
1082 QUICK_END
1083
1084 };
1085
1086 WRect r = { -1, -1, 0, 64 };
1087
1088 quick_dialog_t qdlg = {
1089 r, header, "[Hotlist]",
1090 quick_widgets, NULL, NULL
1091 };
1092
1093 int ret;
1094
1095 ret = quick_dialog (&qdlg);
1096
1097 return (ret != B_CANCEL) ? ret : 0;
1098 }
1099
1100
1101
1102 static void
1103 add_new_group_cmd (void)
1104 {
1105 char *label;
1106 int ret;
1107
1108 ret = add_new_group_input (_("New hotlist group"), _("Name of new group:"), &label);
1109 if (ret == 0 || label == NULL || *label == '\0')
1110 return;
1111
1112 if (ret == B_ENTER || ret == B_APPEND)
1113 add2hotlist (label, 0, HL_TYPE_GROUP, LISTBOX_APPEND_AFTER);
1114 else
1115 add2hotlist (label, 0, HL_TYPE_GROUP, LISTBOX_APPEND_BEFORE);
1116
1117 hotlist_state.modified = TRUE;
1118 }
1119
1120
1121
1122 static void
1123 remove_group (struct hotlist *grp)
1124 {
1125 struct hotlist *current = grp->head;
1126
1127 while (current != NULL)
1128 {
1129 struct hotlist *next = current->next;
1130
1131 if (current->type == HL_TYPE_GROUP)
1132 remove_group (current);
1133
1134 g_free (current->label);
1135 g_free (current->directory);
1136 g_free (current);
1137
1138 current = next;
1139 }
1140 }
1141
1142
1143
1144 static void
1145 remove_from_hotlist (struct hotlist *entry)
1146 {
1147 if (entry == NULL)
1148 return;
1149
1150 if (entry->type == HL_TYPE_DOTDOT)
1151 return;
1152
1153 if (confirm_directory_hotlist_delete)
1154 {
1155 char text[BUF_MEDIUM];
1156 int result;
1157
1158 if (safe_delete)
1159 query_set_sel (1);
1160
1161 g_snprintf (text, sizeof (text), _("Are you sure you want to remove entry \"%s\"?"),
1162 str_trunc (entry->label, 30));
1163 result = query_dialog (Q_ ("DialogTitle|Delete"), text, D_ERROR | D_CENTER, 2,
1164 _("&Yes"), _("&No"));
1165 if (result != 0)
1166 return;
1167 }
1168
1169 if (entry->type == HL_TYPE_GROUP)
1170 {
1171 struct hotlist *head = entry->head;
1172
1173 if (head != NULL && (head->type != HL_TYPE_DOTDOT || head->next != NULL))
1174 {
1175 char text[BUF_MEDIUM];
1176 int result;
1177
1178 g_snprintf (text, sizeof (text), _("Group \"%s\" is not empty.\nRemove it?"),
1179 str_trunc (entry->label, 30));
1180 result = query_dialog (Q_ ("DialogTitle|Delete"), text, D_ERROR | D_CENTER, 2,
1181 _("&Yes"), _("&No"));
1182 if (result != 0)
1183 return;
1184 }
1185
1186 remove_group (entry);
1187 }
1188
1189 unlink_entry (entry);
1190
1191 g_free (entry->label);
1192 g_free (entry->directory);
1193 g_free (entry);
1194
1195 listbox_remove_current (l_hotlist);
1196 hotlist_state.modified = TRUE;
1197 }
1198
1199
1200
1201 static void
1202 load_group (struct hotlist *grp)
1203 {
1204 gchar **profile_keys, **keys;
1205 char *group_section;
1206 struct hotlist *current = 0;
1207
1208 group_section = find_group_section (grp);
1209
1210 keys = mc_config_get_keys (mc_global.main_config, group_section, NULL);
1211
1212 current_group = grp;
1213
1214 for (profile_keys = keys; *profile_keys != NULL; profile_keys++)
1215 add2hotlist (mc_config_get_string (mc_global.main_config, group_section, *profile_keys, ""),
1216 g_strdup (*profile_keys), HL_TYPE_GROUP, LISTBOX_APPEND_AT_END);
1217
1218 g_strfreev (keys);
1219
1220 keys = mc_config_get_keys (mc_global.main_config, grp->directory, NULL);
1221
1222 for (profile_keys = keys; *profile_keys != NULL; profile_keys++)
1223 add2hotlist (mc_config_get_string (mc_global.main_config, group_section, *profile_keys, ""),
1224 g_strdup (*profile_keys), HL_TYPE_ENTRY, LISTBOX_APPEND_AT_END);
1225
1226 g_free (group_section);
1227 g_strfreev (keys);
1228
1229 for (current = grp->head; current; current = current->next)
1230 load_group (current);
1231 }
1232
1233
1234
1235 static int
1236 hot_skip_blanks (void)
1237 {
1238 int c;
1239
1240 while ((c = getc (hotlist_file)) != EOF && c != '\n' && g_ascii_isspace (c))
1241 ;
1242 return c;
1243 }
1244
1245
1246
1247 static int
1248 hot_next_token (void)
1249 {
1250 int c, ret = 0;
1251 size_t l;
1252
1253 if (tkn_buf == NULL)
1254 tkn_buf = g_string_new ("");
1255 g_string_set_size (tkn_buf, 0);
1256
1257 again:
1258 c = hot_skip_blanks ();
1259 switch (c)
1260 {
1261 case EOF:
1262 ret = TKN_EOF;
1263 break;
1264 case '\n':
1265 ret = TKN_EOL;
1266 break;
1267 case '#':
1268 while ((c = getc (hotlist_file)) != EOF && c != '\n')
1269 g_string_append_c (tkn_buf, c);
1270 ret = TKN_COMMENT;
1271 break;
1272 case '"':
1273 while ((c = getc (hotlist_file)) != EOF && c != '"')
1274 {
1275 if (c == '\\')
1276 {
1277 c = getc (hotlist_file);
1278 if (c == EOF)
1279 {
1280 g_string_free (tkn_buf, TRUE);
1281 return TKN_EOF;
1282 }
1283 }
1284 g_string_append_c (tkn_buf, c == '\n' ? ' ' : c);
1285 }
1286 ret = (c == EOF) ? TKN_EOF : TKN_STRING;
1287 break;
1288 case '\\':
1289 c = getc (hotlist_file);
1290 if (c == EOF)
1291 {
1292 g_string_free (tkn_buf, TRUE);
1293 return TKN_EOF;
1294 }
1295 if (c == '\n')
1296 goto again;
1297
1298 MC_FALLTHROUGH;
1299
1300 default:
1301 do
1302 {
1303 g_string_append_c (tkn_buf, g_ascii_toupper (c));
1304 }
1305 while ((c = fgetc (hotlist_file)) != EOF && (g_ascii_isalnum (c) || !isascii (c)));
1306 if (c != EOF)
1307 ungetc (c, hotlist_file);
1308 l = tkn_buf->len;
1309 if (strncmp (tkn_buf->str, "GROUP", l) == 0)
1310 ret = TKN_GROUP;
1311 else if (strncmp (tkn_buf->str, "ENTRY", l) == 0)
1312 ret = TKN_ENTRY;
1313 else if (strncmp (tkn_buf->str, "ENDGROUP", l) == 0)
1314 ret = TKN_ENDGROUP;
1315 else if (strncmp (tkn_buf->str, "URL", l) == 0)
1316 ret = TKN_URL;
1317 else
1318 ret = TKN_UNKNOWN;
1319 break;
1320 }
1321 return ret;
1322 }
1323
1324
1325
1326 static void
1327 hot_load_group (struct hotlist *grp)
1328 {
1329 int tkn;
1330 struct hotlist *new_grp;
1331 char *label, *url;
1332
1333 current_group = grp;
1334
1335 while ((tkn = hot_next_token ()) != TKN_ENDGROUP)
1336 switch (tkn)
1337 {
1338 case TKN_GROUP:
1339 CHECK_TOKEN (TKN_STRING);
1340 new_grp =
1341 add2hotlist (g_strndup (tkn_buf->str, tkn_buf->len), 0, HL_TYPE_GROUP,
1342 LISTBOX_APPEND_AT_END);
1343 SKIP_TO_EOL;
1344 hot_load_group (new_grp);
1345 current_group = grp;
1346 break;
1347 case TKN_ENTRY:
1348 {
1349 CHECK_TOKEN (TKN_STRING);
1350 label = g_strndup (tkn_buf->str, tkn_buf->len);
1351 CHECK_TOKEN (TKN_URL);
1352 CHECK_TOKEN (TKN_STRING);
1353 url = tilde_expand (tkn_buf->str);
1354 add2hotlist (label, url, HL_TYPE_ENTRY, LISTBOX_APPEND_AT_END);
1355 SKIP_TO_EOL;
1356 }
1357 break;
1358 case TKN_COMMENT:
1359 label = g_strndup (tkn_buf->str, tkn_buf->len);
1360 add2hotlist (label, 0, HL_TYPE_COMMENT, LISTBOX_APPEND_AT_END);
1361 break;
1362 case TKN_EOF:
1363 hotlist_state.readonly = TRUE;
1364 hotlist_state.file_error = TRUE;
1365 return;
1366 case TKN_EOL:
1367
1368 break;
1369 default:
1370 hotlist_state.readonly = TRUE;
1371 hotlist_state.file_error = TRUE;
1372 SKIP_TO_EOL;
1373 break;
1374 }
1375 SKIP_TO_EOL;
1376 }
1377
1378
1379
1380 static void
1381 hot_load_file (struct hotlist *grp)
1382 {
1383 int tkn;
1384 struct hotlist *new_grp;
1385 char *label, *url;
1386
1387 current_group = grp;
1388
1389 while ((tkn = hot_next_token ()) != TKN_EOF)
1390 switch (tkn)
1391 {
1392 case TKN_GROUP:
1393 CHECK_TOKEN (TKN_STRING);
1394 new_grp =
1395 add2hotlist (g_strndup (tkn_buf->str, tkn_buf->len), 0, HL_TYPE_GROUP,
1396 LISTBOX_APPEND_AT_END);
1397 SKIP_TO_EOL;
1398 hot_load_group (new_grp);
1399 current_group = grp;
1400 break;
1401 case TKN_ENTRY:
1402 {
1403 CHECK_TOKEN (TKN_STRING);
1404 label = g_strndup (tkn_buf->str, tkn_buf->len);
1405 CHECK_TOKEN (TKN_URL);
1406 CHECK_TOKEN (TKN_STRING);
1407 url = tilde_expand (tkn_buf->str);
1408 add2hotlist (label, url, HL_TYPE_ENTRY, LISTBOX_APPEND_AT_END);
1409 SKIP_TO_EOL;
1410 }
1411 break;
1412 case TKN_COMMENT:
1413 label = g_strndup (tkn_buf->str, tkn_buf->len);
1414 add2hotlist (label, 0, HL_TYPE_COMMENT, LISTBOX_APPEND_AT_END);
1415 break;
1416 case TKN_EOL:
1417
1418 break;
1419 default:
1420 hotlist_state.readonly = TRUE;
1421 hotlist_state.file_error = TRUE;
1422 SKIP_TO_EOL;
1423 break;
1424 }
1425 }
1426
1427
1428
1429 static void
1430 clean_up_hotlist_groups (const char *section)
1431 {
1432 char *grp_section;
1433
1434 grp_section = g_strconcat (section, ".Group", (char *) NULL);
1435 if (mc_config_has_group (mc_global.main_config, section))
1436 mc_config_del_group (mc_global.main_config, section);
1437
1438 if (mc_config_has_group (mc_global.main_config, grp_section))
1439 {
1440 char **profile_keys, **keys;
1441
1442 keys = mc_config_get_keys (mc_global.main_config, grp_section, NULL);
1443
1444 for (profile_keys = keys; *profile_keys != NULL; profile_keys++)
1445 clean_up_hotlist_groups (*profile_keys);
1446
1447 g_strfreev (keys);
1448 mc_config_del_group (mc_global.main_config, grp_section);
1449 }
1450 g_free (grp_section);
1451 }
1452
1453
1454
1455 static void
1456 load_hotlist (void)
1457 {
1458 gboolean remove_old_list = FALSE;
1459 struct stat stat_buf;
1460
1461 if (hotlist_state.loaded)
1462 {
1463 stat (hotlist_file_name, &stat_buf);
1464 if (hotlist_file_mtime < stat_buf.st_mtime)
1465 done_hotlist ();
1466 else
1467 return;
1468 }
1469
1470 if (hotlist_file_name == NULL)
1471 hotlist_file_name = mc_config_get_full_path (MC_HOTLIST_FILE);
1472
1473 hotlist = g_new0 (struct hotlist, 1);
1474 hotlist->type = HL_TYPE_GROUP;
1475 hotlist->label = g_strdup (_("Top level group"));
1476 hotlist->up = hotlist;
1477
1478
1479
1480 hotlist->directory = g_strdup ("Hotlist");
1481
1482 hotlist_file = fopen (hotlist_file_name, "r");
1483 if (hotlist_file == NULL)
1484 {
1485 int result;
1486
1487 load_group (hotlist);
1488 hotlist_state.loaded = TRUE;
1489
1490
1491
1492 hotlist_state.modified = TRUE;
1493 result = save_hotlist ();
1494 hotlist_state.modified = FALSE;
1495 if (result != 0)
1496 remove_old_list = TRUE;
1497 else
1498 message (D_ERROR, _("Hotlist Load"),
1499 _
1500 ("MC was unable to write %s file,\nyour old hotlist entries were not deleted"),
1501 MC_USERCONF_DIR PATH_SEP_STR MC_HOTLIST_FILE);
1502 }
1503 else
1504 {
1505 hot_load_file (hotlist);
1506 fclose (hotlist_file);
1507 hotlist_state.loaded = TRUE;
1508 }
1509
1510 if (remove_old_list)
1511 {
1512 GError *mcerror = NULL;
1513
1514 clean_up_hotlist_groups ("Hotlist");
1515 if (!mc_config_save_file (mc_global.main_config, &mcerror))
1516 setup_save_config_show_error (mc_global.main_config->ini_path, &mcerror);
1517
1518 mc_error_message (&mcerror, NULL);
1519 }
1520
1521 stat (hotlist_file_name, &stat_buf);
1522 hotlist_file_mtime = stat_buf.st_mtime;
1523 current_group = hotlist;
1524 }
1525
1526
1527
1528 static void
1529 hot_save_group (struct hotlist *grp)
1530 {
1531 struct hotlist *current;
1532 int i;
1533 char *s;
1534
1535 #define INDENT(n) \
1536 do { \
1537 for (i = 0; i < n; i++) \
1538 putc (' ', hotlist_file); \
1539 } while (0)
1540
1541 for (current = grp->head; current != NULL; current = current->next)
1542 switch (current->type)
1543 {
1544 case HL_TYPE_GROUP:
1545 INDENT (list_level);
1546 fputs ("GROUP \"", hotlist_file);
1547 for (s = current->label; *s != '\0'; s++)
1548 {
1549 if (*s == '"' || *s == '\\')
1550 putc ('\\', hotlist_file);
1551 putc (*s, hotlist_file);
1552 }
1553 fputs ("\"\n", hotlist_file);
1554 list_level += 2;
1555 hot_save_group (current);
1556 list_level -= 2;
1557 INDENT (list_level);
1558 fputs ("ENDGROUP\n", hotlist_file);
1559 break;
1560 case HL_TYPE_ENTRY:
1561 INDENT (list_level);
1562 fputs ("ENTRY \"", hotlist_file);
1563 for (s = current->label; *s != '\0'; s++)
1564 {
1565 if (*s == '"' || *s == '\\')
1566 putc ('\\', hotlist_file);
1567 putc (*s, hotlist_file);
1568 }
1569 fputs ("\" URL \"", hotlist_file);
1570 for (s = current->directory; *s != '\0'; s++)
1571 {
1572 if (*s == '"' || *s == '\\')
1573 putc ('\\', hotlist_file);
1574 putc (*s, hotlist_file);
1575 }
1576 fputs ("\"\n", hotlist_file);
1577 break;
1578 case HL_TYPE_COMMENT:
1579 fprintf (hotlist_file, "#%s\n", current->label);
1580 break;
1581 case HL_TYPE_DOTDOT:
1582
1583 break;
1584 default:
1585 break;
1586 }
1587 }
1588
1589
1590
1591 static void
1592 add_dotdot_to_list (void)
1593 {
1594 if (current_group != hotlist && hotlist_has_dot_dot)
1595 add2hotlist (g_strdup (".."), g_strdup (".."), HL_TYPE_DOTDOT, LISTBOX_APPEND_AT_END);
1596 }
1597
1598
1599
1600
1601
1602 void
1603 add2hotlist_cmd (WPanel * panel)
1604 {
1605 char *lc_prompt;
1606 const char *cp = N_("Label for \"%s\":");
1607 int l;
1608 char *label_string, *label;
1609
1610 #ifdef ENABLE_NLS
1611 cp = _(cp);
1612 #endif
1613
1614
1615 our_panel = panel;
1616
1617 l = str_term_width1 (cp);
1618 label_string = vfs_path_to_str_flags (panel->cwd_vpath, 0, VPF_STRIP_PASSWORD);
1619 lc_prompt = g_strdup_printf (cp, str_trunc (label_string, COLS - 2 * UX - (l + 8)));
1620 label =
1621 input_dialog (_("Add to hotlist"), lc_prompt, MC_HISTORY_HOTLIST_ADD, label_string,
1622 INPUT_COMPLETE_NONE);
1623 g_free (lc_prompt);
1624
1625 if (label == NULL || *label == '\0')
1626 {
1627 g_free (label_string);
1628 g_free (label);
1629 }
1630 else
1631 {
1632 add2hotlist (label, label_string, HL_TYPE_ENTRY, LISTBOX_APPEND_AT_END);
1633 hotlist_state.modified = TRUE;
1634 }
1635 }
1636
1637
1638
1639 char *
1640 hotlist_show (hotlist_t list_type, WPanel * panel)
1641 {
1642 char *target = NULL;
1643 int res;
1644
1645
1646 our_panel = panel;
1647
1648 hotlist_state.type = list_type;
1649 load_hotlist ();
1650
1651 init_hotlist (list_type);
1652
1653
1654 tty_setcolor (SELECTED_COLOR);
1655
1656 hotlist_state.running = TRUE;
1657 res = dlg_run (hotlist_dlg);
1658 hotlist_state.running = FALSE;
1659 save_hotlist ();
1660
1661 if (res == B_ENTER)
1662 {
1663 char *text = NULL;
1664 struct hotlist *hlp = NULL;
1665
1666 listbox_get_current (l_hotlist, &text, (void **) &hlp);
1667 target = g_strdup (hlp != NULL ? hlp->directory : text);
1668 }
1669
1670 hotlist_done ();
1671 return target;
1672 }
1673
1674
1675
1676 gboolean
1677 save_hotlist (void)
1678 {
1679 gboolean saved = FALSE;
1680 struct stat stat_buf;
1681
1682 if (!hotlist_state.readonly && hotlist_state.modified && hotlist_file_name != NULL)
1683 {
1684 mc_util_make_backup_if_possible (hotlist_file_name, ".bak");
1685
1686 hotlist_file = fopen (hotlist_file_name, "w");
1687 if (hotlist_file == NULL)
1688 mc_util_restore_from_backup_if_possible (hotlist_file_name, ".bak");
1689 else
1690 {
1691 hot_save_group (hotlist);
1692 fclose (hotlist_file);
1693 stat (hotlist_file_name, &stat_buf);
1694 hotlist_file_mtime = stat_buf.st_mtime;
1695 hotlist_state.modified = FALSE;
1696 saved = TRUE;
1697 }
1698 }
1699
1700 return saved;
1701 }
1702
1703
1704
1705
1706
1707
1708
1709 void
1710 done_hotlist (void)
1711 {
1712 if (hotlist != NULL)
1713 {
1714 remove_group (hotlist);
1715 g_free (hotlist->label);
1716 g_free (hotlist->directory);
1717 MC_PTR_FREE (hotlist);
1718 }
1719
1720 hotlist_state.loaded = FALSE;
1721
1722 MC_PTR_FREE (hotlist_file_name);
1723 l_hotlist = NULL;
1724 current_group = NULL;
1725
1726 if (tkn_buf != NULL)
1727 {
1728 g_string_free (tkn_buf, TRUE);
1729 tkn_buf = NULL;
1730 }
1731 }
1732
1733