Ticket #2979: 1_bookmarks_3.patch

File 1_bookmarks_3.patch, 28.8 KB (added by aurel, 7 years ago)
  • lib/keybind.c

    diff -r -u -p mc-4.8.18.orig/lib/keybind.c mc-4.8.18/lib/keybind.c
    old new static name_keymap_t command_names[] = { 
    290290    {"SpellCheckCurrentWord", CK_SpellCheckCurrentWord}, 
    291291    {"SpellCheckSelectLang", CK_SpellCheckSelectLang}, 
    292292#endif /* HAVE_ASPELL */ 
     293    {"BookmarkList", CK_BookmarkList}, 
    293294    {"BookmarkFlush", CK_BookmarkFlush}, 
    294295    {"BookmarkNext", CK_BookmarkNext}, 
    295296    {"BookmarkPrev", CK_BookmarkPrev}, 
  • lib/keybind.h

    diff -r -u -p mc-4.8.18.orig/lib/keybind.h mc-4.8.18/lib/keybind.h
    old new enum 
    246246    CK_BlockShiftRight, 
    247247    CK_DeleteLine, 
    248248    /* bookmarks */ 
     249    CK_BookmarkList, 
    249250    CK_BookmarkFlush, 
    250251    CK_BookmarkNext, 
    251252    CK_BookmarkPrev, 
  • misc/mc.default.keymap

    diff -r -u -p mc-4.8.18.orig/misc/mc.default.keymap mc-4.8.18/misc/mc.default.keymap
    old new ExternalCommand = alt-u 
    319319UserMenu = f11 
    320320Menu = f9 
    321321Bookmark = alt-k 
     322BookmarkList = alt-shift-k; alt-shift-j 
    322323BookmarkFlush = alt-o 
    323324BookmarkNext = alt-j 
    324325BookmarkPrev = alt-i 
  • misc/mc.emacs.keymap

    diff -r -u -p mc-4.8.18.orig/misc/mc.emacs.keymap mc-4.8.18/misc/mc.emacs.keymap
    old new ExternalCommand = alt-u 
    318318UserMenu = f11 
    319319Menu = f9 
    320320# Bookmark = 
     321# BookmarkList = 
    321322# BookmarkFlush = 
    322323# BookmarkNext = 
    323324# BookmarkPrev = 
  • src/editor/bookmark.c

    diff -r -u -p mc-4.8.18.orig/src/editor/bookmark.c mc-4.8.18/src/editor/bookmark.c
    old new  
    4444 
    4545#include "lib/global.h" 
    4646#include "lib/util.h"           /* MAX_SAVED_BOOKMARKS */ 
     47#include "lib/strutil.h" 
     48 
     49#include "lib/skin.h"           /* BOOK_MARK_COLOR ... */ 
     50#include "lib/tty/key.h"        /* KEY_M_CTRL */ 
     51#include "lib/tty/tty.h"        /* LINES, COLS */ 
     52 
     53#include "src/setup.h"          /* option_tab_spacing */ 
    4754 
    4855#include "editwidget.h" 
    4956 
     
    5360 
    5461/*** file scope type declarations ****************************************************************/ 
    5562 
     63typedef struct 
     64{ 
     65    edit_book_mark_t *mark; 
     66    char *text; 
     67    int detail_cols; 
     68    char *detail[4]; 
     69} list_entry_t; 
     70 
    5671/*** file scope variables ************************************************************************/ 
    5772 
    5873/*** file scope functions ************************************************************************/ 
    5974/* --------------------------------------------------------------------------------------------- */ 
     75static void list_add_entry (WEdit * edit, WListbox * list, edit_book_mark_t * book_mark, 
     76                            GString * buff, GString * detail); 
    6077 
    6178/** note, if there is more than one bookmark on a line, then they are 
    6279   appended after each other and the last one is always the one found 
    book_mark_find (WEdit * edit, long line) 
    135152    return NULL;                /* can't get here */ 
    136153} 
    137154 
     155#define UX 3 
     156#define UY 2 
     157 
     158#define DLG_H (LINES - 6) 
     159#define DLG_W (COLS > 86 ? 80 : COLS - 6) 
     160 
     161#define LABELS          3 
     162#define B_ADD_NEW       B_USER 
     163#define B_REMOVE        (B_USER + 1) 
     164#define B_FLUSH         (B_USER + 2) 
     165#define B_FILTER        (B_USER + 3) 
     166#define B_SORT          (B_USER + 4) 
     167#define B_REVERSE       (B_USER + 5) 
     168 
     169#define SORT_LINE 0 
     170#define SORT_FREQ 1 
     171#define SORT_ALPHA 2 
     172 
     173#define FILTER_NONE 0 
     174#define FILTER_BOOK 1 
     175#define FILTER_FOUND 2 
     176 
     177static WDialog *list_dlg; 
     178static WGroupbox *list_grp; 
     179static WListbox *list_box; 
     180static WLabel *list_detail; 
     181static WButton *list_sort; 
     182static WButton *list_filter; 
     183static struct 
     184{ 
     185    WEdit *edit; 
     186    GList *hidden; 
     187    int filter;                 /* find/bookmark/all */ 
     188    int sort;                   /* sort by line num/usage/alpha */ 
     189    gboolean reverse;           /* reverse sort */ 
     190} list_cfg = 
     191{ 
     192    /* *INDENT-OFF* */ 
     193    NULL, NULL, FILTER_NONE, SORT_LINE, FALSE 
     194    /* *INDENT-ON* */ 
     195}; 
     196 
     197static struct 
     198{ 
     199    int ret_cmd, flags, y, x, len; 
     200    const char *text; 
     201    widget_pos_flags_t pos_flags; 
     202} list_btn[] = 
     203{ 
     204    /* *INDENT-OFF* */ 
     205    { B_ENTER, DEFPUSH_BUTTON, 0, 0, 0, N_("&Go to"), 
     206            WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM }, 
     207    { B_ADD_NEW, NORMAL_BUTTON, 0, 12, 0, N_("&Add"), 
     208            WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM }, 
     209    { B_REMOVE, NORMAL_BUTTON, 0, 20, 0, N_("&Remove"), 
     210            WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM }, 
     211    { B_FLUSH, NORMAL_BUTTON, 0, 31, 0, N_("Fl&ush"), 
     212            WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM }, 
     213    { B_CANCEL, NORMAL_BUTTON, 0, -16, 0, N_("&Cancel"), 
     214            WPOS_KEEP_RIGHT | WPOS_KEEP_BOTTOM }, 
     215    { B_FILTER, NORMAL_BUTTON, 1, 0, 0, N_("&Filter"), 
     216            WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM }, 
     217    { B_SORT, NORMAL_BUTTON, 1, 11, 0, N_("&Sort"), 
     218            WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM }, 
     219    { B_REVERSE, NORMAL_BUTTON, 1, 20, 0, N_("Re&verse"), 
     220            WPOS_KEEP_LEFT | WPOS_KEEP_BOTTOM }, 
     221    /* *INDENT-ON* */ 
     222}; 
     223 
     224static const size_t list_btn_num = G_N_ELEMENTS (list_btn); 
     225 
     226/* --------------------------------------------------------------------------------------------- */ 
     227 
     228static void 
     229list_entry_free2 (list_entry_t * entry) 
     230{ 
     231    g_free (entry->text); 
     232    g_free (entry->detail[0]); 
     233    g_free (entry->detail[1]); 
     234    g_free (entry->detail[2]); 
     235    g_free (entry); 
     236} 
     237 
     238static gint 
     239list_sort_alpha (gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer user_data) 
     240{ 
     241    return strcmp (((list_entry_t *) ((WLEntry *) a)->data)->text, 
     242                   ((list_entry_t *) ((WLEntry *) b)->data)->text); 
     243} 
     244 
     245static gint 
     246list_sort_freq (gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer user_data) 
     247{ 
     248    int afreq = ((list_entry_t *) ((WLEntry *) a)->data)->mark->freq; 
     249    int bfreq = ((list_entry_t *) ((WLEntry *) b)->data)->mark->freq; 
     250    return afreq > bfreq ? 1 : (afreq < bfreq ? -1 : 0); 
     251} 
     252 
     253static gint 
     254list_sort_line (gconstpointer a, gconstpointer b, G_GNUC_UNUSED gpointer user_data) 
     255{ 
     256    int aline = ((list_entry_t *) ((WLEntry *) a)->data)->mark->line; 
     257    int bline = ((list_entry_t *) ((WLEntry *) b)->data)->mark->line; 
     258    return aline > bline ? 1 : (aline < bline ? -1 : 0); 
     259} 
     260 
     261static void 
     262list_filter_none (void) 
     263{ 
     264    if (!list_box->list || !list_cfg.hidden) 
     265        return; 
     266 
     267    for (; list_cfg.hidden;) 
     268    { 
     269        GList *next = list_cfg.hidden->next; 
     270        list_cfg.hidden->next = list_cfg.hidden->prev = NULL; 
     271        g_queue_push_tail_link(list_box->list, list_cfg.hidden); 
     272        list_cfg.hidden = next; 
     273    } 
     274} 
     275 
     276static void 
     277list_filter_color (int color) 
     278{ 
     279    guint i, length; 
     280 
     281    list_filter_none (); 
     282 
     283    if (!list_box->list || color == -1) 
     284        return; 
     285 
     286    length = g_queue_get_length(list_box->list); 
     287    for (i = 0; i < length;) 
     288    { 
     289        GList *entry = g_queue_peek_nth_link (list_box->list, i); 
     290        if (!entry) 
     291            continue; 
     292 
     293        if (((list_entry_t *) ((WLEntry *) entry->data)->data)->mark->c != color) 
     294        { 
     295            GList *entry_to_hide = g_queue_pop_nth_link (list_box->list, i); 
     296            list_cfg.hidden = g_list_concat (list_cfg.hidden, entry_to_hide); 
     297            length--; 
     298        } 
     299        else 
     300            i++; 
     301    } 
     302 
     303    // listbox_refresh_list (list_box, list); 
     304} 
     305 
     306/* --------------------------------------------------------------------------------------------- */ 
     307 
     308static void 
     309update_detail (void) 
     310{ 
     311    list_entry_t *entry; 
     312    WListbox *list = list_box; 
     313 
     314    if (list_box->list && g_queue_get_length(list_box->list) != 0) 
     315    { 
     316        char *ctext = NULL; 
     317 
     318        listbox_get_current (list, &ctext, (void **) &entry); 
     319        if (list->widget.cols != entry->detail_cols) 
     320        { 
     321            GString *buff = g_string_new (""); 
     322            g_string_append (buff, str_trunc (entry->detail[0], list->widget.cols - 1)); 
     323            g_string_append (buff, "\n"); 
     324            g_string_append (buff, str_trunc (entry->detail[1], list->widget.cols - 1)); 
     325            g_string_append (buff, "\n"); 
     326            g_string_append (buff, str_trunc (entry->detail[2], list->widget.cols - 1)); 
     327            g_free (entry->detail[3]); 
     328            entry->detail[3] = g_strdup (buff->str); 
     329            entry->detail_cols = list->widget.cols; 
     330        } 
     331        label_set_text (list_detail, entry->detail[3]); 
     332    } 
     333} 
     334 
     335/* --------------------------------------------------------------------------------------------- */ 
     336 
     337static void 
     338update_list_title (void) 
     339{ 
     340    GString *buff = g_string_new (_("Bookmarks")); 
     341 
     342    if (list_cfg.sort != SORT_LINE || list_cfg.reverse) 
     343    { 
     344        g_string_append (buff, _(" - Sort: ")); 
     345        g_string_append (buff, 
     346                         list_cfg.sort == SORT_ALPHA ? _("ABC") : list_cfg.sort == 
     347                         SORT_LINE ? "" : _("FRQ")); 
     348        g_string_append (buff, list_cfg.reverse ? " v" : " ^"); 
     349    } 
     350    if (list_cfg.filter != FILTER_NONE) 
     351    { 
     352        g_string_append (buff, _(" - Filter: ")); 
     353        g_string_append (buff, list_cfg.filter == FILTER_FOUND ? _("FOUND") : _("USER")); 
     354    } 
     355    groupbox_set_title (list_grp, str_trunc (buff->str, list_box->widget.cols - 4)); 
     356    g_string_free (buff, TRUE); 
     357} 
     358 
     359/* --------------------------------------------------------------------------------------------- */ 
     360 
     361static int 
     362list_button_callback (WButton * button, int action) 
     363{ 
     364    list_entry_t *entry = NULL; 
     365    WEdit *edit = list_cfg.edit; 
     366 
     367    (void) button; 
     368 
     369    switch (action) 
     370    { 
     371    case B_REMOVE: 
     372        { 
     373            listbox_get_current (list_box, NULL, (void **) &entry); 
     374            if (entry != NULL) 
     375            { 
     376                book_mark_clear (edit, entry->mark->line, entry->mark->c); 
     377                list_entry_free2 (entry); 
     378                /* now remove list entry from screen */ 
     379                listbox_remove_current (list_box); 
     380            } 
     381        } 
     382        edit_update_screen (edit); 
     383        dlg_redraw (list_dlg); 
     384        break; 
     385 
     386    case B_FLUSH: 
     387        { 
     388            while (list_box->list && g_queue_get_length(list_box->list)) 
     389            { 
     390                GList *list = g_queue_pop_head_link(list_box->list); 
     391                entry = (list_entry_t *) ((WLEntry *) list->data)->data; 
     392                book_mark_clear (edit, entry->mark->line, entry->mark->c); 
     393                list_entry_free2 (entry); 
     394            } 
     395            listbox_set_list (list_box, NULL); 
     396        } 
     397        edit_update_screen (edit); 
     398        dlg_redraw (list_dlg); 
     399        break; 
     400 
     401    case B_ADD_NEW: 
     402        if (!book_mark_query_color (edit, edit->curs_row, BOOK_MARK_FOUND_COLOR) && 
     403            !book_mark_query_color (edit, edit->curs_row, BOOK_MARK_COLOR)) 
     404        { 
     405            edit_book_mark_t *book_mark; 
     406            long int line = edit->curs_row; 
     407            GString *buff = g_string_new (""); 
     408            GString *detail = g_string_new (""); 
     409 
     410            book_mark_insert (edit, edit->curs_row, BOOK_MARK_COLOR); 
     411            book_mark = book_mark_find (edit, edit->curs_row); 
     412            list_add_entry (list_cfg.edit, list_box, book_mark, buff, detail); 
     413            g_string_free (buff, 1); 
     414            g_string_free (detail, 1); 
     415            g_queue_sort (list_box->list, 
     416                          list_cfg.sort == 2 ? 
     417                              list_sort_alpha : 
     418                              (list_cfg.sort == 0 ? 
     419                                   list_sort_line : 
     420                                   list_sort_freq), 
     421                          NULL); 
     422            if (edit->curs_row < line) 
     423                edit_move_down (edit, line - edit->curs_row, FALSE); 
     424            else 
     425                edit_move_up (edit, edit->curs_row - line, FALSE); 
     426        } 
     427        edit_update_screen (edit); 
     428        dlg_redraw (list_dlg); 
     429        break; 
     430 
     431    case B_ENTER: 
     432        { 
     433            return 1; 
     434        } 
     435 
     436    case B_FILTER: 
     437        { 
     438            if (++list_cfg.filter > FILTER_FOUND) 
     439                list_cfg.filter = FILTER_NONE; 
     440            if (list_cfg.filter == FILTER_FOUND) 
     441                list_filter_color (BOOK_MARK_FOUND_COLOR); 
     442            else if (list_cfg.filter == FILTER_NONE) 
     443                list_filter_color (-1); 
     444            else 
     445                list_filter_color (BOOK_MARK_COLOR); 
     446            update_list_title (); 
     447        } 
     448        break; 
     449 
     450    case B_SORT: 
     451        if (++list_cfg.sort > SORT_ALPHA) 
     452            list_cfg.sort = SORT_LINE; 
     453        if (list_box->list) 
     454            g_queue_sort (list_box->list, 
     455                          list_cfg.sort == SORT_ALPHA ? 
     456                              list_sort_alpha : 
     457                              (list_cfg.sort == SORT_LINE ? 
     458                               list_sort_line : 
     459                               list_sort_freq), 
     460                          NULL); 
     461        // listbox_refresh_list (list_box, list_box->list); 
     462        update_list_title (); 
     463        break; 
     464 
     465    case B_REVERSE: 
     466        list_cfg.reverse = !list_cfg.reverse; 
     467        if (list_box->list) 
     468            g_queue_reverse (list_box->list); 
     469        // listbox_refresh_list (list_box, list_box->list); 
     470        update_list_title (); 
     471        break; 
     472 
     473    default: 
     474        return 1; 
     475    } 
     476 
     477    return 0; 
     478} 
     479 
     480/* --------------------------------------------------------------------------------------------- */ 
     481 
     482static inline cb_ret_t 
     483list_handle_key (WDialog * h, int key) 
     484{ 
     485    switch (key) 
     486    { 
     487    case KEY_M_CTRL | '\n': 
     488        goto l1; 
     489 
     490    case '\n': 
     491    case KEY_ENTER: 
     492    case KEY_RIGHT: 
     493        if (list_button_callback (NULL, B_ENTER) != 0) 
     494        { 
     495            h->ret_value = B_ENTER; 
     496            dlg_stop (h); 
     497        } 
     498        return MSG_HANDLED; 
     499 
     500    case KEY_IC: 
     501    case KEY_KP_ADD: 
     502    case '+': 
     503        list_button_callback (NULL, B_ADD_NEW); 
     504        return MSG_HANDLED; 
     505 
     506    case KEY_DC: 
     507    case KEY_BACKSPACE: 
     508    case KEY_KP_SUBTRACT: 
     509    case '-': 
     510        list_button_callback (NULL, B_REMOVE); 
     511        return MSG_HANDLED; 
     512 
     513      l1: 
     514    case ALT ('\n'): 
     515    case ALT ('\r'): 
     516        { 
     517            void *ldata = NULL; 
     518 
     519            listbox_get_current (list_box, NULL, &ldata); 
     520 
     521            if (ldata != NULL) 
     522            { 
     523            } 
     524        } 
     525        return MSG_HANDLED;     /* ignore key */ 
     526 
     527    default: 
     528        return MSG_NOT_HANDLED; 
     529    } 
     530} 
     531 
     532/* --------------------------------------------------------------------------------------------- */ 
     533 
     534static cb_ret_t 
     535list_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data) 
     536{ 
     537    WDialog *h = DIALOG (w); 
     538 
     539    switch (msg) 
     540    { 
     541    case MSG_UNHANDLED_KEY: 
     542        return list_handle_key (h, parm); 
     543 
     544    case MSG_POST_KEY: 
     545        widget_select (WIDGET (list_box)); 
     546 
     547        /* always stay on hotlist */ 
     548        /* fall through */ 
     549 
     550    case MSG_INIT: 
     551        update_detail (); 
     552        update_list_title (); 
     553        return MSG_HANDLED; 
     554 
     555    case MSG_RESIZE: 
     556        /* simply call dlg_set_size() with new size */ 
     557        dlg_set_size (h, DLG_H, DLG_W); 
     558        update_detail (); 
     559        update_list_title (); 
     560        return MSG_HANDLED; 
     561 
     562    default: 
     563        return dlg_default_callback (w, sender, msg, parm, data); 
     564    } 
     565} 
     566 
     567/* --------------------------------------------------------------------------------------------- */ 
     568 
     569static lcback_ret_t 
     570list_listbox_callback (WListbox * list) 
     571{ 
     572    WDialog *dlg = WIDGET (list)->owner; 
     573 
     574    if (list->list && g_queue_get_length(list->list) != 0) 
     575    { 
     576        void *data = NULL; 
     577 
     578        listbox_get_current (list, NULL, &data); 
     579 
     580        if (data == NULL) 
     581        { 
     582            dlg->ret_value = B_ENTER; 
     583            dlg_stop (dlg); 
     584            return LISTBOX_DONE; 
     585        } 
     586    } 
     587 
     588    return LISTBOX_CONT; 
     589} 
     590 
     591/* --------------------------------------------------------------------------------------------- */ 
     592 
     593static void 
     594fill_line_listbox (WEdit * edit, int skip_sp, GString * buff) 
     595{ 
     596    off_t off; 
     597    int cw = 1, c = -1; 
     598 
     599    off = edit_buffer_get_current_bol (&edit->buffer); 
     600    while (c != '\r' && c != '\n' && c != 0) 
     601    { 
     602#ifdef HAVE_CHARSET 
     603        if (edit->utf8) 
     604        { 
     605            c = edit_buffer_get_utf (&edit->buffer, off, &cw); 
     606            if (cw < 1) 
     607                cw = 1; 
     608            if (skip_sp && c != ' ' && c != '\t') 
     609                skip_sp = 0; 
     610            if (c != '\r' && c != '\n' && c != 0 && !skip_sp) 
     611            { 
     612                /* convert TAB to spaces */ 
     613                if (c == '\t') 
     614                { 
     615                    for (c = option_tab_spacing; c > 1; c--) 
     616                        g_string_append_unichar (buff, ' '); 
     617                    c = ' '; 
     618                } 
     619                g_string_append_unichar (buff, c); 
     620            } 
     621        } 
     622        else 
     623#endif 
     624        { 
     625            c = edit_buffer_get_byte (&edit->buffer, off); 
     626            if (skip_sp && c != ' ' && c != '\t') 
     627                skip_sp = 0; 
     628            if (c != '\r' && c != '\n' && c != 0 && !skip_sp) 
     629            { 
     630                /* convert TAB to spaces */ 
     631                if (c == '\t') 
     632                { 
     633                    for (c = option_tab_spacing; c > 1; c--) 
     634                        g_string_append_c (buff, ' '); 
     635                    c = ' '; 
     636                } 
     637                g_string_append_c (buff, c); 
     638            } 
     639        } 
     640        off += cw; 
     641    } 
     642} 
     643 
     644/* --------------------------------------------------------------------------------------------- */ 
     645/* 
     646 * Copy&Paste (and rewrite) from filemanager/hotlsist.c 
     647 */ 
     648/** 
     649 * Expands all button names (once) and recalculates button positions. 
     650 * returns number of columns in the dialog box, which is 10 chars longer 
     651 * then buttonbar. 
     652 * 
     653 * If common width of the window (i.e. in xterm) is less than returned 
     654 * width - sorry :)  (anyway this did not handled in previous version too) 
     655 */ 
     656 
     657static void 
     658init_i18n_stuff (int cols) 
     659{ 
     660    size_t i; 
     661 
     662    static gboolean i18n_flag = FALSE; 
     663    int curr_x = 0; 
     664    int curr_minus_x = cols - 5; 
     665 
     666    if (!i18n_flag) 
     667    { 
     668        for (i = 0; i < list_btn_num; i++) 
     669        { 
     670#ifdef ENABLE_NLS 
     671            list_btn[i].text = _(list_btn[i].text); 
     672#endif /* ENABLE_NLS */ 
     673            list_btn[i].len = str_term_width1 (list_btn[i].text) + 3; 
     674            if (list_btn[i].flags == DEFPUSH_BUTTON) 
     675                list_btn[i].len += 2; 
     676            /* reset current X at line start */ 
     677            if (list_btn[i].x == 0) 
     678            { 
     679                curr_x = 0; 
     680                curr_minus_x = cols - 5; 
     681            } 
     682            if (list_btn[i].x >= 0) 
     683            { 
     684                list_btn[i].x = curr_x; 
     685                curr_x += list_btn[i].len + 1; 
     686            } 
     687            else if (list_btn[i].x < 0) 
     688            { 
     689                curr_minus_x -= list_btn[i].len + 1; 
     690                list_btn[i].x = curr_minus_x; 
     691            } 
     692        } 
     693 
     694        i18n_flag = TRUE; 
     695    } 
     696} 
     697 
     698/* --------------------------------------------------------------------------------------------- */ 
     699 
     700static void 
     701list_add_entry (WEdit * edit, WListbox * list, edit_book_mark_t * book_mark, GString * buff, 
     702                GString * detail) 
     703{ 
     704    list_entry_t *entry; 
     705 
     706    entry = g_malloc (sizeof (list_entry_t)); 
     707    g_string_truncate (buff, 0); 
     708    g_string_truncate (detail, 0); 
     709 
     710    fill_line_listbox (edit, 1, buff); 
     711    fill_line_listbox (edit, 0, detail); 
     712    entry->detail[1] = g_strdup (detail->str); 
     713    g_string_truncate (detail, 0); 
     714 
     715    if (book_mark->line != 0) 
     716    { 
     717        edit_move_up (edit, 1, FALSE); 
     718        fill_line_listbox (edit, 0, detail); 
     719    } 
     720    entry->detail[0] = g_strdup (detail->str); 
     721    g_string_truncate (detail, 0); 
     722 
     723    if (book_mark->line != edit->buffer.lines) 
     724    { 
     725        edit_move_down (edit, (book_mark->line == 0) ? 1 : 2, FALSE); 
     726        fill_line_listbox (edit, 0, detail); 
     727    } 
     728    entry->detail[2] = g_strdup (detail->str); 
     729    entry->detail[3] = g_strdup (""); 
     730    entry->detail_cols = -1; 
     731 
     732    entry->text = g_strndup (buff->str, 80); 
     733    entry->mark = book_mark; 
     734    g_string_printf (buff, "% 6ld [%c/%d] -> %s", book_mark->line + 1, 
     735                     book_mark->c == BOOK_MARK_FOUND_COLOR ? 'F' : 'U', book_mark->freq, 
     736                     str_trunc (buff->str, list->widget.cols - 1)); 
     737    listbox_add_item (list, LISTBOX_APPEND_AT_END, 0, buff->str, entry, FALSE); 
     738} 
     739 
     740/* --------------------------------------------------------------------------------------------- */ 
     741 
     742static void 
     743fill_list_box (WEdit * edit, WListbox * list) 
     744{ 
     745    edit_book_mark_t *book_mark; 
     746    GString *detail; 
     747    GString *buff; 
     748    long int curs_line = edit->buffer.curs_line; 
     749 
     750    buff = g_string_new (""); 
     751    detail = g_string_new (""); 
     752    // edit_bol (edit, edit->curs1); // ??? Is it needed? 
     753 
     754    for (book_mark = book_mark_find (edit, 0); book_mark != NULL; book_mark = book_mark->next) 
     755    { 
     756        if (book_mark->line == -1) 
     757            continue; 
     758        if (edit->buffer.curs_line == book_mark->line) 
     759            ; 
     760        else if (edit->buffer.curs_line < book_mark->line) 
     761            edit_move_down (edit, book_mark->line - edit->buffer.curs_line, FALSE); 
     762        else 
     763            edit_move_up (edit, edit->buffer.curs_line - book_mark->line, FALSE); 
     764 
     765        list_add_entry (edit, list, book_mark, buff, detail); 
     766    } 
     767    if (edit->buffer.curs_line < curs_line) 
     768        edit_move_down (edit, curs_line - edit->buffer.curs_line, FALSE); 
     769    else 
     770        edit_move_up (edit, edit->buffer.curs_line - curs_line, FALSE); 
     771    g_string_free (buff, TRUE); 
     772    g_string_free (detail, TRUE); 
     773} 
     774 
     775/* --------------------------------------------------------------------------------------------- */ 
     776 
     777static void 
     778list_init (WEdit * edit) 
     779{ 
     780    size_t i; 
     781    const char *title, *help_node; 
     782    int lines, cols; 
     783    int y; 
     784    int dh = 0; 
     785    WGroupbox *dtl_box; 
     786    Widget *list_widget; 
     787 
     788    do_refresh (); 
     789 
     790    lines = DLG_H; 
     791    cols = DLG_W; 
     792    init_i18n_stuff (cols); 
     793 
     794    title = _("Bookmark list"); 
     795    help_node = "[Bookmarklist]"; 
     796 
     797    list_cfg.hidden = NULL; 
     798    list_cfg.edit = edit; 
     799    list_dlg = 
     800        dlg_create (TRUE, 0, 0, lines, cols, 
     801                    WPOS_CENTER, FALSE, 
     802                    dialog_colors, list_callback, NULL, 
     803                    help_node, title); 
     804    y = UY; 
     805    list_grp = groupbox_new (y, UX, lines - 12 + dh, cols - 2 * UX, _("Bookmarks")); 
     806    list_widget = WIDGET (list_grp); 
     807    add_widget_autopos (list_dlg, list_widget, WPOS_KEEP_ALL, NULL); 
     808 
     809    list_box = 
     810        listbox_new (y + 1, UX + 1, list_widget->lines - 2, list_widget->cols - 2, FALSE, 
     811                     list_listbox_callback); 
     812 
     813    fill_list_box (edit, list_box); 
     814 
     815    /* insert before groupbox to view scrollbar */ 
     816    add_widget_autopos (list_dlg, list_box, WPOS_KEEP_ALL, NULL); 
     817 
     818    y += list_widget->lines; 
     819 
     820    dtl_box = groupbox_new (y, UX, 5, list_widget->cols, _("Bookmark detail")); 
     821    add_widget_autopos (list_dlg, dtl_box, WPOS_KEEP_BOTTOM | WPOS_KEEP_HORZ, NULL); 
     822 
     823    list_detail = label_new (y + 1, UX + 2, ""); 
     824    widget_set_size ((Widget *) list_detail, y + 1, UX + 2, 80, 3); 
     825    add_widget_autopos (list_dlg, list_detail, WPOS_KEEP_BOTTOM | WPOS_KEEP_LEFT, NULL); 
     826    y += WIDGET (dtl_box)->lines; 
     827 
     828    add_widget_autopos (list_dlg, hline_new (y++, -1, -1), WPOS_KEEP_BOTTOM, NULL); 
     829 
     830    for (i = 0; i < list_btn_num; i++) 
     831    { 
     832        WButton *btn; 
     833        if (list_btn[i].x < 0) 
     834            list_btn[i].x = cols + list_btn[i].x; 
     835        btn = button_new (y + list_btn[i].y, UX + list_btn[i].x, 
     836                          list_btn[i].ret_cmd, list_btn[i].flags, 
     837                          list_btn[i].text, list_button_callback); 
     838        if (i == 5) 
     839            list_filter = btn; 
     840        if (i == 6) 
     841            list_sort = btn; 
     842        add_widget_autopos (list_dlg, btn, list_btn[i].pos_flags, NULL); 
     843    } 
     844 
     845    widget_select (WIDGET (list_box)); 
     846} 
     847 
     848 
     849/* --------------------------------------------------------------------------------------------- */ 
     850 
     851static void 
     852list_entry_free (void *data) 
     853{ 
     854    list_entry_free2 (((WLEntry *) data)->data); 
     855} 
     856 
    138857/* --------------------------------------------------------------------------------------------- */ 
    139858/*** public functions ****************************************************************************/ 
    140859/* --------------------------------------------------------------------------------------------- */ 
    141860 
     861void 
     862book_mark_list_show (WEdit * edit) 
     863{ 
     864    int res; 
     865 
     866/*** Check list_box running...?? */ 
     867    list_init (edit); 
     868 
     869    res = dlg_run (list_dlg); 
     870    if (res == B_ENTER) 
     871    { 
     872        char *text; 
     873        list_entry_t *entry; 
     874 
     875        listbox_get_current (list_box, &text, (void **) &entry); 
     876        if (entry != NULL) 
     877        { 
     878            if (entry->mark->line >= edit->start_line + WIDGET (edit)->lines 
     879                || entry->mark->line < edit->start_line) 
     880                edit_move_display (edit, entry->mark->line - WIDGET (edit)->lines / 2); 
     881            edit_move_to_line (edit, entry->mark->line); 
     882            if (entry->mark->freq < 128 * 1024) 
     883                entry->mark->freq++; 
     884        } 
     885    } 
     886    g_queue_foreach (list_box->list, (GFunc) list_entry_free, NULL); 
     887    dlg_destroy (list_dlg); 
     888    list_cfg.edit = NULL; 
     889} 
     890 
    142891/**  
    143892 * Check if bookmark bookmark exists at this line of this color 
    144893 * 
    book_mark_insert (WEdit * edit, long lin 
    192941    q = g_new (edit_book_mark_t, 1); 
    193942    q->line = line; 
    194943    q->c = c; 
     944    q->freq = 0; 
    195945    q->next = p->next; 
    196946    /* insert into list */ 
    197947    q->prev = p; 
  • src/editor/edit.c

    diff -r -u -p mc-4.8.18.orig/src/editor/edit.c mc-4.8.18/src/editor/edit.c
    old new edit_execute_cmd (WEdit * edit, long com 
    37393739                if (p->line >= edit->start_line + w->lines || p->line < edit->start_line) 
    37403740                    edit_move_display (edit, p->line - w->lines / 2); 
    37413741                edit_move_to_line (edit, p->line); 
     3742                if (p->freq < 128*1024) 
     3743                    p->freq++; 
     3744                if (p->freq < 128*1024) 
     3745                    p->freq++; 
    37423746            } 
    37433747        } 
    37443748        break; 
     3749    case CK_BookmarkList: 
     3750        book_mark_list_show (edit); 
     3751        break; 
    37453752 
    37463753    case CK_Top: 
    37473754    case CK_MarkToFileBegin: 
  • src/editor/edit-impl.h

    diff -r -u -p mc-4.8.18.orig/src/editor/edit-impl.h mc-4.8.18/src/editor/edit-impl.h
    old new void book_mark_inc (WEdit * edit, long l 
    269269void book_mark_dec (WEdit * edit, long line); 
    270270void book_mark_serialize (WEdit * edit, int color); 
    271271void book_mark_restore (WEdit * edit, int color); 
     272void book_mark_list_show (WEdit * edit); 
    272273 
    273274gboolean edit_line_is_blank (WEdit * edit, long line); 
    274275gboolean is_break_char (char c); 
  • src/editor/editmenu.c

    diff -r -u -p mc-4.8.18.orig/src/editor/editmenu.c mc-4.8.18/src/editor/editmenu.c
    old new create_search_replace_menu (void) 
    135135    entries = g_list_prepend (entries, menu_entry_create (_("&Toggle bookmark"), CK_Bookmark)); 
    136136    entries = g_list_prepend (entries, menu_entry_create (_("&Next bookmark"), CK_BookmarkNext)); 
    137137    entries = g_list_prepend (entries, menu_entry_create (_("&Prev bookmark"), CK_BookmarkPrev)); 
     138    entries = g_list_prepend (entries, menu_entry_create (_("&List bookmarks"), CK_BookmarkList)); 
    138139    entries = g_list_prepend (entries, menu_entry_create (_("&Flush bookmarks"), CK_BookmarkFlush)); 
    139140 
    140141    return g_list_reverse (entries); 
  • src/editor/editwidget.h

    diff -r -u -p mc-4.8.18.orig/src/editor/editwidget.h mc-4.8.18/src/editor/editwidget.h
    old new struct edit_book_mark_t 
    3434{ 
    3535    long line;                  /* line number */ 
    3636    int c;                      /* color */ 
     37    int freq;                   /* usage freq */ 
    3738    edit_book_mark_t *next; 
    3839    edit_book_mark_t *prev; 
    3940}; 
  • src/keybind-defaults.c

    diff -r -u -p mc-4.8.18.orig/src/keybind-defaults.c mc-4.8.18/src/keybind-defaults.c
    old new static const global_keymap_ini_t default 
    403403    {"MatchBracket", "alt-b"}, 
    404404    {"ParagraphFormat", "alt-p"}, 
    405405    {"Bookmark", "alt-k"}, 
     406    {"BookmarkList", "alt-shift-k; alt-shift-j"}, 
    406407    {"BookmarkFlush", "alt-o"}, 
    407408    {"BookmarkNext", "alt-j"}, 
    408409    {"BookmarkPrev", "alt-i"},