/*
JSVI - VI in JavaScript.
Copyright (C) 2006-2008 Internet Connection, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
var emacsen = false;
//Making a comment
/* TODO
sortof bugs:
the toolbar is kind of ugly- possibly replace with an image-version-
or more likely- replace with styled buttons
ideas:
uneditable sections?
a ruler at the 72 character mark? possibly word-wrapping?
want to switch between vi/emacs modes?
*/
var term_cols;
var term_rows;
var term_win_width;
var term_win_height;
var term_cur_width;
var tools;
var suggest;
var backing;
var tagstyle = 0;
var line_height = 0;
var cclick = undefined;
var mode = 0;
var accum = 0;
var lastaccum = 0;
var marks = new Object();
var registers = new Object();
var lastreg = '';
var lastcommand;
var lastmotion;
var cursoriv;
var drawiv;
var printer;
var term;
var base = 0;
var left = 0;
var vselm = 0;
var vselx = undefined;
var vsely = undefined;
var vseld = false;
var lastkey = undefined;
var statustext = '';
var command = '';
var oldcommand = '';
var commandleft = 0;
var savex, savey;
var once = true;
var cursorx, cursory;
var file = new Array();
var tags = new Array();
var palette;
var cursor;
var yank_buffer = undefined;
var term_save_h = new Array();
var term_save_ss;
var term_save_mc;
var term_save_kd;
var term_save_kp;
var term_save_rs;
var term_save_op;
var lastsearch;
var lastsubst;
var lastflags;
var undoset = undefined;
var undoline = undefined;
var undoy = -1;
var term_ex_motion;
var vi_ft_reg;
var viflags = '';
var lastinsert = '';
var spelling = false;
var spellcheck = new Object();
var safewords = new Object();
var brokenwords = new Object();
var suggestions = new Object();
safewords['jsvi']=true;
safewords['javascript']=true;
safewords['URL']=true;
safewords['hyperlinks']=true;
safewords['HTML']=true;
safewords['UNIX']=true;
safewords['Firefox']=true;
safewords['MSIE']=true;
safewords['Ctrl']=true;
safewords['vi']=true;
safewords['vi-keys']=true;
safewords[':hardcopy']=true;
safewords['unicode-aware']=true;
safewords['developer-centric']=true;
var doing_backing_paste = false;
function _true() { return true; }
function _false() { return false; }
function _cbrestore() {
var i;
for (i = 0; i < term_save_h.length; i++) {
var z = term_save_h[i];
z();
}
term_save_h = new Array();
}
function _cbw(nx,ny) {
var nz = window['on'+nx];
(function(x,y,z) {
term_save_h[term_save_h.length] = function() {
window['on'+x] = z;
};
})(nx,ny,nz);
window['on'+nx]=ny;
}
function _cbd(nx,ny) {
var nz = document['on'+nx];
(function(x,y,z) {
term_save_h[term_save_h.length] = function() {
document['on'+x] = z;
};
})(nx, ny, nz);
document['on'+nx]=ny;
}
function _rer(re,t,aa) {
if (RegExp.rightContext != undefined) return RegExp.rightContext;
// emulate rightContext
var s = re.toString();
if ((s.substr(0,2) == '/^' && s.substr(s.length-1,1) == '/') || s.substr(0,1) == '^') {
// bound at beginning
return t.substr(aa[0].length, t.length - aa[0].length);
}
if ((s.substr(0,1) == '/' && s.substr(s.length-2,2) == '$/') || s.substr(s.length-1,1) == '$') {
// bound at end
return "";
}
var j = t.lastIndexOf(aa[0]);
if (j != -1) return t.substr(j.t.length-j);
return t;
}
function _rel(re,t,aa) {
if (RegExp.leftContext != undefined) return RegExp.leftContext;
// emulate leftContext
var s = re.toString();
if ((s.substr(0,2) == '/^' && s.substr(s.length-1,1) == '/') || s.substr(0,1) == '^') {
// bound at beginning
return "";
}
if ((s.substr(0,1) == '/' && s.substr(s.length-2,2) == '$/') || s.substr(s.length-1,1) == '$') {
// bound at end
return t.substr(0, t.length - aa[0].length);
}
var j = t.indexOf(aa[0]);
if (j != -1) return t.substr(0,j);
return "";
}
function _hra(x) {
var i;
var cx = 0;
var t = '';
var g = '';
for (i = 0; i < x.length; i++) {
var x3 = x.substr(i,3);
var gx = String.fromCharCode(cx);
if (x3 == '') {
cx = cx | 1;
i += 2;
} else if (x3 == '') {
cx = cx | 2;
i += 2;
} else if (x3 == '') {
cx = cx | 16;
i += 2;
} else if (x3 == '
cx = cx | 4;
i += 16;
} else if (x3 == '
cx = (cx | 4) ^ 4;
i += 6;
} else if (x3 == '&am') { // &
t += '&';
g += gx;
i += 4;
} else if (x3 == '<') { // <
t += '<';
g += gx;
i += 3;
} else {
t += x.substr(i,1);
g += gx;
}
}
var aa = new Array();
aa[0] = t;
aa[1] = g;
return aa;
}
function _rtf(t,g) {
var cx = 0;
var i;
var o = '';
if (t == undefined) {
t = '';
g = '';
}
for (i = 0; i < t.length; i++) {
var gx = g.substr(i, 1).charCodeAt(0);
var tx = t.substr(i, 1);
if (tx == "<") tx = "<";
else if (tx == '&') tx = '&';
if (gx != cx) {
if ((gx & 1) && !(cx & 1)) {
o += "";
} else if (!(gx & 1) && (cx & 1)) {
o += "";
}
if ((gx & 2) && !(cx & 2)) {
o += "";
} else if (!(gx & 2) && (cx & 2)) {
o += "";
}
if ((gx & 4) && !(cx & 4)) {
o += "";
} else if (!(gx & 4) && (cx & 4)) {
o += "";
}
if ((gx & 16) && !(cx & 16)) {
o += "";
} else if (!(gx & 16) && (cx & 16)) {
o += "";
}
cx = gx;
}
o += tx;
}
return o;
}
function _rtfl(y) {
return _rtf(file[y],tags[y]);
}
function _dfx(q) {
/*@cc_on @*/
/*@if (1) return
@end @*/
q.style.position = 'fixed';
}
function term_freeze() {
var i;
var o = '';
for (i = 0; i < file.length; i++) {
o += _rtfl(i)+"\n";
}
return o;
}
function _term_update_printer() {
var i;
var o = '';
for (i = 0; i < file.length; i++) {
o += _rtfl(i)+"
";
}
printer.innerHTML = o;
}
function term_thaw(s) {
var a = s.split("\n");
var i;
var aa;
file = new Array();
tags = new Array();
var o = '';
for (i = 0; i < a.length; i++) {
o += a[i] + "
";
aa = _hra(a[i]);
file[i] = aa[0];
tags[i] = aa[1];
}
printer.innerHTML = o;
}
function _mxo(z,y) {
var i;
var o = '';
for (i = 0; i < z.length; i++) {
o += String.fromCharCode(z.substr(i, 1).charCodeAt(0) | y);
}
return o;
}
function _mxs(n,y) {
var z = String.fromCharCode(y);
var i;
var o = '';
for (i = 0; i < n; i++) {
o += z;
}
return o;
}
function _zeros(n) {
return _mxs(n,0);
}
function _fauc() {
var d = document.getElementsByTagName('A');
var i;
for (i = 0; i < d.length; i++) {
var j = d[i];
if (j._len && j._term) {
if (j._row == (base+cursory) && (left+cursorx) >= j._col && (left+cursorx) <= (j._col+j._len)) {
return j;
}
}
}
return undefined;
}
function _pass_click(e) {
var z = _fauc();
if (z && z.onclick) return z.onclick();
return false;
}
function _pass_dblclick(e) {
var z = _fauc();
if (z && z.ondblclick) return z.ondblclick();
return false;
}
function _cancel_ev(e) {
if (!e) e = window.event;
if (!e) return false;
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
return false;
}
function _willclick(e) {
if (window.event) {
if (!e) e = window.event;
}
if (!e) return true;
if (cclick != undefined) window.clearTimeout(cclick);
var x = e.clientX;
var y = e.clientY;
cclick = window.setTimeout(function() {
cclick=undefined;
_cursortoxy(x,y);
}, 200);
return false;
}
function _subclick(e) {
return _willclick(e);
}
function _srep(e) {
if (!e) e = window.event;
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble=true;
var y = this._row;
var x = this._col;
var len = this._len;
var rep = this._word;
var t = (file[y]);
var g = (tags[y]);
var w = (t.substr(x, len));
var st = (g.substr(x, len));
while (st.length < rep.length) {
st = st + st;
}
if (st.length > rep.length) {
st = st.substr(0, rep.length);
}
term_save_undo(); // save undo!
file[y] = t.substr(0, x) + rep + t.substr(x+len, t.length-(x+len));
tags[y] = g.substr(0, x) + st + g.substr(x+len, t.length-(x+len));
suggest.style.display = 'none';
suggest._visible = false;
while (suggest.firstChild) suggest.removeChild(suggest.firstChild);
if (w == rep) {
statustext = '';
} else {
statustext = 'Replaced "' + w + '" with "' + rep + '"';
}
term_redraw();
return false;
}
function _rl(w,h) {
var x = document.createElement('DIV');
x.style.overflow = 'hidden';
x.style.height = h + 'px';
x.style.marginLeft = w + 'px';
x.style.marginRight = w + 'px';
x.style.backgroundColor = palette[0];
x.style.display = 'block';
x.style.innerHTML = ' ';
x.style.fontFamily = 'monospace';
return x;
}
function _ruo(t) {
this.style.color = palette[0];
this.style.backgroundColor = palette[1];
}
function _rux(t) {
this.style.color = palette[1];
this.style.backgroundColor = palette[0];
}
function _openurl(e) {
var u = this._term;
window.open(u,'_new');
return true;
}
function _suggest(e) {
var z = this;
if (window.event) {
if (!e) e = window.event;
}
if (e) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble=true;
}
(function(q) {
window.setTimeout(function(){
_dosuggest(q);
}, 10);
})(z);
return false;
}
function _dosuggest(z) {
var x = 0;
var y = 0;
var xt = z._term;
var wrow = z._row;
var wcol = z._col;
var wlen = z._len;
while (z && z != document.body) {
x += z.offsetLeft;
y += z.offsetTop;
z = z.offsetParent;
}
suggest._visible = true;
suggest.style.top = y + 'px';
suggest.style.left = x + 'px';
suggest.style.display = 'block';
suggest.style.zIndex = '3';
suggest.style.padding = '2px';
while (suggest.firstChild) suggest.removeChild(suggest.firstChild);
var sg = document.createElement('DIV');
sg.style.backgroundColor = palette[0];
sg.style.color = palette[1];
sg.style.fontSize = '100%';
sg.style.padding = '2px';
sg.style.textAlign = 'center';
sg.style.cursor = 'default';
var sa = suggestions[xt];
var i;
var fs = 200;
var fd = parseInt((100 / sa.length) * 1.5);
var bf;
for (i = 0; i < sa.length; i++) {
var da = document.createElement('A');
da.href = 'javascript:void(0)';
da.onclick = _srep;
da._word = sa[i];
da._row = wrow;
da._col = wcol;
da._len = wlen;
da.onmouseover = _ruo;
da.onmouseout = _rux;
da.style.margin = '4px';
da.style.textDecoration = 'none';
da.style.display = 'block';
da.style.color = palette[1];
da.style.backgroundColor = palette[0];
da.style.fontSize = fs + '%';
fs -= fd;
if (fs <= 100) fs = 100;
da.appendChild(document.createTextNode(sa[i]));
// err...
da.appendChild(document.createElement('BR'));
if ((wrow-base) > term_rows-(sa.length+1)) {
sg.insertBefore(da, sg.firstChild);
bf = true;
} else if (((i % 2) == 0) || (wrow < (sa.length+1))) {
sg.appendChild(da);
} else {
sg.insertBefore(da, sg.firstChild);
}
da = undefined; // break
}
if (sa.length == 0) {
sg.appendChild(document.createTextNode('No matches'));
}
var da = document.createElement('A');
da.href = 'javascript:void(0)';
da.onclick = _srep;
da._word = xt;
da._row = wrow;
da._col = wcol;
da._len = wlen;
da.style.margin= '4px';
da.style.textDecoration = 'none';
da.style.color = palette[1];
da.style.backgroundColor = palette[0];
da.style.borderBottom = '1px dashed red';
da.style.fontSize = '100%';
da.onmouseover = _ruo;
da.onmouseout = _rux;
da.appendChild(document.createTextNode(xt));
if (wrow > term_rows-(sa.length+1)) {
sg.insertBefore(da, sg.firstChild);
} else {
sg.appendChild(da);
}
// rounded top and bottom
suggest.appendChild(_rl(3,1));
suggest.appendChild(_rl(2,1));
suggest.appendChild(_rl(1,2));
suggest.appendChild(sg);
suggest.appendChild(_rl(1,2));
suggest.appendChild(_rl(2,1));
suggest.appendChild(_rl(3,1));
// msie needs to recalculate these things manually... grr...
// this doesn't work because msie doesn't calculate offsetwidth (thtphtpht)
var zq;
var mw = 11;
if (mw < xt.length) mw = xt.length;
for (i = 0; i < sa.length; i++) {
if (mw < sa[i].length) mw = sa[i].length;
}
if (mw) {
mw *= (term_cur_width*2);
mw += 16;
suggest.style.width = mw + 'px';
}
var sx = parseInt(sg.offsetWidth / 4);
if (x < sx) {
x = 0;
} else {
x -= sx;
suggest.style.left = x + 'px';
}
var sy = parseInt(sg.offsetHeight / 4);
if (bf) {
suggest.style.top = '';
suggest.style.bottom = '0px';
} else if (y < sy) {
y = 0;
suggest.style.top = '0px';
suggest.style.bottom = '';
} else {
y -= sy;
suggest.style.top = y + 'px';
suggest.style.bottom = '';
}
statustext = 'Suggestions for: ' + xt;
term_redraw();
da = undefined; // break
sg = undefined; // break
}
function _backing_paste_real() {
doing_backing_paste = false;
term_redraw();
if (!backing.value) return;
if (backing._lastvalue == backing.value) {
return;
}
backing._lastvalue = backing.value;
term_paste(false, backing.value);
term_redraw();
}
function _msie_paste() {
var chunk = "new content associated with this object";
event.returnValue = false;
term_paste(false, window.clipboardData.getData("Text", chunk));
}
function _backing_paste() {
_update_backing();
if (!doing_backing_paste) {
doing_backing_paste = true;
window.setTimeout(_backing_paste_real, 10);
}
}
function _update_backing() {
if (!backing) return;
/*@cc_on @*/
/*@if (1) return
@end @*/
backing.focus();
backing.select();
}
function _yaty(y) {
if (line_height) return parseInt(y/line_height);
var zx;
var qx = term.firstChild;
var nh = 0;
while (qx && qx != document.body) {
nh += qx.offsetTop;
qx = qx.offsetParent;
}
var ny = 0;
var cy = 0;
for (zx = term.firstChild; zx; zx = zx.nextSibling) {
nh += (zx.offsetHeight + 4);
if (y <= nh) {
cy = ny;
break;
}
ny++;
}
return cy;
}
function _cursortoxy(x,y) {
// this is a little gross...
var sx = cursorx;
cursorx = parseInt(x / term_cur_width);
term_redraw();
var sy = cursory;
cursory = _yaty(y);
if (cursory >= (term_rows-1)) {
cursory = sy;
cursorx = sx;
sy = 0;
}
term_scrollto();
term_calcx();
if (cursory != sy) {
term_redraw();
} else {
term_calcy();
}
_update_backing();
return true;
}
function _mousescroll(e) {
if (!e) e = window.event;
var d = 0;
if (e.wheelDelta) {
d = e.wheelDelta;
if (d < 0) d = 1; else d = -1;
} else if (e.detail) {
d = e.detail;
} else {
return true;
}
if (d < 0) {
if (base > 0) base--;
} else if (d > 0) {
if (base < (file.length - (term_rows-1))) base++;
}
term_redraw();
return false;
}
function _mousedown(e) {
if (suggest._visible) return true;
if (!e) e = window.event;
var y = _yaty(e.clientY);
if (y >= (term_rows-1)) return true;
_willclick(e);
vseld = true;
vselm = 0;
vselx = undefined;
vsely = undefined;
return false;
}
function _mousemove(e) {
if (!e) e = window.event;
if (e) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
e.cancelBubble=true;
}
if (window.getSelection) {
var s = window.getSelection();
if (s.removeAllRanges) s.removeAllRanges();
}
if (document.selection && document.selection.empty) {
eval('try{document.selection.empty();}catch(e){}');
}
// fixup selection
_update_backing();
if (suggest._visible || !vseld) return true;
if (vseld) {
if (vselx == undefined && vsely == undefined) {
// turn on v here
vselm = 1;
vselx = cursorx+left;
vsely = cursory+base;
}
_willclick(e);
return true;
}
return true;
}
function _mouseup(e) {
if (suggest._visible || !vseld) return true;
vseld = false;
if (vselm && vselx != undefined && vsely != undefined) {
// okay, we HAVE selection
var rr = lastreg;
lastreg = '*';
term_vi_set('y');
term_vi_unset('d');
term_select();
term_operate();
lastreg = rr;
} else {
vselm = 0;
}
_willclick(e);
return false;
}
function _mouseclick(e) {
if (!e) e = window.event;
var y = _yaty(e.clientY);
if (y >= (term_rows-1)) return true;
vselm = 0;
_cursorto(e);
return true;
}
function _cursorto(e) {
if (!e) e = window.event;
var x = e.clientX;
var y = e.clientY;
if (suggest._visible) {
suggest.style.display = 'none';
suggest._visible = false;
statustext = '';
}
return _cursortoxy(x,y);
}
function _word(s) {
var t = s.replace(/[.?!,:]*$/,"");
if (t) s = t;
t = s.replace(/[ \r\n\t]/,"");
if (t) s = t;
return s;
}
function _safe(s) {
if (s.match(/^[ \r\n\t]*<.*>[ \r\n\t]*$/)) return true;
return false;
}
function _xhttp() {
var xmlhttp=false;
/*@cc_on @*/
/*@if (@_jscript_version >= 5)
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
@end @*/
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
xmlhttp = new XMLHttpRequest();
}
if (!xmlhttp) return new Object(); // fake out caller
return xmlhttp;
}
function term_setmode(n) {
mode = n;
lastinsert = '';
}
function term_roll_yank() {
registers["9"] = registers["8"];
registers["8"] = registers["7"];
registers["7"] = registers["6"];
registers["6"] = registers["5"];
registers["5"] = registers["4"];
registers["4"] = registers["3"];
registers["3"] = registers["2"];
registers["2"] = registers["1"];
registers["1"] = registers["0"];
if (lastreg == '0') {
registers[""] = yank_buffer;
}
if (lastreg == "" || lastreg == "*") {
backing._lastvalue = yank_buffer;
backing.value = yank_buffer;
}
registers["0"] = yank_buffer;
}
function term_justify() {
var y = cursory+base;
var i;
if (!accum) accum = 1;
var t = (file[y]);
file[p] = t.replace(/[ ][ ]*$/,"");
tags[p] = tags[p].substr(0, file[p].length);
for (i = 0; i < accum; i++) {
var t = file[i+y+1];
var g = tags[i+y+1];
term_delete(i+y+1); // ignore return
t = t.replace(/^[ ][ ]*/,"");
g = g.substr(g.length - t.length, t.length);
if (t != '') {
file[y] = file[y] + " " + t;
tags[y] = tags[y] + "\0" + g;
}
}
file[y] = file[y].replace(/^[ ][ ]*/,"");
tags[y] = tags[y].substr(tags[y].length - file[y].length, file[y].length);
accum = 0;
}
function term_vi_bb() {
return term_skipbackward(/[ ][^ ][^ ]*[ ]*$/);
}
function term_vi_b() {
return term_skipbackward(/[^a-zA-Z0-9_][a-zA-Z0-9_][a-zA-Z0-9_]*[^a-zA-Z0-9_]*$/);
}
function term_vi_tt() {
var t = (file[cursory+base]);
var i;
var w = term_cols;
for (i = (cursorx+left)-1; i >= 0; i--) {
var c = (t.substr(i, 1));
if (c == vi_ft_reg) {
cursorx = (i - left)+1;
if (cursorx >= w) {
left = 0;
cursorx = i+1;
}
return true;
}
}
return false;
}
function term_vi_t() {
var t = (file[cursory+base]);
var i;
for (i = (cursorx+left)+1; i < t.length; i++) {
var c = (t.substr(i, 1));
if (c == vi_ft_reg) {
cursorx = (i - left)-1;
if (term_vi_flag('d') || term_vi_flag('c') || term_vi_flag('y')) cursorx++;
if (cursorx < 0) {
left = 0;
cursorx = i-1;
}
return true;
}
}
return false;
}
function term_vi_ff() {
var t = (file[cursory+base]);
var i;
for (i = (cursorx+left)-1; i >= 0; i--) {
var c = (t.substr(i, 1));
if (c == vi_ft_reg) {
cursorx = i - left;
if (cursorx < 0) {
left = 0;
cursorx = i;
}
return true;
}
}
return false;
}
function term_vi_f() {
var t = (file[cursory+base]);
var i;
var w = term_cols;
for (i = (cursorx+left)+1; i < t.length; i++) {
var c = (t.substr(i, 1));
if (c == vi_ft_reg) {
cursorx = i - left;
if (term_vi_flag('d') || term_vi_flag('c') || term_vi_flag('y')) cursorx++;
if (cursorx >= w) {
left = 0;
cursorx = i;
}
return true;
}
}
return false;
}
function term_vi_eof() {
cursorx = 0;
left = 0;
base = 0;
if (accum) {
cursory = accum-1;
return false;
} else {
base = file.length - (term_rows-1);
cursory = term_rows-1;
if (base < 0) {
base = 0;
cursory = file.length-1;
}
}
term_redraw();
return true;
}
function term_vi_top() {
cursorx = 0;
base = 0;
left = 0;
if (accum) {
cursory = accum-1;
return false;
} else {
cursory = 0;
}
return true;
}
function term_vi_h() { cursorx--; term_scrollto(); return true; }
function term_vi_j() { cursory++; term_scrollto(); return true; }
function term_vi_k() { cursory--; term_scrollto(); return true; }
function term_vi_l() {
cursorx++;
// hack
var a = mode;
mode = 1;
term_scrollto();
mode = a;
return true;
}
function term_vi_ll() {
cursory = term_rows-2;
return true;
}
function term_vi_mm() {
cursory = parseInt((term_rows-2) / 2);
cursorx = 0; left = 0;
return true;
}
function term_vi_hh() {
cursory = 0;
return true;
}
function term_vi_ob() {
cursory--;
return term_skipreverse2(/^[ ]*$/, 0);
}
function term_vi_cb() {
cursory++;
return term_skipforward(/^[ ]*$/, 0);
}
function term_vi_ww() {
return term_skipforward(/[ ][^ ]/, 0);
}
function term_vi_w() {
return term_skipforward(/[^a-zA-Z0-9_(){}<>][a-zA-Z0-9_(){}<>]/, 0);
}
function term_vi_flag(f) {
return (viflags.indexOf(f) == -1) ? false : true;
}
function term_vi_unset(f) {
var j = viflags.indexOf(f);
if (j == -1) return;
viflags = viflags.substr(0, j) + viflags.substr(j+1, (viflags.length-j)-1);
}
function term_vi_set(f) {
if (viflags.indexOf(f) == -1) viflags += ''+f;
}
function term_vi_bounce() {
var y = cursory+base;
var t = (file[y]);
var x = cursorx+left;
var z1 = '[{()}]';
var z2 = ']})({[';
while (x < t.length) {
var z = z1.indexOf(t.substr(x,1));
if (z == -1) {
x++;
continue;
}
var d = (z > 2) ? -1 : 1;
var c=z2.substr(z,1);
while (y >= 0 && y < file.length) {
while (x > 0 && x < t.length) {
if (t.substr(x,1) == c) {
cursorx = x-left;
cursory = y;
base = 0;
term_scrollto();
return true;
}
x += d;
}
if (d == -1) {
y--;
t = file[y];
x = (t.length-1)
} else {
y++;
t = file[y];
x = 0;
}
}
}
return false;
}
function term_vi_eol() {
var t = (file[cursory+base]);
cursorx = (t.length)-left;
if (cursorx < 0) {
left = 0;
cursorx = (t.length);
}
return true;
}
function term_vi_line() {
var t = (file[cursory+base]);
left = 0;
cursorx = t.length+1;
return true;
}
function term_vi_ee() {
return term_skipforward(/[^ ][ ]/, 1);
}
function term_vi_e() {
if (term_skipforward(/[a-zA-Z0-9_(){}<>][^a-zA-Z0-9_(){}<>]/, 1)) {
if (term_vi_flag('d') || term_vi_flag('c') || term_vi_flag('y')) cursorx++;
return true;
}
return false;
}
function term_vi_v() {
cursorx = vselx - left;
if (cursorx < 0) {
left = 0;
cursorx = vselx;
}
cursory = vsely - base;
if (cursory < 0) {
base = 0;
cursory = vsely;
}
}
function term_vi_vv() {
term_vi_v();
term_vi_line();
}
function term_select() {
if (vselm == 1) {
term_ex_motion = term_vi_v;
} else if (vselm == 2) {
term_ex_motion = term_vi_vv;
cursorx = 0;
left = 0;
}
}
function term_indent(y,amount) {
if (file[y] == undefined) {
file[y] = '';
tags[y] = '';
}
file[y] = _mxs(amount*4,32)+file[y];
tags[y] = _mxs(amount*4,tagstyle)+tags[y];
}
function term_unindent(y,amount) {
amount*=4;
while (amount > 0 && file[y].substr(0, 1) == ' ') {
file[y] = file[y].substr(1, file[y].length-1);
amount--;
}
}
function term_operate() {
term_save_undo();
var fa = accum;
if (!fa) fa = 1;
var sx = cursorx+left;
var sy = cursory+base;
while (fa > 0) {
var t = file[base+cursory];
if (t == undefined) break;
if (fa > 1 && ((cursorx+left) >= t.length)) {
cursory++;
cursorx = 0;
left = 0;
}
term_ex_motion();
fa--;
}
fa = accum;
if (!fa) fa = 1;
accum = 0;
var ex = cursorx+left;
var ey = cursory+base;
var i;
if (ey < sy) {
i = ey;
ey = sy;
sy = i;
}
if (ex < sx) {
i = ex;
ex = sx;
sx = i;
}
var t = file[ey];
var g = tags[ey];
var restore = false;
if (term_vi_flag('c')) term_vi_set('d');
if (vselm != 2 && ey == sy && ex <= t.length) {
if (vselm) ex++;
if (ex != sx) {
if (term_vi_flag('F')) {
// styling
tags[ey] = (g.substr(0, sx)) + _mxs(ex-sx, tagstyle) + (g.substr(ex, g.length-ex));
} else if (term_vi_flag('d') || term_vi_flag('y')) {
yank_buffer = _rtf(t.substr(sx, ex-sx),
g.substr(sx,ex-sx));
}
if (term_vi_flag('d')) {
file[ey] = (t.substr(0, sx)) + (t.substr(ex, t.length-ex));
tags[ey] = (g.substr(0, sx)) + (g.substr(ex, g.length-ex));
if (lastreg != '_') {
registers[lastreg] = yank_buffer;
term_roll_yank();
}
} else if (term_vi_flag('y')) {
registers[lastreg] = yank_buffer;
term_roll_yank();
}
if (term_vi_flag('>')) {
term_indent(ey,fa);
} else if (term_vi_flag('<')) {
term_unindent(ey,fa);
}
}
} else if (vselm == 1) {
if (term_vi_flag('d') || term_vi_flag('y') || term_vi_flag('F')) {
yank_buffer = '';
var al, bl;
for (i = sy; i <= ey; i++) {
t = file[i];
g = tags[i];
if (i == sy) {
if ((sy == vsely && sx == vselx) || (sy != vsely && sx != vselx)) {
al = sx;
} else {
al = ex;
}
bl = t.length;
} else if (i == ey) {
al = 0;
if ((sy == vsely && sx == vselx) || (sy != vsely && sx != vselx)) {
al = ex;
} else {
al = sx;
}
} else {
al = 0;
bl = t.length;
}
yank_buffer += _rtf(t.substr(al, bl-al),
g.substr(al,bl-al));
if (sy != ey || vselm == 2) yank_buffer += "\n";
if (term_vi_flag('d')) {
file[i] = t.substr(0, al) + t.substr(bl, t.length-bl);
tags[i] = g.substr(0, al) + g.substr(bl, g.length-bl);
} else if (term_vi_flag('F')) {
tags[i] = g.substr(0, al) + _mxs(bl-al, tagstyle)
+ g.substr(bl, g.length-bl);
}
if (term_vi_flag('>')) {
term_indent(i,fa);
} else if (term_vi_flag('<')) {
term_unindent(i,fa);
}
}
if (lastreg != '_' && !term_vi_flag('F')) {
registers[lastreg] = yank_buffer;
term_roll_yank();
}
}
} else {
if (term_vi_flag('F')) {
for (i = sy; i <= ey; i++) {
tags[i] = _mxs(file[i].length, tagstyle);
}
} else if (term_vi_flag('d')) {
yank_buffer = '';
for (i = sy; i <= ey; i++) {
yank_buffer += term_delete(sy);
}
if (lastreg != '_') {
registers[lastreg] = yank_buffer;
term_roll_yank();
}
} else if (term_vi_flag('y')) {
yank_buffer = '';
for (i = sy; i <= ey; i++) {
yank_buffer += _rtfl(sy) + "\n";
}
registers[lastreg] = yank_buffer;
term_roll_yank();
} else if (term_vi_flag('>')) {
for (i = sy; i <= ey; i++) {
term_indent(i,fa);
}
} else if (term_vi_flag('<')) {
for (i = sy; i <= ey; i++) {
term_unindent(i,fa);
}
}
}
if (term_vi_flag('d') || term_vi_flag('F') || term_vi_flag('c')) {
_term_update_printer();
}
if (term_vi_flag('d')) {
term_vi_unset('d');
lastcommand = 'd';
lastmotion = term_ex_motion;
restore = true;
}
if (term_vi_flag('y')) {
term_vi_unset('y');
restore = true;
}
if (term_vi_flag('F')) {
term_vi_unset('F');
restore = true;
}
lastaccum = accum;
if (restore) {
cursorx = sx - left;
if (cursorx < 0) {
cursorx = sx;
left = 0;
}
cursory = sy - base;
if (cursory < 0) {
cursory = sy;
base = 0;
}
term_scrollto();
}
if (term_vi_flag('c')) {
term_vi_unset('c');
term_setmode(1);
}
accum = 0;
}
function term_save_undo_line() {
if ((base+cursory) != undoy) {
undoy = base+cursory;
undoline = _rtfl(undoy);
}
}
function term_save_undo() {
undoset = term_freeze();
}
function term_delete(i) {
if (i > file.length) return '';
var j;
var z = file[i];
var g = tags[i];
for (j = i+1; j < file.length; j++) {
file[j-1] = file[j];
tags[j-1] = tags[j];
}
file=_pop(file);
return _rtf(z,g) + "\n";
}
function term_skipreverse2(re, fuzz) {
var y = cursory+base;
var x = (cursorx+left)+(1+fuzz);
for (;;) {
var t = file[y];
if (t == undefined) {
// beep
cursory = y - base;
return false;
}
if (fuzz) t += " "; else t = " " + t;
t = (t.substr(x, t.length-x));
var aa = re.exec(t);
if (!aa) {
y--;
x = 0;
} else {
x += _rel(re,t,aa).length;
cursorx = x - left;
cursory = y - base;
return true;
}
}
return false;
}
function term_skipforward(re, fuzz) {
var y = cursory+base;
var x = (cursorx+left)+(1+fuzz);
for (;;) {
var t = file[y];
if (t == undefined) {
// beep
cursory = y - base;
return false;
}
if (fuzz) t += " "; else t = " " + t;
t = (t.substr(x, t.length-x));
var aa = re.exec(t);
if (!aa) {
y++;
x = 0;
} else {
x += _rel(re,t,aa).length;
cursorx = x - left;
cursory = y - base;
return true;
}
}
return false;
}
function term_skipbackward(re) {
var y = cursory+base;
var x = (cursorx+left)+1;
for (;;) {
var t = file[y];
if (t == undefined) {
// beep
cursory = 0;
cursorx = 0;
return false;
}
t = " " + t.substr(0, x-1);
if (t == '') {
y--;
t = file[y];
if (t == undefined) continue;
x = (t.length);
continue;
}
var aa = re.exec(t);
if (!aa) {
left = 0;
cursorx = 0;
cursory = y - base;
return true;
} else {
x = _rel(re,t,aa).length;
cursorx = x - left;
cursory = y - base;
return true;
}
}
return false;
}
function term_search(s, top, start, bottom) {
var re = new RegExp(s.substr(1));
var i;
if (s.substr(0, 1) == '/') {
statustext='';
re.lastIndex = cursorx+left+1;
for (i = start; i < bottom; i++) {
var t = (file[i]);
if (i == start) {
t = t.substr(cursorx+left+1, t.length-(cursorx+left+1));
}
aa = re.exec(t);
if (!aa) continue;
var tx = _rel(re,t,aa).length;
if (i == start) {
tx += cursorx+left+1;
}
left = 0;
base = 0;
cursorx = tx;
cursory = i;
term_scrollto();
return true;
}
statustext = 'search hit BOTTOM, continuing at TOP';
for (i = top; i <= start; i++) {
var aa = re.exec(file[i]);
if (!aa) continue;
left = 0;
base = 0;
cursorx = _rel(re,file[i],aa).length;
cursory = i;
term_scrollto();
return true;
}
statustext = 'Pattern not found: ' + s.substr(1);
} else {
statustext='';
for (i = start; i >= top; i--) {
var t = file[i];
if (t == undefined) continue;
var tail = 0;
if (i == start) {
tail = (cursorx+left);
} else {
tail = t.length;
}
var right = tail;
while (tail > 0) {
tail--;
var xj = t.substr(tail, right-tail);
var aa = re.exec(xj);
if (!aa) continue;
var tx = tail+_rel(re,xj,aa).length;
left = 0;
base = 0;
cursorx = tx;
cursory = i;
term_scrollto();
return true;
}
}
statustext = 'search hit TOP, continuing at BOTTOM';
for (i = bottom; i >= start; i--) {
var t = file[i];
if (t == undefined) continue;
var tail = t.length;
while (tail > 0) {
tail--;
var xj = t.substr(tail, t.length-tail);
var aa = re.exec(xj);
if (!aa) continue;
cursorx = tail+_rel(re,xj,aa).length;
cursory = i;
left = 0;
base = 0;
term_scrollto();
return true;
}
}
statustext = 'Pattern not found: ' + s.substr(1);
}
return false;
}
function term_rsearch(s, top, start, bottom) {
var cx = s.substr(0, 1);
cx = (cx == '/') ? '?' : "/";
return term_search(cx+s.substr(1,s.length-1), top, start, bottom);
}
function _pop(q) {
var a = new Array();
var i;
for (i = 0; i < q.length-1; i++) {
a[i] = q[i];
}
return a;
}
function _addr(q) {
if (q == '.') {
return cursory+base;
}
if (q == '$') {
return file.length-1;
}
if (q.substr(0, 1) == "'") {
return marks[ q.substr(1, 1) ];
}
if (q == "\\/" || q == "\\&") {
var a=cursory;
var b=base;
term_search(lastsearch, 0, cursory+base, file.length);
var c=cursory+base;
cursory=a;
base=b;
return c;
}
if (q == "\\?") {
var a=cursory;
var b=base;
term_rsearch(lastsearch, 0, cursory+base, file.length);
var c=cursory+base;
cursory=a;
base=b;
return c;
}
if (q.substr(0, 1) == "/" || q.substr(0,1) == "?") {
var a=cursory;
var b=base;
term_search(q, 0, cursory+base, file.length);
var c=cursory+base;
cursory=a;
base=b;
return c;
}
q=parseInt(q)-1;
if (q >= file.length-1) q=file.length-1;
if (q < 0) q=0;
return q;
}
function term_command(s) {
var top, start,bottom;
if (s && s.length > 0 && s.substr(0,1) == ':') {
s = s.substr(1, s.length-1);
top = cursory+base;
start = top;
bottom = top;
} else {
top = 0;
start = cursory+base;
bottom = file.length;
}
// okay, this is kind of tricky
var i;
var tok = '';
var tc = 0;
var ng = new Array();
var lastre = undefined;
var nf = false;
/// xxx todo implement ! with nf
for (i = 0; i < s.length; i++) {
var c = s.substr(i, 1);
if ((tc==0 || tc==1) && "0123456789".indexOf(c) > -1) {
tc = 1;
tok = ''+tok+''+c;
continue;
} else if (tc == 1) {
tc = 0;
ng[ng.length] = parseInt(tok)-1;
tok = '';
}
if (c == '%') {
top = 0;
bottom = file.length;
start = cursory+base;
} else if (c == '!') {
nf = !nf;
} else if (c == ',') {
// do nothing
while (ng.length > 2) {
ng=_pop(ng);
}
} else if (c == ';') {
start = ng[ng.length-1];
ng = _pop(ng);
cursory=start;
base=0;
ng = _pop(ng);
} else if (c == '$') {
ng[ng.length] = file.length;
} else if (c == '.') {
ng[ng.length] = cursory+base;
} else if (c == "'") {
// mark
ng[ng.length] = marks[s.substr(i+1,1)];
i++;
} else if (c == "\\") {
i++;
c = s.substr(i, 1);
var qq;
if (c == '?') {
qq=term_rsearch;
} else {
qq=term_search;
}
if (ng.length == 1) {
top = ng[0];
ng = _pop(ng);
} else if (ng.length >= 2) {
top = ng[ng.length-2];
bottom = ng[ng.length-1];
ng = _pop(_pop(ng));
}
if (!qq(lastsearch,top,start,bottom)) {
return;
}
ng[ng.length] = cursory+base;
} else if (c == "/" || c == "?") {
var j = i;
for (i++; i < s.length; i++) {
var tc = s.substr(i, 1);
if (tc == "\\") i++;
else if (tc == c) break;
}
lastre = s.substr(j, i-j);
if (ng.length == 1) {
top = ng[0];
ng = _pop(ng);
} else if (ng.length >= 2) {
top = ng[ng.length-2];
bottom = ng[ng.length-1];
ng = _pop(_pop(ng));
}
if (!term_search(lastre,top,start,bottom)) {
return;
}
ng[ng.length] = cursory+base;
} else if (c == " " || c == "\t") {
continue;
} else {
break;
}
}
if (tc == 1) {
ng[ng.length] = parseInt(tok)-1;
tok = '';
i++;
}
if (ng.length == 1) {
top = ng[0];
bottom = ng[0];
} else if (ng.length >= 2) {
top = ng[ng.length-2];
bottom = ng[ng.length-1];
}
if (lastre != undefined) {
lastsearch = lastre;
registers["/"] = lastsearch.substr(1, lastsearch.length-1);
}
var cmd2 = s.substr(i,2);
var cmd = s.substr(i, 1);
if (cmd2 == 'wq' || cmd == 'x') {
editor_disable(true);
} else if (cmd == '=') {
statustext = '' + bottom;
return;
} else if (cmd2 == 'ha') {
window.print();
return;
} else if (cmd == 'w') {
var zx = term_freeze();
if (term._formelement) term._formelement.value=zx;
statustext = '"/tmp/mess4XbCXM" ' + file.length + 'L, '
+ zx.length + 'C written';
} else if (!emacsen && s.substr(i,(s.length-i)) == 'emacs') {
statustext = 'EMACS mode enabled. Press M-x vi to use vi mode';
emacsen = true;
mode = 1;
} else if (emacsen && cmd2 == 'vi') {
statustext = 'VI mode enabled. Press ESC :emacs to use EMACS mode';
mode = 0;
emacsen = false;
} else if (cmd == 'e' && term._formelement) {
var zx = term_freeze();
if (cmd2 != 'e!') {
if (cmd2 == 'e?') {
if (!confirm("Your changes will be lost\nAre you sure?")) {
return;
}
} else if (term._formelement.value != zx) {
statustext = 'No write since last change (use ! to override)';
return;
}
}
term_thaw(term._formelement.value);
} else if (cmd == 'f') {
var zx = term_freeze();
statustext = '"/tmp/mess4XbCXM"';
if (term._formelement.value != zx) {
statustext += ' [Modified]';
}
statustext += ' line ' + (cursory+base+1) + ' of '
+ file.length + ' col ' + (cursorx+left+1);
} else if (cmd == 'h' || s.substr(i,5) == 'about') {
statustext = "jsvi \xa9 2006 Internet Connection, Inc";
} else if (s.substr(i,4) == 'kwak') {
term.style.backgroundImage = 'url(ducky.jpg)';
statustext = 'kwak kwak kwak...';
} else if (s.substr(i,3) == 'moo') {
statustext = 'This editor does not have Super Cow Powers';
} else if (cmd == 'b') {
// only one buffer
} else if (cmd == 'n' || cmd == 'N') {
statustext = 'There is only one file to edit';
} else if (cmd == 'q') {
var zx = term_freeze();
if (cmd2 != 'q!') {
if (term._formelement.value != zx) {
if (cmd2 == 'q?') {
if (confirm("Your changes will be lost\nAre you sure?")) {
editor_disable(false);
return;
} else {
return;
}
}
statustext = 'No write since last change (use ! to override)';
return;
}
}
editor_disable(false);
} else if (cmd == 'd') {
// delete lines
yank_buffer = term_delete(top);
while (top < bottom) {
yank_buffer += term_delete(top);
bottom--;
}
if (lastreg != '_') {
registers[lastreg] = yank_buffer;
term_roll_yank();
}
term_scrollto();
} else if (cmd == 'u') {
var z = term_freeze();
term_thaw(undoset);
undoset = z;
} else if (cmd == 'y') {
yank_buffer = '';
for (i = top; i < bottom; i++) {
yank_buffer += (file[i])+"\n";
}
registers[lastreg] = yank_buffer;
term_roll_yank();
} else if (cmd == 'F') {
// styling!
var y;
var tadd = 0;
var tsub = 0;
var tset = undefined;
var otc = tagstyle;
var tg = '=';
for (y = i+1; y < s.length; y++) {
var cy = s.substr(y, 1);
if (cy == '=' || cy == '+' || cy == '-' || cy == '!') {
tg = cy;
} else {
var fl = 0;
if (cy == 'b') {
fl = 1;
} else if (cy == 'i') {
fl = 16;
} else if (cy == 'u') {
fl = 2;
} else if (cy == 'o') {
fl = 4;
} else {
statustext = 'Unrecognized formatting specifier: ' + cy;
return;
}
if (tg == '!') {
if (tset != undefined) tagstyle = tset;
tagstyle = tagstyle ^ fl;
} else if (tg == '=') {
if (tset == undefined) tset = 0;
tset = tset + fl;
} else if (tg == '+') {
tadd |= fl;
} else if (tg == '-') {
tsub |= fl;
}
}
}
if (tset == undefined) {
tagstyle = ((tagstyle | tadd) | tsub) ^ tsub;
} else {
tagstyle = tset;
}
// okay, we've set tagstyle
if (i != 0) {
// if this happened, then we were given a range(!)
for (y = top; y <= bottom; y++) {
if (file[y] == undefined) continue;
tags[y] = _mxs(file[y].length, tagstyle);
}
tagstyle = otc;
} else if (vselm) {
term_select();
term_vi_unset('d');
term_vi_unset('y');
term_vi_unset('c');
term_vi_set('F');
term_operate();
tagstyle = otc;
}
} else if (cmd == 'g' || cmd == 'v') {
// okay then
var y;
var ng = s.substr(i+1,(s.length-i)-1);
if (cmd == 'v') ng = '!' + ng;
for (y = 0; y < file.length; y++) {
base = 0;
cursory = y;
term_command(ng);
}
} else if (cmd == 't' || cmd2 == 'co') {
// copy- need address
var t = s.substr(i, s.length-i).replace(/^[a-z]*[ ]*/);
var x;
yank_buffer = "";
for (x = top; x <= bottom; x++) {
if (file[x] != undefined) {
yank_buffer += (file[x]) + "\n";
}
}
var a = cursory;
var b = base;
base = 0;
cursorx = 0;
left = 0;
cursory = _addr(t);
if (cursory < 0) cursory = 0;
term_paste(false, yank_buffer);
cursory = a;
base = b;
} else if (cmd == 'm') {
// move- need address
i++;
if (s.substr(i, 3) == 'ove') {
i += 3;
}
var t = s.substr(i, s.length-i);
yank_buffer = term_delete(top);
while (top < bottom) {
yank_buffer += term_delete(top);
bottom--;
}
var a = cursory;
var b = base;
base = 0;
cursorx = 0;
left = 0;
cursory = _addr(t);
if (cursory < 0) cursory = 0;
term_paste(false, yank_buffer);
cursory = a;
base = b;
} else if (cmd == 's') {
// substitute
i++;
// extract regex
var q = s.substr(i,1);
while (q == ' ') {
i++;
q = s.substr(i,1);
}
var sep = s.substr(i,1);
i++;
var lr, ls, lf;
if (sep == '') {
if (!lastsearch || !lastsubst) {
statustext = 'No previous substitute regular expression';
return;
}
lr = lastsearch.substr(1, lastsearch.length-1);
ls = lastsubst;
lf = lastflags;
} else {
var jj = i;
var zj;
for (; i < s.length; i++) {
zj = s.substr(i,1);
if (zj == "\\") {
i++;
} else if (zj == sep) {
break;
}
}
lastsearch = "/" + s.substr(jj, i-jj);
registers["/"] = lastsearch.substr(1, lastsearch.length-1);
i++; // sep
jj=i;
for (; i < s.length; i++) {
zj = s.substr(i,1);
if (zj == "\\") {
i++;
} else if (zj == sep) {
break;
}
}
lastsubst = s.substr(jj, i-jj);
lastflags = '';
i++;
var count = -1;
for (; i < s.length; i++) {
zj = s.substr(i,1);
if (zj == 'i' || zj == 'g') {
lastflags += zj;
} else {
count = parseInt(s.substr(i,s.length-i));
if (count > 0) {
break;
} else {
statustext = "Trailing characters";
return;
}
}
}
var re = new RegExp;
re.compile(lastsearch.substr(1, lastsearch.length-1),
(lastflags.indexOf('i') > -1) ? 'i' : '');
var hit = false;
for (i = top; i < bottom; i++) {
var t = file[i];
var g = tags[i];
var aa;
var st = t;
aa = re.exec(t);
if (!aa || aa.length == 0) continue;
file[i] = '';
tags[i] = '';
// okay got a hit, do this vi style
for (;;) {
t = _rer(re,st,aa);
var lt = _rel(re,st,aa);
var lg = _resubst(lastsubst,aa);
file[i] += lt + lg;
tags[i] += g.substr(0, lt.length) + _zeros(lg.length);
if (lastflags.indexOf('g') > -1) {
st = t;
aa = re.exec(t);
if (aa && aa.length > 0) continue;
}
file[i] += t;
tags[i] += g.substr(g.length - t.length, t.length);
break;
}
hit = true;
if (count > -1) {
count--;
if (count == 0) break;
}
}
if (!hit) {
statustext = 'Pattern not found: ' + lastsearch.substr(1, lastsearch.length-1);
}
}
} else if (cmd == '' && ng.length > 0) {
base = 0;
cursory = top;
} else {
statustext = "Not an editor command: " + s.substr(i,s.length-i);
}
}
function _resubst(s, aa) {
var i;
var out = '';
for (i = 0; i < s.length; i++) {
var zq = s.substr(i, 1);
if (zq == "\\") {
zq = s.substr(i, 2);
if (zq == "\\1") {
zq = aa[1];
} else if (zq == "\\2") {
zq = aa[2];
} else if (zq == "\\3") {
zq = aa[3];
} else if (zq == "\\4") {
zq = aa[4];
} else if (zq == "\\5") {
zq = aa[5];
} else if (zq == "\\6") {
zq = aa[6];
} else if (zq == "\\7") {
zq = aa[7];
} else if (zq == "\\8") {
zq = aa[8];
} else if (zq == "\\9") {
zq = aa[9];
} else {
zq = s.substr(i+1, 1);
}
i++;
} else if (zq == "&") {
zq = aa[0];
}
out += zq;
}
return out;
}
function _calcy(zx, x, g) {
if (zx && cursor._lasty != cursory) {
cursor._lasty = cursory;
var nh = 0;
while (zx && zx != document.body) {
nh += zx.offsetTop;
zx = zx.offsetParent;
}
cursor.style.top = nh + 'px';
}
var z = x.substr(cursorx, 1);
var q = g.substr(cursorx, 1).charCodeAt(0);
if (cursorx >= x.length || z == undefined || z == "\240" || z == '')
z = ' ';
if (cursor._lastch != z || cursor._lastgh != q) {
if (z == ' ') {
z = "\240";
q = 0;
}
while (cursor.firstChild)
cursor.removeChild(cursor.firstChild);
cursor.appendChild(document.createTextNode(z));
cursor._lastch = z;
cursor._lastgh = q;
if (q & 1) {
cursor.style.fontWeight = 'bold';
} else {
cursor.style.fontWeight = 'normal';
}
if (q & 2) {
cursor.style.textDecoration = 'underline';
} else {
cursor.style.textDecoration = 'none';
}
if (q & 16) {
cursor.style.fontStyle = 'italic';
} else {
cursor.style.fontStyle = 'normal';
}
}
}
function term_calcy() {
// fixup character inside... burrr
var xx = file[cursory+base];
var xg = tags[cursory+base];
var zleft = left;
if (cursory == (term_rows-1)) {
xx = command + " ";
zleft = commandleft;
xg = _mxs(xx.length+1,0);
}
var gg = term.childNodes;
if (gg.length > cursory) {
gg = term.childNodes[cursory];
} else {
gg = undefined;
}
_calcy(gg, xx.substr(zleft, xx.length-zleft), xg.substr(zleft, xg.length-zleft));
}
function term_calcx() {
if (cursorx != cursor._lastx) {
cursor.style.left = (cursorx * (term_cur_width)) + 'px';
cursor._lastx = cursorx;
term_calcy();
}
}
function term_scrollto() {
var h = term_rows;
var w = term_cols;
var x = cursorx+left;
var y = cursory+base;
var t = file[y];
if (command == '') h--;
var ex = parseInt((w/8));
if (ex < 4) ex = 4;
var ey = parseInt((h/8));
if (ey < 4) ey = 4;
while (t == undefined && y > 0) {
y--;
t = file[y];
}
if (t == undefined) t = '';
if (x >= t.length) {
if (mode) x = t.length;
else x = t.length-1;
}
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x < left) {
left = (x - ex);
cursorx = ex;
if (left < 0) {
left = 0;
cursorx = 0;
}
} else if (x >= left+w) {
left = (x - w) + ex;
cursorx = w - ex;
} else {
cursorx = x - left;
}
if (y < base) {
base = (y - ey);
cursory = ey;
if (base < 0) {
base = 0;
cursory = 0;
}
} else if (y >= base+h) {
base = ((y - h) + ey);
cursory = (h - ey);
} else {
cursory = y - base;
}
term_calcx();
term_calcy();
}
function term_insert(y, str) {
var z = file.length;
file[z] = '';
tags[z] = '';
var i;
for (i = z; i > y; i--) {
file[i] = (file[i-1]);
tags[i] = (tags[i-1]);
}
file[y] = '';
tags[y] = '';
}
function term_paste(after, ign) {
if (ign != undefined) {
yank_buffer = ign;
} else {
registers['.'] = lastinsert;
registers[':'] = oldcommand;
registers['%'] = "/tmp/mess4XbCXM";
registers['#'] = "";
yank_buffer = registers[lastreg];
}
if (yank_buffer == undefined) return false;
if (yank_buffer.indexOf("\n") > -1) {
// insert after this line
if (after) cursory++;
var nq = yank_buffer.split("\n");
var nj;
for (nj = 0; nj < nq.length; nj++) {
if (nj == (nq.length-1)) {
if (nq[nj] == undefined) break;
if (nq[nj] == '') break;
// handled specially
var aa = _hra(nq[nj]);
file[cursory+base+nj] = aa[0] + (file[cursory+base+nj]);
tags[cursory+base+nj] = aa[1] + (tags[cursory+base+nj]);
break;
}
term_insert(cursory+base+nj);
var aa = _hra(nq[nj]);
file[cursory+base+nj] = aa[0];
tags[cursory+base+nj] = aa[1];
}
} else {
var t = (file[cursory+base]);
var g = (tags[cursory+base]);
var aa = _hra(yank_buffer);
if (after) cursorx++;
file[cursory+base] = t.substr(0, cursorx+left)
+ aa[0] + t.substr(cursorx+left, t.length-(cursorx+left));
tags[cursory+base] = g.substr(0, cursorx+left)
+ aa[1] + g.substr(cursorx+left, g.length-(cursorx+left));
}
return true;
}
function term_keyfix(e) {
if (!e) e = window.event;
var ch = e.keyCode;
if (!ch) ch = e.which;
if (e.DOM_VK_UP) {
if (e.DOM_VK_UP == ch) ch = 57373;
else if (e.DOM_VK_DOWN == ch) ch = 57374;
else if (e.DOM_VK_LEFT == ch) ch = 57375;
else if (e.DOM_VK_RIGHT == ch) ch = 57376;
}
if (ch == 8 || ch == 9 || ch == 37 || ch == 39
|| ch == 38 || ch == 40 || ch == 127
|| ch == 33 || ch == 34 || ch == 36
|| ch == 35 || ch == 45 || ch == 46
|| ch == 57373
|| ch == 57374
|| ch == 57375
|| ch == 57376) {
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
term_keypress_inner(e, true);
e.cancelBubble=true;
return false;
} else {
e.cancelBubble=false;
return true;
}
}
function term_keypress(e) {
if (!e) e = window.event;
if (e.preventDefault) e.preventDefault();
if (e.stopPropagation) e.stopPropagation();
if (suggest._visible) {
suggest.style.display = 'none';
suggest._visible = false;
}
e.cancelBubble=true;
term_keypress_inner(e, false);
return false;
}
function term_keypress_inner(e, synth) {
var k = e.which;
var kc;
if (e.charCode) {
if (e.charCode == 27 || e.charCode == 13 || e.charCode == 10
|| e.charCode == 8
|| e.charCode == 9) {
k = e.charCode;
kc = String.fromCharCode(e.charCode);
} else if (e.charCode == 63232) {
k = 57373;
} else if (e.charCode == 63233) {
k = 57374;
} else if (e.charCode == 63234) {
k = 57375;
} else if (e.charCode == 63235) {
k = 57376;
} else {
if (e.charCode == 191) return; // wtf?
kc = String.fromCharCode(e.charCode);
k = 0;
}
} else if (e.keyCode) {
k = e.keyCode;
if (e.DOM_VK_UP) {
if (e.DOM_VK_UP == k) k = 57373;
else if (e.DOM_VK_DOWN == k) k = 57374;
else if (e.DOM_VK_LEFT == k) k = 57375;
else if (e.DOM_VK_RIGHT == k) k = 57376;
} else {
kc = String.fromCharCode(e.keyCode);
}
if (k == 191) return; // unicode i think
} else {
if (!k || k == 191) return;
kc = String.fromCharCode(k);
var i;
}
var mod;
if (e.modifiers) mod = e.modifiers; else mod = 0;
var ctrl = e.ctrlKey | (mod & 2);
var shift = e.shiftKey | (mod & 4);
var meta = e.altKey | e.metaKey | (mod & 1);
var lk = lastkey;
lastkey = kc;
if (kc == undefined) kc = '';
if (!emacsen && mode == 0) {
if (kc == 'U') {
if ((base+cursory) == undoy) {
var aa = _hra(undoline);
file[undoy] = aa[0];
tags[undoy] = aa[1];
}
} else if (kc == 'u' && undoset) {
var z = term_freeze();
term_thaw(undoset);
undoset = z;
}
if (kc == 'u' || kc == 'U') {
term_scrollto();
term_redraw();
lastkey = undefined;
return;
}
}
var fakemode = false;
// emacsen
if (emacsen && meta && (kc == 'x' || kc == 'X')) {
kc = ':'
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 't' || kc == 'T')) {
kc = '?'
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 's' || kc == 'S')) {
kc = '/'
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 'k' || kc == 'K')) {
term_command(':d');
lastkey = undefined;
return;
} else if (emacsen && meta && (kc == 'd' || kc == 'D')) {
kc = 'D';
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 'a' || kc == 'A')) {
kc = '0';
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 'd' || kc == 'D')) {
if (emacsen) {
kc = 'x';
} else {
// err...
if (!accum) accum=term_rows+1;
cursory += parseInt(accum/2)+2;
accum=0;
term_scrollto();
term_redraw();
lk = undefined;
lastkey = undefined;
return;
}
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 'g' || kc == 'G')) {
term_command(':f');
lastkey = undefined;
return;
} else if (ctrl && (kc == 'e' || kc == 'E')) {
if (emacsen) {
kc = '$';
} else {
if (!accum) accum = 1;
cursory += accum;
accum = 0;
term_scrollto();
term_redraw();
lk = undefined;
lastkey = undefined;
return;
}
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (emacsen && meta && (kc == 'b' || kc == 'B')) {
kc = 'b';
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (emacsen && meta && (kc == 'l' || kc == 'L')) {
kc = 'e';
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (emacsen && meta && (kc == 'f' || kc == 'F')) {
kc = 'w';
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 'f' || kc == 'F')) {
if (emacsen) {
kc = 'l';
} else {
// vi pagedown
if (!accum) accum = 0;
cursory += (term_rows*accum);
accum = 0;
term_scrollto();
term_redraw();
lk = undefined;
lastkey = undefined;
return;
}
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 'y' || kc == 'Y')) {
if (emacsen) {
term_command(':y');
lastkey = undefined;
return;
} else {
if (!accum) accum = 1;
cursory -= accum;
accum = 0;
term_scrollto();
term_redraw();
lk = undefined;
lastkey = undefined;
return;
}
} else if (ctrl && (kc == 'l' || kc == 'L')) {
term_redraw();
lk = undefined;
lastkey = undefined;
return;
} else if (ctrl && (kc == 'u' || kc == 'U')) {
if (emacsen) {
// emacs undo
kc = 'u';
} else {
// vi pageup
if (!accum) accum=term_rows+1;
cursory -= parseInt(accum/2)+2;
accum=0;
term_scrollto();
term_redraw();
lk = undefined;
lastkey = undefined;
return;
}
fakemode = true;
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 'w' || kc == 'W')) {
// vim uses this for window control; this is actually useful
fakemode = true;
term_vi_set('d');
kc = 'b';
lk = undefined;
lastkey = undefined;
} else if (ctrl && (kc == 'b' || kc == 'B')) {
if (emacsen) {
kc = 'h';
} else {
// vi pageup
if (!accum) accum=1;
cursory -= (term_rows*accum);
accum=0;
term_scrollto();
term_redraw();
lk = undefined;
lastkey = undefined;
return;
}
fakemode = true;
lk = undefined;
lastkey = undefined;
}
if (k >= 57373 && k <= 57376 && !synth) {
// bail
return
} else if (!synth && (k < 57373 || k > 57376)) {
// no touching...
} else if (k == 31 || k == 40 || k == 57374) { // down
if (!synth) return;
fakemode = true;
kc = 'j';
lk = undefined;
lastkey = undefined;
} else if (k == 30 || k == 38 || k == 57373) { // up
if (!synth) return;
fakemode = true;
kc = 'k';
lk = undefined;
lastkey = undefined;
} else if (k == 28 || k == 37 || k == 57375) { // left
if (!synth) return;
fakemode = true;
kc = ctrl ? 'B' : 'h';
lk = undefined;
lastkey = undefined;
} else if (k == 29 || k == 39 || k == 57376) { // right
if (!synth) return;
fakemode = true;
kc = ctrl ? 'W' : 'l';
lk = undefined;
lastkey = undefined;
} else if (k == 33) { // pageup
cursory -= term_rows;
term_scrollto();
term_redraw();
lk = undefined;
lastkey = undefined;
return;
} else if (k == 34) { // pagedown
cursory += term_rows;
term_scrollto();
term_redraw();
lk = undefined;
lastkey = undefined;
return;
} else if (k == 36) { // home
if (ctrl) {
lk = 'g';
kc = 'g';
} else {
kc = '0';
}
fakemode = true;
lk = undefined;
lastkey = undefined;
accum = 0;
} else if (k == 35) { // end
fakemode = true;
accum = 0;
if (ctrl) {
kc = 'G';
} else {
kc = '$';
}
lk = undefined;
lastkey = undefined;
} else if (k == 45) { // insert
fakemode = true;
if (mode == 1) {
mode = 2;
} else if (mode == 2) {
mode = 1;
} else {
term_setmode(1);
}
lk = undefined;
lastkey = undefined;
term_redraw();
return;
} else if (k == 46) { // delete
fakemode = true;
kc = 'x';
lk = undefined;
lastkey = undefined;
} else if (synth && k != 8) {
return;
}
term_save_undo_line();
if (fakemode || mode == 0) {
if (!fakemode && ctrl) return;
if (lk == 'F' || lk == 'T' || lk == 'f' || lk == 't') {
vi_ft_reg = kc;
if (lk == 'F') {
term_ex_motion = term_vi_ff;
} else if (lk == 'T') {
term_ex_motion = term_vi_tt;
} else if (lk == 'f') {
term_ex_motion = term_vi_f;
} else if (lk == 't') {
term_ex_motion = term_vi_t;
}
term_operate();
lastkey = undefined;
term_scrollto();
term_redraw();
_update_backing();
return;
} else if (lk == 'm') {
// set mark
marks[kc] = cursory+base;
lastkey = undefined;
accum = 0;
return;
} else if (lk == "'") {
term_ex_motion = function() {
cursory = marks[kc];
base = 0;
term_scrollto();
term_redraw();
return true;
};
if (!accum) accum = 1;
term_operate();
return;
} else if (lk == '"') {
// set last register
lastreg = kc;
lastkey = undefined;
accum = 0;
return;
} else if (lk == 'r') {
var p = cursorx + left;
var t = (file[cursory+base]);
if (!accum) accum = 1;
var ng = '';
var i;
for (i = 0; i < accum; i++) ng += kc;
term_save_undo();
file[cursory+base] = (t.substr(0, p))
+ (ng) + (t.substr(p+accum, t.length-(p+accum)));
// tags remains unchanged (same length)
accum = 0;
lastkey = undefined;
term_scrollto();
term_redraw();
_update_backing();
_term_update_printer();
return;
}
if (kc == ':' || kc == '/' || kc == '?') {
command = kc;
commandleft = 0;
savex = cursorx;
savey = cursory;
cursorx = 1;
cursory = term_rows-1;
mode=1;
term_redraw();
term_calcx();
return;
} else if (kc == "'") {
// jump to mark (ick)
} else if (kc == '"') {
// do nothing for now
} else if (kc == '.') {
term_vi_set(lastcommand);
term_ex_motion = lastmotion;
term_operate();
} else if (kc == '$') {
term_ex_motion = term_vi_eol;
term_operate();
} else if (kc == '%') {
if (accum <= 0) {
term_ex_motion = term_vi_bounce;
term_operate();
} else if (file.length > 0) {
base = 0;
cursorx = 0;
left = 0;
cursory = parseInt(accum * (term_rows / (file.length+1.0)));
accum = 0;
}
} else if (kc == '0') {
if (accum) {
accum *= 10;
} else {
cursorx = 0;
left = 0;
}
} else if (kc == '1') {
accum *= 10; accum++;
} else if (kc == '2') {
accum *= 10; accum += 2;
} else if (kc == '3') {
accum *= 10; accum += 3;
} else if (kc == '4') {
accum *= 10; accum += 4;
} else if (kc == '5') {
accum *= 10; accum += 5;
} else if (kc == '6') {
accum *= 10; accum += 6;
} else if (kc == '7') {
accum *= 10; accum += 7;
} else if (kc == '8') {
accum *= 10; accum += 8;
} else if (kc == '9') {
accum *= 10; accum += 9;
} else if (kc == 'A') {
var t = (file[cursory+base]);
cursorx = t.length; // will be fixed up...
term_setmode(1);
term_save_undo();
} else if (kc == 'a') {
term_setmode(1);
cursorx++;
term_save_undo();
} else if (kc == 'B') {
term_ex_motion = term_vi_bb;
term_operate();
} else if (kc == 'b') {
term_ex_motion = term_vi_b;
term_operate();
} else if (kc == 'c') {
if (term_vi_flag('c')) {
term_vi_set('d');
term_vi_unset('c');
savex = cursorx+left;
savey = cursory+base;
cursorx = 0; left = 0;
term_ex_motion = term_vi_line;
term_operate();
cursorx = savex-left;
cursory = savey-base;
term_setmode(1);
} else {
term_vi_set('c');
}
} else if (kc == 'C') {
term_ex_motion = term_vi_eol;
term_vi_set('d');
term_operate();
term_setmode(1);
} else if (kc == 'D') {
term_ex_motion = term_vi_eol;
term_vi_set('d');
term_operate();
} else if (kc == 'd') {
if (vselm) {
term_vi_set('d');
term_vi_unset('y');
term_select();
term_operate();
vselm = 0;
} else if (term_vi_flag('d')) {
accum++;
savex = cursorx+left;
savey = cursory+base;
cursorx = 0; left = 0;
term_ex_motion = term_vi_line;
term_operate();
cursorx = savex-left;
cursory = savey-base;
} else {
term_vi_set('d');
term_vi_unset('y');
}
} else if (kc == '>' || kc == '<') {
if (vselm) {
term_vi_unset('<');
term_vi_unset('>');
term_vi_set(kc);
term_vi_unset('d');
term_vi_unset('y');
term_operate();
vselm = 0;
} else if (term_vi_flag(kc)) {
accum++;
savex = cursorx+left;
savey = cursory+base;
cursorx = 0; left = 0;
term_ex_motion = term_vi_line;
term_operate();
cursorx = savex-left;
cursory = savey-base;
term_vi_unset('<');
term_vi_unset('>');
} else {
term_vi_unset('<');
term_vi_unset('>');
term_vi_set(kc);
term_vi_unset('d');
term_vi_unset('y');
}
} else if (kc == 'E') {
term_ex_motion = term_vi_ee;
term_operate();
} else if (kc == 'e') {
term_ex_motion = term_vi_e;
term_operate();
} else if (kc == 'F' || kc == 'f') {
// does nothing here
} else if (kc == 'G') {
term_ex_motion = term_vi_eof;
term_operate();
} else if (kc == 'g' && lk == 'g') {
term_ex_motion = term_vi_top;
term_operate();
} else if (kc == 'H') {
term_ex_motion = term_vi_hh;
term_operate();
} else if (kc == 'h') {
term_ex_motion = term_vi_h;
term_operate();
} else if (kc == 'I') {
term_save_undo();
if (vselm) {
term_vi_set('d');
term_vi_unset('y');
term_select();
term_operate();
vselm = 0;
}
term_setmode(1);
cursorx = 0;
left = 0;
} else if (kc == 'i') {
term_save_undo();
if (vselm) {
term_vi_set('d');
term_vi_unset('y');
term_select();
term_operate();
vselm = 0;
}
term_setmode(1);
} else if (kc == 'J') {
term_save_undo();
term_justify();
} else if (kc == 'j') {
term_ex_motion = term_vi_j;
term_operate();
} else if (kc == 'K') {
// err..
} else if (kc == 'k') {
term_ex_motion = term_vi_k;
term_operate();
} else if (kc == 'L') {
term_ex_motion = term_vi_ll;
term_operate();
} else if (kc == 'l') {
term_ex_motion = term_vi_l;
term_operate();
} else if (kc == 'M') {
term_ex_motion = term_vi_mm;
term_operate();
} else if (kc == 'm') {
// set mark
} else if (kc == 'N') {
if (lastsearch == '') {
statustext = 'No previous regular expression';
} else {
if (!accum) accum = 1;
var sl = lastsearch;
var cx = lastsearch.substr(0, 1);
cx = (cx == '?') ? '/' : '?';
var i;
for (i = 0; i < accum; i++) {
term_command(cx+(sl.substr(1, sl.length-1)));
}
lastsearch = sl;
accum = 0;
}
} else if (kc == 'n') {
if (lastsearch == '') {
statustext = 'No previous regular expression';
} else {
if (!accum) accum = 1;
var i;
for (i = 0; i < accum; i++)
term_command(lastsearch);
accum = 0;
}
} else if (kc == 'O') {
cursorx = 0;
left = 0;
term_insert(cursory+base);
term_setmode(1);
} else if (kc == 'o') {
cursory++;
cursorx = 0;
left = 0;
term_insert(cursory+base);
term_setmode(1);
term_save_undo();
} else if (kc == 'P' || kc == 'p') {
term_save_undo();
term_paste(kc == 'P' ? false : true);
accum = 0;
} else if (kc == 'R') {
term_save_undo();
if (vselm) {
term_vi_set('d');
term_vi_unset('y');
term_select();
term_operate();
vselm = 0;
}
term_setmode(2);
} else if (kc == 'S') {
term_vi_set('d');
term_vi_unset('c');
savex = cursorx+left;
savey = cursory+base;
cursorx = 0; left = 0;
term_ex_motion = term_vi_line;
term_operate();
cursorx = savex-left;
cursory = savey-base;
term_setmode(1);
} else if (kc == 's') {
term_vi_set('d');
term_vi_unset('c');
savex = cursorx+left;
savey = cursory+base;
term_ex_motion = term_vi_l;
term_operate();
cursorx = savex-left;
cursory = savey-base;
term_setmode(1);
} else if (kc == 'T' || kc == 't') {
// nothing here
} else if (kc == 'V' || kc == 'v') {
if (vselm) {
vselm = 0;
vselx = undefined;
vsely = undefined;
} else {
vselm = (kc == 'v') ? 1 : 2;
vselx = cursorx+left;
vsely = cursory+base;
}
} else if (kc == 'W') {
term_ex_motion = term_vi_ww;
term_operate();
} else if (kc == '{') {
term_ex_motion = term_vi_ob;
term_operate();
} else if (kc == '}') {
term_ex_motion = term_vi_cb;
term_operate();
} else if (kc == 'w') {
term_ex_motion = term_vi_w;
term_operate();
} else if (kc == 'x' || kc == 'X') {
if (term_vi_set('d')) {
term_vi_unset('d');
} else {
term_vi_set('d');
if (kc == 'x') {
term_ex_motion = term_vi_l;
} else {
term_ex_motion = term_vi_h;
}
term_operate();
}
} else if (kc == 'y') {
if (vselm) {
term_vi_set('y');
term_vi_unset('d');
term_select();
term_operate();
vselm = 0;
} else if (term_vi_flag('y')) {
accum++;
savex = cursorx+left;
savey = cursory+base;
cursorx = 0; left = 0;
term_ex_motion = term_vi_line;
term_operate();
cursorx = savex-left;
cursory = savey-base;
} else {
term_vi_set('y');
term_vi_unset('d');
}
} else if (kc == 'Z' && lk == 'Z') {
editor_disable(true);
accum = 0;
} else if (k == 27 || (k == 91 && ctrl)) { // escape or ^[
vselm = 0;
statustext = '';
mode = 0;
} else {
accum = 0;
}
term_scrollto();
} else if ((k == 27 || (k == 91 && ctrl))) { // escape or ^[
vselm = 0;
statustext = '';
if (command != '') {
cursorx = savex;
cursory = savey;
} else {
if (mode) _term_update_printer();
if (accum > 1) {
var i, j;
j = lastreg;
lastreg = '.';
for (i = 1; i < accum; i++) {
term_paste(false);
}
lastreg = j;
accum = 0;
}
cursorx--;
term_scrollto();
}
mode = emacsen ? 1 : 0;
command = '';
commandleft = 0;
} else if (command != '') {
if (k == 10 || k == 13) {
// cr and execute command
cursorx = savex;
cursory = savey;
if (emacsen) {
mode = 1;
} else {
mode = 0;
}
var cy = command;
command = '';
commandleft = 0;
term_command(cy);
var cx = command.substr(0,1);
if (cx == '/' || cx == '?') lastsearch = cy;
else oldcommand = cy;
// incase its needed
term_scrollto();
} else if (k == 8) {
if (!synth) return;
command = command.substr(command, command.length-1);
cursorx--;
if (cursorx <= 0) {
var w = term_cols;
commandleft -= (w-16);
cursorx = w - 8;
if (commandleft < 0) {
cursorx = savex;
cursory = savey;
if (emacsen) {
mode = 1;
} else {
mode = 0;
}
}
}
} else {
command = command + kc;
cursorx++;
var w = term_cols;
if (cursorx >= (w-8)) {
cursorx = 8;
commandleft += w-16;
}
}
term_redraw();
term_calcx();
_update_backing();
return;
} else {
var t = (file[cursory+base]);
var lx = (t.substr(0, cursorx+left));
var ly = (t.substr(cursorx+left+(mode-1)));
var lz = (t.substr(cursorx+left));
var g = (tags[cursory+base]);
var gx = (g.substr(0, cursorx+left));
var gy = (g.substr(cursorx+left+(mode-1)));
var gz = (g.substr(cursorx+left));
if (!lx) lx = '';
if (k == 9) kc = ' ';
if (k == 10 || k == 13) {
// CR
if (!lz) lz = '';
file[cursory+base] = lx;
tags[cursory+base] = gx;
cursory++;
cursorx=0;
left=0;
term_insert(cursory+base);
file[cursory+base] = lz;
tags[cursory+base] = gz;
lastinsert += "\n";
} else if (k == 8) {
if (!synth) return;
// backspace
file[cursory+base] = lx.substr(0,lx.length-1)+lz;
tags[cursory+base] = gx.substr(0,lx.length-1)+gz;
lastinsert = lastinsert.substr(0,lastinsert.length-1);
cursorx--;
} else {
if (kc == '') return;
file[cursory+base] = lx+kc+ly;
tags[cursory+base] = gx+String.fromCharCode(tagstyle)+gy;
lastinsert += kc;
cursorx+=kc.length;
}
term_scrollto();
}
term_redraw();
_update_backing();
return;
}
function _redraw_cursor() {
term_draw_cursor(true);
_update_backing();
}
function term_draw_cursor(tf) {
// maybe use vertical bar if mode==1 hrm?
if (!tf || !cursor._opaque) {
cursor._opaque = true;
cursor.style.color = palette[1];
cursor.style.backgroundColor = palette[0];
} else {
cursor._opaque = false;
cursor.style.color = palette[0];
cursor.style.backgroundColor = palette[1];
}
}
function _redraw_term_force() {
while (term.firstChild) term.removeChild(term.firstChild);
}
function _redraw_term() {
var h = term_rows;
var w = term_cols;
var ka, kb;
var tospell = 0;
var osp = '';
var y;
var tago = new Array();
var isurl = new Array();
var ca, cb;
var sa, sb;
var qp;
if (vselm) {
sa = vsely-base;
sb = cursory;
if (sa > sb) {
zx = sa;
sa = sb;
sb = zx;
}
ca = vselx-left;
cb = cursorx;
if (ca > cb) {
zx = ca;
ca = cb;
cb = zx;
}
}
for (y = 0; y < h; y++) {
ka = ''; kb = '';
var x = file[y+base];
var g;
var zleft = 0;
var cx;
var j, vj;
if (y == (h-1)) {
if (cursory == y) {
zleft = commandleft;
x = command;
cx = 0;
statustext = '';
} else if (emacsen) {
x = '[' + (mode == 1 ? 'Ins' : 'Ovr') + '] ' + statustext;
while (x.length < w) {
x += ' ';
}
cx = 4;
} else if (vselm == 1) {
cx = 1; x = '-- VISUAL --';
statustext = '';
} else if (vselm == 2) {
cx = 1; x = '-- VISUAL LINE --';
statustext = '';
} else if (mode == 0) {
x = statustext;
cx = 16;
} else if (mode == 1) {
cx = 1; x = '-- INSERT --';
statustext = '';
} else if (mode == 2) {
cx = 1; x = '-- REPLACE --';
statustext = '';
}
g = _mxs(x.length, cx);
} else if (x == undefined) {
x = '~';
g = "\010";
} else {
zleft = left;
g = tags[y+base];
// do spellchecking
var p = 0;
vj = x.split(/[ ,;]+/);
for (j = 0; j < vj.length; j++) {
var vx = vj[j];
var vm = _word(vx);
if (j != 0) p++;
if (vx.match(/^(https?|ftp):\/\//)) {
g = g.substr(0, p)
+ _mxo(g.substr(p, vx.length), ((1+tago.length)*256))
+ g.substr(p+vx.length);
isurl[tago.length] = true;
tago[tago.length] = vx;
} else if (brokenwords[vm] && !safewords[vm]) {
g = g.substr(0, p)
+ _mxo(g.substr(p, vx.length), ((1+tago.length)*256))
+ g.substr(p+vx.length);
isurl[tago.length] = false;
tago[tago.length] = vx;
} else {
if (vm.length > 3 && !_safe(vm) && !safewords[vm] && !spelling) {
tospell++;
osp += escape("c"+tospell) + "="
+ escape(vm) + "&";
spellcheck[tospell] = vm;
}
}
p += vx.length;
}
}
if (x == undefined) {
x = '';
g = '';
}
var zx;
vx = 0;
// truncate as necessary
x = x.substr(zleft, x.length-zleft);
g = g.substr(zleft, g.length-zleft);
if (x.length >= w) {
x = x.substr(0, w);
g = g.substr(0, w);
}
if (vselm) {
if (vselm == 1 && sa == sb && sa == y) {
// middle of line between ca->cb is selected
g = g.substr(0,ca) + _mxo(g.substr(ca,(cb-ca)+1), 4) + g.substr(cb,(g.length-cb)-1);
} else if ((sa < y && sb > y) || (vselm == 2 && (sa <= y && sb >= y))) {
// entire line selected
g = _mxo(g, 4);
} else if (sa < y && sb == y) {
// beginning of line selected (up to q)
// if (sb is cursory) then q = cursorx otherwise vselx
qp = (sb == cursory) ? cursorx : (vselx-left);
g = _mxo(g.substr(0, qp+1), 4) + g.substr(qp, (g.length-qp)-1);
} else if (sa == y && sb > y) {
// end of line selected (beginning at q)
// if (sa is cursory) then q = cursorx otherwise vselx
qp = (sa == cursory) ? cursorx : (vselx-left);
g = g.substr(0, qp) + _mxo(g.substr(qp, g.length-qp), 4);
}
}
vj = 0;
g += "\377"; // terminate
x += " ";
x = x.replace(/ /g, "\240");
if (term.childNodes.length > y) {
zx = term.childNodes[y];
if (zx._cachex == x && zx._cacheg == g) {
if (y == cursory) _calcy(zx, x, g);
continue;
}
// as a last ditch effort- to accelerate deletions...
// and inserts...
if (term.childNodes.length > (y+1)) {
var zy = term.childNodes[y+1];
if (zy._cachex == x && zy._cacheg == g) {
// okay then, so the NEXT line is the winner
// copy its nodes
term.removeChild(zy);
term.replaceChild(zy, zx);
if (zy.nextSibling) {
term.insertBefore(zx, zy.nextSibling);
} else {
term.appendChild(zx);
}
if (y == cursory) _calcy(zy, x, g);
continue;
}
}
// update
while (zx.firstChild) zx.removeChild(zx.firstChild);
} else {
zx = document.createElement('PRE');
zx.style.display='block';
zx.style.fontFamily = 'monospace';
zx.style.fontSize = '100%';
_zmp(zx);
zx.style.marginBottom = '1px';
}
cx = 255;
var ax = zx;
for (j = 0; j < x.length; j++) {
var gx = g.charCodeAt(j);
if (gx != cx) {
if (j != vj && ax) {
var t = x.substr(vj, (j-vj));
if (!t) t = '';
ax.appendChild(document.createTextNode(t));
if (zx != ax) zx.appendChild(ax);
vj = j;
}
if (gx > 255) {
var wx = parseInt(gx / 256)-1;
ax = document.createElement('A');
if (isurl[wx]) {
ax.style.borderBottom = '1px double blue';
ax.href = tago[wx];
ax.target = '_new';
ax.ondblclick = _openurl;
} else {
ax.style.borderBottom = '1px dashed red';
ax.href = 'javascript:void(0)';
ax.ondblclick = _suggest;
}
ax._term = _word(tago[wx]);
ax._len = tago[wx].length;
ax._row = y+base;
ax._col = j+zleft;
ax.onclick = _subclick;
} else {
ax = document.createElement('SPAN');
}
if (gx == 255) gx = 0;
if (gx & 1) {
ax.style.fontWeight = 'bold';
} else {
ax.style.fontWeight = 'normal';
}
if (gx & 2) {
ax.style.textDecoration = 'underline';
} else {
ax.style.textDecoration = 'none';
}
if (gx & 4) { // reverse video
ax.style.color = palette[1];
ax.style.backgroundColor = palette[0];
} else {
ax.style.color = palette[0];
ax.style.backgroundColor = palette[1];
}
if (gx & 8) { // unselectable
ax.unselectable = true;
if (ax.setAttribute) ax.setAttribute('unselectable', 'on');
ax.style.color = palette[0];
ax.style.backgroundColor = palette[1];
ax.style.userSelect = 'none';
ax.style['-moz-user-select'] = 'none';
}
if (gx & 16) {
ax.style.fontStyle = 'italic';
} else {
ax.style.fontStyle = 'normal';
}
cx = gx;
}
}
if (j != vj) {
var t = x.substr(vj, (j-vj)-1);
ax.appendChild(document.createTextNode(t));
if (zx != ax) zx.appendChild(ax);
vj = j;
}
ax.appendChild(document.createTextNode("\240"));
zx._cachex = x;
zx._cacheg = g;
if (term.childNodes.length <= y) {
term.appendChild(zx);
}
if (y == 1) {
var qx = zx;
var nh = 0;
while (qx && qx != document.body) {
nh += qx.offsetTop;
qx = qx.offsetParent;
}
if (nh != line_height) {
line_height = nh;
term_resize();
}
}
if (y == cursory) {
_calcy(zx, x, g);
}
ax = undefined; // break;
}
while (term.childNodes.length > h) {
term.removeChild(term.lastChild);
}
zx = undefined; // break
if (!spelling && tospell > 0) {
spelling = true;
var xh = _xhttp();
osp=osp.substr(0,osp.length-1);
xh.open("GET", "spell.cgi?"+osp, true);
xh.onreadystatechange = function() {
if (xh.readyState == 4) {
var j;
var a = xh.responseText.split("\n");
for (j = 0; j < a.length; j++) {
var kp = a[j].split("=", 2);
var k, v;
if (kp.length == 2) {
k = kp[0];
v = kp[1];
} else if (kp.length == 1) {
k = kp[0];
v = '';
} else {
k = a[j];
v = '';
}
if (k.substr(0,1) != 'c') continue;
k = k.substr(1, k.length-1);
var term = spellcheck[k];
if (v == undefined || v == '') {
brokenwords[term] = true;
suggestions[term] = new Array();
} else if (v == term) {
safewords[term] = true;
} else {
safewords[v] = true;
if (!suggestions[term]) {
suggestions[term] = new Array();
}
suggestions[term][ suggestions[term].length ] = v;
brokenwords[term] = true;
}
}
spelling=false;
window.setTimeout(term_redraw,10);
xh = undefined; // break (deferred)
}
};
xh.send(undefined);
}
if (cursory == (h-1)) {
tools.style.display = 'none';
} else {
tools.style.display = 'block';
}
_update_backing();
}
function _redraw_term_back() {
drawiv = undefined;
_redraw_term();
term_draw_cursor();
}
function term_redraw() {
if (drawiv) window.clearTimeout(drawiv);
drawiv = window.setTimeout(_redraw_term_back, 10);
}
function term_resize() {
var h = term.offsetHeight;
var r = line_height;
if (!line_height) r = cursor.offsetHeight-1; // 1 px overlap
var nh = (h/r);
term_rows = parseInt(nh);
term_win_height = h;
h = term.offsetWidth;
r = (term_cur_width+1); // 1 px padding
nh = (h/r);
term_cols = parseInt(nh);
term_win_width = h;
term_redraw();
}
function editor_disable(sav) {
if (cursoriv) {
window.clearInterval(cursoriv);
cursoriv = undefined;
}
_cbrestore();
if (term._formelement) {
if (sav) term._formelement.value = term_freeze();
// disconnect
term._formelement = undefined;
}
if (backing.removeEventListener) {
backing.removeEventListener('DOMAttrModified',_backing_paste,false);
backing.removeEventListener('Input',_backing_paste,false);
backing.removeEventListener('input',_backing_paste,false);
}
backing.oninput = undefined;
backing.onInput = undefined;
document.body.removeChild(suggest);
document.body.removeChild(term);
document.body.removeChild(printer);
document.body.removeChild(tools);
document.body.removeChild(cursor);
var z;
for (z = document.body.firstChild; z; z = z.nextSibling) {
if (z.tagName && z._flipe) z.style.display = z._orige;
}
// bug in firefox: can't remove this
//document.body.removeChild(backing);
if (backing.blur) backing.blur();
backing.style.display = 'none';
if (document.body.focus) document.body.focus();
if (document.focus) document.focus();
document.body.style.overflow = '';
}
function _cursor_fix() {
term_cur_width = cursor.offsetWidth;
}
function _zmp(o) {
o.style.marginTop='0px';
o.style.marginLeft='0px';
o.style.marginRight='0px';
o.style.marginBottom='0px';
o.style.paddingTop='0px';
o.style.paddingLeft='0px';
o.style.paddingRight='0px';
o.style.paddingBottom='0px';
}
function editor(t) {
if (term && term._formelement && term._formelement != t) {
editor_disable(false);
}
// okay, find EVERYTHING inside body and display none it
var z;
for (z = document.body.firstChild; z; z = z.nextSibling) {
if (z.tagName) {
z._orige = z.style.display;
z._flipe = true;
z.style.display = 'none';
}
}
if (!term) {
term = document.createElement('DIV');
printer = document.createElement('DIV');
suggest = document.createElement('DIV');
backing = document.createElement('TEXTAREA');
tools = document.createElement('DIV');
cursor = document.createElement('DIV');
}
// if (document.documentElement) {
// _zmp(document.documentElement);
// document.documentElement.height = '100%';
// _zmp(document.body);
// document.body.height = '100%';
// }
printer.className = 'print';
cursor.className = 'editorcursor';
term.className = 'editor';
suggest.style.position = 'absolute';
suggest.style.display = 'none';
backing.tabIndex = -1;
backing.style.position = 'absolute';
backing.style.bottom = '0px';
backing.style.right = '0px';
backing.style.width = '1px';
backing.style.height = '1px';
backing.style.visibility = 'hidden';
backing.oninput = _backing_paste;
backing.onInput = _backing_paste;
if (backing.addEventListener) {
backing.addEventListener('DOMAttrModified',_backing_paste,false);
backing.addEventListener('Input',_backing_paste,false);
backing.addEventListener('input',_backing_paste,false);
}
if (window.addEventListener) {
window.addEventListener('DOMMouseScroll',_mousescroll,false);
}
tools.className = 'editortools';
tools.style.position = 'absolute';
tools.style.right = '0px';
tools.style.bottom = '0px';
tools.innerHTML = ''
+ ''
+ ''
+ ''
+ ' '
+ ''
+ ' '
+ ''
+ ''
cursor.onclick = _pass_click;
cursor.ondblclick = _pass_dblclick;
document.body.appendChild(suggest);
document.body.appendChild(term);
document.body.appendChild(printer);
document.body.appendChild(tools);
// firefox bug
if (once) document.body.appendChild(backing);
document.body.appendChild(cursor);
cursoriv = window.setInterval(_redraw_cursor, 300);
term.style.position = 'absolute';
term.style.top = '0px';
term.style.left = '0px';
term.style.display = 'block';
term.style.overflow = 'hidden';
term.style.width = '100%';
term.style.height = '100%';
term.style.cursor = 'default';
term.style.fontFamily = 'monospace';
term.style.fontSize = '100%';
_zmp(term);
term._formelement = t;
document.body.style.overflow = 'hidden';
tools.style.display = 'block';
_cbd('select', _cancel_ev);
_cbd('selectstart', _cancel_ev);
_cbd('keydown', term_keyfix);
_cbd('keypress', term_keypress);
_cbd('paste', _msie_paste);
_cbd('click', _mouseclick);
_cbd('mousedown', _mousedown);
_cbd('mousemove', _mousemove);
_cbd('mouseup', _mouseup);
_cbd('mousewheel', _mousescroll);
vselm = 0;
vseld = false;
vselx = undefined;
vsely = undefined;
t.blur();
cursorx = 0;
cursory = 0;
cursor.style.position = 'absolute';
cursor.style.top = 0;
cursor.style.left = 0;
cursor.style.fontFamily = 'monospace';
cursor.style.fontSize = '100%';
cursor.style.width = 'auto';
cursor.style.cursor = 'default';
_zmp(cursor);
cursor.style.overflow = 'hidden';
cursor.innerHTML = 'X';
cursor._opaque = false;
cursor._lasty = -1;
cursor._lastx = -1;
cursor._lastch = '-xyz-';
cursor._lastgh = 0;
palette = undefined;
if (document.defaultView && document.defaultView.getComputedStyle) {
palette = new Array();
var cs = document.defaultView.getComputedStyle(term, null);
palette[0] = cs.color;
palette[1] = cs.backgroundColor;
} else if (window.getComputedStyle) {
palette = new Array();
var cs = window.getComputedStyle(term, null);
palette[0] = cs.color;
palette[1] = cs.backgroundColor;
} else if (term.currentStyle) {
palette = new Array();
palette[0] = term.currentStyle.color;
palette[1] = term.currentStyle.backgroundColor;
}
if (emacsen) {
mode = 1;
} else {
mode = 0;
}
once = false;
backing._lastvalue = '';
backing.value = '';
backing.defaultValue = '';
suggest._visible = false;
suggest.display = 'none';
tools.style.backgroundColor = palette[0];
_dfx(tools);
// degrading...
file = new Array();
tags = new Array();
var st = t.value.split("\n");
var j;
for (j = 0; j < st.length; j++) {
if (st[j].substr(st[j].length-1, 1) == "\r") {
st[j] = st[j].substr(0, st[j].length-1);
}
var aa = _hra(st[j]);
file[j] = aa[0];
tags[j] = aa[1];
}
// fix
t.value = term_freeze();
_term_update_printer();
cursor.style.display = 'inline';
_cursor_fix();
window.setTimeout(term_redraw,1);
term_resize();
_cbw('resize', term_resize);
_cbw('beforeprint', _term_update_printer);
_update_backing();
}