[PATCH] lynx-like jumpkeys

Tomas Styblo tripie at cpan.org
Mon Dec 30 05:15:40 UTC 2002


* Adam Byrtek 'alpha' <alpha at student.uci.agh.edu.pl> [Sun, 22 Dec 2002]:
> Maybe after the release you could port this to cvs version?

I updated the patch for 4.6.0-pre2. It was also submitted to
the patch tracker.

-- 
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-pre2/doc/mc.1.in mc-4.6.0-pre2.dev/doc/mc.1.in
--- mc-4.6.0-pre2/doc/mc.1.in	Thu Dec 26 21:15:51 2002
+++ mc-4.6.0-pre2.dev/doc/mc.1.in	Mon Dec 30 04:39:42 2002
@@ -344,6 +344,13 @@ return to your application just type C-o
 suspended by using this trick, you won't be able to execute other
 programs from the Midnight Commander until you terminate the suspended
 application.
+.TP
+.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
 .\"NODE "  Directory Panels"
 .SH "  Directory Panels"
 This section lists the keys which operate on the directory panels. If
@@ -591,6 +598,12 @@ does the filename, command, variable, us
 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 ""
 .\"NODE "Menu Bar"
 .SH "Menu Bar"
@@ -740,6 +753,9 @@ the group of the file.
 .TP
 .B inode
 the inode of the file.
+.TP
+.B jumpkey,
+number of the entry, used by the "lynx-like jumpkeys" feature.
 .PP
 Also you can use following keywords to define the panel layout:
 .TP
@@ -1568,6 +1584,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-pre2/src/complete.c mc-4.6.0-pre2.dev/src/complete.c
--- mc-4.6.0-pre2/src/complete.c	Wed Nov 13 07:06:34 2002
+++ mc-4.6.0-pre2.dev/src/complete.c	Mon Dec 30 04:33:45 2002
@@ -995,6 +995,7 @@ complete_engine (WInput *in, int what_to
 				    dialog_colors, query_callback,
 				    "[Completion]", NULL, DLG_COMPACT);
     	    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-pre2/src/dir.h mc-4.6.0-pre2.dev/src/dir.h
--- mc-4.6.0-pre2/src/dir.h	Fri Nov 15 07:44:16 2002
+++ mc-4.6.0-pre2.dev/src/dir.h	Mon Dec 30 04:33:45 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-pre2/src/main.c mc-4.6.0-pre2.dev/src/main.c
--- mc-4.6.0-pre2/src/main.c	Thu Dec 26 17:38:37 2002
+++ mc-4.6.0-pre2.dev/src/main.c	Mon Dec 30 04:33:45 2002
@@ -282,6 +282,10 @@ static int edit_one_file_start_line = 0;
    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;
 
@@ -1181,6 +1185,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-pre2/src/main.h mc-4.6.0-pre2.dev/src/main.h
--- mc-4.6.0-pre2/src/main.h	Thu Dec 26 17:20:51 2002
+++ mc-4.6.0-pre2.dev/src/main.h	Mon Dec 30 04:33:45 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,
@@ -80,6 +81,7 @@ extern int alternate_plus_minus;
 extern int only_leading_plus_minus;
 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-pre2/src/option.c mc-4.6.0-pre2.dev/src/option.c
--- mc-4.6.0-pre2/src/option.c	Sun Dec  8 09:19:27 2002
+++ mc-4.6.0-pre2.dev/src/option.c	Mon Dec 30 04:50:59 2002
@@ -75,6 +75,7 @@ static struct {
    {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" },
    {N_("ma&Rk moves down"),   &mark_moves_down,   TOGGLE_VARIABLE,       0, "mark-moves" },
+   {N_("&lynx-like jumpkeys"),   &use_jumpkeys,   toggle_use_jumpkeys,    0, "jumpkeys" },
    {N_("show &Hidden files"), &show_dot_files,    toggle_show_hidden,    0, "show-hidden" },
    {N_("show &Backup files"), &show_backups,      toggle_show_backup,    0, "show-backup" },
    { 0, 0, 0, 0 }
@@ -82,7 +83,7 @@ static struct {
 
 /* Make sure this corresponds to the check_options structure */
 #define OTHER_OPTIONS 12
-#define PANEL_OPTIONS 6
+#define PANEL_OPTIONS 7
 
 static WRadio *pause_radio;
 
@@ -229,7 +230,7 @@ init_configure (void)
     /* Add checkboxes for "panel options" */
     for (i = 0; i < PANEL_OPTIONS; i++) {
 	check_options[i + OTHER_OPTIONS].widget =
-	    check_new (PY + (6 - i), PX + 2, XTRACT (i + OTHER_OPTIONS));
+	    check_new (PY + (PANEL_OPTIONS - i), PX + 2, XTRACT (i + OTHER_OPTIONS));
 	add_widget (conf_dlg, check_options[i + OTHER_OPTIONS].widget);
     }
 }
diff -purN mc-4.6.0-pre2/src/screen.c mc-4.6.0-pre2.dev/src/screen.c
--- mc-4.6.0-pre2/src/screen.c	Thu Dec 26 17:20:51 2002
+++ mc-4.6.0-pre2.dev/src/screen.c	Mon Dec 30 04:57:25 2002
@@ -44,6 +44,7 @@
 #include "user.h"
 #include "profile.h"
 #include "widget.h"
+#include "command.h"
 
 #ifdef NATIVE_WIN32
 #  include "drive.h"
@@ -389,6 +390,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 {
@@ -420,6 +429,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 *
@@ -699,6 +709,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 ();
@@ -1409,17 +1420,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";
     }
 }
 
@@ -2099,7 +2119,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)
@@ -2127,6 +2150,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 (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-pre2/src/setup.c mc-4.6.0-pre2.dev/src/setup.c
--- mc-4.6.0-pre2/src/setup.c	Thu Dec 26 17:20:51 2002
+++ mc-4.6.0-pre2.dev/src/setup.c	Mon Dec 30 04:35:21 2002
@@ -181,6 +181,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 USE_VFS
     { "vfs_timeout", &vfs_timeout },
 #ifdef USE_NETCODE
diff -purN mc-4.6.0-pre2/src/util.h mc-4.6.0-pre2.dev/src/util.h
--- mc-4.6.0-pre2/src/util.h	Thu Dec 26 14:07:10 2002
+++ mc-4.6.0-pre2.dev/src/util.h	Mon Dec 30 04:33:45 2002
@@ -30,6 +30,7 @@ void wipe_password (char *passwd);
 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);
@@ -89,6 +90,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-pre2/src/utilunix.c mc-4.6.0-pre2.dev/src/utilunix.c
--- mc-4.6.0-pre2/src/utilunix.c	Thu Dec 26 16:10:06 2002
+++ mc-4.6.0-pre2.dev/src/utilunix.c	Mon Dec 30 04:33:45 2002
@@ -725,6 +725,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-pre2/src/widget.c mc-4.6.0-pre2.dev/src/widget.c
--- mc-4.6.0-pre2/src/widget.c	Thu Dec 26 00:31:14 2002
+++ mc-4.6.0-pre2.dev/src/widget.c	Mon Dec 30 04:34:41 2002
@@ -42,6 +42,7 @@
 #include "key.h"		/* XCTRL and ALT macros  */
 #include "profile.h"	/* for history loading and saving */
 #include "wtools.h"		/* For common_dialog_repaint() */
+#include "main.h"       /* for jumpkeys */
 
 static int button_event (Gpm_Event *event, WButton *b);
 
@@ -1729,7 +1730,10 @@ listbox_draw (WListbox *l, int focused)
 	    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)
@@ -1920,7 +1924,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;
     
@@ -1960,6 +1966,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;
 }
@@ -2109,6 +2148,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-pre2/src/widget.h mc-4.6.0-pre2.dev/src/widget.h
--- mc-4.6.0-pre2/src/widget.h	Wed Nov 13 07:06:35 2002
+++ mc-4.6.0-pre2.dev/src/widget.h	Mon Dec 30 04:33:45 2002
@@ -90,6 +90,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;
@@ -122,6 +123,7 @@ typedef struct WListbox {
     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