Ticket #2979: mc.2979.diff

File mc.2979.diff, 29.4 KB (added by szaszg, 11 years ago)

a "filemanager:hotlist" like bookmark list dialog

  • lib/keybind.c

    diff --git a/lib/keybind.c b/lib/keybind.c
    index eedea6b..05e3088 100644
    a b static name_keymap_t command_names[] = { 
    286286    {"SpellCheckCurrentWord", CK_SpellCheckCurrentWord}, 
    287287    {"SpellCheckSelectLang", CK_SpellCheckSelectLang}, 
    288288#endif /* HAVE_ASPELL */ 
     289    {"BookmarkList", CK_BookmarkList}, 
    289290    {"BookmarkFlush", CK_BookmarkFlush}, 
    290291    {"BookmarkNext", CK_BookmarkNext}, 
    291292    {"BookmarkPrev", CK_BookmarkPrev}, 
  • lib/keybind.h

    diff --git a/lib/keybind.h b/lib/keybind.h
    index 5bfb81b..d945848 100644
    a b enum 
    242242    CK_BlockShiftRight, 
    243243    CK_DeleteLine, 
    244244    /* bookmarks */ 
     245    CK_BookmarkList, 
    245246    CK_BookmarkFlush, 
    246247    CK_BookmarkNext, 
    247248    CK_BookmarkPrev, 
  • lib/widget/listbox.c

    diff --git a/lib/widget/listbox.c b/lib/widget/listbox.c
    index 1bcda01..24a8722 100644
    a b listbox_remove_current (WListbox * l) 
    669669/* --------------------------------------------------------------------------------------------- */ 
    670670 
    671671void 
    672 listbox_set_list (WListbox * l, GList * list) 
     672listbox_refresh_list (WListbox * l, GList * list) 
    673673{ 
    674     listbox_remove_list (l); 
    675  
    676674    if (l != NULL) 
    677675    { 
    678676        l->list = list; 
    679         l->top = l->pos = 0; 
    680677        l->count = g_list_length (list); 
     678        if (l->count == 0) 
     679            l->top = l->pos = 0; 
     680        else if (l->pos >= l->count) 
     681            l->pos = l->count - 1; 
     682        if (l->top > l->pos) 
     683            l->top = l->pos; 
    681684    } 
    682685} 
    683686 
    684687/* --------------------------------------------------------------------------------------------- */ 
    685688 
    686689void 
     690listbox_set_list (WListbox * l, GList * list) 
     691{ 
     692    listbox_remove_list (l); 
     693    listbox_refresh_list (l, list); 
     694} 
     695 
     696/* --------------------------------------------------------------------------------------------- */ 
     697 
     698void 
    687699listbox_remove_list (WListbox * l) 
    688700{ 
    689701    if ((l != NULL) && (l->count != 0)) 
  • lib/widget/listbox.h

    diff --git a/lib/widget/listbox.h b/lib/widget/listbox.h
    index eee50b7..11268d2 100644
    a b void listbox_select_entry (WListbox * l, int dest); 
    7070void listbox_get_current (WListbox * l, char **string, void **extra); 
    7171void listbox_remove_current (WListbox * l); 
    7272void listbox_set_list (WListbox * l, GList * list); 
     73void listbox_refresh_list (WListbox * l, GList * list); 
    7374void listbox_remove_list (WListbox * l); 
    7475char *listbox_add_item (WListbox * l, listbox_append_t pos, 
    7576                        int hotkey, const char *text, void *data); 
  • misc/mc.default.keymap

    diff --git a/misc/mc.default.keymap b/misc/mc.default.keymap
    index 9d1bb60..0be3977 100644
    a b ExternalCommand = alt-u 
    315315UserMenu = f11 
    316316Menu = f9 
    317317Bookmark = alt-k 
     318BookmarkList = alt-shift-k; alt-shift-j 
    318319BookmarkFlush = alt-o 
    319320BookmarkNext = alt-j 
    320321BookmarkPrev = alt-i 
  • misc/mc.emacs.keymap

    diff --git a/misc/mc.emacs.keymap b/misc/mc.emacs.keymap
    index 6d503b4..6582a94 100644
    a b ExternalCommand = alt-u 
    314314UserMenu = f11 
    315315Menu = f9 
    316316# Bookmark = 
     317# BookmarkList = 
    317318# BookmarkFlush = 
    318319# BookmarkNext = 
    319320# BookmarkPrev = 
  • src/editor/bookmark.c

    diff --git a/src/editor/bookmark.c b/src/editor/bookmark.c
    index 552d3c8..a96875d 100644
    a b  
    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) 
     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) 
     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) 
     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    GList *list = list_box->list; 
     265    list = g_list_concat (list, list_cfg.hidden); 
     266    list_box->list = list; 
     267    list_cfg.hidden = NULL; 
     268} 
     269 
     270static void 
     271list_filter_color (int color) 
     272{ 
     273    GList *e, *list; 
     274 
     275    list_filter_none (); 
     276    if (color != -1) 
     277    { 
     278        e = list = list_box->list; 
     279 
     280        while (e != NULL) 
     281        { 
     282            if (((list_entry_t *) ((WLEntry *) e->data)->data)->mark->c != color) 
     283            { 
     284                list = g_list_remove_link (list, e); 
     285                list_cfg.hidden = g_list_concat (list_cfg.hidden, e); 
     286                e = list; 
     287            } 
     288            else 
     289            { 
     290                e = g_list_next (e); 
     291            } 
     292        } 
     293    } 
     294    else 
     295    { 
     296        list = list_box->list; 
     297    } 
     298    listbox_refresh_list (list_box, list); 
     299} 
     300 
     301/* --------------------------------------------------------------------------------------------- */ 
     302 
     303static void 
     304update_detail (void) 
     305{ 
     306    list_entry_t *entry; 
     307    WListbox *list = list_box; 
     308 
     309    if (list->count != 0) 
     310    { 
     311        char *ctext = NULL; 
     312 
     313        listbox_get_current (list, &ctext, (void **) &entry); 
     314        if (list->widget.cols != entry->detail_cols) 
     315        { 
     316            GString *buff = g_string_new (""); 
     317            g_string_append (buff, str_trunc (entry->detail[0], list->widget.cols - 1)); 
     318            g_string_append (buff, "\n"); 
     319            g_string_append (buff, str_trunc (entry->detail[1], list->widget.cols - 1)); 
     320            g_string_append (buff, "\n"); 
     321            g_string_append (buff, str_trunc (entry->detail[2], list->widget.cols - 1)); 
     322            g_free (entry->detail[3]); 
     323            entry->detail[3] = g_strdup (buff->str); 
     324            entry->detail_cols = list->widget.cols; 
     325        } 
     326        label_set_text (list_detail, entry->detail[3]); 
     327    } 
     328} 
     329 
     330/* --------------------------------------------------------------------------------------------- */ 
     331 
     332static void 
     333update_list_title (void) 
     334{ 
     335    GString *buff = g_string_new (_("Bookmarks")); 
     336 
     337    if (list_cfg.sort != SORT_LINE || list_cfg.reverse) 
     338    { 
     339        g_string_append (buff, _(" - Sort: ")); 
     340        g_string_append (buff, 
     341                         list_cfg.sort == SORT_ALPHA ? _("ABC") : list_cfg.sort == 
     342                         SORT_LINE ? "" : _("FRQ")); 
     343        g_string_append (buff, list_cfg.reverse ? " v" : " ^"); 
     344    } 
     345    if (list_cfg.filter != FILTER_NONE) 
     346    { 
     347        g_string_append (buff, _(" - Filter: ")); 
     348        g_string_append (buff, list_cfg.filter == FILTER_FOUND ? _("FOUND") : _("USER")); 
     349    } 
     350    groupbox_set_title (list_grp, str_trunc (buff->str, list_box->widget.cols - 4)); 
     351    g_string_free (buff, TRUE); 
     352} 
     353 
     354/* --------------------------------------------------------------------------------------------- */ 
     355 
     356static int 
     357list_button_callback (WButton * button, int action) 
     358{ 
     359    list_entry_t *entry = NULL; 
     360    WEdit *edit = list_cfg.edit; 
     361 
     362    (void) button; 
     363 
     364    switch (action) 
     365    { 
     366    case B_REMOVE: 
     367        { 
     368            listbox_get_current (list_box, NULL, (void **) &entry); 
     369            if (entry != NULL) 
     370            { 
     371                book_mark_clear (edit, entry->mark->line, entry->mark->c); 
     372                list_entry_free2 (entry); 
     373                /* now remove list entry from screen */ 
     374                listbox_remove_current (list_box); 
     375            } 
     376        } 
     377        edit_update_screen (edit); 
     378        dlg_redraw (list_dlg); 
     379        break; 
     380 
     381    case B_FLUSH: 
     382        { 
     383            GList *list = list_box->list; 
     384 
     385            while (list != NULL) 
     386            { 
     387                entry = (list_entry_t *) ((WLEntry *) list->data)->data; 
     388                book_mark_clear (edit, entry->mark->line, entry->mark->c); 
     389                list_entry_free2 (entry); 
     390 
     391                list = g_list_next (list); 
     392            } 
     393            listbox_set_list (list_box, NULL); 
     394        } 
     395        edit_update_screen (edit); 
     396        dlg_redraw (list_dlg); 
     397        break; 
     398 
     399    case B_ADD_NEW: 
     400        if (!book_mark_query_color (edit, edit->curs_line, BOOK_MARK_FOUND_COLOR) && 
     401            !book_mark_query_color (edit, edit->curs_line, BOOK_MARK_COLOR)) 
     402        { 
     403            edit_book_mark_t *book_mark; 
     404            GList *new_list; 
     405            long int line = edit->curs_line; 
     406            GString *buff = g_string_new (""); 
     407            GString *detail = g_string_new (""); 
     408 
     409            book_mark_insert (edit, edit->curs_line, BOOK_MARK_COLOR); 
     410            book_mark = book_mark_find (edit, edit->curs_line); 
     411            list_add_entry (list_cfg.edit, list_box, book_mark, buff, detail); 
     412            g_string_free (buff, 1); 
     413            g_string_free (detail, 1); 
     414            new_list = g_list_sort (list_box->list, list_cfg.sort == 2 ? 
     415                                    list_sort_alpha : (list_cfg.sort == 
     416                                                       0 ? list_sort_line : list_sort_freq)); 
     417            list_box->list = new_list; 
     418            if (edit->curs_line < line) 
     419                edit_move_down (edit, line - edit->curs_line, FALSE); 
     420            else 
     421                edit_move_up (edit, edit->curs_line - line, FALSE); 
     422        } 
     423        edit_update_screen (edit); 
     424        dlg_redraw (list_dlg); 
     425        break; 
     426 
     427    case B_ENTER: 
     428        { 
     429            return 1; 
     430        } 
     431 
     432    case B_FILTER: 
     433        { 
     434            if (++list_cfg.filter > FILTER_FOUND) 
     435                list_cfg.filter = FILTER_NONE; 
     436            if (list_cfg.filter == FILTER_FOUND) 
     437                list_filter_color (BOOK_MARK_FOUND_COLOR); 
     438            else if (list_cfg.filter == FILTER_NONE) 
     439                list_filter_color (-1); 
     440            else 
     441                list_filter_color (BOOK_MARK_COLOR); 
     442            update_list_title (); 
     443        } 
     444        break; 
     445 
     446    case B_SORT: 
     447        if (++list_cfg.sort > SORT_ALPHA) 
     448            list_cfg.sort = SORT_LINE; 
     449        list_box->list = g_list_sort (list_box->list, 
     450                                      list_cfg.sort == SORT_ALPHA ? list_sort_alpha : 
     451                                      (list_cfg.sort == 
     452                                       SORT_LINE ? list_sort_line : list_sort_freq)); 
     453        listbox_refresh_list (list_box, list_box->list); 
     454        update_list_title (); 
     455        break; 
     456 
     457    case B_REVERSE: 
     458        list_cfg.reverse = !list_cfg.reverse; 
     459        list_box->list = g_list_reverse (list_box->list); 
     460        listbox_refresh_list (list_box, list_box->list); 
     461        update_list_title (); 
     462        break; 
     463 
     464    default: 
     465        return 1; 
     466    } 
     467 
     468    return 0; 
     469} 
     470 
     471/* --------------------------------------------------------------------------------------------- */ 
     472 
     473static inline cb_ret_t 
     474list_handle_key (WDialog * h, int key) 
     475{ 
     476    switch (key) 
     477    { 
     478    case KEY_M_CTRL | '\n': 
     479        goto l1; 
     480 
     481    case '\n': 
     482    case KEY_ENTER: 
     483    case KEY_RIGHT: 
     484        if (list_button_callback (NULL, B_ENTER) != 0) 
     485        { 
     486            h->ret_value = B_ENTER; 
     487            dlg_stop (h); 
     488        } 
     489        return MSG_HANDLED; 
     490 
     491    case KEY_IC: 
     492    case KEY_KP_ADD: 
     493    case '+': 
     494        list_button_callback (NULL, B_ADD_NEW); 
     495        return MSG_HANDLED; 
     496 
     497    case KEY_DC: 
     498    case KEY_BACKSPACE: 
     499    case KEY_KP_SUBTRACT: 
     500    case '-': 
     501        list_button_callback (NULL, B_REMOVE); 
     502        return MSG_HANDLED; 
     503 
     504      l1: 
     505    case ALT ('\n'): 
     506    case ALT ('\r'): 
     507        { 
     508            void *ldata = NULL; 
     509 
     510            listbox_get_current (list_box, NULL, &ldata); 
     511 
     512            if (ldata != NULL) 
     513            { 
     514            } 
     515        } 
     516        return MSG_HANDLED;     /* ignore key */ 
     517 
     518    default: 
     519        return MSG_NOT_HANDLED; 
     520    } 
     521} 
     522 
     523/* --------------------------------------------------------------------------------------------- */ 
     524 
     525static cb_ret_t 
     526list_callback (Widget * w, Widget * sender, widget_msg_t msg, int parm, void *data) 
     527{ 
     528    WDialog *h = DIALOG (w); 
     529 
     530    switch (msg) 
     531    { 
     532    case MSG_UNHANDLED_KEY: 
     533        return list_handle_key (h, parm); 
     534 
     535    case MSG_POST_KEY: 
     536        dlg_select_widget (list_box); 
     537        /* always stay on hotlist */ 
     538        /* fall through */ 
     539 
     540    case MSG_INIT: 
     541        update_detail (); 
     542        update_list_title (); 
     543        return MSG_HANDLED; 
     544 
     545    case MSG_RESIZE: 
     546        /* simply call dlg_set_size() with new size */ 
     547        dlg_set_size (h, DLG_H, DLG_W); 
     548        update_detail (); 
     549        update_list_title (); 
     550        return MSG_HANDLED; 
     551 
     552    default: 
     553        return dlg_default_callback (w, sender, msg, parm, data); 
     554    } 
     555} 
     556 
     557/* --------------------------------------------------------------------------------------------- */ 
     558 
     559static lcback_ret_t 
     560list_listbox_callback (WListbox * list) 
     561{ 
     562    WDialog *dlg = WIDGET (list)->owner; 
     563 
     564    if (list->count != 0) 
     565    { 
     566        void *data = NULL; 
     567 
     568        listbox_get_current (list, NULL, &data); 
     569 
     570        if (data == NULL) 
     571        { 
     572            dlg->ret_value = B_ENTER; 
     573            dlg_stop (dlg); 
     574            return LISTBOX_DONE; 
     575        } 
     576    } 
     577 
     578    return LISTBOX_CONT; 
     579} 
     580 
     581/* --------------------------------------------------------------------------------------------- */ 
     582 
     583static void 
     584fill_line_listbox (WEdit * edit, int skip_sp, GString * buff) 
     585{ 
     586    off_t off; 
     587    int cw = 1, c = -1; 
     588 
     589    off = edit_bol (edit, edit->curs1); 
     590    while (c != '\r' && c != '\n' && c != 0) 
     591    { 
     592#ifdef HAVE_CHARSET 
     593        if (edit->utf8) 
     594        { 
     595            c = edit_get_utf (edit, off, &cw); 
     596            if (cw < 1) 
     597                cw = 1; 
     598            if (skip_sp && c != ' ' && c != '\t') 
     599                skip_sp = 0; 
     600            if (c != '\r' && c != '\n' && c != 0 && !skip_sp) 
     601            { 
     602                /* convert TAB to spaces */ 
     603                if (c == '\t') 
     604                { 
     605                    for (c = option_tab_spacing; c > 1; c--) 
     606                        g_string_append_unichar (buff, ' '); 
     607                    c = ' '; 
     608                } 
     609                g_string_append_unichar (buff, c); 
     610            } 
     611        } 
     612        else 
     613#endif 
     614        { 
     615            c = edit_get_byte (edit, off); 
     616            if (skip_sp && c != ' ' && c != '\t') 
     617                skip_sp = 0; 
     618            if (c != '\r' && c != '\n' && c != 0 && !skip_sp) 
     619            { 
     620                /* convert TAB to spaces */ 
     621                if (c == '\t') 
     622                { 
     623                    for (c = option_tab_spacing; c > 1; c--) 
     624                        g_string_append_c (buff, ' '); 
     625                    c = ' '; 
     626                } 
     627                g_string_append_c (buff, c); 
     628            } 
     629        } 
     630        off += cw; 
     631    } 
     632} 
     633 
     634/* --------------------------------------------------------------------------------------------- */ 
     635/* 
     636 * Copy&Paste (and rewrite) from filemanager/hotlsist.c 
     637 */ 
     638/** 
     639 * Expands all button names (once) and recalculates button positions. 
     640 * returns number of columns in the dialog box, which is 10 chars longer 
     641 * then buttonbar. 
     642 * 
     643 * If common width of the window (i.e. in xterm) is less than returned 
     644 * width - sorry :)  (anyway this did not handled in previous version too) 
     645 */ 
     646 
     647static void 
     648init_i18n_stuff (int cols) 
     649{ 
     650    size_t i; 
     651 
     652    static gboolean i18n_flag = FALSE; 
     653    int curr_x = 0; 
     654    int curr_minus_x = cols - 5; 
     655 
     656    if (!i18n_flag) 
     657    { 
     658        for (i = 0; i < list_btn_num; i++) 
     659        { 
     660#ifdef ENABLE_NLS 
     661            list_btn[i].text = _(list_btn[i].text); 
     662#endif /* ENABLE_NLS */ 
     663            list_btn[i].len = str_term_width1 (list_btn[i].text) + 3; 
     664            if (list_btn[i].flags == DEFPUSH_BUTTON) 
     665                list_btn[i].len += 2; 
     666            /* reset current X at line start */ 
     667            if (list_btn[i].x == 0) 
     668            { 
     669                curr_x = 0; 
     670                curr_minus_x = cols - 5; 
     671            } 
     672            if (list_btn[i].x >= 0) 
     673            { 
     674                list_btn[i].x = curr_x; 
     675                curr_x += list_btn[i].len + 1; 
     676            } 
     677            else if (list_btn[i].x < 0) 
     678            { 
     679                curr_minus_x -= list_btn[i].len + 1; 
     680                list_btn[i].x = curr_minus_x; 
     681            } 
     682        } 
     683 
     684        i18n_flag = TRUE; 
     685    } 
     686} 
     687 
     688/* --------------------------------------------------------------------------------------------- */ 
     689 
     690static void 
     691list_add_entry (WEdit * edit, WListbox * list, edit_book_mark_t * book_mark, GString * buff, 
     692                GString * detail) 
     693{ 
     694    list_entry_t *entry; 
     695 
     696    entry = g_malloc (sizeof (list_entry_t)); 
     697    g_string_truncate (buff, 0); 
     698    g_string_truncate (detail, 0); 
     699 
     700    fill_line_listbox (edit, 1, buff); 
     701    fill_line_listbox (edit, 0, detail); 
     702    entry->detail[1] = g_strdup (detail->str); 
     703    g_string_truncate (detail, 0); 
     704 
     705    if (book_mark->line != 0) 
     706    { 
     707        edit_move_up (edit, 1, FALSE); 
     708        fill_line_listbox (edit, 0, detail); 
     709    } 
     710    entry->detail[0] = g_strdup (detail->str); 
     711    g_string_truncate (detail, 0); 
     712 
     713    if (book_mark->line != edit->total_lines) 
     714    { 
     715        edit_move_down (edit, (book_mark->line == 0) ? 1 : 2, FALSE); 
     716        fill_line_listbox (edit, 0, detail); 
     717    } 
     718    entry->detail[2] = g_strdup (detail->str); 
     719    entry->detail[3] = g_strdup (""); 
     720    entry->detail_cols = -1; 
     721 
     722    entry->text = g_strndup (buff->str, 80); 
     723    entry->mark = book_mark; 
     724    g_string_printf (buff, "% 6ld [%c/%d] -> %s", book_mark->line + 1, 
     725                     book_mark->c == BOOK_MARK_FOUND_COLOR ? 'F' : 'U', book_mark->freq, 
     726                     str_trunc (buff->str, list->widget.cols - 1)); 
     727    listbox_add_item (list, LISTBOX_APPEND_AT_END, 0, buff->str, entry); 
     728} 
     729 
     730/* --------------------------------------------------------------------------------------------- */ 
     731 
     732static void 
     733fill_list_box (WEdit * edit, WListbox * list) 
     734{ 
     735    edit_book_mark_t *book_mark; 
     736    GString *detail; 
     737    GString *buff; 
     738    long int curs_line = edit->curs_line; 
     739 
     740    buff = g_string_new (""); 
     741    detail = g_string_new (""); 
     742    edit_bol (edit, edit->curs1); 
     743 
     744    for (book_mark = book_mark_find (edit, 0); book_mark != NULL; book_mark = book_mark->next) 
     745    { 
     746        if (book_mark->line == -1) 
     747            continue; 
     748        if (edit->curs_line == book_mark->line) 
     749            ; 
     750        else if (edit->curs_line < book_mark->line) 
     751            edit_move_down (edit, book_mark->line - edit->curs_line, FALSE); 
     752        else 
     753            edit_move_up (edit, edit->curs_line - book_mark->line, FALSE); 
     754 
     755        list_add_entry (edit, list, book_mark, buff, detail); 
     756    } 
     757    if (edit->curs_line < curs_line) 
     758        edit_move_down (edit, curs_line - edit->curs_line, FALSE); 
     759    else 
     760        edit_move_up (edit, edit->curs_line - curs_line, FALSE); 
     761    g_string_free (buff, TRUE); 
     762    g_string_free (detail, TRUE); 
     763} 
     764 
     765/* --------------------------------------------------------------------------------------------- */ 
     766 
     767static void 
     768list_init (WEdit * edit) 
     769{ 
     770    size_t i; 
     771    const char *title, *help_node; 
     772    int lines, cols; 
     773    int y; 
     774    int dh = 0; 
     775    WGroupbox *dtl_box; 
     776    Widget *list_widget; 
     777 
     778    do_refresh (); 
     779 
     780    lines = DLG_H; 
     781    cols = DLG_W; 
     782    init_i18n_stuff (cols); 
     783 
     784    title = _("Bookmark list"); 
     785    help_node = "[Bookmarklist]"; 
     786 
     787    list_cfg.hidden = NULL; 
     788    list_cfg.edit = edit; 
     789    list_dlg = 
     790        create_dlg (TRUE, 0, 0, lines, cols, dialog_colors, list_callback, NULL, help_node, 
     791                    title, DLG_CENTER); 
     792    y = UY; 
     793    list_grp = groupbox_new (y, UX, lines - 12 + dh, cols - 2 * UX, _("Bookmarks")); 
     794    list_widget = WIDGET (list_grp); 
     795    add_widget_autopos (list_dlg, list_widget, WPOS_KEEP_ALL, NULL); 
     796 
     797    list_box = 
     798        listbox_new (y + 1, UX + 1, list_widget->lines - 2, list_widget->cols - 2, FALSE, 
     799                     list_listbox_callback); 
     800 
     801    fill_list_box (edit, list_box); 
     802 
     803    /* insert before groupbox to view scrollbar */ 
     804    add_widget_autopos (list_dlg, list_box, WPOS_KEEP_ALL, NULL); 
     805 
     806    y += list_widget->lines; 
     807 
     808    dtl_box = groupbox_new (y, UX, 5, list_widget->cols, _("Bookmark detail")); 
     809    add_widget_autopos (list_dlg, dtl_box, WPOS_KEEP_BOTTOM | WPOS_KEEP_HORZ, NULL); 
     810 
     811    list_detail = label_new (y + 1, UX + 2, ""); 
     812    widget_set_size ((Widget *) list_detail, y + 1, UX + 2, 80, 3); 
     813    add_widget_autopos (list_dlg, list_detail, WPOS_KEEP_BOTTOM | WPOS_KEEP_LEFT, NULL); 
     814    y += WIDGET (dtl_box)->lines; 
     815 
     816    add_widget_autopos (list_dlg, hline_new (y++, -1, -1), WPOS_KEEP_BOTTOM, NULL); 
     817 
     818    for (i = 0; i < list_btn_num; i++) 
     819    { 
     820        WButton *btn; 
     821        if (list_btn[i].x < 0) 
     822            list_btn[i].x = cols + list_btn[i].x; 
     823        btn = button_new (y + list_btn[i].y, UX + list_btn[i].x, 
     824                          list_btn[i].ret_cmd, list_btn[i].flags, 
     825                          list_btn[i].text, list_button_callback); 
     826        if (i == 5) 
     827            list_filter = btn; 
     828        if (i == 6) 
     829            list_sort = btn; 
     830        add_widget_autopos (list_dlg, btn, list_btn[i].pos_flags, NULL); 
     831    } 
     832 
     833    dlg_select_widget (list_box); 
     834} 
     835 
     836 
     837/* --------------------------------------------------------------------------------------------- */ 
     838 
     839static void 
     840list_entry_free (void *data) 
     841{ 
     842    list_entry_free2 (((WLEntry *) data)->data); 
     843} 
     844 
    138845/* --------------------------------------------------------------------------------------------- */ 
    139846/*** public functions ****************************************************************************/ 
    140847/* --------------------------------------------------------------------------------------------- */ 
    141848 
     849void 
     850book_mark_list_show (WEdit * edit) 
     851{ 
     852    int res; 
     853 
     854/*** Check list_box running...?? */ 
     855    list_init (edit); 
     856 
     857    res = run_dlg (list_dlg); 
     858    if (res == B_ENTER) 
     859    { 
     860        char *text; 
     861        list_entry_t *entry; 
     862 
     863        listbox_get_current (list_box, &text, (void **) &entry); 
     864        if (entry != NULL) 
     865        { 
     866            if (entry->mark->line >= edit->start_line + WIDGET (edit)->lines 
     867                || entry->mark->line < edit->start_line) 
     868                edit_move_display (edit, entry->mark->line - WIDGET (edit)->lines / 2); 
     869            edit_move_to_line (edit, entry->mark->line); 
     870            if (entry->mark->freq < 128 * 1024) 
     871                entry->mark->freq++; 
     872        } 
     873    } 
     874    g_list_foreach (list_box->list, (GFunc) list_entry_free, NULL); 
     875    destroy_dlg (list_dlg); 
     876    list_cfg.edit = NULL; 
     877} 
     878 
    142879/**  
    143880 * Check if bookmark bookmark exists at this line of this color 
    144881 * 
    book_mark_insert (WEdit * edit, long line, int c) 
    192929    q = g_new (edit_book_mark_t, 1); 
    193930    q->line = line; 
    194931    q->c = c; 
     932    q->freq = 0; 
    195933    q->next = p->next; 
    196934    /* insert into list */ 
    197935    q->prev = p; 
  • src/editor/edit-impl.h

    diff --git a/src/editor/edit-impl.h b/src/editor/edit-impl.h
    index 0cf7e52..f79968e 100644
    a b void book_mark_inc (WEdit * edit, long line); 
    312312void book_mark_dec (WEdit * edit, long line); 
    313313void book_mark_serialize (WEdit * edit, int color); 
    314314void book_mark_restore (WEdit * edit, int color); 
     315void book_mark_list_show (WEdit * edit); 
    315316 
    316317gboolean edit_line_is_blank (WEdit * edit, long line); 
    317318gboolean is_break_char (char c); 
  • src/editor/edit.c

    diff --git a/src/editor/edit.c b/src/editor/edit.c
    index 2cd91c9..ef09f4f 100644
    a b edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion) 
    41124112                if (p->line >= edit->start_line + w->lines || p->line < edit->start_line) 
    41134113                    edit_move_display (edit, p->line - w->lines / 2); 
    41144114                edit_move_to_line (edit, p->line); 
     4115                if (p->freq < 128*1024) 
     4116                    p->freq++; 
    41154117            } 
    41164118        } 
    41174119        break; 
    edit_execute_cmd (WEdit * edit, unsigned long command, int char_for_insertion) 
    41294131                if (p->line >= edit->start_line + w->lines || p->line < edit->start_line) 
    41304132                    edit_move_display (edit, p->line - w->lines / 2); 
    41314133                edit_move_to_line (edit, p->line); 
     4134                if (p->freq < 128*1024) 
     4135                    p->freq++; 
    41324136            } 
    41334137        } 
    41344138        break; 
     4139    case CK_BookmarkList: 
     4140        book_mark_list_show (edit); 
     4141        break; 
    41354142 
    41364143    case CK_Top: 
    41374144    case CK_MarkToFileBegin: 
  • src/editor/editmenu.c

    diff --git a/src/editor/editmenu.c b/src/editor/editmenu.c
    index a55636d..3cf0ab8 100644
    a b 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 --git a/src/editor/editwidget.h b/src/editor/editwidget.h
    index faa1a9a..c81a001 100644
    a b struct edit_book_mark_t 
    3333{ 
    3434    long line;                  /* line number */ 
    3535    int c;                      /* color */ 
     36    int freq;                   /* usage freq */ 
    3637    edit_book_mark_t *next; 
    3738    edit_book_mark_t *prev; 
    3839}; 
  • src/keybind-defaults.c

    diff --git a/src/keybind-defaults.c b/src/keybind-defaults.c
    index 7ad1f55..e6434a9 100644
    a b static const global_keymap_ini_t default_editor_keymap[] = { 
    401401    {"MatchBracket", "alt-b"}, 
    402402    {"ParagraphFormat", "alt-p"}, 
    403403    {"Bookmark", "alt-k"}, 
     404    {"BookmarkList", "alt-shift-k; alt-shift-j"}, 
    404405    {"BookmarkFlush", "alt-o"}, 
    405406    {"BookmarkNext", "alt-j"}, 
    406407    {"BookmarkPrev", "alt-i"},