[PATCH] lynx-like jumpkeys

Tomas Styblo tripie at cpan.org
Wed Dec 18 03:06:24 UTC 2002


Here is an updated version of the patch.

In previous version the jumpkey numbers were displayed even for
empty entries. This was most noticeable in the hotlist. I think it
was quite confusing. Now the numbers are displayed only for
non-empty entries.

The new version of the patch is attached to this message.

The only difference between the two versions:

diff -purN mc-4.6.0-pre1/src/widget.c mc-4.6.0-pre1.new/src/widget.c
--- mc-4.6.0-pre1/src/widget.c  Wed Dec 18 04:04:33 2002
+++ mc-4.6.0-pre1.new/src/widget.c      Wed Dec 18 04:04:17 2002
@@ -1729,7 +1729,7 @@ listbox_draw (WListbox *l, Dlg_head *h, 
            text = e->text;
            e = e->next;
        }
-       if (l->use_jumpkeys)
+       if (l->use_jumpkeys && *text)
            printw (" %3d | %-*s ", i + 1, l->width-7, name_trunc (text, l->width-7));
        else
            printw (" %-*s ", l->width-2, name_trunc (text, l->width-2));


-- 
Tomas Styblo <tripie at cpan.org>
PGP: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0xC97EA4B6
-------------- next part --------------
diff -purN mc-4.6.0-pre1/doc/mc.1.in mc-4.6.0-pre1.new/doc/mc.1.in
--- mc-4.6.0-pre1/doc/mc.1.in	Wed Aug 21 03:08:46 2002
+++ mc-4.6.0-pre1.new/doc/mc.1.in	Wed Dec 18 03:23:49 2002
@@ -337,6 +337,12 @@ suspended by using this trick, you won't
 programs from the Midnight Commander until you terminate the suspended
 application.
 .PP
+.B number keys,
+When the "lynx-like jumpkeys" configuration option is enabled, then you
+can use number keys to select numbered entries in the panels, the
+history and the hotlist. More information about this feature is in
+the "Configuration: Panel Options" section.
+.PP
 .SH "  Directory Panels"
 This section lists the keys which operate on the directory panels. If
 you want to know how to change the appearance of the panels take a
@@ -585,6 +591,11 @@ completion
 .\"Completion"
 for you.
 .PP
+When the configuration option "lynx-like jumpkeys" is enabled and the
+command line is empty, then the number keys are intercepted by the
+panels. To execute a command which begins with a number, the command
+must be prefixed with a space.
+.PP
 .SH ""
 .SH "Menu Bar"
 The menu bar pops up when you press F9 or click the mouse on the top
@@ -732,6 +743,9 @@ the group of the file.
 .B inode,
 the inode of the file.
 .PP
+.B jumpkey,
+number of the entry, used by the "lynx-like jumpkeys" feature.
+.PP
 Also you may use these field names for arranging the display:
 .PP
 .B space,
@@ -1569,6 +1583,14 @@ mode or owner changes, etc) the display 
 if you have the option on, you have to rescan the directory manually
 (with C-r).
 .PP
+.I Lynx-like jumpkeys.
+This option enables a lynx-like navigation using numbered entries in
+the panels and other widgets. Each displayed entry is numbered and
+may be selected by one or two keystrokes.
+To select for example a file or a hotlist entry numbered "23", 
+just press the keys "2" and "3" in quick succession.
+The selection cursor will immediately move to that entry.
+.PP
 .B Pause after run
 .PP
 After executing your commands, the Midnight Commander can pause, so
diff -purN mc-4.6.0-pre1/src/complete.c mc-4.6.0-pre1.new/src/complete.c
--- mc-4.6.0-pre1/src/complete.c	Tue Mar 26 03:09:39 2002
+++ mc-4.6.0-pre1.new/src/complete.c	Wed Dec 18 03:23:49 2002
@@ -990,6 +990,7 @@ complete_engine (WInput *in, int what_to
 				    dialog_colors, query_callback,
 				    "[Completion]", "complete", DLG_NONE);
     	    query_list = listbox_new (1, 1, w - 2, h - 2, 0, querylist_callback, NULL);
+            query_list->use_jumpkeys = 0; /* never use jumpkeys in completion menu */
     	    add_widget (query_dlg, query_list);
     	    for (p = in->completions + 1; *p; p++)
     	    	listbox_add_item (query_list, 0, 0, *p, NULL);
diff -purN mc-4.6.0-pre1/src/dir.h mc-4.6.0-pre1.new/src/dir.h
--- mc-4.6.0-pre1/src/dir.h	Fri Dec 28 02:11:52 2001
+++ mc-4.6.0-pre1.new/src/dir.h	Wed Dec 18 03:23:49 2002
@@ -10,6 +10,7 @@ typedef struct {
     /* File attributes */
 
     int  fnamelen;
+    int  jumpkey_num;
     char *fname;
     struct stat  buf;
 
diff -purN mc-4.6.0-pre1/src/main.c mc-4.6.0-pre1.new/src/main.c
--- mc-4.6.0-pre1/src/main.c	Wed Aug 21 03:08:49 2002
+++ mc-4.6.0-pre1.new/src/main.c	Wed Dec 18 03:23:49 2002
@@ -286,6 +286,10 @@ static int edit_one_file_start_line = 1;
    shut down */
 int midnight_shutdown = 0;
 
+/* Grab number keys in panels and listbox widgets and use them
+ * as lynx-like jumpkeys */
+int use_jumpkeys = 0;
+
 /* to show nice prompts */
 static int last_paused = 0;
 
@@ -1176,6 +1180,20 @@ toggle_show_hidden (void)
     update_panels (UP_RELOAD, UP_KEEPSEL);
 }
 
+void
+toggle_use_jumpkeys (void)
+{
+    int i;
+    WPanel *p;
+    
+    use_jumpkeys = !use_jumpkeys;
+    for (i = 0; i <= 1; i++) {
+        p = (i == 0 ? left_panel : right_panel);
+        if (p) set_panel_formats (p);
+    }
+    update_panels (UP_RELOAD, UP_KEEPSEL);
+}
+
 /*
  * Just a hack for allowing url-like pathnames to be accepted from the
  * command line.
diff -purN mc-4.6.0-pre1/src/main.h mc-4.6.0-pre1.new/src/main.h
--- mc-4.6.0-pre1/src/main.h	Mon Aug 19 06:16:47 2002
+++ mc-4.6.0-pre1.new/src/main.h	Wed Dec 18 03:23:49 2002
@@ -5,6 +5,7 @@ void toggle_fast_reload (void);
 void toggle_mix_all_files (void);
 void toggle_show_backup (void);
 void toggle_show_hidden (void);
+void toggle_use_jumpkeys (void);
 
 enum {
     RP_NOCLEAR,
@@ -84,6 +85,7 @@ extern int only_leading_plus_minus;
 extern int ftpfs_directory_timeout;
 extern int output_starts_shell;
 extern int midnight_shutdown;
+extern int use_jumpkeys;
 extern char search_buffer [256];
 extern char cmd_buf [512];
 extern char *cmdline_geometry;
diff -purN mc-4.6.0-pre1/src/option.c mc-4.6.0-pre1.new/src/option.c
--- mc-4.6.0-pre1/src/option.c	Tue Aug 20 04:57:25 2002
+++ mc-4.6.0-pre1.new/src/option.c	Wed Dec 18 03:23:49 2002
@@ -82,6 +82,7 @@ static struct {
    {N_("shell &Patterns"),    &easy_patterns,     TOGGLE_VARIABLE,       0, "shell-patt" },
    {N_("Compute &Totals"),    &file_op_compute_totals,           TOGGLE_VARIABLE,       0, "compute-totals" },
    {N_("&Verbose operation"), &verbose,           TOGGLE_VARIABLE,       0, "verbose" },
+   {N_("&lynx-like jumpkeys"),   &use_jumpkeys,   toggle_use_jumpkeys,    0, "jumpkeys" },
    {N_("&Fast dir reload"),   &fast_reload,       toggle_fast_reload,    0, "fast-reload" },
    {N_("mi&X all files"),     &mix_all_files,     toggle_mix_all_files,  0, "mix-files" },
    {N_("&Drop down menus"),   &drop_menus,        TOGGLE_VARIABLE,       0, "drop-menus" },
@@ -105,7 +106,7 @@ static int configure_callback (struct Dl
 	attrset (COLOR_NORMAL);
 	dlg_erase (h);
 	draw_box (h, 1, 2, h->lines - 2, h->cols - 4);
-	draw_box (h, PY, PX, 8, first_width);
+	draw_box (h, PY, PX, 9, first_width);
 	draw_box (h, RY, RX, 5, first_width);
 	draw_box (h, OY, OX, 15, second_width);
 
@@ -221,8 +222,8 @@ static void init_configure (void)
     pause_radio = radio_new (RY+1, RX+2, 3, pause_options, 1, "pause-radio");
     pause_radio->sel = pause_after_run;
     add_widget (conf_dlg, pause_radio);
-    for (i = 0; i < 6; i++){
-	check_options [i+13].widget = check_new (PY + (6-i), PX+2,
+    for (i = 0; i < 7; i++){
+	check_options [i+13].widget = check_new (PY + (7-i), PX+2,
 						  XTRACT(i+13));
 	add_widget (conf_dlg, check_options [i+13].widget);
     }
diff -purN mc-4.6.0-pre1/src/screen.c mc-4.6.0-pre1.new/src/screen.c
--- mc-4.6.0-pre1/src/screen.c	Mon Aug 19 00:07:09 2002
+++ mc-4.6.0-pre1.new/src/screen.c	Wed Dec 18 03:23:49 2002
@@ -44,6 +44,7 @@
 #include "user.h"
 #include "profile.h"
 #include "widget.h"
+#include "command.h"
 #include "../vfs/vfs.h"
 
 #ifdef _OS_NT
@@ -371,6 +372,14 @@ string_dot (file_entry *fe, int len)
     return ".";
 }
 
+static const char *
+string_jumpkey (file_entry *fe, int len)
+{
+    static char jumpkey[4];
+    snprintf(jumpkey, sizeof(jumpkey), "%3d", fe->jumpkey_num);
+    return (jumpkey);
+}
+
 #define GT 1
 
 static struct {
@@ -402,6 +411,7 @@ static struct {
 { "|",     1,  0, J_RIGHT,	" ",		0, NULL,		   NULL },
 { "space", 1,  0, J_RIGHT,	" ",		0, string_space,	   NULL },
 { "dot",   1,  0, J_RIGHT,	" ",		0, string_dot,		   NULL },
+{ "jumpkey",   3,  0, J_RIGHT,	" ",		0, string_jumpkey,		   NULL },
 };
 
 static char *
@@ -679,6 +689,7 @@ paint_dir (WPanel *panel)
 	    color = 2 * (panel->dir.list [i+panel->top_file].f.marked);
 	    color += (panel->selected==i+panel->top_file && panel->active);
 	}
+    panel->dir.list[i+panel->top_file].jumpkey_num = i + 1;
 	repaint_file (panel, i+panel->top_file, 1, color, 0);
     }
     standend ();
@@ -1399,17 +1410,26 @@ panel_format (WPanel *panel)
     switch (panel->list_type){
 
     case list_long:
-	return "full perm,space,nlink,space,owner,space,group,space,size,space,mtime,space,name";
+    if (use_jumpkeys)
+	    return "full jumpkey,|,perm,space,nlink,space,owner,space,group,space,size,space,mtime,space,name";
+    else 
+    	return "full perm,space,nlink,space,owner,space,group,space,size,space,mtime,space,name";
 
     case list_brief:
-	return "half 2,type,name";
+    if (use_jumpkeys)
+        return "half 2,jumpkey,|,type,name";
+    else
+    	return "half 2,type,name";
 
     case list_user:
 	return panel->user_format;
 
     default:
     case list_full:
-	return "half type,name,|,size,|,mtime";
+    if (use_jumpkeys)
+        return "half jumpkey,|,type,name,|,size,|,mtime";
+    else
+	    return "half type,name,|,size,|,mtime";
     }
 }
 
@@ -2137,7 +2157,10 @@ static inline int
 panel_key (WPanel *panel, int key)
 {
     int i;
-
+    static int jumpkey_num = 0; /* number of entry the user wants to select */
+    static struct timeval jumpkey_time; /* time of last jumpkey keystroke */
+    int items = llines (panel) * (panel->split ? 2 : 1);
+    
     for (i = 0; panel_keymap [i].key_code; i++){
 	if (key == panel_keymap [i].key_code){
 	    if (panel_keymap [i].fn != start_search)
@@ -2165,6 +2188,40 @@ panel_key (WPanel *panel, int key)
 	return 1;
     }
 
+    switch (key) {
+        case '0': case '1': case '2': case '3': case '4': 
+        case '5': case '6': case '7': case '8': case '9':
+            if (! use_jumpkeys)
+                break;
+            
+            /* process jumpkeys only if command line is empty */
+            if (input_w(cmdline)->point > 0)
+                break;
+            
+            if (jumpkey_num > 0 && 
+                gettimeofday_diff_ms(&jumpkey_time, NULL) <= JUMPKEY_MAXDELAY) {
+                if ((jumpkey_num * 10) + char_to_int(key) > items) {
+                jumpkey_num = char_to_int(key);
+                }
+                else
+                jumpkey_num = (jumpkey_num * 10) + char_to_int(key);
+            }
+            else {
+                jumpkey_num = char_to_int(key);
+            }
+            gettimeofday(&jumpkey_time, NULL);
+
+            if (jumpkey_num == 0 || jumpkey_num > items)
+                return 0;
+
+            unselect_item(panel);
+            panel->selected = (panel->top_file + jumpkey_num) - 1; 
+            select_item(panel);
+            paint_panel(panel);
+            return 1;
+            break;
+    }
+    
     /* Do not eat characters not meant for the panel below ' ' (e.g. C-l). */
     if ((key >= ' '&& key <= 255) || key == 8 || key == KEY_BACKSPACE) {
 	if (panel->searching){
diff -purN mc-4.6.0-pre1/src/setup.c mc-4.6.0-pre1.new/src/setup.c
--- mc-4.6.0-pre1/src/setup.c	Mon Aug 19 06:16:47 2002
+++ mc-4.6.0-pre1.new/src/setup.c	Wed Dec 18 03:23:49 2002
@@ -193,6 +193,7 @@ static const struct {
     { "xtree_mode", &xtree_mode },
     { "num_history_items_recorded", &num_history_items_recorded },
     { "file_op_compute_totals", &file_op_compute_totals },
+    { "use_jumpkeys", &use_jumpkeys },
 #ifdef SAVE_CHANGES_OUTSIDE_OPTIONS_MENU
     { "dive_into_subdirs", &dive_into_subdirs },
     { "preserve_uidgid", &preserve_uidgid },
diff -purN mc-4.6.0-pre1/src/util.h mc-4.6.0-pre1.new/src/util.h
--- mc-4.6.0-pre1/src/util.h	Tue Aug 20 04:57:25 2002
+++ mc-4.6.0-pre1.new/src/util.h	Wed Dec 18 03:23:49 2002
@@ -31,6 +31,7 @@ char *reverse_string (char *string);
 char *diff_two_paths (char *first, char *second);
 
 char *x_basename (char *s);
+#define char_to_int(CH) (CH - '0')
 
 /* Profile managing functions */
 int set_int (char *, char *, int);
@@ -90,6 +91,7 @@ char *canonicalize_pathname (char *);
 char *get_current_wd (char *buffer, int size);
 int my_mkdir (char *s, mode_t mode);
 int my_rmdir (char *s);
+long gettimeofday_diff_ms (struct timeval *from, struct timeval *to);
 
 /* Rotating dash routines */
 void use_dash (int flag); /* Disable/Enable rotate_dash routines */
diff -purN mc-4.6.0-pre1/src/utilunix.c mc-4.6.0-pre1.new/src/utilunix.c
--- mc-4.6.0-pre1/src/utilunix.c	Tue Aug 20 04:57:25 2002
+++ mc-4.6.0-pre1.new/src/utilunix.c	Wed Dec 18 03:23:49 2002
@@ -640,6 +640,34 @@ int gettimeofday (struct timeval *tp, vo
 }
 #endif /* HAVE_GET_PROCESS_STATS */
 
+/* Return the difference between two timeval timestamps in
+ * miliseconds.
+ * The seconds timestamp must be larger or equal to the first.
+ * The first timestamp is mandatory.
+ * If the second timestamp is NULL then the first timestamp is
+ * compared to the current time.
+ * The return value is "long", therefore it may overflow if the
+ * difference is too big. */
+long gettimeofday_diff_ms (struct timeval *from, struct timeval *to)
+{
+    struct timeval now;
+    long diff;
+   
+    if (from == NULL)
+	return (-1);
+    
+    if (to == NULL) {
+	gettimeofday(&now, NULL);
+	to = &now;
+    }
+
+    diff = ((to->tv_sec == from->tv_sec ? 
+		to->tv_usec - from->tv_usec :
+		to->tv_usec + (1e6 - from->tv_usec) + 
+		(((to->tv_sec - from->tv_sec) - 1) * 1e6)) / 1000);
+    return (diff);
+}
+
 #ifndef HAVE_PUTENV
 
 /* The following piece of code was copied from the GNU C Library */
diff -purN mc-4.6.0-pre1/src/widget.c mc-4.6.0-pre1.new/src/widget.c
--- mc-4.6.0-pre1/src/widget.c	Sat Jul 20 04:54:52 2002
+++ mc-4.6.0-pre1.new/src/widget.c	Wed Dec 18 03:17:50 2002
@@ -42,6 +42,7 @@
 #include "complete.h"
 #include "key.h"		/* XCTRL and ALT macros  */
 #include "profile.h"	/* for history loading and saving */
+#include "main.h"
 
 static int button_event (Gpm_Event *event, WButton *b);
 
@@ -1728,7 +1729,10 @@ listbox_draw (WListbox *l, Dlg_head *h, 
 	    text = e->text;
 	    e = e->next;
 	}
-	printw (" %-*s ", l->width-2, name_trunc (text, l->width-2));
+	if (l->use_jumpkeys && *text)
+	    printw (" %3d | %-*s ", i + 1, l->width-7, name_trunc (text, l->width-7));
+	else
+	    printw (" %-*s ", l->width-2, name_trunc (text, l->width-2));
     }
     l->cursor_y = sel_line;
     if (!l->scrollbar)
@@ -1919,7 +1923,9 @@ listbox_key (WListbox *l, int key)
 {
     int i;
     int j = 0;
-
+    static int jumpkey_num = 0; /* number of entry the user wants to select */
+    static struct timeval jumpkey_time; /* time of last jumpkey keystroke */
+	WLEntry *e = NULL;
     if (!l->list)
 	return 0;
     
@@ -1959,6 +1965,39 @@ listbox_key (WListbox *l, int key)
 	for (i = 0; i < l->height-1; i++)
 	    j |= listbox_back (l);
 	return j > 0;
+
+    case '0': case '1': case '2': case '3': case '4': 
+    case '5': case '6': case '7': case '8': case '9':
+	if (! l->use_jumpkeys)
+	    break;
+
+	if (jumpkey_num > 0 && 
+		gettimeofday_diff_ms(&jumpkey_time, NULL) <= JUMPKEY_MAXDELAY) {
+	    if ((jumpkey_num * 10) + char_to_int(key) > 
+		    (l->height > l->count ? l->count : l->height)) {
+		jumpkey_num = char_to_int(key);
+	    }
+	    else
+		jumpkey_num = (jumpkey_num * 10) + char_to_int(key);
+	}
+	else {
+	    jumpkey_num = char_to_int(key);
+	}
+	gettimeofday(&jumpkey_time, NULL);
+
+	if (jumpkey_num == 0 || jumpkey_num > 
+		(l->height > l->count ? l->count : l->height))
+	    return 0;
+	if (! (e = l->top))
+	    return 0;
+	for (i = 1; i < jumpkey_num; i++) {
+	    if (e->next)
+		e = e->next;	
+	}
+	if (e != l->current) {
+	    listbox_select_entry(l, e);
+	    return 1;
+	}
     }
     return 0;
 }
@@ -2108,6 +2147,7 @@ listbox_new (int y, int x, int width, in
     l->cback  = callback;
     l->action = action;
     l->allow_duplicates = 1;
+    l->use_jumpkeys = use_jumpkeys;
     l->scrollbar = slow_terminal ? 0 : 1;
     widget_want_hotkey (l->widget, 1);
     
diff -purN mc-4.6.0-pre1/src/widget.h mc-4.6.0-pre1.new/src/widget.h
--- mc-4.6.0-pre1/src/widget.h	Mon Oct  1 15:30:24 2001
+++ mc-4.6.0-pre1.new/src/widget.h	Wed Dec 18 03:23:49 2002
@@ -96,6 +96,7 @@ typedef struct {
     int	   transparent;		/* Paint in the default color fg/bg */
 } WLabel;
 
+#define JUMPKEY_MAXDELAY 1500
 typedef struct WLEntry {
     char *text;			/* Text to display */
     int  hotkey;
@@ -128,6 +129,7 @@ typedef struct {
     int height;			/* Size of the widget */
     int action;			/* Action type */
     int allow_duplicates;	/* Do we allow duplicates on the list? */
+    int use_jumpkeys;
     int scrollbar;		/* Draw a scrollbar? */
     lcback cback;		/* The callback function */
     int cursor_x, cursor_y;	/* Cache the values */


More information about the mc-devel mailing list