/******************************************************************
editor.js Muze Helene
------------------------------------------------------------------
Author: Muze (info@muze.nl)
Date: 28 februari 2004
Copyright 2002 Muze
This file is part of Helene.
Helene 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 2 of the License,
or (at your option) any later version.
Helene 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 Helene; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA
-------------------------------------------------------------------
This file contains the basic editor functionality.
******************************************************************/
var currentLine = 1;
var previousLine = 1;
var lastLine = 0;
var screenWidth = 0;
var lineHeight = 16;
var contentDiv;
var lines;
var inputLine;
var inputLineEntry;
var oldpos=-1;
var isDirty=false;
var winW = 630;
var winH = 460;
var inputLineHasFocus = false;
var offsetLine = 0;
var currInputHeight = lineHeight;
var letterWidth = 9;
var clickPosOffsetLeft = 0;
var longestLine = 0;
var adjustTop = 0;
var minInputWidth = 0;
var addedSpaces=0;
var userSelecting = false;
var selectIni=-1;
var selectLineIni=-1;
var keyBinding = new Array();
var keyBindings = new Array();
var cancelKey = false;
var autoIndent = true;
var startcoordinate = false;
/* Undo/Redo vars */
var undoBuffer = [];
var redoBuffer = [];
var startCursorPos = -1; // Cursor position before text alteration
var saveUndo = true;
var isMoz = false;
var checkPastedReturns = false;
var unsaved = false;
/* states */
var holdingdownkey = false;
var holdingupkey = false;
var holdingdeletekey = false;
var holdingbackkey = false;
var holdingenterkey = false;
var holdingpgdownkey = false;
var holdingpgupkey = false;
/* search variables */
var str_search = 'texto';
/* keybindings */
keyBindings["default"] = new Array();
keyBindings["default"]["default"] = do_Default; // Default action for unrecognized keys
keyBindings["default"]["40"] = do_Down; // down
keyBindings["default"]["s40"] = do_SelectDown; // shift-down
keyBindings["default"]["38"] = do_Up; // up
keyBindings["default"]["s38"] = do_SelectUp; // shift-up
keyBindings["default"]["37"] = do_Left; // left
keyBindings["default"]["s37"] = do_SelectLeft; // shift-left
keyBindings["default"]["39"] = do_Right; // right
keyBindings["default"]["s39"] = do_SelectRight; // shift-right
keyBindings["default"]["8"] = do_Backspace; // backspace
keyBindings["default"]["46"] = do_Delete; // delete
keyBindings["default"]["13"] = do_Linebreak; // enter
keyBindings["default"]["34"] = do_PageDown; // page-down
keyBindings["default"]["s34"] = do_SelectPageDown; // shift-page-down
keyBindings["default"]["33"] = do_PageUp; // page-up
keyBindings["default"]["s33"] = do_SelectPageUp; // shift-page-up
keyBindings["default"]["36"] = do_Home; // home
keyBindings["default"]["c36"] = do_BeginCode; // ctrl-home
keyBindings["default"]["35"] = do_End; // End
keyBindings["default"]["c35"] = do_EndCode; // ctrl-end
keyBindings["default"]["9"] = do_Tab; // Tab
keyBindings["default"]["c86"] = do_Paste; // ctrl-v
keyBindings["default"]["c90"] = do_Undo; // ctrl-z
keyBindings["default"]["c89"] = do_Redo; // ctrl-y
keyBindings["default"]["cs90"] = do_Redo; // ctrl-shift-z
//keyBindings["default"]["c67"] = do_Copy; // ctrl-c
/* joe bindings */
keyBindings["joe"] = new Array();
keyBindings["joe"]["c65"] = do_Home; // ctrl-e
keyBindings["joe"]["c69"] = do_End; // ctrl-a
keyBindings["joe"]["c88"] = do_skipCharsRight; // ctrl-x
keyBindings["joe"]["c90"] = do_skipCharsLeft; // ctrl-z
keyBindings["joe"]["c75"] = joe_Ctrlk; // ctrl-k
keyBindings["joe"]["cs189"] = do_Undo; // ctrl shift -
keyBindings["joe"]["cs54"] = do_Redo; // ctrl shift 6
keyBindings["joe"]["default"] = joe_Default;
/* joe ctrl-k bindings */
keyBindings["joe"]["ctrl-k"] = new Array();
keyBindings["joe"]["ctrl-k"]["85"] = joe_ScrollHome; // ctrl-k u
keyBindings["joe"]["ctrl-k"]["86"] = joe_ScrollEnd; // ctrl-k v
keyBindings["joe"]["ctrl-k"]["default"] = joe_Default_Ctrlk;
/* keybinding to use */
keyBinding = keyBindings["default"];
/* undo buffer constants */
var undo = { CHANGE_TEXT: 1, LINE_AFTER: 2, DELETE_LINE: 3 };
var window_title;
function handleMouseWheel(e)
{
if (!e) e = window.event;
if ( e.wheelDelta <= 0 || e.detail > 0)
{
window.scrollBy(0,30);
}
else
{
window.scrollBy(0,-30);
}
}
function setInputFocus()
{
inputLineEntry.focus();
}
function init() {
contentDiv = document.getElementById('content');
codeframeDiv = document.getElementById('codeframe');
lines = document.getElementById('lines');
lineHeight = lines.childNodes[0].offsetHeight;
currInputHeight = lineHeight;
lastLine = lines.childNodes.length;
inputLine = document.getElementById('inputLine');
inputLineEntry = document.getElementById('inputLineEntry');
window_title = window.parent.document.title;
if (parseInt(navigator.appVersion) > 3)
{
if (navigator.appName == "Netscape")
{
isMoz = true;
winW = window.innerWidth-42;
winH = window.innerHeight-2;
minInputWidth = winW-16;
document.onkeypress = moz_onKeyPress;
document.onkeydown = keyDownHandler;
document.onkeyup = keyUpHandler;
init_mozilla_compat();
window.addEventListener("DOMMouseScroll", handleMouseWheel, false);
/* do some w3c dom magic to get the current font size */
var vw = document.defaultView;
var currStyle = vw.getComputedStyle(lines,"");
var fontSize = currStyle.getPropertyValue("font-size");
var fontFamily = currStyle.getPropertyValue("font-family");
}
else
if (navigator.appName.indexOf("Microsoft")!=-1)
{
winW = document.body.offsetWidth;
winH = document.body.offsetHeight;
document.onkeydown = keyDownHandler;
document.onkeyup = keyUpHandler;
/* get current font size */
var fontSize = lines.currentStyle.fontSize;
var fontFamily = lines.currentStyle.fontFamily;
clickPosOffsetLeft = 44;
minInputWidth = winW-60;
// To handle clipboard paste
inputLineEntry.onpaste = pasteText;
}
else
{
document.onkeydown = keyDownHandler;
/* do some w3c dom magic to get the current font size */
var vw = document.defaultView;
var currStyle = vw.getComputedStyle(lines,"");
var fontSize = currStyle.getPropertyValue("font-size");
var fontFamily = currStyle.getPropertyValue("font-family");
}
}
/* if the user closes the editor without saving his work, a confirmation is required to do so */
window.onbeforeunload = confirmExit;
function confirmExit()
{
if (unsaved)
return "Existem alterações neste arquivo que serão perdidas caso esta janela seja fechada.";
}
document.getElementById('linenumbers').style.height = winH;
updateLineNumbers();
inputLine.style.width = minInputWidth;
inputLine.style.height = lineHeight;
inputLineEntry.onfocus = inputFocus;
inputLineEntry.onblur = inputBlur;
inputLineEntry.style.fontSize = fontSize;
inputLineEntry.style.fontFamily = fontFamily;
inputLineEntry.style.height = lineHeight;
inputLineEntry.style.overflow = 'hidden';
// this is needed because MSIE sometimes shifts the textarea a bit...
adjustTop = -inputLineEntry.offsetTop;
/* calculate width, height of one letter, fix padding if needed */
var templine = lines.childNodes[0].innerHTML;
lines.childNodes[0].innerHTML='m';
letterWidth=document.getElementById("editorLetterWidth").offsetWidth;
spanHeight=document.getElementById("editorLetterWidth").offsetHeight;
spanTopPadding=document.getElementById("editorLetterWidth").offsetTop;
if (lineHeight>spanHeight) {
// this is to make background colors span the entire height of the line
spanBottomPadding=(lineHeight-spanHeight)-spanTopPadding;
} else {
spanBottomPadding=0;
}
if (spanTopPadding || spanBottomPadding) {
// get the stylesheet and apply this padding to each span
var editorStylesheet=document.styleSheets[0];
if (navigator.appName.indexOf("Microsoft")!=-1) {
editorStylesheet.addRule("SPAN", "padding-top: "+spanTopPadding+"px; padding-bottom: "+spanBottomPadding+"px;", 0);
} else {
editorStylesheet.insertRule("SPAN { padding-top: "+spanTopPadding+"px; padding-bottom: "+spanBottomPadding+"px; }", 0);
}
}
lines.childNodes[0].innerHTML=templine;
document.onmousedown = mouseDownHandler;
document.onmouseup = mouseUpHandler;
window.onresize = resizeHandler;;
var _temp='';
for (var i=0; ilongestLine) {
longestLine=_temp.length;
}
currLine=new hLine(i, _temp);
currLine.doHighlight(applyHighlightedLine);
}
if ((longestLine*letterWidth)>minInputWidth) {
inputLine.style.width=longestLine*letterWidth+4;
}
redrawInputLine();
}
function pasteText() {
var content = clipboardData.getData('text');
var re = /^([^\n\r]*)(\r\n|\r|\n)/;
var match;
var lines;
var cur = currentLine;
if (document.selection) { // For IE only
var tr = document.selection.createRange();
tr.text = content;
content = inputLineEntry.value;
} else { // There is nothing to do in Mozilla
return;
}
/*
match = re.exec(content);
if( match && match[1] != null ) {
inputLineEntry.value = match[1];
isDirty = true;
checkDirty();
updateLine(currentLine,match[1]);
content = content.substr(match[0].length);
} else {
isDirty = true;
checkDirty();
updateLine(currentLine,content);
content = false;
}
if(content != false) {
while( content != false ) {
var trans;
match = re.exec(content);
if( match && match[1] != null ) {
trans = match[1];
content = content.substr(match[0].length);
} else {
trans = content;
content = false;
}
insertLineAfter(cur++,trans);
}
}
*/
content = content.replace(/\r\n/g, "\n");
content = content.replace(/\r/g, "\n");
lines = content.split('\n');
inputLineEntry.value = lines[0];
isDirty = true;
checkDirty();
updateLine(currentLine,lines[0]);
for (i = 1; i'+highlightedLine+'');
}
function moveDown(amount) {
//FIXME: start made with selections
// change moveUp as well
// and change textarea size back again in stopselect
if (userSelecting) {
if( (currentLine + offsetLine) < lastLine ) { // Don't select past the last line...
currInputHeight+=lineHeight;
inputLine.style.height=currInputHeight;
inputLineEntry.style.height=currInputHeight;
inputLineEntry.value+='\n'+getLineContent(currentLine+offsetLine+1);
offsetLine = inputLineEntry.value.split('\n').length - 1;
window.scrollBy(0,lineHeight);
setCursorPos(selectIni,getCursorPos());
return !isMoz;
} else {
return false;
}
} else {
checkDirty();
if (currentLinelastLine) {
currentLine=lastLine;
}
redrawInputLine();
}
return !isMoz;
}
}
function moveUp(amount) {
if( userSelecting) {
if( offsetLine > 0 ) { // Don't select smaller than 1 line
currInputHeight -= lineHeight;
inputLine.style.height = currInputHeight;
inputLineEntry.style.height = currInputHeight;
var myValue = inputLineEntry.value;
var lines;
if (isMoz) {
myValue = myValue.replace(/(.*)\n(.*[\n]?)$/,"$1"); //remove last line
} else {
myValue = myValue.replace(/(.*)\r\n(.*)$/,"$1"); //remove last line
}
inputLineEntry.value = myValue;
offsetLine = inputLineEntry.value.split('\n').length - 1;
window.scrollBy(0,-lineHeight);
setCursorPos(selectIni,getCursorPos());
return !isMoz;
} else {
return false;
}
} else {
checkDirty();
if (currentLine>1) {
previousLine = currentLine;
currentLine-=amount;
if (currentLine<1) {
currentLine=1;
}
redrawInputLine();
}
return !isMoz;
}
}
function redrawInputLine(dontfocus) {
var pos;
if (!dontfocus) {
var oldline;
oldpos = getCursorPos();
/*
* we are gona calculate the real old pos by counting tabs for 8
*/
//oldline = getLineContent(previousLine);
newline = getLineContent(currentLine);
if (newline.length < oldpos)
oldpos = newline.length;
}
// mozilla sometimes jumps the lines offset around, so we need to get the
// offset of the content of the line, not the line itself
var mytop=lines.childNodes[currentLine-1].firstChild.offsetTop+adjustTop;
//inputLine.style.top = mytop;
inputLine.style.top = (currentLine - 1)*lineHeight;
var value=getLineContent(currentLine);
inputLineEntry.value=value;
if (!dontfocus) {
pos = oldpos;
setCursorPos(pos);
// I don't think this is needed anymore
// inputLineEntry.focus(); // scroll into view pls..
}
startCursorPos = -1;
/* update the informatin panel */
parent.document.getElementById('info').innerHTML = currentLine + " / " + lines.childNodes.length;
}
function getCursorPos() {
// don't set the focus to the input line here, or the screen
// will 'dance' around. Its not needed anyway.
if (document.selection) {
var mtext=document.selection.createRange();
var count=0;
var moved=0;
while (moved=mtext.moveStart('character', -100)) {
count-=moved;
}
chars=mtext.text.length;
return chars;
} else {
var selection=window.getSelection();
if (selection.anchorNode) {
var len = inputLineEntry.selectionEnd;
return len;
}
}
}
function setCursorPos(cursorstart, cursorend, clicked) {
var counter;
var contents=new String(inputLineEntry.value);
if (cursorstart==-1) {
cursorstart=contents.length;
}
/*
counter = cursorstart;
cursorstart = 0;
while(counter > 0){
if(contents.charAt(cursorstart) == "\t"){
counter -= 7;
}
cursorstart++;
counter--;
}
cursorstart = cursorstart;
*/
if (contents.lengthcontents.length) {
cursorstart=contents.length;
}
addedSpaces=0;
} else {
addedSpaces=0;
}
if (document.selection) {
var mtext=inputLineEntry.createTextRange();
mtext.collapse(true);
mtext.moveStart('character', cursorstart);
mtext.collapse(true);
if (cursorend) {
mtext.moveEnd('character', (cursorend-cursorstart));
}
mtext.select();
} else {
// do something Mozilla style
if (!cursorend) {
cursorend=cursorstart;
}
// for mozilla, set the focus to scroll the input line into view
inputLineEntry.focus();
inputLineEntry.setSelectionRange(cursorstart, cursorend);
/*
var selection=window.getSelection();
if (selection.anchorNode) {
inputLineEntry.selectionStart = cursorstart;
if (cursorend) {
inputLineEntry.selectionEnd = cursorend;
} else {
inputLineEntry.selectionEnd = cursorstart;
}
}
*/
}
// calculate cursor position in px
if (cursorend) {
var scrollToChar=cursorend;
} else {
var scrollToChar=cursorstart;
}
cursorpx=letterWidth*(scrollToChar+10);
if (cursorpx>150) { //(winW-44)) {
// don't do this, let IE and mozilla handle it themselves
// document.body.scrollLeft=cursorpx+44;
} else {
document.body.scrollLeft=0;
}
return false;
}
function removeAddedSpaces() {
if (addedSpaces) {
var _temp=new String(inputLineEntry.value);
_temp=_temp.substr(0, _temp.length-addedSpaces);
inputLineEntry.value=_temp;
addedSpaces=0;
}
}
function getLineContent(lineNo) {
var myString = new String();
if(lines.childNodes[lineNo-1]){
if( typeof(lines.childNodes[lineNo-1].originalInnerText)!="undefined" ) {
return lines.childNodes[lineNo-1].originalInnerText;
}
if (lines.childNodes[lineNo-1].innerText) {
return lines.childNodes[lineNo-1].innerText;
} else if (document.createRange) {
var html = document.createRange();
var myLine = lineNo-1;
while( lines.childNodes[myLine].tagName != 'LI' ) {
myLine++;
}
html.selectNodeContents(lines.childNodes[myLine]);
myString = html.toString();
myString = myString.replace(/\n/g, '');
myString = myString.replace(/\r/g, '');
return myString;
}
}
return "";
}
function getContents() {
var i=1;
var myContent='';
checkDirty();
while( lines.childNodes[i-1] ) {
myContent = myContent + getLineContent(i) + '\n';
i++;
}
return myContent;
}
function setContents(content) {
var myHead;
var re = /^([^\n\r]*)(\r\n|\r|\n)/;
var match;
var originalArray = new Array();
deleteContents();
match = re.exec(content);
if( match && match[1] != null ) {
updateLine(1,match[1]);
originalArray[lastLine] = match[1];
content = content.substr(match[0].length);
} else {
updateLine(1,content);
originalArray[lastLine] = content;
content = false;
}
if(content != false) {
var htmlcontent = '';
while( content != false ) {
var trans;
match = re.exec(content);
if( match && match[1] != null ) {
trans = match[1];
content = content.substr(match[0].length);
} else {
trans = content;
content = false;
}
lastLine++;
originalArray[lastLine] = trans;
trans = trans.replace(/[&]/g,"&");
trans = trans.replace(/[<]/g,"<");
trans = trans.replace(/[>]/g,">");
trans = trans.replace(/[ ]/g," ");
trans = trans.replace(/["]/g,""");
htmlcontent += ""+trans+"\n";
}
if(htmlcontent){
lines.childNodes[0].insertAdjacentHTML("AfterEnd",htmlcontent);
}
}
var _temp='';
for (var i=1; ilongestLine) {
longestLine=_temp.length;
}
currLine=new hLine(i, _temp);
currLine.doHighlight(applyHighlightedLine);
}
if ((longestLine*letterWidth)>minInputWidth) {
inputLine.style.width=longestLine*letterWidth+4;
}
currentLine=1;
updateLineNumbers();
redrawInputLine();
undoBuffer = [];
redoBuffer = [];
//inputLine.style.display = 'none';
//document.getElementById('editor').contentWindow.document.designMode = "on";
}
function setKeyBinding(keybind) {
if( keyBindings[keybind] ) {
keyBinding = keyBindings[keybind];
}
}
function setAutoIndent(indentvalue) {
if( indentvalue == "on" ) {
autoIndent = true;
} else {
autoIndent = false;
}
}
function keyUpHandler(evt) {
var charCode;
var iniDelLine;
if (isMoz) {
charCode = (evt.charCode ? evt.charCode : ((evt.keyCode) ? evt.keyCode : evt.which));
} else {
charCode = window.event.keyCode;
evt = window.event;
}
charCode = parseInt(charCode);
holdingupkey = false;
holdingdownkey = false;
holdingdeletekey = false;
holdingbackkey = false;
holdingpgupkey = false;
holdingpgdownkey = false;
if ( holdingenterkey ) {
redrawInputLine();
holdingenterkey = false;
}
if( isMoz && checkPastedReturns ) {
fixPastedReturns();
checkPastedReturns = false;
}
if ( ( ( evt.ctrlKey ) && ( charCode != 88 ) ) || ( charCode == 67 ) )
return false;
if (userSelecting &&
(
isNormalKey(charCode)
|| ( charCode == 46 ) /*delete key*/
|| ( charCode == 8 ) /*bakspace key*/
)
) {
iniDelLine = currentLine + 1;
isDirty = true;
checkDirty();
deleteMultipleLines(iniDelLine,currentLine+offsetLine);
//for (i=iniDelLine;i<=currentLine+offsetLine;i++)
// deleteLine(iniDelLine);
stopSelect();
//redrawInputLine(true);
}
if (
isNormalKey(charCode)
|| ( charCode == 46 ) /*delete key*/
|| ( charCode == 8 ) /*bakspace key*/
|| ( charCode == 13 ) /*enter key*/
)
{
window.parent.document.title = window_title + ' (+)';
unsaved = true;
}
if ( ( charCode == 38 ) && userSelecting ) {
//inputLineEntry.setSelectionRange(selectIni, inputLineEntry.value.length);
setCursorPos(selectIni,inputLineEntry.value.length);
}
if (isMoz) {
if ( ( charCode == 37 ) && userSelecting ) {
if (inputHasLineEnd())
fixLineGap();
}
}
window.status = 'L: '+currentLine+' C: '+(getCursorPos()+1);
}
function fixPastedReturns(mousepaste) {
var re = /^([^\n\r]*)(\r\n|\r|\n)/;
var match;
var content = inputLineEntry.value;
var cur = currentLine;
var lines;
if (isMoz) {
if (mousepaste) {
content = content.replace(/#/g, ""); //remove # from mozilla browsers!!
} else {
content = content.replace(/^#/g, ""); //remove # from mozilla browsers!!
}
/*
content = content.replace(/\r\n/g, "\n");
content = content.replace(/\r/g, "\n");
*/
}
match = re.exec(content);
if( match && match[1] != null ) {
inputLineEntry.value = match[1];
isDirty = true;
checkDirty();
updateLine(currentLine,match[1]);
content = content.substr(match[0].length);
} else {
content = false;
}
while( content != false ) {
var trans;
match = re.exec(content);
if( match && match[1] != null ) {
trans = match[1];
content = content.substr(match[0].length);
} else {
trans = content;
content = false;
}
insertLineAfter(cur++,trans);
}
inputLineEntry.focus();
/*
lines = content.split('\n');
inputLineEntry.value = lines[0];
isDirty = true;
checkDirty();
updateLine(currentLine,lines[0]);
for (i = 1; i=_currline.length) {
// moveDown(1);
// setCursorPos(0);
// result=false;
// }
//}
oldpos=-1;
if ( isMoz && ( getCursorPos() == ( inputLineEntry.value.length - 1 ) ) )
{
setCursorPos(inputLineEntry.value.length);
}
return result;
}
function do_Backspace() {
var result=true;
holdingbackkey = true;
if (addedSpaces) {
removeAddedSpaces();
result=false;
} else {
oldpos=-1;
if (getCursorPos()==0) {
checkDirty();
glueCurrentLine(-1);
result=false;
}
isDirty=true;
}
return result;
}
function do_Delete() {
var result=true;
holdingdeletekey = true;
if (addedSpaces) {
removeAddedSpaces();
result=false;
} else {
oldpos=-1;
if (currentLine window.parent.innerWidth) {
window.parent.scrollBy(getCursorPos()*letterWidth,0);
}
oldpos = -1;
return false;
}
function do_Tab() {
var line = inputLineEntry.value;
var cursor = getCursorPos();
if (userSelecting)
return false;
line = line.substr(0,cursor) + "\t" + line.substr(cursor);
inputLineEntry.value = line;
setCursorPos(cursor + 1);
isDirty=true;
return false;
}
function do_skipCharsRight() {
return skipChars(1);
}
function do_skipCharsLeft() {
return skipChars(-1);
}
function do_Paste() {
if( isMoz ) {
checkPastedReturns = true;
}
isDirty = true;
return true;
}
function do_Undo() {
checkDirty();
if(undoBuffer.length<1) {
return false;
}
var u = undoBuffer.pop();
UndoIt(u,redoBuffer);
return false;
}
function do_Redo() {
if(redoBuffer.length<1) {
return false;
}
var u = redoBuffer.pop();
UndoIt(u,undoBuffer);
return false;
}
function UndoIt(u,redoBuffer) {
saveUndo = false;
switch(u.type) {
case undo.CHANGE_TEXT:
updateLine(u.line,u.text);
redoBuffer.push({ type: u.type, line: u.line, text: u.newText, newText: u.text, cursor: u.newCursor, newCursor: u.cursor });
break;
case undo.LINE_AFTER:
deleteLine(u.line);
redoBuffer.push({ type: undo.DELETE_LINE, line: u.line, text: u.text, cursor: u.newCursor, newCursor: u.cursor });
break;
case undo.DELETE_LINE:
insertLineAfter(u.line-1,u.text);
redoBuffer.push({ type: undo.LINE_AFTER, line: u.line, text: u.text, cursor: u.newCursor, newCursor: u.cursor });
break;
default:
saveUndo = true;
return false;
}
currentLine = u.line;
inputLineEntry.value = getLineContent(currentLine);
redrawInputLine();
setCursorPos(u.cursor);
saveUndo = true;
return true;
}
function addUndo(ob) {
undoBuffer.push(ob);
redoBuffer = [];
}
function skipChars(dir) {
var cursor, curstate, curchar;
function is_letter (l) {
if (l >= 'a' && l <= 'z' ||
l >= 'A' && l <= 'Z') {
return true;
} else {
return false;
}
}
removeAddedSpaces();
cursor = getCursorPos();
if (dir < 0) {
cursor--;
}
curstate = is_letter(inputLineEntry.value.charAt(cursor));
if (!curstate) {
/* forward over current state */
while (curstate == is_letter(inputLineEntry.value.charAt(cursor+=dir))
&& cursor > 0 && cursor < inputLineEntry.value.length){};
} else {
cursor += dir;
}
curstate = is_letter(inputLineEntry.value.charAt(cursor));
/* forward over next state */
while (curstate == is_letter(inputLineEntry.value.charAt(cursor+=dir))
&& cursor > 0 && cursor < inputLineEntry.value.length);
if (dir < 0) {
cursor++;
}
if (cursor < 0) {
cursor = 0;
} else if (cursor >= inputLineEntry.value.length) {
cursor = inputLineEntry.value.length;
}
setCursorPos(cursor);
oldpos = -1;
return false;
}
function KeyUpHandler() {
}
function Coordinate(x, y) {
this.x=x;
this.y=y;
}
function mouseGetCoordinates(evt) {
var target = (evt.target) ? evt.target : evt.srcElement;
var clickX = -1;
var clickY = -1;
if( target && target.nodeName!='HTML' && target.nodeName!='BODY' ) { // HTML(moz) and BODY(IE) means clicked outside of our code..
while (target && target.nodeName!='LI' && target.nodeName!='TEXTAREA' && target.nodeName!='DIV') {
if( target.parentElement ) {
target=target.parentElement;
} else {
// mozilla style
target = target.parentNode;
}
}
if( target ) {
// get click position
if (evt.pageX) {
var offsetX=evt.pageX - ((target.offsetLeft) ? target.offsetLeft : target.left);
var offsetY=evt.pageY - ((target.offsetTop) ? target.offsetTop : target.top);
} else if (evt.offsetX || evt.offsetY) {
var offsetX = evt.offsetX;
var offsetY = evt.offsetY;
} else if (evt.clientX || evt.clientY) {
var offsetX = evt.clientX - ((target.offsetLeft) ? target.offsetLeft : 0);
var offsetY = evt.clientY - ((target.offsetTop) ? target.offsetTop : 0);
}
offsetX-=clickPosOffsetLeft;
var clickX=Math.round(offsetX/letterWidth);
// find a known container of the mouseclick
if (target.nodeName=='LI') {
clickY=1;
while (target=target.previousSibling) {
clickY++;
}
} else if (target.nodeName=='INPUT') {
} else if (target.nodeName=='TEXTAREA') {
} else if (target.nodeName=='DIV') {
} else {
clickY=Math.round(offsetY/lineHeight)+1;
}
}
}
if (clickX>-1 && clickY>-1) {
return new Coordinate(clickX, clickY);
} else {
return false;
}
}
function mouseUpHandler(evt) {
evt = (evt) ? evt : event;
var coordinate=mouseGetCoordinates(evt);
if (coordinate) {
checkDirty();
if (startcoordinate &&
(!(startcoordinate.x==coordinate.x) ||
!(startcoordinate.y==coordinate.y)) ) {
if (startcoordinate.y==coordinate.y) {
// single line selection
if (startcoordinate.x>coordinate.x) {
var _temp=coordinate;
coordinate=startcoordinate;
startcoordinate=_temp;
}
currentLine=coordinate.y;
redrawInputLine(true);
setCursorPos(startcoordinate.x, coordinate.x, true);
oldpos=-1;
evt.cancelBubble=true;
return false;
} else {
// multi line selection
if (startcoordinate.y>coordinate.y) {
var _temp=coordinate;
coordinate=startcoordinate;
startcoordinate=_temp;
}
}
} else {
// no selection
currentLine=coordinate.y;
redrawInputLine(true);
setCursorPos(coordinate.x, 0, true);
oldpos=-1;
evt.cancelBubble=true;
return false;
}
}
if (isMoz && (evt.button == 1))
{
checkPastedReturns = true;
setTimeout("fixmousepaste()",200);
}
}
function mouseDownHandler(evt) {
evt = (evt) ? evt : event;
startcoordinate=mouseGetCoordinates(evt);
stopSelect();
if ( inputHasLineEnd() )
redrawInputLine();
}
function startSelect() {
userSelecting=true;
if (selectIni == -1) {
selectIni=getCursorPos();
}
if (selectLineIni == -1) {
selectLineIni=currentLine;
}
}
function stopSelect() {
// Return the inputline to it's original size
inputLine.style.height=lineHeight;
inputLineEntry.style.height=lineHeight;
currInputHeight = lineHeight;
offsetLine=0;
selectIni = -1;
userSelecting=false;
// get selected contents, put them in a buffer or something
}
function updateLine(lineNo, lineContent) {
lines.childNodes[lineNo-1].originalInnerText = lineContent;
highlightUpdateLine(lineNo-1, lineContent, applyHighlightedLine);
if (lineContent.length>longestLine) {
longestLine=lineContent.length;
if( (longestLine*letterWidth) > minInputWidth ) {
inputLine.style.width=longestLine*letterWidth+4;
}
}
}
function setLineContent(lineNo, lineContent) {
if(lines.childNodes[lineNo-1]){
lines.childNodes[lineNo-1].innerHTML=lineContent;
lines.childNodes[lineNo-1].originalInnerHTML=lineContent;
}
}
function insertLineAfter(lineNo, lineContent) {
var oldCursor = getCursorPos();
lines.childNodes[lineNo-1].insertAdjacentHTML("AfterEnd","");
highlightAppendLine(lineNo-1, lineContent, false); // do not display this yet
currentLine=lineNo+1;
updateLine(currentLine, lineContent);
oldpos=-1;
redrawInputLine(true);
updateLineNumbers();
lastLine++;
if(saveUndo) {
undoBuffer.push({type: undo.LINE_AFTER, line: currentLine, text: lineContent, cursor: getCursorPos(), newCursor: oldCursor });
}
}
function deleteLine(lineNo) {
if(saveUndo) {
var content = getLineContent(lineNo);
undoBuffer.push({type: undo.DELETE_LINE, line: lineNo, text: content, cursor: getCursorPos() , newCursor: content.length });
}
lines.childNodes[lineNo-1].removeNode(true);
highlightDeleteLine(lineNo-1, applyHighlightedLine);
updateLineNumbers();
lastLine--;
}
function deleteMultipleLines(lineIni,lineCount)
{
var i;
for (i = lineIni; i <= lineCount; i++)
{
if(saveUndo) {
var content = getLineContent(lineIni);
undoBuffer.push({type: undo.DELETE_LINE, line: lineIni, text: content, cursor: getCursorPos() , newCursor: content.length });
}
lines.childNodes[lineIni-1].removeNode(true);
highlightDeleteLine(lineIni-1, applyHighlightedLine);
lastLine--;
}
updateLineNumbers();
if ( (currentLine-1)*lineHeight < window.pageYOffset )
{
window.scrollTo(0,(currentLine-1)*lineHeight);
}
}
function deleteContents() {
var len = lines.childNodes.length;
for (var i=len-1; i>0; i--) {
lines.childNodes[i].removeNode(true);
}
setCursorPos(0);
highlightReset();
updateLineNumbers();
lastLine=1;
undoBuffer = [];
redoBuffer = [];
}
function updateLineNumbers() {
if (contentDiv.offsetHeight>winH) {
document.getElementById('linenumbers').style.height=contentDiv.offsetHeight;
}
alignLineNumbers(); //fix mozilla align
}
function checkDirty() {
if (isDirty) {
var newContents = inputLineEntry.value;
var oldContents = getLineContent(currentLine);
if(newContents != oldContents) {
undoBuffer.push({ type: undo.CHANGE_TEXT, line: currentLine, text: oldContents, newText: newContents,
cursor: startCursorPos, newCursor: getCursorPos() });
updateLine(currentLine, newContents);
isDirty=false;
startCursorPos = -1;
return true;
}
} else {
}
return false;
}
function getLineHead() {
var _line = new String(getLineContent(currentLine));
var _pos = getCursorPos();
if (_pos == 0) {
return '\t';
} else {
return _line.substr(0, _pos);
}
}
function getLineTail() {
var _line=new String(getLineContent(currentLine));
var _pos=getCursorPos();
return _line.substr(_pos);
}
function breakCurrentLine() {
checkDirty();
var head=getLineHead();
var tail=getLineTail();
var re = /([\t ]+)/;
var match = re.exec(head);
var newCursor = 0;
if( autoIndent && match ) {
tail = match[1] + tail;
newCursor = match[1].length;
}
insertLineAfter(currentLine, tail);
updateLine(currentLine-1, head);
setCursorPos(newCursor);
inputLineEntry.focus();
}
function glueCurrentLine(direction) {
checkDirty();
if (direction==-1) {
if (currentLine>1) {
var tail=getLineContent(currentLine);
var head=getLineContent(currentLine-1);
updateLine(currentLine-1, head+tail);
deleteLine(currentLine);
currentLine--;
redrawInputLine();
setCursorPos(head.length);
}
} else {
if (currentLine= 48 ) && ( parseInt( charCode ) <= 90 ) ) ||
( ( parseInt( charCode ) >= 96 ) && ( parseInt( charCode ) <= 111 ) ) ||
( parseInt( charCode ) == 32 ) ||
( ( parseInt( charCode ) >= 186 ) && ( parseInt( charCode ) <= 222 ) );
}
function inputHasLineEnd()
{
var re = /\n/;
var match;
var content;
content = inputLineEntry.value;
match = re.exec(content);
if( match ) {
return true;
} else {
return false;
}
}
function alignLineNumbers()
{
if (isMoz) {
document.getElementById('lines').style.listStyleType='decimal-leading-zero';
document.getElementById('lines').style.listStyleType='decimal';
}
}
function fixLineGap() {
/* synchronize line end with cursor position */
var gap;
var nlines;
var old_cursor_pos = getCursorPos();
var newEntry;
gap = inputLineEntry.value;
gap = gap.substr(getCursorPos());
nlines = gap.split('\n');
currInputHeight = currInputHeight - lineHeight*(nlines.length-1);
inputLine.style.height = currInputHeight;
inputLineEntry.style.height = currInputHeight;
newEntry = inputLineEntry.value;
for (i=0; i < nlines.length - 1; i++) {
if (isMoz) {
newEntry = newEntry.replace(/(.*)\n(.*[\n]?)$/,"$1"); //remove last line
} else {
newEntry = newEntry.replace(/(.*)\r\n(.*)$/,"$1"); //remove last line
}
}
inputLineEntry.value = newEntry;
setCursorPos(selectIni,old_cursor_pos);
offsetLine = newEntry.split('\n').length - 1;
}
function do_BeginCode() {
jumpToLine(1);
inputLineEntry.focus();
}
function do_EndCode() {
jumpToLine(lines.childNodes.length);
inputLineEntry.focus();
}
function do_Indent() {
var old_text = inputLineEntry.value;
var old_pos;
inputLineEntry.focus();
if (userSelecting) {
for (i = currentLine; i <= (currentLine+offsetLine); i++ ) {
old_text = getLineContent(i);
old_text = old_text.replace(/^/,"\t"); //add tabs
updateLine(i,old_text);
}
stopSelect();
if ( inputHasLineEnd() ) {
redrawInputLine();
}
} else {
old_pos = getCursorPos();
old_text = inputLineEntry.value;
old_text = old_text.replace(/^/,"\t"); //add tabs
inputLineEntry.value = old_text;
setCursorPos(old_pos+1);
}
}
function do_Unindent() {
var old_text = inputLineEntry.value;
var old_pos;
inputLineEntry.focus();
if (userSelecting) {
for (i = currentLine; i <= (currentLine+offsetLine); i++ ) {
old_text = getLineContent(i);
old_text = old_text.replace(/^\t/,""); //del tabs
updateLine(i,old_text);
}
stopSelect();
if ( inputHasLineEnd() ) {
redrawInputLine();
}
} else {
old_pos = getCursorPos();
old_text = inputLineEntry.value;
old_text = old_text.replace(/^\t/,""); //add tabs
inputLineEntry.value = old_text;
setCursorPos(old_pos-1);
}
}
function do_Find(text) {
var idx;
str_search = text;
if( userSelecting ) {
stopSelect();
if ( inputHasLineEnd() )
redrawInputLine();
}
str_search.toLowerCase();
for (var i=currentLine; i<=lines.childNodes.length; i++) {
// need to remove trailing ' ', which IE puts there.
_temp = getLineContent(i);
_temp.toLowerCase();
idx = _temp.indexOf(str_search);
if (idx >= 0) {
jumpToLine(i);
inputLineEntry.focus();
setCursorPos(idx,idx+str_search.length);
break;
}
}
}
function do_FindNext(text) {
var idx;
str_search = text;
if( userSelecting ) {
stopSelect();
if ( inputHasLineEnd() )
redrawInputLine();
}
str_search = str_search.toLowerCase();
for (var i=currentLine+1; i<=lines.childNodes.length; i++) {
// need to remove trailing ' ', which IE puts there.
_temp = getLineContent(i);
_temp = _temp.toLowerCase();
idx = _temp.indexOf(str_search);
if (idx >= 0) {
jumpToLine(i);
inputLineEntry.focus();
setCursorPos(idx,idx+str_search.length);
break;
}
}
}
function do_Replace() {
var idx;
var inicio = false;
var ini_line = currentLine;
var str_search;
var str_replace;
var contents;
var reg_exp;
if ( str_search == null ) {
str_search = 'texto';
}
if( userSelecting ) {
stopSelect();
if ( inputHasLineEnd() )
redrawInputLine();
}
if ( !( str_search = prompt('Digite o texto a ser substituido:',str_search) ) ) return;
if ( !( str_replace = prompt('Digite o novo texto:','') ) ) return;
reg_exp = new RegExp(str_search,'ig');
contents = getContents();
setContents(contents.replace(reg_exp, str_replace));
}
function resizeHandler()
{
if (parseInt(navigator.appVersion) > 3)
{
if (navigator.appName == "Netscape")
{
winW = window.innerWidth-42;
winH = window.innerHeight-2;
minInputWidth = winW-16;
}
else
if (navigator.appName.indexOf("Microsoft")!=-1)
{
winW = document.body.offsetWidth;
winH = document.body.offsetHeight;
minInputWidth = winW-60;
// To handle clipboard paste
}
}
document.getElementById('linenumbers').style.height = winH;
updateLineNumbers();
}