/* 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(); }