about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile12
-rw-r--r--hinting.js194
-rw-r--r--input-focus.js29
-rw-r--r--javascript.h2
-rw-r--r--js-merge-helper.pl33
-rw-r--r--xxxterm.c101
6 files changed, 358 insertions, 13 deletions
diff --git a/Makefile b/Makefile
index 9f589db..4ff3cc7 100644
--- a/Makefile
+++ b/Makefile
@@ -20,4 +20,16 @@ LDFLAGS+= $(GTK_LDFLAGS) -pthread
 
 MANDIR= ${PREFIX}/man/cat
 
+CLEANFILES += javascript.h
+
+javascript.h: hinting.js input-focus.js
+	perl js-merge-helper.pl
+
+
+#tables.h: ${.CURDIR}/../tables ${.CURDIR}/../parsedb.pl
+#        perl ${.CURDIR}/../parsedb.pl < ${.CURDIR}/../tables
+
+
+${PROG} ${OBJS} beforedepend: javascript.h
+
 .include <bsd.prog.mk>
diff --git a/hinting.js b/hinting.js
new file mode 100644
index 0000000..2f994ee
--- /dev/null
+++ b/hinting.js
@@ -0,0 +1,194 @@
+/*
+    (c) 2009 by Leon Winter
+    (c) 2009 by Hannes Schueller
+    see LICENSE file
+*/
+
+function vimprobable_clearfocus() {
+    if(document.activeElement && document.activeElement.blur)
+        document.activeElement.blur();
+}
+
+function vimprobable_show_hints(inputText) {
+    if (document.getElementsByTagName("body")[0] !== null && typeof(document.getElementsByTagName("body")[0]) == "object") {
+        var height = window.innerHeight;
+        var width = window.innerWidth;
+        var scrollX = document.defaultView.scrollX;
+        var scrollY = document.defaultView.scrollY;
+        /* prefixing html: will result in namespace error */
+        var hinttags;
+        if (typeof(inputText) == "undefined" || inputText == "") {
+            hinttags = "//*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href] | //input[not(@type='hidden')] | //a | //area | //iframe | //textarea | //button | //select";
+        } else {
+            /* only elements which match the text entered so far */
+            hinttags = "//*[(@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href) and contains(., '" + inputText + "')] | //input[not(@type='hidden') and contains(., '" + inputText + "')] | //a[contains(., '" + inputText + "')] | //area[contains(., '" + inputText + "')] | //iframe[contains(@name, '" + inputText + "')] | //textarea[contains(., '" + inputText + "')] | //button[contains(@value, '" + inputText + "')] | //select[contains(., '" + inputText + "')]";
+        }
+
+        /* iterator type isn't suitable here, because: "DOMException NVALID_STATE_ERR: The document has been mutated since the result was returned." */
+        var r = document.evaluate(hinttags, document,
+            function(p) {
+                return 'http://www.w3.org/1999/xhtml';
+            }, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+        div = document.createElement("div");
+        /* due to the different XPath result type, we will need two counter variables */
+        vimprobable_j = 0;
+        var i;
+        vimprobable_a = [];
+        vimprobable_colors = [];
+        vimprobable_backgrounds = [];
+        for (i = 0; i < r.snapshotLength; i++)
+        {
+            var elem = r.snapshotItem(i);
+            rect = elem.getBoundingClientRect();
+            if (!rect || rect.top > height || rect.bottom < 0 || rect.left > width || rect.right < 0 || !(elem.getClientRects()[0]))
+                continue;
+            var computedStyle = document.defaultView.getComputedStyle(elem, null);
+            if (computedStyle.getPropertyValue("visibility") != "visible" || computedStyle.getPropertyValue("display") == "none")
+                continue;
+            var leftpos = Math.max((rect.left + scrollX), scrollX);
+            var toppos = Math.max((rect.top + scrollY), scrollY);
+            vimprobable_a.push(elem);
+            /* making this block DOM compliant */
+            var hint = document.createElement("span");
+            hint.setAttribute("class", "hinting_mode_hint");
+            hint.setAttribute("id", "vimprobablehint" + vimprobable_j);
+            hint.style.position = "absolute";
+            hint.style.left = leftpos + "px";
+            hint.style.top =  toppos + "px";
+            hint.style.background = "red";
+            hint.style.color = "#fff";
+            hint.style.font = "bold 10px monospace";
+            hint.style.zIndex = "99";
+            var text = document.createTextNode(vimprobable_j + 1);
+            hint.appendChild(text);
+            div.appendChild(hint);
+            /* remember site-defined colour of this element */
+            vimprobable_colors[vimprobable_j] = elem.style.color;
+            vimprobable_backgrounds[vimprobable_j] = elem.style.background;
+            /* make the link black to ensure it's readable */
+            elem.style.color = "#000";
+            elem.style.background = "#ff0";
+            vimprobable_j++;
+        }
+        i = 0;
+        while (typeof(vimprobable_a[i]) != "undefined") {
+            vimprobable_a[i].className += " hinting_mode_hint";
+            i++;
+        }
+        document.getElementsByTagName("body")[0].appendChild(div);
+        vimprobable_clearfocus();
+        vimprobable_h = null;
+        if (i == 1) {
+            /* just one hinted element - might as well follow it */
+            return vimprobable_fire(1);
+        }
+	return "found;" + i;
+    }
+}
+function vimprobable_fire(n)
+{
+    if (typeof(vimprobable_a[n - 1]) != "undefined") {
+        el = vimprobable_a[n - 1];
+        tag = el.nodeName.toLowerCase();
+        vimprobable_clear();
+        if(tag == "iframe" || tag == "frame" || tag == "textarea" || tag == "input" && (el.type == "text" || el.type == "password" || el.type == "checkbox" || el.type == "radio") || tag == "select") {
+            el.focus();
+            if (tag == "textarea" || tag == "input")
+                console.log('insertmode_on');
+        } else {
+            if (el.onclick) {
+                var evObj = document.createEvent('MouseEvents');
+                evObj.initMouseEvent('click', true, true, window, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, null);
+                el.dispatchEvent(evObj);
+            } else if (el.href) {
+                if (el.href.match(/^javascript:/)) {
+                    var evObj = document.createEvent('MouseEvents');
+                    evObj.initMouseEvent('click', true, true, window, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, null);
+                    el.dispatchEvent(evObj);
+                } else {
+                    /* send signal to open link */
+                    return "open;" + el.href;
+                }
+            } else {
+                var evObj = document.createEvent('MouseEvents');
+                evObj.initMouseEvent('click', true, true, window, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, null);
+                el.dispatchEvent(evObj);
+            }
+        }
+    }
+}
+function vimprobable_cleanup()
+{
+    for(e in vimprobable_a) {
+        if (typeof(vimprobable_a[e].className) != "undefined") {
+            vimprobable_a[e].className = vimprobable_a[e].className.replace(/hinting_mode_hint/,'');
+            /* reset to site-defined colour */
+            vimprobable_a[e].style.color = vimprobable_colors[e];
+            vimprobable_a[e].style.background = vimprobable_backgrounds[e];
+        }
+    }
+    div.parentNode.removeChild(div);
+    window.onkeyup = null;
+}
+function vimprobable_clear()
+{
+    vimprobable_cleanup();
+    console.log("hintmode_off")
+}
+
+function vimprobable_update_hints(n)
+{
+    if(vimprobable_h != null) {
+        vimprobable_h.className = vimprobable_h.className.replace("_focus","");
+        vimprobable_h.style.background = "#ff0";
+    }
+    if (vimprobable_j - 1 < n * 10 && typeof(vimprobable_a[n - 1]) != "undefined") {
+        /* return signal to follow the link */
+        return "fire;" + n;
+    } else {
+        if (typeof(vimprobable_a[n - 1]) != "undefined") {
+            (vimprobable_h = vimprobable_a[n - 1]).className = vimprobable_a[n - 1].className.replace("hinting_mode_hint", "hinting_mode_hint_focus");
+            vimprobable_h.style.background = "#8f0";
+        }
+    }
+}
+
+function vimprobable_focus_input()
+{
+    if (document.getElementsByTagName("body")[0] !== null && typeof(document.getElementsByTagName("body")[0]) == "object") {
+        /* prefixing html: will result in namespace error */
+        var hinttags = "//input[@type='text'] | //input[@type='password'] | //textarea";
+        var r = document.evaluate(hinttags, document,
+            function(p) {
+                return 'http://www.w3.org/1999/xhtml';
+            }, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+        var i;
+        var j = 0;
+        var first = null;
+        for (i = 0; i < r.snapshotLength; i++) {
+            var elem = r.snapshotItem(i);
+            if (i == 0) {
+                first = elem;
+            }
+            if (j == 1) {
+                elem.focus();
+                var tag = elem.nodeName.toLowerCase();
+                if (tag == "textarea" || tag == "input")
+                    console.log('insertmode_on');
+                break;
+            } else {
+                if (elem == document.activeElement)
+                    j = 1;
+            }
+        }
+        if (j == 0) {
+            /* no appropriate field found focused - focus the first one */
+            if (first !== null) {
+                first.focus();
+                var tag = elem.nodeName.toLowerCase();
+                if (tag == "textarea" || tag == "input")
+                    console.log('insertmode_on');
+            }
+        }
+    }
+}
diff --git a/input-focus.js b/input-focus.js
new file mode 100644
index 0000000..323efd0
--- /dev/null
+++ b/input-focus.js
@@ -0,0 +1,29 @@
+/*
+    (c) 2009 by Leon Winter
+    (c) 2009 by Hannes Schueller
+    see LICENSE file
+*/
+
+function vimprobable_v(e, y) {
+    t = e.nodeName.toLowerCase();
+    if((t == 'input' && /^(text|password|checkbox|radio)$/.test(e.type))
+    || /^(select|textarea)$/.test(t)
+    || e.contentEditable == 'true')
+        console.log('insertmode_'+(y=='focus'?'on':'off'));
+}
+
+if(document.activeElement)
+    vimprobable_v(document.activeElement,'focus');
+
+vimprobable_m=['focus','blur'];
+
+if (document.getElementsByTagName("body")[0] !== null && typeof(document.getElementsByTagName("body")[0]) == "object") {
+    for(i in vimprobable_m)
+        document.getElementsByTagName('body')[0].addEventListener(vimprobable_m[i], function(x) {
+            vimprobable_v(x.target,x.type);
+        }, true);
+}
+
+self.onunload = function() {
+    vimprobable_v(document.activeElement, '');
+};
diff --git a/javascript.h b/javascript.h
index 6184b0d..45cce4d 100644
--- a/javascript.h
+++ b/javascript.h
@@ -1,2 +1,2 @@
-#define JS_SETUP_HINTS "/*(c)2009 by Leon Winter(c)2009 by Hannes Schueller see LICENSE file*/ function vimprobable_clearfocus(){if(document.activeElement&&document.activeElement.blur)document.activeElement.blur();}function vimprobable_show_hints(inputText){if(document.getElementsByTagName(\"body\")[0]!==null&&typeof(document.getElementsByTagName(\"body\")[0])==\"object\"){var height=window.innerHeight;var width=window.innerWidth;var scrollX=document.defaultView.scrollX;var scrollY=document.defaultView.scrollY;var hinttags;if(typeof(inputText)==\"undefined\"||inputText==\"\"){hinttags=\"//*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href]|//input[not(@type='hidden')]|//a|//area|//iframe|//textarea|//button|//select\";}else{hinttags=\"//*[(@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href)and contains(.,'\"+inputText+\"')]|//input[not(@type='hidden')and contains(.,'\"+inputText+\"')]|//a[contains(.,'\"+inputText+\"')]|//area[contains(.,'\"+inputText+\"')]|//iframe[contains(@name,'\"+inputText+\"')]|//textarea[contains(.,'\"+inputText+\"')]|//button[contains(@value,'\"+inputText+\"')]|//select[contains(.,'\"+inputText+\"')]\";}var r=document.evaluate(hinttags,document,function(p){return 'http://www.w3.org/1999/xhtml';},XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);div=document.createElement(\"div\");vimprobable_j=0;var i;vimprobable_a=[];vimprobable_colors=[];vimprobable_backgrounds=[];for(i=0;i<r.snapshotLength;i++){var elem=r.snapshotItem(i);rect=elem.getBoundingClientRect();if(!rect||rect.top>height||rect.bottom<0||rect.left>width||rect.right<0||!(elem.getClientRects()[0]))continue;var computedStyle=document.defaultView.getComputedStyle(elem,null);if(computedStyle.getPropertyValue(\"visibility\")!=\"visible\"||computedStyle.getPropertyValue(\"display\")==\"none\")continue;var leftpos=Math.max((rect.left+scrollX),scrollX);var toppos=Math.max((rect.top+scrollY),scrollY);vimprobable_a.push(elem);var hint=document.createElement(\"span\");hint.setAttribute(\"class\",\"hinting_mode_hint\");hint.setAttribute(\"id\",\"vimprobablehint\"+vimprobable_j);hint.style.position=\"absolute\";hint.style.left=leftpos+\"px\";hint.style.top=toppos+\"px\";hint.style.background=\"red\";hint.style.color=\"#fff\";hint.style.font=\"bold 10px monospace\";hint.style.zIndex=\"99\";var text=document.createTextNode(vimprobable_j+1);hint.appendChild(text);div.appendChild(hint);vimprobable_colors[vimprobable_j]=elem.style.color;vimprobable_backgrounds[vimprobable_j]=elem.style.background;elem.style.color=\"#000\";elem.style.background=\"#ff0\";vimprobable_j++;}i=0;while(typeof(vimprobable_a[i])!=\"undefined\"){vimprobable_a[i].className+=\" hinting_mode_hint\";i++;}document.getElementsByTagName(\"body\")[0].appendChild(div);vimprobable_clearfocus();vimprobable_h=null;if(i==1){return vimprobable_fire(1);}}}function vimprobable_fire(n){if(typeof(vimprobable_a[n-1])!=\"undefined\"){el=vimprobable_a[n-1];tag=el.nodeName.toLowerCase();vimprobable_clear();if(tag==\"iframe\"||tag==\"frame\"||tag==\"textarea\"||tag==\"input\"&&(el.type==\"text\"||el.type==\"password\"||el.type==\"checkbox\"||el.type==\"radio\")||tag==\"select\"){el.focus();if(tag==\"textarea\"||tag==\"input\")console.log('insertmode_on');}else{if(el.onclick){var evObj=document.createEvent('MouseEvents');evObj.initMouseEvent('click',true,true,window,1,1,1,0,0,0,0,0,0,0,null);el.dispatchEvent(evObj);}else if(el.href){if(el.href.match(/^javascript:/)){var evObj=document.createEvent('MouseEvents');evObj.initMouseEvent('click',true,true,window,1,1,1,0,0,0,0,0,0,0,null);el.dispatchEvent(evObj);}else{return \"open;\"+el.href;}}else{var evObj=document.createEvent('MouseEvents');evObj.initMouseEvent('click',true,true,window,1,1,1,0,0,0,0,0,0,0,null);el.dispatchEvent(evObj);}}}}function vimprobable_cleanup(){for(e in vimprobable_a){if(typeof(vimprobable_a[e].className)!=\"undefined\"){vimprobable_a[e].className=vimprobable_a[e].className.replace(/hinting_mode_hint/,'');vimprobable_a[e].style.color=vimprobable_colors[e];vimprobable_a[e].style.background=vimprobable_backgrounds[e];}}div.parentNode.removeChild(div);window.onkeyup=null;}function vimprobable_clear(){vimprobable_cleanup();console.log(\"hintmode_off\")}function vimprobable_update_hints(n){if(vimprobable_h!=null){vimprobable_h.className=vimprobable_h.className.replace(\"_focus\",\"\");vimprobable_h.style.background=\"#ff0\";}if(vimprobable_j-1<n*10&&typeof(vimprobable_a[n-1])!=\"undefined\"){return \"fire;\"+n;}else{if(typeof(vimprobable_a[n-1])!=\"undefined\"){(vimprobable_h=vimprobable_a[n-1]).className=vimprobable_a[n-1].className.replace(\"hinting_mode_hint\",\"hinting_mode_hint_focus\");vimprobable_h.style.background=\"#8f0\";}}}function vimprobable_focus_input(){if(document.getElementsByTagName(\"body\")[0]!==null&&typeof(document.getElementsByTagName(\"body\")[0])==\"object\"){var hinttags=\"//input[@type='text']|//input[@type='password']|//textarea\";var r=document.evaluate(hinttags,document,function(p){return 'http://www.w3.org/1999/xhtml';},XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);var i;var j=0;var first=null;for(i=0;i<r.snapshotLength;i++){var elem=r.snapshotItem(i);if(i==0){first=elem;}if(j==1){elem.focus();var tag=elem.nodeName.toLowerCase();if(tag==\"textarea\"||tag==\"input\")console.log('insertmode_on');break;}else{if(elem==document.activeElement)j=1;}}if(j==0){if(first!==null){first.focus();var tag=elem.nodeName.toLowerCase();if(tag==\"textarea\"||tag==\"input\")console.log('insertmode_on');}}}}"
+#define JS_SETUP_HINTS "/*(c)2009 by Leon Winter(c)2009 by Hannes Schueller see LICENSE file*/ function vimprobable_clearfocus(){if(document.activeElement&&document.activeElement.blur)document.activeElement.blur();}function vimprobable_show_hints(inputText){if(document.getElementsByTagName(\"body\")[0]!==null&&typeof(document.getElementsByTagName(\"body\")[0])==\"object\"){var height=window.innerHeight;var width=window.innerWidth;var scrollX=document.defaultView.scrollX;var scrollY=document.defaultView.scrollY;var hinttags;if(typeof(inputText)==\"undefined\"||inputText==\"\"){hinttags=\"//*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href]|//input[not(@type='hidden')]|//a|//area|//iframe|//textarea|//button|//select\";}else{hinttags=\"//*[(@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href)and contains(.,'\"+inputText+\"')]|//input[not(@type='hidden')and contains(.,'\"+inputText+\"')]|//a[contains(.,'\"+inputText+\"')]|//area[contains(.,'\"+inputText+\"')]|//iframe[contains(@name,'\"+inputText+\"')]|//textarea[contains(.,'\"+inputText+\"')]|//button[contains(@value,'\"+inputText+\"')]|//select[contains(.,'\"+inputText+\"')]\";}var r=document.evaluate(hinttags,document,function(p){return 'http://www.w3.org/1999/xhtml';},XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);div=document.createElement(\"div\");vimprobable_j=0;var i;vimprobable_a=[];vimprobable_colors=[];vimprobable_backgrounds=[];for(i=0;i<r.snapshotLength;i++){var elem=r.snapshotItem(i);rect=elem.getBoundingClientRect();if(!rect||rect.top>height||rect.bottom<0||rect.left>width||rect.right<0||!(elem.getClientRects()[0]))continue;var computedStyle=document.defaultView.getComputedStyle(elem,null);if(computedStyle.getPropertyValue(\"visibility\")!=\"visible\"||computedStyle.getPropertyValue(\"display\")==\"none\")continue;var leftpos=Math.max((rect.left+scrollX),scrollX);var toppos=Math.max((rect.top+scrollY),scrollY);vimprobable_a.push(elem);var hint=document.createElement(\"span\");hint.setAttribute(\"class\",\"hinting_mode_hint\");hint.setAttribute(\"id\",\"vimprobablehint\"+vimprobable_j);hint.style.position=\"absolute\";hint.style.left=leftpos+\"px\";hint.style.top=toppos+\"px\";hint.style.background=\"red\";hint.style.color=\"#fff\";hint.style.font=\"bold 10px monospace\";hint.style.zIndex=\"99\";var text=document.createTextNode(vimprobable_j+1);hint.appendChild(text);div.appendChild(hint);vimprobable_colors[vimprobable_j]=elem.style.color;vimprobable_backgrounds[vimprobable_j]=elem.style.background;elem.style.color=\"#000\";elem.style.background=\"#ff0\";vimprobable_j++;}i=0;while(typeof(vimprobable_a[i])!=\"undefined\"){vimprobable_a[i].className+=\" hinting_mode_hint\";i++;}document.getElementsByTagName(\"body\")[0].appendChild(div);vimprobable_clearfocus();vimprobable_h=null;if(i==1){return vimprobable_fire(1);}return \"found;\"+i;}}function vimprobable_fire(n){if(typeof(vimprobable_a[n-1])!=\"undefined\"){el=vimprobable_a[n-1];tag=el.nodeName.toLowerCase();vimprobable_clear();if(tag==\"iframe\"||tag==\"frame\"||tag==\"textarea\"||tag==\"input\"&&(el.type==\"text\"||el.type==\"password\"||el.type==\"checkbox\"||el.type==\"radio\")||tag==\"select\"){el.focus();if(tag==\"textarea\"||tag==\"input\")console.log('insertmode_on');}else{if(el.onclick){var evObj=document.createEvent('MouseEvents');evObj.initMouseEvent('click',true,true,window,1,1,1,0,0,0,0,0,0,0,null);el.dispatchEvent(evObj);}else if(el.href){if(el.href.match(/^javascript:/)){var evObj=document.createEvent('MouseEvents');evObj.initMouseEvent('click',true,true,window,1,1,1,0,0,0,0,0,0,0,null);el.dispatchEvent(evObj);}else{return \"open;\"+el.href;}}else{var evObj=document.createEvent('MouseEvents');evObj.initMouseEvent('click',true,true,window,1,1,1,0,0,0,0,0,0,0,null);el.dispatchEvent(evObj);}}}}function vimprobable_cleanup(){for(e in vimprobable_a){if(typeof(vimprobable_a[e].className)!=\"undefined\"){vimprobable_a[e].className=vimprobable_a[e].className.replace(/hinting_mode_hint/,'');vimprobable_a[e].style.color=vimprobable_colors[e];vimprobable_a[e].style.background=vimprobable_backgrounds[e];}}div.parentNode.removeChild(div);window.onkeyup=null;}function vimprobable_clear(){vimprobable_cleanup();console.log(\"hintmode_off\")}function vimprobable_update_hints(n){if(vimprobable_h!=null){vimprobable_h.className=vimprobable_h.className.replace(\"_focus\",\"\");vimprobable_h.style.background=\"#ff0\";}if(vimprobable_j-1<n*10&&typeof(vimprobable_a[n-1])!=\"undefined\"){return \"fire;\"+n;}else{if(typeof(vimprobable_a[n-1])!=\"undefined\"){(vimprobable_h=vimprobable_a[n-1]).className=vimprobable_a[n-1].className.replace(\"hinting_mode_hint\",\"hinting_mode_hint_focus\");vimprobable_h.style.background=\"#8f0\";}}}function vimprobable_focus_input(){if(document.getElementsByTagName(\"body\")[0]!==null&&typeof(document.getElementsByTagName(\"body\")[0])==\"object\"){var hinttags=\"//input[@type='text']|//input[@type='password']|//textarea\";var r=document.evaluate(hinttags,document,function(p){return 'http://www.w3.org/1999/xhtml';},XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);var i;var j=0;var first=null;for(i=0;i<r.snapshotLength;i++){var elem=r.snapshotItem(i);if(i==0){first=elem;}if(j==1){elem.focus();var tag=elem.nodeName.toLowerCase();if(tag==\"textarea\"||tag==\"input\")console.log('insertmode_on');break;}else{if(elem==document.activeElement)j=1;}}if(j==0){if(first!==null){first.focus();var tag=elem.nodeName.toLowerCase();if(tag==\"textarea\"||tag==\"input\")console.log('insertmode_on');}}}}"
 #define JS_SETUP_INPUT_FOCUS "/*(c)2009 by Leon Winter(c)2009 by Hannes Schueller see LICENSE file*/ function vimprobable_v(e,y){t=e.nodeName.toLowerCase();if((t=='input'&&/^(text|password|checkbox|radio)$/.test(e.type))||/^(select|textarea)$/.test(t)||e.contentEditable=='true')console.log('insertmode_'+(y=='focus'?'on':'off'));}if(document.activeElement)vimprobable_v(document.activeElement,'focus');vimprobable_m=['focus','blur'];if(document.getElementsByTagName(\"body\")[0]!==null&&typeof(document.getElementsByTagName(\"body\")[0])==\"object\"){for(i in vimprobable_m)document.getElementsByTagName('body')[0].addEventListener(vimprobable_m[i],function(x){vimprobable_v(x.target,x.type);},true);}self.onunload=function(){vimprobable_v(document.activeElement,'');};"
diff --git a/js-merge-helper.pl b/js-merge-helper.pl
new file mode 100644
index 0000000..050d871
--- /dev/null
+++ b/js-merge-helper.pl
@@ -0,0 +1,33 @@
+#!/bin/env perl -w
+use strict;
+
+sub escape_c_string {
+	shift;
+	s/\t|\r|\n/ /g;     # convert spacings to whitespaces
+	s/[^\/]\/\*.*?\*\///g;   # remove comments (careful: hinttags look like comment!)
+	s/ {2,}/ /g;        # strip whitespaces
+	s/(^|\(|\)|;|,|:|\}|\{|=|\+|\-|\*|\&|\||\<|\>|!) +/$1/g;
+	s/ +($|\(|\)|;|,|:|\}|\{|=|\+|\-|\*|\&|\||\<|\>|!)/$1/g;
+	s/\\/\\\\/g;        # escape backslashes
+	s/\"/\\\"/g;        # escape quotes
+	return $_
+}
+
+open(JSFILE, "hinting.js") or die "Failed to open file: $!";
+$_ = do { local $/; <JSFILE> };
+close(JSFILE);
+my $js_hints = escape_c_string($_);
+
+open(JSFILE, "input-focus.js") or die "Failed to open file: $!";
+$_ = do { local $/; <JSFILE> };
+close(JSFILE);
+my $js_input = escape_c_string($_);
+
+open(HFILE, ">javascript.h") or die "Failed to open javascript.h: $!";
+print HFILE "#define JS_SETUP_HINTS ";
+printf  HFILE "\"%s\"\n", $js_hints;
+print HFILE "#define JS_SETUP_INPUT_FOCUS ";
+printf  HFILE "\"%s\"\n", $js_input;
+close(HFILE);
+
+exit;
diff --git a/xxxterm.c b/xxxterm.c
index 71a2333..97a0ed8 100644
--- a/xxxterm.c
+++ b/xxxterm.c
@@ -138,13 +138,18 @@ struct tab {
 	GtkAdjustment		*adjust_v;
 
 	/* flags */
-	int			hints_on;
 	int			focus_wv;
 	int			ctrl_click;
 	gchar			*hover;
 
 	/* hints */
+	int			hints_on;
+	int			hint_mode;
+#define XT_HINT_NONE		(0)
+#define XT_HINT_NUMERICAL	(1)
+#define XT_HINT_ALPHANUM	(2)
 	char			hint_buf[128];
+	char			hint_num[128];
 
 	/* search */
 	char			*search_text;
@@ -556,8 +561,10 @@ void
 disable_hints(struct tab *t)
 {
 	bzero(t->hint_buf, sizeof t->hint_buf);
+	bzero(t->hint_num, sizeof t->hint_num);
 	run_script(t, "vimprobable_clear()");
 	t->hints_on = 0;
+	t->hint_mode = XT_HINT_NONE;
 }
 
 void
@@ -566,12 +573,15 @@ enable_hints(struct tab *t)
 	bzero(t->hint_buf, sizeof t->hint_buf);
 	run_script(t, "vimprobable_show_hints()");
 	t->hints_on = 1;
+	t->hint_mode = XT_HINT_NONE;
 }
 
 #define XT_JS_OPEN	("open;")
 #define XT_JS_OPEN_LEN	(strlen(XT_JS_OPEN))
 #define XT_JS_FIRE	("fire;")
 #define XT_JS_FIRE_LEN	(strlen(XT_JS_FIRE))
+#define XT_JS_FOUND	("found;")
+#define XT_JS_FOUND_LEN	(strlen(XT_JS_FOUND))
 
 int
 run_script(struct tab *t, char *s)
@@ -616,6 +626,11 @@ run_script(struct tab *t, char *s)
 			disable_hints(t);
 		}
 
+		if (!strncmp(es, XT_JS_FOUND, XT_JS_FOUND_LEN)) {
+			if (atoi(&es[XT_JS_FOUND_LEN]) == 0)
+				disable_hints(t);
+		}
+
 		free(es);
 	}
 
@@ -1687,41 +1702,103 @@ webview_keypress_cb(GtkWidget *w, GdkEventKey *e, struct tab *t)
 
 		/* RETURN */
 		if (CLEAN(e->state) == 0 && e->keyval == GDK_Return) {
-			link = strtonum(t->hint_buf, 1, 1000, &errstr);
+			link = strtonum(t->hint_num, 1, 1000, &errstr);
 			if (errstr) {
 				/* we have a string */
 			} else {
 				/* we have a number */
 				snprintf(buf, sizeof buf, "vimprobable_fire(%s)",
-				    t->hint_buf);
+				    t->hint_num);
 				run_script(t, buf);
 			}
-			/* FALLTHROUGH */
+			disable_hints(t);
+		}
+
+		/* BACKSPACE */
+		/* XXX unfuck this */
+		if (CLEAN(e->state) == 0 && e->keyval == GDK_BackSpace) {
+			if (t->hint_mode == XT_HINT_NUMERICAL) {
+				/* last input was numerical */
+				int		l;
+				l = strlen(t->hint_num);
+				if (l > 0) {
+					l--;
+					if (l == 0) {
+						disable_hints(t);
+						enable_hints(t);
+					} else {
+						t->hint_num[l] = '\0';
+						goto num;
+					}
+				}
+			} else if (t->hint_mode == XT_HINT_ALPHANUM) {
+				/* last input was alphanumerical */
+				int		l;
+				l = strlen(t->hint_buf);
+				if (l > 0) {
+					l--;
+					if (l == 0) {
+						disable_hints(t);
+						enable_hints(t);
+					} else {
+						t->hint_buf[l] = '\0';
+						goto anum;
+					}
+				}
+			} else {
+				/* bogus */
+				disable_hints(t);
+			}
 		}
 
 		/* numerical input */
 		if (CLEAN(e->state) == 0 &&
-		    (e->keyval >= GDK_0 && e->keyval <= GDK_9)) {
+		    ((e->keyval >= GDK_0 && e->keyval <= GDK_9) || (e->keyval >= GDK_KP_0 && e->keyval <= GDK_KP_9))) {
 			snprintf(s, sizeof s, "%c", e->keyval);
-			strlcat(t->hint_buf, s, sizeof t->hint_buf);
+			strlcat(t->hint_num, s, sizeof t->hint_num);
 			DNPRINTF(XT_D_JS, "webview_keypress_cb: numerical %s\n",
-			    t->hint_buf);
-
-			link = strtonum(t->hint_buf, 1, 1000, &errstr);
+			    t->hint_num);
+num:
+			link = strtonum(t->hint_num, 1, 1000, &errstr);
 			if (errstr) {
 				DNPRINTF(XT_D_JS, "webview_keypress_cb: invalid link number\n");
 				disable_hints(t);
 			} else {
 				snprintf(buf, sizeof buf, "vimprobable_update_hints(%s)",
-				    t->hint_buf);
+				    t->hint_num);
+				t->hint_mode = XT_HINT_NUMERICAL;
 				run_script(t, buf);
 			}
 
+			/* empty the counter buffer */
+			bzero(t->hint_buf, sizeof t->hint_buf);
+			return (XT_CB_HANDLED);
+		}
+
+		/* alphanumerical input */
+		if (
+		    (CLEAN(e->state) == 0 && e->keyval >= GDK_a && e->keyval <= GDK_z) ||
+		    (CLEAN(e->state) == GDK_SHIFT_MASK && e->keyval >= GDK_A && e->keyval <= GDK_Z) ||
+		    (CLEAN(e->state) == 0 && ((e->keyval >= GDK_0 && e->keyval <= GDK_9) ||
+		    ((e->keyval >= GDK_KP_0 && e->keyval <= GDK_KP_9) && (t->hint_mode != XT_HINT_NUMERICAL))))) {
+			snprintf(s, sizeof s, "%c", e->keyval);
+			strlcat(t->hint_buf, s, sizeof t->hint_buf);
+			DNPRINTF(XT_D_JS, "webview_keypress_cb: alphanumerical %s\n",
+			    t->hint_buf);
+anum:
+			snprintf(buf, sizeof buf, "vimprobable_cleanup()");
+			run_script(t, buf);
+
+			snprintf(buf, sizeof buf, "vimprobable_show_hints('%s')",
+			    t->hint_buf);
+			t->hint_mode = XT_HINT_ALPHANUM;
+			run_script(t, buf);
+
+			/* empty the counter buffer */
+			bzero(t->hint_num, sizeof t->hint_num);
 			return (XT_CB_HANDLED);
 		}
 
-		/* unhandled so invalid hint handling */
-		disable_hints(t);
 		return (XT_CB_HANDLED);
 	}