[Patch] Link numbering with ascii characters

Martin Miller <[email protected]> Tue, 12 Jan 2016 13:35:29 -0600
Newsgroups gmane.comp.web.links
Message-ID <20160112193529.GB6427@boots>
--===============2281920510276795991==
Content-Type: multipart/signed; micalg=pgp-sha1;
	protocol="application/pgp-signature"; boundary="veXX9dWIonWZEC6h"
Content-Disposition: inline


--veXX9dWIonWZEC6h
Content-Type: multipart/mixed; boundary="w7PDEPdKQumQfZlR"
Content-Disposition: inline


--w7PDEPdKQumQfZlR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi

Let me start by saying that it was a bit tough to subscribe to this list as=
 the
information on elinks.cz is out of date, and the link to the archive makes =
it
look like there has been no ML activity since 2014.

I'm attaching a patch that allows users to label links not only with number=
s,
but with characters from a specified set. Some may be familiar with this fe=
ature
=66rom vimperator (though it's not the default) or similar keyboard driven =
GUI
browsers.

Using non-numeric link labels means that a key must be bound to bring up the
link selection dialog, whereas using numbers you can just start typing the =
link
number directly. This adds one keystroke, but alpha link labels keep your h=
ands
near the home row, which I personally find preferable.

The patch essentially lets the user set the base for link numbering and
the tokens used for the numbers. I made the default so that there is no cha=
nge,
i.e. "0123456789". For my usage, I have set
"gfdsahjkl;GFDSAHJKLtrewqyuiopvcxznm"

To bring up the link selection dialog, the user can bind "link-dialog":
   =20
    bind "main" "f" =3D "link-dialog"

I kept the functionality where typing a number will also bring up the dialo=
g.
The difference is that using a number will enter that number into the dialo=
g,
whereas using link-dialog opens with an empty text box.

I have packaged a slightly earlier version as an rpm:
ftp://witsquash.com/rpms/elinks-0.12-0.48.pre6.fc23.x86_64.rpm

Add this to your elinks.conf:

    bind "main" "f" =3D "link-dialog"
    set document.browse.links.number_links_with_key =3D "gfdsahjkl;GFDSAHJK=
Ltrewqyuiopvcxznm"

The attached patch was written against 0.12-pre6. I modified dialog behavio=
r to
agree with the above paragraph, and changed the config variable to something
shorter, so use this in your elinks.conf:

    bind "main" "f" =3D "link-dialog"
    set document.browse.links.label_key =3D "gfdsahjkl;GFDSAHJKLtrewqyuiopv=
cxznm"

Can we add this feature into elinks? Thanks and enjoy.


--=20
Martin Miller
MS Electrical Engineering 2016
University of Illinois at Urbana-Champaign
Phone: (217) 344-2850


--w7PDEPdKQumQfZlR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="elinks-0.12-pre6-linklabel.patch"
Content-Transfer-Encoding: quoted-printable

=46rom b5e209036ae308e0f11bc05342b965b38493867c Mon Sep 17 00:00:00 2001
=46rom: Martin Miller <[email protected]>
Date: Tue, 12 Jan 2016 10:26:51 -0600
Subject: [PATCH] Transfer changes for ascii link labeling

---
 src/config/actions-main.inc  |  1 +
 src/config/options.inc       |  6 ++++++
 src/document/html/renderer.c | 43 ++++++++++++++++++++++++++++++++++++++++=
++-
 src/document/html/renderer.h |  1 +
 src/viewer/action.c          |  8 ++++++++
 src/viewer/text/link.c       | 15 +++++++++++++++
 src/viewer/text/link.h       |  1 +
 src/viewer/text/view.c       | 10 ++++++++++
 8 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/src/config/actions-main.inc b/src/config/actions-main.inc
index 331af94..979245a 100644
--- a/src/config/actions-main.inc
+++ b/src/config/actions-main.inc
@@ -40,6 +40,7 @@ ACTION_(MAIN, "history-move-forward", HISTORY_MOVE_FORWAR=
D, N__("Go forward in h
 ACTION_(MAIN, "jump-to-link", JUMP_TO_LINK, N__("Jump to link"), ACTION_RE=
QUIRE_VIEW_STATE | ACTION_JUMP_TO_LINK),
 ACTION_(MAIN, "keybinding-manager", KEYBINDING_MANAGER, N__("Open keybindi=
ng manager"), ACTION_RESTRICT_ANONYMOUS),
 ACTION_(MAIN, "kill-backgrounded-connections", KILL_BACKGROUNDED_CONNECTIO=
NS, N__("Kill all backgrounded connections"), 0),
+ACTION_(MAIN, "link-dialog", LINK_DIALOG, N__("Open link selection dialog"=
), 0),
 ACTION_(MAIN, "link-download", LINK_DOWNLOAD, N__("Download the current li=
nk"), ACTION_RESTRICT_ANONYMOUS | ACTION_REQUIRE_VIEW_STATE | ACTION_REQUIR=
E_LOCATION | ACTION_JUMP_TO_LINK | ACTION_REQUIRE_LINK),
 ACTION_(MAIN, "link-download-image", LINK_DOWNLOAD_IMAGE, N__("Download th=
e current image"), ACTION_RESTRICT_ANONYMOUS | ACTION_REQUIRE_VIEW_STATE | =
ACTION_REQUIRE_LOCATION | ACTION_JUMP_TO_LINK | ACTION_REQUIRE_LINK),
 ACTION_(MAIN, "link-download-resume", LINK_DOWNLOAD_RESUME, N__("Attempt t=
o resume download of the current link"), ACTION_RESTRICT_ANONYMOUS | ACTION=
_REQUIRE_VIEW_STATE | ACTION_REQUIRE_LOCATION | ACTION_JUMP_TO_LINK | ACTIO=
N_REQUIRE_LINK),
diff --git a/src/config/options.inc b/src/config/options.inc
index 9f64204..3822794 100644
--- a/src/config/options.inc
+++ b/src/config/options.inc
@@ -344,6 +344,12 @@ static union option_info config_options_info[] =3D {
 		"the order in which links should receive focus when using the "
 		"keyboard to navigate the document.")),
=20
+    INIT_OPT_STRING("document.browse.links", N_("Specify link label key"),
+        "label_key", 0, "0123456789",
+        N_("Default is 0123456789, which is standard numeric labeling."
+           "Ascii based strings like gfdsahjkl;trewqyuiopvcxznm can also"
+           "be used.")),
+
 	INIT_OPT_BOOL("document.browse.links", N_("Missing fragment reporting"),
 		"missing_fragment", 0, 1,
 		N_("Open a message box when document has no tag with given "
diff --git a/src/document/html/renderer.c b/src/document/html/renderer.c
index 4b95f36..b1868ae 100644
--- a/src/document/html/renderer.c
+++ b/src/document/html/renderer.c
@@ -1362,9 +1362,50 @@ put_chars_conv(struct html_context *html_context,
 		       NULL, (void (*)(void *, unsigned char *, int)) put_chars, html_co=
ntext);
 }
=20
+/*
+ * Converts a number in base 10 to a string in another base whose symbols =
are
+ * represented by key. I the trivial case, key=3D"0123456789". A more home=
row
+ * friendly key=3D"gfdsahjkl;trewqyuiopvcxznm". Returns the length of link=
_sym.
+ */
+static int
+dec2qwerty(int num, char *link_sym, const char *key)
+{
+    int base =3D strlen(key);
+
+    int newlen =3D 1;
+    while (pow(base, newlen) < num) ++newlen;
+
+    link_sym[newlen] =3D '\0';
+    for (int i=3D1; i<=3Dnewlen; ++i) {
+        int key_index =3D num % base;
+        link_sym[newlen-i] =3D key[key_index];
+        num /=3D base;
+    }
+    return newlen;
+}
+
+/*
+ * Returns the value of link_sym in decimal according to key.
+ */
+int
+qwerty2dec(const char *link_sym, const char *key)
+{
+    int z =3D 0;
+    int base =3D strlen(key);
+    int symlen =3D strlen(link_sym);
+
+    for (int i=3D0; i<symlen; ++i) {
+        int j=3D0;
+        while (key[j] !=3D link_sym[symlen-1-i]) ++j;
+        z +=3D j*pow(base,i);
+    }
+    return z;
+}
+
 static inline void
 put_link_number(struct html_context *html_context)
 {
+    char *symkey =3D get_opt_str("document.browse.links.label_key");
 	struct part *part =3D html_context->part;
 	unsigned char s[64];
 	unsigned char *fl =3D format.link;
@@ -1377,7 +1418,7 @@ put_link_number(struct html_context *html_context)
 	format.form =3D NULL;
=20
 	s[slen++] =3D '[';
-	ulongcat(s, &slen, part->link_num, sizeof(s) - 3, 0);
+    slen +=3D dec2qwerty(part->link_num, s+1, symkey);
 	s[slen++] =3D ']';
 	s[slen] =3D '\0';
=20
diff --git a/src/document/html/renderer.h b/src/document/html/renderer.h
index 82e2060..ffae4cb 100644
--- a/src/document/html/renderer.h
+++ b/src/document/html/renderer.h
@@ -68,4 +68,5 @@ void free_table_cache(void);
=20
 struct part *format_html_part(struct html_context *html_context, unsigned =
char *, unsigned char *, int, int, int, struct document *, int, int, unsign=
ed char *, int);
=20
+int qwerty2dec(const char *link_sym, const char *key);
 #endif
diff --git a/src/viewer/action.c b/src/viewer/action.c
index b24979f..3c9662e 100644
--- a/src/viewer/action.c
+++ b/src/viewer/action.c
@@ -44,6 +44,11 @@
 #include "viewer/text/search.h"
 #include "viewer/text/view.h"
=20
+static void
+link_dialog_action(struct session *ses)
+{
+    open_link_dialog(ses);
+}
=20
 static void
 goto_url_action(struct session *ses,
@@ -286,6 +291,9 @@ do_action(struct session *ses, enum main_action action_=
id, int verbose)
 			abort_background_connections();
 			break;
=20
+        case ACT_MAIN_LINK_DIALOG:
+            link_dialog_action(ses);
+            break;
 		case ACT_MAIN_LINK_DOWNLOAD:
 		case ACT_MAIN_LINK_DOWNLOAD_IMAGE:
 		case ACT_MAIN_LINK_DOWNLOAD_RESUME:
diff --git a/src/viewer/text/link.c b/src/viewer/text/link.c
index f12aeff..6aca380 100644
--- a/src/viewer/text/link.c
+++ b/src/viewer/text/link.c
@@ -1202,6 +1202,21 @@ goto_link_number(struct session *ses, unsigned char =
*num)
 	goto_link_number_do(ses, doc_view, atoi(num) - 1);
 }
=20
+void
+goto_link_symbol(struct session *ses, unsigned char *sym)
+{
+    char *symkey =3D get_opt_str("document_browse.links.label_key");
+    struct document_view *doc_view;
+
+    assert(ses && sym);
+    if_assert_failed return;
+    doc_view =3D current_frame(ses);
+    assert(doc_view);
+    if_assert_failed return;
+    int num =3D qwerty2dec(sym, symkey);
+    goto_link_number_do(ses, doc_view, num - 1);
+}
+
 /** See if this document is interested in the key user pressed. */
 enum frame_event_status
 try_document_key(struct session *ses, struct document_view *doc_view,
diff --git a/src/viewer/text/link.h b/src/viewer/text/link.h
index 2f68b40..25707d8 100644
--- a/src/viewer/text/link.h
+++ b/src/viewer/text/link.h
@@ -48,6 +48,7 @@ void jump_to_link_number(struct session *ses, struct docu=
ment_view *doc_view, in
=20
 struct link *goto_current_link(struct session *ses, struct document_view *=
, int);
 void goto_link_number(struct session *ses, unsigned char *num);
+void goto_link_symbol(struct session *ses, unsigned char *sym);
 void get_link_x_bounds(struct link *link, int y, int *min_x, int *max_x);
=20
=20
diff --git a/src/viewer/text/view.c b/src/viewer/text/view.c
index 13a61f5..c78b5c4 100644
--- a/src/viewer/text/view.c
+++ b/src/viewer/text/view.c
@@ -988,6 +988,16 @@ try_mark_key(struct session *ses, struct document_view=
 *doc_view,
 }
 #endif
=20
+void
+open_link_dialog(struct session *ses)
+{
+    input_dialog(ses->tab->term, NULL,
+            N_("Go to link"), N_("Enter link number"),
+            ses, NULL,
+            MAX_STR_LEN, "", 0, 0, NULL,
+            (void (*)(void *, unsigned char *)) goto_link_symbol, NULL);
+}
+
 static enum frame_event_status
 try_prefix_key(struct session *ses, struct document_view *doc_view,
 	       struct term_event *ev)
--=20
2.5.0


--w7PDEPdKQumQfZlR--

--veXX9dWIonWZEC6h
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iEYEARECAAYFAlaVVYEACgkQBxEdxt7pqe2XRgCgrGtj/uuSPhG4PZgZRRazf+N+
eIgAnjXugUgqZS/LXTzBTNcy2F3v9paQ
=c5Wh
-----END PGP SIGNATURE-----

--veXX9dWIonWZEC6h--

--===============2281920510276795991==
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: inline

LS0gCmh0dHA6Ly9saXN0cy5saW51eGZyb21zY3JhdGNoLm9yZy9saXN0aW5mby9lbGlua3MtZGV2
ClVuc3Vic2NyaWJlOiBTZWUgdGhlIGFib3ZlIGluZm9ybWF0aW9uIHBhZ2UK

--===============2281920510276795991==--