00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 var CodeEditor = CodeEditor || {};
00023
00024 if (typeof DesktopContent == 'undefined')
00025 throw('ERROR: DesktopContent is undefined! Must include DesktopWindowContentCode.js before CodeEditor.js');
00026
00027
00028 CodeEditor.MENU_PRIMARY_COLOR = "rgb(220, 187, 165)";
00029 CodeEditor.MENU_SECONDARY_COLOR = "rgb(130, 51, 51)";
00030
00031
00032 CodeEditor.editor;
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 function htmlOpen(tag,attObj,innerHTML,doCloseTag)
00043 {
00044 var str = "";
00045 var attKeys = Object.keys(attObj);
00046 str += "<" + tag + " ";
00047 for(var i=0;i<attKeys.length;++i)
00048 str += " " + attKeys[i] + "='" +
00049 attObj[attKeys[i]] + "' ";
00050 str += ">";
00051 if(innerHTML) str += innerHTML;
00052 if(doCloseTag)
00053 str += "</" + tag + ">";
00054 return str;
00055 }
00056
00057
00058
00059 function htmlClearDiv()
00060 {
00061 return "<div id='clearDiv'></div>";
00062 }
00063
00064
00065
00066
00067
00068 if (!Element.prototype.scrollIntoViewIfNeeded) {
00069 Element.prototype.scrollIntoViewIfNeeded = function (centerIfNeeded) {
00070 centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded;
00071
00072 var parent = this.parentNode,
00073 tdParent = parent.parentNode,
00074 editorParent = parent.parentNode.parentNode.parentNode.parentNode.parentNode,
00075 parentComputedStyle = window.getComputedStyle(parent, null),
00076 parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')),
00077 parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')),
00078 overTop = this.offsetTop - tdParent.offsetTop < editorParent.scrollTop,
00079 overBottom = (this.offsetTop - tdParent.offsetTop + this.clientHeight - parentBorderTopWidth) > (editorParent.scrollTop + editorParent.clientHeight),
00080 overLeft = this.offsetLeft - tdParent.offsetLeft < editorParent.scrollLeft,
00081 overRight = (this.offsetLeft + tdParent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (editorParent.scrollLeft + editorParent.clientWidth),
00082 alignWithTop = overTop && !overBottom;
00083
00084 if ((overTop || overBottom) && centerIfNeeded) {
00085 editorParent.scrollTop = this.offsetTop - tdParent.offsetTop - editorParent.clientHeight / 2 - parentBorderTopWidth + this.clientHeight / 2;
00086
00087 }
00088
00089 if ((overLeft || overRight) && centerIfNeeded) {
00090 editorParent.scrollLeft = this.offsetLeft + tdParent.offsetLeft - editorParent.clientWidth / 2 - parentBorderLeftWidth + this.clientWidth / 2;
00091
00092 }
00093
00094 if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) {
00095 this.scrollIntoView(alignWithTop);
00096 }
00097 };
00098 }
00099
00100
00101
00102
00103 CodeEditor.showTooltip = function(alwaysShow)
00104 {
00105 DesktopContent.tooltip(
00106 (alwaysShow?"ALWAYS":"Code Editor"),
00107 "Welcome to the Code Editor user interface. "+
00108 "Edit your code, save it, and compile!\n\n" +
00109 "Hover your mouse over the icons and buttons to see what they do. " +
00110 "If you hover your mouse over the filename additional icons will appear for changing the filename, downloading, uploading, undo, and redo. The buttons in the top corners are described below followed by hot-keys:\n\n" +
00111 "<INDENT>" +
00112 "<b>Open a file:</b>\n<INDENT>Use the folder icon in the top-left to navigate to a code file to edit.</INDENT>\n" +
00113 "<b>Toggle view:</b>\n<INDENT>Use the split-pane icon in the top-right to toggle another code editor in the same window.</INDENT>\n" +
00114 "<b>Save:</b>\n<INDENT>Use the save icon in the top-left to save your changes.</INDENT>\n" +
00115 "<b>Compile:</b>\n<INDENT>Use the Incremmental Build or Clean Build icons in the top-right.</INDENT>\n" +
00116
00117 "<b>Global Hot Keys:</b>\n<INDENT>" +
00118
00119 "<table border=0 cellspacing=0 cellpadding=0 style='border: 1px solid grey;'>" +
00120 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> " +
00121 "Ctrl + B </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Incremental Build</td></tr>" +
00122 "<tr><td style='white-space: nowrap; padding:5px;'> " +
00123 "Ctrl + N </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Clean Build</td></tr>" +
00124 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> " +
00125 "Ctrl + 2 </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Toggle Split-View Mode (single, dual-vertical, dual-horizontal)</td></tr>" +
00126 "</table></INDENT>\n" +
00127
00128
00129 "<b>Editor Pane Hot Keys:</b>\n<INDENT>" +
00130
00131 "<table border=0 cellspacing=0 cellpadding=0 style='border: 1px solid grey;'>" +
00132
00133 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> " +
00134 "Ctrl + S </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Save File</td></tr>" +
00135
00136 "<tr><td style='white-space: nowrap; padding:5px;'> " +
00137 "Ctrl + D </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Toggle Directory Navigation</td></tr>" +
00138
00139 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> " +
00140 "Ctrl + F </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Find & Replace</td></tr>" +
00141
00142 "<tr><td style='white-space: nowrap; padding:5px;'> " +
00143 "Ctrl + U </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Undo Text Editing</td></tr>" +
00144
00145 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> " +
00146 "Shift + Ctrl + U </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Redo Text Editing</td></tr>" +
00147
00148 "<tr><td style='white-space: nowrap; padding:5px;'> " +
00149 "Ctrl + L or G </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Goto Line Number</td></tr>" +
00150
00151 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> " +
00152 "Ctrl + 1 </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Switch to Related File (associated .h or .cc)</td></tr>" +
00153
00154 "<tr><td style='white-space: nowrap; padding:5px;'> " +
00155 "Ctrl + 0 </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Reload Current File from Server</td></tr>" +
00156
00157 "</table></INDENT>\n" +
00158
00159
00160 "<b>Selected-Text Hot Keys:</b>\n<INDENT>" +
00161
00162 "<table border=0 cellspacing=0 cellpadding=0 style='border: 1px solid grey;'>" +
00163 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> TAB</td><td style='padding:5px'> ==> </td><td style='padding:5px'> Add leading TAB character to all highlighted lines.</td></tr>" +
00164 "<tr><td style='white-space: nowrap; padding:5px;'> Shift + TAB </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Remove leading TAB character from all highlighted lines.</td></tr>" +
00165 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> Ctrl + T or Y </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Add TAB character at starting cursor position of all highlighted line (i.e. Block Tab effect).</td></tr>" +
00166 "<tr><td style='white-space: nowrap; padding:5px;'> Shift + Ctrl + T or Y</td><td style='padding:5px'> ==> </td><td style='padding:5px'> Remove TAB character from starting cursor position of all highlighted line (i.e. reverse Block Tab effect).</td></tr>" +
00167 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> Ctrl + / </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Add leading comment character(s) to all highlighted lines.</td></tr>" +
00168 "<tr><td style='white-space: nowrap; padding:5px;'> Shift + Ctrl + / </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Remove leading comment character(s) to all highlighted lines.</td></tr>" +
00169 "<tr style='background-color: rgb(106, 102, 119);'><td style='white-space: nowrap; padding:5px;'> Ctrl + I </td><td style='padding:5px'> ==> </td><td style='padding:5px'> Auto-indent all highlighted lines.</td></tr>" +
00170 "</table></INDENT>\n" +
00171 "</INDENT>"
00172 );
00173 }
00174
00175
00178
00181 CodeEditor.create = function() {
00182
00183
00184
00185 CodeEditor.showTooltip();
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 var _WINDOW_MIN_SZ = 525;
00250
00251 var _ALLOWED_FILE_EXTENSIONS = [];
00252
00253 var _needEventListeners = true;
00254
00255 var _viewMode = 0;
00256 var _navMode = [0,0];
00257 var _filePath = ["",""];
00258 var _fileExtension = ["",""];
00259 var _fileLastSave = [0,0];
00260 var _fileWasModified = [false,false];
00261 var _numberOfLines = [0,0];
00262
00263 var _eel = [undefined,undefined];
00264
00265 var _updateTimerHandle = 0;
00266 var _updateHandlerTargetPane = [false,false];
00267 var _commandKeyDown = false;
00268 var _lastPageUpDownLine = -1;
00269 var _startPageUpDownLine = -1;
00270 var _startPageUpDownNodeIndex = -1;
00271 var _startPageUpDownPos = -1;
00272
00273 var _fileNameMouseMoveTimerHandle = 0;
00274 var _fileNameEditing = [false,false];
00275 var _fileUploadString;
00276
00277 var _activePaneIsPrimary = 1;
00278
00279 var _undoStackLatestIndex = [-1,-1];
00280 var _undoStack_MAX_SIZE = 10;
00281 var _undoStack = [[],[]];
00282
00283 var _fileHistoryStack = {};
00284
00285 var _findAndReplaceCursorInContent = [undefined,undefined];
00286
00287 var _fileStringHoverEl = 0;
00288 var _fileStringHoverTimeout = 0;
00289
00290 var _UPDATE_DECOR_TIMEOUT = 2000;
00291
00292 var _TAB_SIZE = 4;
00293
00296
00297 CodeEditor.editor = this;
00298 Debug.log("CodeEditor.editor constructed");
00299
00300
00301 this.lastFileNameHistorySelectIndex = -1;
00302 this.findAndReplaceFind = ["",""];
00303 this.findAndReplaceReplace = ["",""];
00304 this.findAndReplaceScope = [0,0];
00305 this.findAndReplaceDirection = [0,0];
00306 this.findAndReplaceCaseSensitive = [0,0];
00307 this.findAndReplaceWholeWord = [1,1];
00308 this.findAndReplaceLastButton = [-1,-1];
00309
00310
00311 init();
00312 Debug.log("CodeEditor.editor initialized");
00313
00314
00315
00316
00317 function init()
00318 {
00319 Debug.log("Code Editor init ");
00320
00321
00322 var parameterStartFile = [
00323
00324
00325
00326
00327
00328 DesktopContent.getParameter(0,"startFilePrimary"),
00329 DesktopContent.getParameter(0,"startFileSecondary")
00330 ];
00331 var parameterGotoLine = [
00332 DesktopContent.getParameter(0,"gotoLinePrimary"),
00333 DesktopContent.getParameter(0,"gotoLineSecondary")
00334 ];
00335 var parameterOpenDirectory = [
00336 DesktopContent.getParameter(0,"openDirectoryPrimary"),
00337 DesktopContent.getParameter(0,"openDirectorySecondary")
00338 ];
00339 if(parameterOpenDirectory[0] === undefined)
00340 parameterOpenDirectory[0] = "/";
00341 if(parameterOpenDirectory[1] === undefined)
00342 parameterOpenDirectory[1] = "/";
00343
00344 var parameterViewMode = DesktopContent.getParameter(0,"startViewMode");
00345 if(parameterViewMode !== undefined)
00346 {
00347 _viewMode = parameterViewMode|0;
00348 }
00349 console.log("parameterStartFile",parameterStartFile);
00350 console.log("parameterGotoLine",parameterGotoLine);
00351 console.log("parameterViewMode",parameterViewMode);
00352 console.log("parameterOpenDirectory",parameterOpenDirectory);
00353
00354
00355
00356
00357
00358 createElements();
00359 redrawWindow();
00360
00361 if(_needEventListeners)
00362 {
00363 window.addEventListener("resize",redrawWindow);
00364 _needEventListeners = false;
00365 }
00366
00367
00368
00369 DesktopContent.XMLHttpRequest("Request?RequestType=codeEditor" +
00370 "&option=getAllowedExtensions"
00371 , "" ,
00372 function(req)
00373 {
00374 console.log("getAllowedExtensions",req);
00375
00376 _ALLOWED_FILE_EXTENSIONS = DesktopContent.getXMLValue(req,"AllowedExtensions");
00377 console.log("_ALLOWED_FILE_EXTENSIONS",_ALLOWED_FILE_EXTENSIONS);
00378 _ALLOWED_FILE_EXTENSIONS = _ALLOWED_FILE_EXTENSIONS.split(',');
00379 console.log("_ALLOWED_FILE_EXTENSIONS",_ALLOWED_FILE_EXTENSIONS);
00380
00381 DesktopContent.XMLHttpRequest("Request?RequestType=codeEditor" +
00382 "&option=getDirectoryContent" +
00383 "&path=/"
00384 , "" ,
00385 function(req)
00386 {
00387 var fileSplit;
00388
00389
00390
00391
00392 CodeEditor.editor.handleDirectoryContent(1 , req);
00393 CodeEditor.editor.handleDirectoryContent(0 , req);
00394
00395
00396 fileSplit = [];
00397 if(parameterStartFile[0] && parameterStartFile[0] != "")
00398 fileSplit = parameterStartFile[0].split('.');
00399
00400
00401
00402 if(fileSplit.length == 2)
00403 CodeEditor.editor.openFile(
00404 1 ,
00405 fileSplit[0] ,
00406 fileSplit[1] ,
00407 false ,
00408 parameterGotoLine[0 ] );
00409 else
00410 {
00411 CodeEditor.editor.openDirectory(
00412 1 ,
00413 parameterOpenDirectory[0]
00414 );
00415
00416 }
00417
00418
00419 fileSplit = [];
00420 if(parameterStartFile[1] && parameterStartFile[1] != "")
00421 fileSplit = parameterStartFile[1].split('.');
00422
00423 if(fileSplit.length == 2)
00424 CodeEditor.editor.openFile(
00425 0 ,
00426 fileSplit[0] ,
00427 fileSplit[1] ,
00428 false ,
00429 parameterGotoLine[1 ] );
00430 else
00431 {
00432
00433 CodeEditor.editor.openDirectory(
00434 0 ,
00435 parameterOpenDirectory[1]
00436 );
00437
00438 }
00439
00440
00441 _activePaneIsPrimary = 1;
00442
00443 });
00444 });
00445
00446 }
00447
00448
00449
00450
00451 function createElements()
00452 {
00453 Debug.log("createElements");
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 var cel,el,al,sl,str;
00464
00465 cel = document.getElementById("content");
00466 if(!cel)
00467 {
00468 cel = document.createElement("div");
00469 cel.setAttribute("id","content");
00470 }
00471
00472
00473 cel.innerHTML = "";
00474
00475 {
00476
00477
00478
00479 var forPrimary;
00480 for(forPrimary=1;forPrimary >= 0;--forPrimary)
00481 {
00482 el = document.createElement("div");
00483 el.setAttribute("class","editorPane");
00484 el.setAttribute("id","editorPane" + forPrimary);
00485 {
00486 var str = "";
00487 str += createTextEditor(forPrimary);
00488 str += createDirectoryNav(forPrimary);
00489 str += localCreatePaneControls(forPrimary);
00490 el.innerHTML = str;
00491 }
00492 cel.appendChild(el);
00493 }
00494
00495
00496 function localCreatePaneControls(forPrimary)
00497 {
00498
00499
00500
00501 str = "";
00502
00503
00504 str += htmlOpen("div",
00505 {
00506 "class":"controlsPane",
00507 },"" , 0 );
00508 {
00509
00510 str += htmlOpen("div",
00511 {
00512 "id":"directoryNavToggle",
00513 "class":"controlsButton",
00514 "style":"float:left",
00515 "onclick":"CodeEditor.editor.toggleDirectoryNav(" + forPrimary + ");",
00516 "title": "Open a file... (Ctrl + D)",
00517 },"" , 0 );
00518 {
00519 str += htmlOpen("div",
00520 {
00521 "id":"directoryNavToggleTop",
00522
00523 },"" , 1 );
00524 str += htmlOpen("div",
00525 {
00526 "id":"directoryNavToggleBottom",
00527
00528 },"" , 1 );
00529 }
00530 str += "</div>";
00531
00532
00533 str += htmlOpen("div",
00534 {
00535 "id":"saveFile",
00536 "class":"controlsButton",
00537 "style":"float:left;",
00538 "onclick":"CodeEditor.editor.saveFile(" + forPrimary + ");",
00539 "title": "Click to Save the File (Ctrl + S)\nUndo changes (Ctrl + U)\nRedo changes (Shift + Ctrl + U)",
00540 },"" , 0 );
00541 {
00542 str += htmlOpen("div",
00543 {
00544 "id":"saveFileMain",
00545
00546 },"" , 1 );
00547 str += htmlOpen("div",
00548 {
00549 "id":"saveFileMainTop",
00550
00551 },"" , 1 );
00552 str += htmlOpen("div",
00553 {
00554 "id":"saveFileMainBottom",
00555
00556 },"" , 1 );
00557 }
00558 str += "</div>";
00559
00560 }
00561 str += "</div>";
00562 return str;
00563 }
00564
00565
00566
00567
00568
00569 el = document.createElement("div");
00570 el.setAttribute("class","controlsPane");
00571 {
00572
00573
00574 str = "";
00575
00576
00577 str += htmlOpen("div",
00578 {
00579 "id":"viewToggle",
00580 "class":"controlsButton",
00581 "style":"float:right",
00582 "onclick":"CodeEditor.editor.toggleView();",
00583 "title":"Toggle Verical/Horizontal Split-view (Ctrl + W)",
00584 },"" , 0 );
00585 {
00586
00587 str += htmlOpen("div",
00588 {
00589 "id":"viewToggleRight",
00590
00591 },"" , 1 );
00592 str += htmlOpen("div",
00593 {
00594 "id":"viewToggleLeftTop",
00595
00596 },"" , 1 );
00597 str += htmlOpen("div",
00598 {
00599 "id":"viewToggleLeftBottom",
00600
00601 },"" , 1 );
00602 }
00603 str += "</div>";
00604
00605
00606 str += htmlOpen("div",
00607 {
00608 "id":"incrementalBuild",
00609 "class":"controlsButton",
00610 "style":"float:right",
00611 "onclick":"CodeEditor.editor.build(0 /*cleanBuild*/);",
00612 "title":"Incremental Build... (Ctrl + B)",
00613 },"" , 0 );
00614 {
00615
00616 str += htmlOpen("div",
00617 {
00618 "style":"margin:11px 0 0 13px;",
00619 },"b" , 1 );
00620 }
00621 str += "</div>";
00622
00623
00624 str += htmlOpen("div",
00625 {
00626 "id":"cleanBuild",
00627 "class":"controlsButton",
00628 "style":"float:right",
00629 "onclick":"CodeEditor.editor.build(1 /*cleanBuild*/);",
00630 "title":"Clean Build... (Ctrl + N)",
00631 },"" , 0 );
00632 {
00633
00634 str += htmlOpen("div",
00635 {
00636 "style":"margin:10px 0 0 13px;",
00637 },"z" , 1 );
00638 }
00639 str += "</div>";
00640
00641
00642 str += htmlOpen("div",
00643 {
00644 "id":"displayHelp",
00645 "class":"controlsButton",
00646 "style":"float:right",
00647 "onclick":"CodeEditor.showTooltip(1 /*alwaysShow*/);",
00648 "title":"Click for help, short-cuts, etc.",
00649 },"" , 0 );
00650 {
00651
00652 str += htmlOpen("div",
00653 {
00654 "style":"margin:12px 0 0 13px;",
00655 },"?" , 1 );
00656 }
00657 str += "</div>";
00658
00659 el.innerHTML = str;
00660 }
00661 cel.appendChild(el);
00662
00663 }
00664
00665 document.body.appendChild(cel);
00666 _eel = [document.getElementById("editableBox" + 0),
00667 document.getElementById("editableBox" + 1)];
00668
00669
00671
00672 var box;
00673 for(var i=0;i<2;++i)
00674 {
00675 _eel[i].addEventListener("input",
00676 function(e)
00677 {
00678 e.stopPropagation();
00679
00680 var forPrimary = this.id[this.id.length-1]|0;
00681 forPrimary = forPrimary?1:0;
00682
00683 Debug.log("input forPrimary=" + forPrimary);
00684
00685 _fileWasModified[forPrimary] = true;
00686 CodeEditor.editor.updateLastSave(forPrimary);
00687
00688 CodeEditor.editor.startUpdateHandling(forPrimary);
00689
00690 });
00691
00692 _eel[i].addEventListener("keydown",
00693 function(e)
00694 {
00695 if(e.keyCode == 91 || e.keyCode == 93 ||
00696 e.keyCode == 224)
00697 _commandKeyDown = true;
00698
00699 var forPrimary = this.id[this.id.length-1]|0;
00700 forPrimary = forPrimary?1:0;
00701
00702
00703 CodeEditor.editor.keyDownHandler(e,forPrimary);
00704 e.stopPropagation();
00705 });
00706
00707 _eel[i].addEventListener("keyup",
00708 function(e)
00709 {
00710 if(e.keyCode == 91 || e.keyCode == 93 ||
00711 e.keyCode == 224)
00712 _commandKeyDown = false;
00713 });
00714
00715 _eel[i].addEventListener("click",
00716 function(e)
00717 {
00718
00719 if(e.which > 1)
00720 {
00721 Debug.log("Special mouse click handling");
00722
00723 e.preventDefault();
00724 e.stopPropagation();
00725 return;
00726 }
00727
00728 e.stopPropagation();
00729 });
00730
00731 _eel[i].addEventListener("dblclick",
00732 function(e)
00733 {
00734
00735 var forPrimary = this.id[this.id.length-1]|0;
00736 forPrimary = forPrimary?1:0;
00737
00738 Debug.log("dblclick handler for editor" + forPrimary);
00739 e.stopPropagation();
00740
00741 CodeEditor.editor.doubleClickHandler(forPrimary);
00742 });
00743
00744 _eel[i].addEventListener("contextmenu",
00745 function(e)
00746 {
00747
00748 if(e.which > 1)
00749 {
00750 Debug.log("Special context menu handling");
00751
00752 e.preventDefault();
00753 e.stopPropagation();
00754 return;
00755 }
00756
00757 });
00758
00759 _eel[i].addEventListener("mousedown",
00760 function(e)
00761 {
00762 if(e.which > 1)
00763 {
00764 Debug.log("Special mouse down handling");
00765
00766 e.preventDefault();
00767 e.stopPropagation();
00768 return;
00769 }
00770
00771 CodeEditor.editor.stopUpdateHandling(e);
00772
00773 var forPrimary = this.id[this.id.length-1]|0;
00774 forPrimary = forPrimary?1:0;
00775
00776 Debug.log("mousedown handler for editor" + forPrimary + " " + e.which);
00777
00778
00779 if(_activePaneIsPrimary != forPrimary)
00780 CodeEditor.editor.updateDualView(!forPrimary);
00781
00782 _activePaneIsPrimary = forPrimary;
00783
00784
00785 });
00786
00787 _eel[i].addEventListener("mouseup",
00788 function(e)
00789 {
00790 var forPrimary = this.id[this.id.length-1]|0;
00791 forPrimary = forPrimary?1:0;
00792
00793 Debug.log("mouseup handler for editor" + forPrimary);
00794
00795 if(e.which > 1)
00796 {
00797 Debug.log("Special mouse up handling");
00798
00799 e.preventDefault();
00800 e.stopPropagation();
00801 return;
00802 }
00803
00804 CodeEditor.editor.startUpdateHandling(forPrimary);
00805
00806 });
00807
00808
00809 box = document.getElementById("editorPane" + i);
00810 box.addEventListener("click",
00811 function(e)
00812 {
00813 var forPrimary = this.id[this.id.length-1]|0;
00814 forPrimary = forPrimary?1:0;
00815
00816 Debug.log("click handler for pane" + forPrimary);
00817
00818
00819
00820 if(_activePaneIsPrimary != forPrimary)
00821 CodeEditor.editor.updateDualView(!forPrimary);
00822
00823 _activePaneIsPrimary = forPrimary;
00824
00825
00826 CodeEditor.editor.showFindAndReplaceSelection(forPrimary);
00827
00828
00829 var el = document.getElementById("textEditorBody" + forPrimary);
00830 var scrollLeft = el.scrollLeft;
00831 var scrollTop = el.scrollTop;
00832
00833 _eel[forPrimary].focus();
00834
00835 el.scrollLeft = scrollLeft;
00836 el.scrollTop = scrollTop;
00837
00838
00839 });
00840
00841
00842
00843 }
00844 box = document.body;
00845 box.addEventListener("keydown",
00846 function(e)
00847 {
00848 if(e.keyCode == 91 || e.keyCode == 93 ||
00849 e.keyCode == 224)
00850 _commandKeyDown = true;
00851
00852 var forPrimary = _activePaneIsPrimary;
00853 Debug.log("keydown handler for body" + forPrimary);
00854 CodeEditor.editor.keyDownHandler(e,forPrimary,true );
00855
00856 });
00857 box.addEventListener("keyup",
00858 function(e)
00859 {
00860 if(e.keyCode == 91 || e.keyCode == 93 ||
00861 e.keyCode == 224)
00862 _commandKeyDown = false;
00863 });
00864 box.addEventListener("mouseover",
00865 function()
00866 {
00867
00868 if(_fileStringHoverEl.parentNode)
00869 {
00870 Debug.log("body removing string hover");
00871 window.clearTimeout(_fileStringHoverTimeout);
00872 _fileStringHoverTimeout = window.setTimeout(
00873 function()
00874 {
00875 Debug.log("body removed string hover");
00876 try
00877 {
00878 _fileStringHoverEl.parentNode.removeChild(_fileStringHoverEl);
00879 }
00880 catch(e)
00881 {}
00882 }, 1000 );
00883 }
00884
00885 });
00886
00887 }
00888
00889
00890
00891 function createTextEditor(forPrimary)
00892 {
00893 forPrimary = forPrimary?1:0;
00894
00895 Debug.log("createTextEditor forPrimary=" + forPrimary);
00896
00897 var str = "";
00898
00899 str += htmlOpen("div",
00900 {
00901 "class":"textEditor",
00902 "id":"textEditor" + forPrimary,
00903 "style":"overflow:hidden;",
00904 },0 , false );
00905
00906
00907
00908
00909
00910
00911
00912 str += htmlOpen("div",
00913 {
00914 "class":"textEditorHeader",
00915 "id":"textEditorHeader" + forPrimary,
00916 },0 ,
00917 true );
00918
00919 str += htmlOpen("div",
00920 {
00921 "class":"textEditorBody",
00922 "id":"textEditorBody" + forPrimary,
00923 },0 , false );
00924
00925 str += "<table class='editableBoxTable' style='margin-bottom:200px'>" +
00926 "<tr><td valign='top'>";
00927 str += htmlOpen("div",
00928 {
00929 "class":"editableBoxLeftMargin",
00930 "id":"editableBoxLeftMargin" + forPrimary,
00931 },"0\n1\n2" ,true );
00932 str += "</td><td valign='top'>";
00933 str += htmlOpen("div",
00934 {
00935 "class":"editableBox",
00936 "id":"editableBox" + forPrimary,
00937 "contenteditable":"true",
00938 "autocomplete":"off",
00939 "autocorrect":"off",
00940 "autocapitalize":"off",
00941 "spellcheck":"false",
00942 },0 ,true );
00943 str += "</td></tr></table>";
00944
00945 str += "</div>";
00946
00947 str += "</div>";
00948
00949 return str;
00950 }
00951
00952
00953
00954 function createDirectoryNav(forPrimary)
00955 {
00956 forPrimary = forPrimary?1:0;
00957
00958 Debug.log("createDirectoryNav forPrimary=" + forPrimary);
00959
00960 var str = "";
00961
00962 str += htmlOpen("div",
00963 {
00964 "class":"directoryNav",
00965 "id":"directoryNav" + forPrimary,
00966 },"Directory" , 1 );
00967
00968 return str;
00969
00970 }
00971
00972
00973
00974
00975 function redrawWindow()
00976 {
00977
00978
00979
00980 var w = window.innerWidth | 0;
00981 var h = window.innerHeight | 0;
00982
00983 if(w < _WINDOW_MIN_SZ)
00984 w = _WINDOW_MIN_SZ;
00985 if(h < _WINDOW_MIN_SZ)
00986 h = _WINDOW_MIN_SZ;
00987
00988 Debug.log("redrawWindow to " + w + " - " + h);
00989
00990 var eps = document.getElementsByClassName("editorPane");
00991 var epHdrs = document.getElementsByClassName("textEditorHeader");
00992 var epBdys = document.getElementsByClassName("textEditorBody");
00993 var dns = document.getElementsByClassName("directoryNav");
00994 var rect = [{},{}];
00995
00996
00997 eps[0].style.position = "absolute";
00998 eps[1].style.position = "absolute";
00999
01000 var DIR_NAV_MARGIN = 50;
01001 var EDITOR_MARGIN = 20;
01002 var EDITOR_HDR_H = 56;
01003 switch(_viewMode)
01004 {
01005 case 0:
01006
01007 rect = [{"left":0,"top":0,"w":w,"h":h},
01008 undefined];
01009 break;
01010 case 1:
01011
01012 rect = [{"left":0,"top":0,"w":((w/2)|0),"h":h},
01013 {"left":((w/2)|0),"top":0,"w":(w-((w/2)|0)),"h":h}];
01014
01015 break;
01016 case 2:
01017
01018 rect = [{"left":0,"top":0,"h":((h/2)|0),"w":w},
01019 {"top":((h/2)|0),"left":0,"h":(h-((h/2)|0)),"w":w}];
01020
01021 break;
01022 default:
01023 Debug.log("Invalid view mode encountered: " + _viewMode);
01024 }
01025
01026
01027 for(var i=0;i<2;++i)
01028 {
01029 if(!rect[i])
01030 {
01031 eps[i].style.display = "none";
01032 continue;
01033 }
01034
01035 dns[i].style.left = (DIR_NAV_MARGIN) + "px";
01036 dns[i].style.top = (DIR_NAV_MARGIN) + "px";
01037 dns[i].style.width = (rect[i].w - 2*DIR_NAV_MARGIN) + "px";
01038 dns[i].style.height = (rect[i].h - 2*DIR_NAV_MARGIN) + "px";
01039
01040 eps[i].style.left = rect[i].left + "px";
01041 eps[i].style.top = rect[i].top + "px";
01042 eps[i].style.height = rect[i].h + "px";
01043 eps[i].style.width = rect[i].w + "px";
01044
01045 epHdrs[i].style.left = EDITOR_MARGIN + "px";
01046 epHdrs[i].style.top = (DIR_NAV_MARGIN - 2*EDITOR_MARGIN) + "px";
01047 epHdrs[i].style.height = (EDITOR_HDR_H + 2*EDITOR_MARGIN) + "px";
01048 epHdrs[i].style.width = (rect[i].w - 2*EDITOR_MARGIN) + "px";
01049
01050
01051 epBdys[i].style.left = 0 + "px";
01052 epBdys[i].style.top = (DIR_NAV_MARGIN + EDITOR_HDR_H) + "px";
01053 epBdys[i].style.height = (rect[i].h - DIR_NAV_MARGIN - EDITOR_HDR_H) + "px";
01054 epBdys[i].style.width = (rect[i].w - 0) + "px";
01055
01056 eps[i].style.display = "block";
01057 }
01058
01059 }
01060
01061
01062
01063
01064
01065 this.toggleView = function(v)
01066 {
01067 if(v !== undefined)
01068 _viewMode = v;
01069 else
01070 _viewMode = (_viewMode+1)%3;
01071 Debug.log("toggleView _viewMode=" + _viewMode);
01072 redrawWindow();
01073 }
01074
01075
01076
01077
01078 this.toggleDirectoryNav = function(forPrimary, v)
01079 {
01080 forPrimary = forPrimary?1:0;
01081 _activePaneIsPrimary = forPrimary;
01082
01083 Debug.log("toggleDirectoryNav forPrimary=" + forPrimary);
01084
01085 if(v !== undefined)
01086 _navMode[forPrimary] = v?1:0;
01087 else
01088 _navMode[forPrimary] = _navMode[forPrimary]?0:1;
01089 Debug.log("toggleDirectoryNav _navMode=" + _navMode[forPrimary]);
01090
01091 var el = document.getElementById("directoryNav" + forPrimary);
01092 var wasHidden = el.style.display == "none";
01093 el.style.display =
01094 _navMode[forPrimary]?"block":"none";
01095
01096 if(_navMode[forPrimary] && wasHidden)
01097 {
01098 var paths = document.getElementById("directoryNav" +
01099 forPrimary).getElementsByClassName("dirNavPath");
01100 var buildPath = "/";
01101 for(var i=1;i<paths.length;++i)
01102 buildPath += (i>1?"/":"") + paths[i].textContent;
01103 Debug.log("refresh " + buildPath);
01104
01105 CodeEditor.editor.openDirectory(forPrimary,buildPath);
01106 }
01107 }
01108
01109
01110
01111
01112 this.saveFile = function(forPrimary, quiet)
01113 {
01114 forPrimary = forPrimary?1:0;
01115
01116 Debug.log("saveFile forPrimary=" + forPrimary);
01117
01118 Debug.log("saveFile _filePath=" + _filePath[forPrimary]);
01119 Debug.log("saveFile _fileExtension=" + _fileExtension[forPrimary]);
01120
01121 if(_filePath[forPrimary] == "")
01122 {
01123 Debug.log("Error, can not save to empty file name!",
01124 Debug.HIGH_PRIORITY);
01125 return;
01126 }
01127
01128 if(!quiet)
01129 {
01130 DesktopContent.popUpVerification(
01131 "Are you sure you want to save...<br>" +
01132 _filePath[forPrimary] + "." + _fileExtension[forPrimary] + "?",
01133 localDoIt,
01134 undefined,undefined,undefined,
01135 undefined,undefined,
01136 "90%"
01137 );
01138 return;
01139 }
01140 else
01141 localDoIt();
01142
01143 function localDoIt()
01144 {
01145
01146
01147 var textObj = {"text":
01148 _eel[forPrimary].innerText,
01149 "time":undefined};
01150
01151
01152
01153
01154
01155 textObj.text = textObj.text.replace(/%C2%A0%C2%A0/g,"%20%20").replace(/%C2%A0/g,
01156 "%20").replace(/%C2/g,"%20").replace(/%A0/g,"%20");
01157
01158
01159
01160 DesktopContent.XMLHttpRequest("Request?RequestType=codeEditor" +
01161 "&option=saveFileContent" +
01162 "&path=" + _filePath[forPrimary] +
01163 "&ext=" + _fileExtension[forPrimary]
01164 , "content=" + encodeURIComponent(textObj.text) ,
01165 function(req)
01166 {
01167 Debug.log("Successfully saved " +
01168 _filePath[forPrimary] + "." +
01169 _fileExtension[forPrimary],quiet?Debug.LOW_PRIORITY:Debug.INFO_PRIORITY);
01170
01171 _fileWasModified[forPrimary] = false;
01172 textObj.time = Date.now();
01173 _fileLastSave[forPrimary] = textObj.time;
01174
01175
01176 CodeEditor.editor.updateLastSave(forPrimary);
01177
01178 if(_filePath[0] == _filePath[1] &&
01179 _fileExtension[0] == _fileExtension[1])
01180 {
01181 CodeEditor.editor.updateDualView(forPrimary);
01182
01183 CodeEditor.editor.updateFileSnapshot(!forPrimary,
01184 textObj,
01185 true );
01186 }
01187
01188
01189 CodeEditor.editor.updateFileSnapshot(forPrimary,
01190 textObj,
01191 true );
01192
01193 });
01194
01195 }
01196 }
01197
01198
01199
01200
01201 this.build = function(cleanBuild)
01202 {
01203 cleanBuild = cleanBuild?1:0;
01204
01205 Debug.log("build cleanBuild=" + cleanBuild);
01206
01207 if(cleanBuild)
01208 {
01209 DesktopContent.popUpVerification(
01210 "Are you sure you want to do a clean build?!",
01211 localDoIt
01212 );
01213 return;
01214 }
01215 else
01216 localDoIt();
01217
01218 function localDoIt()
01219 {
01220 DesktopContent.XMLHttpRequest("Request?RequestType=codeEditor" +
01221 "&option=build" +
01222 "&clean=" + (cleanBuild?1:0)
01223 , "" ,
01224 function(req)
01225 {
01226 Debug.log("Build was launched! Check " +
01227 "<a onclick='DesktopContent.openNewBrowserTab(" +
01228 "\"Console\");' " +
01229 "title='Click to open the Console web app in a new browser tab.'>" +
01230 "console</a> for result!", Debug.INFO_PRIORITY);
01231
01232 });
01233 }
01234
01235 }
01236
01237
01238
01239
01240 this.undo = function(forPrimary,redo)
01241 {
01242 DesktopContent.showLoading(localDoIt);
01243 return;
01244
01245 function localDoIt()
01246 {
01247 forPrimary = forPrimary?1:0;
01248
01249 Debug.log("undo() forPrimary=" + forPrimary + " redo=" + redo);
01250 console.log("undo stack index",_undoStackLatestIndex[forPrimary]);
01251 console.log("undo stack length",_undoStack[forPrimary].length);
01252
01253 console.log("undo stack",_undoStack[forPrimary]);
01254
01255 var el = _eel[forPrimary];
01256
01257
01258 CodeEditor.editor.updateFileSnapshot(forPrimary,
01259 {"text":el.textContent,
01260 "time":Date.now()},
01261 true );
01262
01263 var newIndex = _undoStackLatestIndex[forPrimary];
01264 newIndex += redo?1:-1;
01265 if(newIndex >= _undoStack_MAX_SIZE)
01266 newIndex = 0;
01267 else if(newIndex < 0)
01268 newIndex = _undoStack[forPrimary].length-1;
01269
01270 console.log("new stack index",newIndex);
01271
01272
01273 if(!redo &&
01274 _undoStack[forPrimary][newIndex][1] >=
01275 _undoStack[forPrimary][_undoStackLatestIndex[forPrimary]][1])
01276 {
01277 Debug.log("Reached end of undo history...",Debug.WARN_PRIORITY);
01278 return;
01279 }
01280 if(redo &&
01281 (newIndex >= _undoStack[forPrimary].length ||
01282 _undoStack[forPrimary][newIndex][1] <=
01283 _undoStack[forPrimary][_undoStackLatestIndex[forPrimary]][1]))
01284 {
01285 Debug.log("Reached end of redo history...",Debug.WARN_PRIORITY);
01286 return;
01287 }
01288
01289
01290 _undoStackLatestIndex[forPrimary] = newIndex;
01291 console.log("result stack index",newIndex);
01292
01293 var cursor = CodeEditor.editor.getCursor(el);
01294
01295 el.textContent =
01296 _undoStack[forPrimary][_undoStackLatestIndex[forPrimary]][0];
01297 _fileWasModified[forPrimary] = true;
01298
01299 CodeEditor.editor.updateDecorations(forPrimary,
01300 false ,
01301 true );
01302
01303 CodeEditor.editor.setCursor(el,cursor,true );
01304 }
01305 }
01306
01307
01308
01309
01310 this.handleDirectoryContent = function(forPrimary,req)
01311 {
01312 forPrimary = forPrimary?1:0;
01313
01314 Debug.log("handleDirectoryContent forPrimary=" + forPrimary);
01315 console.log(req);
01316
01317 var path = DesktopContent.getXMLValue(req,"path");
01318 if(path == "/") path = "";
01319
01320 var specials = req.responseXML.getElementsByTagName("special");
01321 var dirs = req.responseXML.getElementsByTagName("directory");
01322 var files = req.responseXML.getElementsByTagName("file");
01323 var specialFiles = req.responseXML.getElementsByTagName("specialFile");
01324
01325 Debug.log("handleDirectoryContent path=" + path);
01326 console.log(dirs);console.log(files);
01327
01328 var str = "";
01329 var i;
01330 var name;
01331 str += htmlOpen("div",
01332 {
01333 "style":"margin:20px;" +
01334 "white-space: nowrap;",
01335 });
01336
01338
01339 {
01340 var pathSplit = path.split('/');
01341 var buildPath = "";
01342 var pathSplitName;
01343
01344 str += "Path: <a class='dirNavPath' onclick='CodeEditor.editor.openDirectory(" +
01345 forPrimary + ",\"" +
01346 "/" + "\"" +
01347 ")'>" +
01348 "srcs</a>";
01349
01350
01351
01352 for(i=0;i<pathSplit.length;++i)
01353 {
01354 pathSplitName = pathSplit[i].trim();
01355 if(pathSplitName == "") continue;
01356 Debug.log("pathSplitName " + pathSplitName);
01357
01358 buildPath += "/" + pathSplitName;
01359
01360 str += "/";
01361 str += "<a class='dirNavPath' onclick='CodeEditor.editor.openDirectory(" +
01362 forPrimary + ",\"" +
01363 buildPath + "\"" +
01364 ")' title='Open folder: \nsrcs" + buildPath +
01365 "' >" +
01366 pathSplitName + "</a>";
01367
01368 }
01369 str += "/";
01370
01371
01372 str += htmlOpen("a",
01373 {
01374 "title":"Open folder in the other editor pane of the split-view: \n" +
01375 "srcs" + buildPath,
01376 "onclick":"CodeEditor.editor.openDirectory(" +
01377 (!forPrimary) + ",\"" +
01378 buildPath+ "\");",
01379 },
01380 "<img class='dirNavFileNewWindowImgNewPane' " +
01381 "src='/WebPath/images/windowContentImages/CodeEditor-openInOtherPane.png'>"
01382 , true );
01383
01384
01385 str += htmlOpen("a",
01386 {
01387 "title":"Open folder in a new browser tab: \n" +
01388 "srcs" + buildPath,
01389 "onclick":"DesktopContent.openNewBrowserTab(" +
01390 "\"Code Editor\",\"\"," +
01391 "\"/WebPath/html/CodeEditor.html?openDirectoryPrimary=" +
01392 buildPath + "\",0 /*unique*/);' ",
01393 },
01394 "<img class='dirNavFileNewWindowImgNewWindow' " +
01395 "src='/WebPath/images/windowContentImages/CodeEditor-openInNewWindow.png'>"
01396 , true );
01397
01398
01399 str += "<br><br>";
01400 }
01401
01403
01404 for(i=0;i<specials.length;++i)
01405 {
01406 name = specials[i].getAttribute('value');
01407
01408
01409 str += htmlOpen("a",
01410 {
01411 "title":"Open folder in a new browser tab: \n" +
01412 "srcs" + path + "/" + name,
01413 "onclick":"DesktopContent.openNewBrowserTab(" +
01414 "\"Code Editor\",\"\"," +
01415 "\"/WebPath/html/CodeEditor.html?openDirectoryPrimary=" +
01416 path + "/" + name + "\",0 /*unique*/);' ",
01417 },
01418 "<img class='dirNavFileNewWindowImgNewWindow' " +
01419 "src='/WebPath/images/windowContentImages/CodeEditor-openInNewWindow.png'>"
01420 , true );
01421
01422
01423 str += htmlOpen("a",
01424 {
01425 "title":"Open folder in the other editor pane of the split-view: \n" +
01426 "srcs" + path + "/" + name,
01427 "onclick":"CodeEditor.editor.openDirectory(" +
01428 (!forPrimary) + ",\"" +
01429 path + "/" + name + "\");",
01430 },
01431 "<img class='dirNavFileNewWindowImgNewPane' " +
01432 "src='/WebPath/images/windowContentImages/CodeEditor-openInOtherPane.png'>"
01433 , true );
01434
01435
01436 str += "<a class='dirNavSpecial' onclick='CodeEditor.editor.openDirectory(" +
01437 forPrimary + ",\"" +
01438 path + "/" + name + "\"" +
01439 ")' title='Open folder: \nsrcs" + path + "/" + name + "' >" +
01440 name + "</a>";
01441
01442
01443 str += "<br>";
01444
01445 }
01447
01448 var nameSplit;
01449 if(specialFiles.length)
01450 {
01451 str += "<table>";
01452 str += "<tr><th>" + path.substr(1,path.length-2) + " Files</th><th style='padding-left:20px'>Repository</th></tr>";
01453 }
01454 for(i=0;i<specialFiles.length;++i)
01455 {
01456 name = specialFiles[i].getAttribute('value');
01457
01458 str += "<tr><td>";
01459
01460
01461 str += htmlOpen("a",
01462 {
01463 "title":"Open file in a new browser tab: \n" +
01464 "srcs" + name,
01465 "onclick":"DesktopContent.openNewBrowserTab(" +
01466 "\"Code Editor\",\"\"," +
01467 "\"/WebPath/html/CodeEditor.html?startFilePrimary=" +
01468 name + "\",0 /*unique*/);' ",
01469 },
01470 "<img class='dirNavFileNewWindowImgNewWindow' " +
01471 "src='/WebPath/images/windowContentImages/CodeEditor-openInNewWindow.png'>"
01472 , true );
01473
01474
01475 str += htmlOpen("a",
01476 {
01477 "title":"Open file in the other editor pane of the split-view: \n" +
01478 "srcs" + name,
01479 "onclick":"CodeEditor.editor.openFile(" +
01480 (!forPrimary) + ",\"" +
01481 name + "\", \"" +
01482 name.substr(name.indexOf('.')+1) + "\"" +
01483 ");",
01484 },
01485 "<img class='dirNavFileNewWindowImgNewPane' " +
01486 "src='/WebPath/images/windowContentImages/CodeEditor-openInOtherPane.png'>"
01487 , true );
01488
01489
01490 str += "<a class='dirNavFile' onclick='CodeEditor.editor.openFile(" +
01491 forPrimary + ",\"" +
01492 name + "\",\"" +
01493 name.substr(name.indexOf('.')+1) + "\"" +
01494 ")' title='Open file: \nsrcs" + name + "' >";
01495 nameSplit = name.split('/');
01496 str += nameSplit[nameSplit.length-1] + "</a>";
01497
01498
01499
01500 str += "</td><td style='padding-left:20px'>" + nameSplit[1] + "</td></tr>";
01501
01502 }
01503 if(specialFiles.length)
01504 {
01505 str += "</table>";
01506 }
01508
01509 for(i=0;i<dirs.length;++i)
01510 {
01511 name = dirs[i].getAttribute('value');
01512
01513
01514 str += htmlOpen("a",
01515 {
01516 "title":"Open file in a new browser tab: \n" +
01517 "srcs" + path + "/" + name,
01518 "onclick":"DesktopContent.openNewBrowserTab(" +
01519 "\"Code Editor\",\"\"," +
01520 "\"/WebPath/html/CodeEditor.html?openDirectoryPrimary=" +
01521 path + "/" + name + "\",0 /*unique*/);' ",
01522 },
01523 "<img class='dirNavFileNewWindowImgNewWindow' " +
01524 "src='/WebPath/images/windowContentImages/CodeEditor-openInNewWindow.png'>"
01525 , true );
01526
01527
01528 str += htmlOpen("a",
01529 {
01530 "title":"Open folder in the other editor pane of the split-view: \n" +
01531 "srcs" + path + "/" + name,
01532 "onclick":"CodeEditor.editor.openDirectory(" +
01533 (!forPrimary) + ",\"" +
01534 path + "/" + name + "\");",
01535 },
01536 "<img class='dirNavFileNewWindowImgNewPane' " +
01537 "src='/WebPath/images/windowContentImages/CodeEditor-openInOtherPane.png'>"
01538 , true );
01539
01540
01541 str += "<a class='dirNavFolder' onclick='CodeEditor.editor.openDirectory(" +
01542 forPrimary + ",\"" +
01543 path + "/" + name + "\"" +
01544 ")' title='Open folder: \nsrcs" + path + "/" + name + "' >" +
01545 name + "</a>";
01546
01547
01548 str += "<br>";
01549
01550 }
01552
01553 for(i=0;i<files.length;++i)
01554 {
01555 name = files[i].getAttribute('value');
01556
01557
01558 str += htmlOpen("a",
01559 {
01560 "title":"Open file in a new browser tab: \n" +
01561 "srcs" + path + "/" + name,
01562 "onclick":"DesktopContent.openNewBrowserTab(" +
01563 "\"Code Editor\",\"\"," +
01564 "\"/WebPath/html/CodeEditor.html?startFilePrimary=" +
01565 path + "/" + name + "\",0 /*unique*/);' ",
01566 },
01567 "<img class='dirNavFileNewWindowImgNewWindow' " +
01568 "src='/WebPath/images/windowContentImages/CodeEditor-openInNewWindow.png'>"
01569 , true );
01570
01571
01572 str += htmlOpen("a",
01573 {
01574 "title":"Open file in the other editor pane of the split-view: \n" +
01575 "srcs" + path + "/" + name,
01576 "onclick":"CodeEditor.editor.openFile(" +
01577 (!forPrimary) + ",\"" +
01578 path + "/" + name + "\", \"" +
01579 name.substr(name.indexOf('.')+1) + "\"" +
01580 ");",
01581 },
01582 "<img class='dirNavFileNewWindowImgNewPane' " +
01583 "src='/WebPath/images/windowContentImages/CodeEditor-openInOtherPane.png'>"
01584 , true );
01585
01586
01587
01588 str += "<a class='dirNavFile' onclick='CodeEditor.editor.openFile(" +
01589 forPrimary + ",\"" +
01590 path + "/" + name + "\", \"" +
01591 name.substr(name.indexOf('.')+1) + "\"" +
01592 ")' title='Open file: \nsrcs" + path + "/" + name + "' >" +
01593 name + "</a>";
01594
01595
01596
01597 str += "<br>";
01598
01599 }
01600 str += "</div>";
01601 document.getElementById("directoryNav" + forPrimary).innerHTML = str;
01602 }
01603
01604
01605
01606
01607 this.openDirectory = function(forPrimary,path)
01608 {
01609 forPrimary = forPrimary?1:0;
01610
01611 if(!path || path == "") path = "/";
01612 Debug.log("openDirectory forPrimary=" + forPrimary +
01613 " path=" + path);
01614
01615
01616 DesktopContent.XMLHttpRequest("Request?RequestType=codeEditor" +
01617 "&option=getDirectoryContent" +
01618 "&path=" + path
01619 , "" ,
01620 function(req)
01621 {
01622 CodeEditor.editor.handleDirectoryContent(forPrimary, req);
01623 CodeEditor.editor.toggleDirectoryNav(forPrimary,1 );
01624
01625 });
01626 }
01627
01628
01629
01630
01631 this.openRelatedFile = function(forPrimary)
01632 {
01633 Debug.log("openRelatedFile forPrimary=" + forPrimary +
01634 " path=" + _filePath[forPrimary]);
01635
01636 var relatedPath = _filePath[forPrimary];
01637 var relatedExtension = _fileExtension[forPrimary];
01638
01639 var altPaths = [];
01640 var altExtensions = [];
01641
01642 if(relatedExtension == "html")
01643 {
01644 relatedExtension = "js";
01645 var i = relatedPath.indexOf("/html/");
01646 if(i >= 0)
01647 {
01648 altPaths.push(relatedPath.substr(0,i) + "/css/" +
01649 relatedPath.substr(i + ("/html/").length));
01650 altExtensions.push("css");
01651
01652 relatedPath = relatedPath.substr(0,i) + "/js/" +
01653 relatedPath.substr(i + ("/html/").length);
01654 }
01655 else
01656 {
01657 altPaths.push(relatedPath);
01658 altExtensions.push("css");
01659 }
01660
01661 CodeEditor.editor.openFile(forPrimary,relatedPath,relatedExtension,
01662 undefined , undefined,
01663 altPaths , altExtensions);
01664 return;
01665 }
01666 else if(relatedExtension[0] == "h")
01667 {
01668 relatedExtension = "cc";
01669
01670 var i = relatedPath.indexOf("/FEInterfaces/");
01671
01672 altPaths.push(relatedPath);
01673 altExtensions.push("cc");
01674 altPaths.push(relatedPath);
01675 altExtensions.push("cpp");
01676 altPaths.push(relatedPath);
01677 altExtensions.push("CC");
01678 altPaths.push(relatedPath);
01679 altExtensions.push("cxx");
01680 altPaths.push(relatedPath);
01681 altExtensions.push("c");
01682 altPaths.push(relatedPath);
01683 altExtensions.push("C");
01684
01685 relatedPath += "_interface";
01686 CodeEditor.editor.openFile(forPrimary,relatedPath,relatedExtension,
01687 undefined , undefined,
01688 altPaths , altExtensions);
01689 return;
01690 }
01691 else if(relatedExtension == "css")
01692 {
01693 relatedExtension = "js";
01694 var i = relatedPath.indexOf("/css/");
01695
01696 if(i >= 0)
01697 {
01698 altPaths.push(relatedPath.substr(0,i) + "/html/" +
01699 relatedPath.substr(i + ("/css/").length));
01700 altExtensions.push("html");
01701
01702 relatedPath = relatedPath.substr(0,i) + "/js/" +
01703 relatedPath.substr(i + ("/css/").length);
01704 }
01705 else
01706 {
01707 altPaths.push(relatedPath);
01708 altExtensions.push("html");
01709 }
01710
01711 CodeEditor.editor.openFile(forPrimary,relatedPath,relatedExtension,
01712 undefined , undefined,
01713 altPaths , altExtensions);
01714 return;
01715 }
01716 else if(relatedExtension[0] == 'c' ||
01717 relatedExtension[0] == 'C')
01718 {
01719 relatedExtension = "h";
01720
01721 altPaths.push(relatedPath);
01722 altExtensions.push("h");
01723
01724 var i = relatedPath.indexOf("_interface");
01725 if(i > 0 && i == relatedPath.length-("_interface").length)
01726 relatedPath = relatedPath.substr(0,i);
01727
01728 altPaths.push(relatedPath);
01729 altExtensions.push("hh");
01730 altPaths.push(relatedPath);
01731 altExtensions.push("hpp");
01732 altPaths.push(relatedPath);
01733 altExtensions.push("hxx");
01734 altPaths.push(relatedPath);
01735 altExtensions.push("H");
01736
01737 CodeEditor.editor.openFile(forPrimary,relatedPath,relatedExtension,
01738 undefined , undefined,
01739 altPaths , altExtensions);
01740 return;
01741 }
01742 else if(relatedExtension == "js")
01743 {
01744 relatedExtension = "css";
01745 var i = relatedPath.indexOf("/js/");
01746
01747 if(i >= 0)
01748 {
01749 altPaths.push(relatedPath.substr(0,i) + "/html/" +
01750 relatedPath.substr(i + ("/js/").length));
01751 altExtensions.push("html");
01752
01753 relatedPath = relatedPath.substr(0,i) + "/css/" +
01754 relatedPath.substr(i + ("/js/").length);
01755 }
01756 else
01757 {
01758 altPaths.push(relatedPath);
01759 altExtensions.push("html");
01760 }
01761
01762 CodeEditor.editor.openFile(forPrimary,relatedPath,relatedExtension,
01763 undefined , undefined,
01764 altPaths , altExtensions);
01765 return;
01766 }
01767
01768 Debug.log("Giving up on attempt to open a related file for " +
01769 relatedPath + "." + relatedExtension +
01770 "... no known related file.", Debug.HIGH_PRIORITY);
01771
01772 }
01773
01774
01775
01776
01777
01778
01779
01780
01781 this.openFile = function(forPrimary,path,extension,doConfirm,gotoLine,
01782 altPaths,altExtensions,propagateErr)
01783 {
01784 forPrimary = forPrimary?1:0;
01785
01786 Debug.log("openFile forPrimary=" + forPrimary +
01787 " path=" + path);
01788 var i = path.indexOf('.');
01789 if(i > 0)
01790 path = path.substr(0,i);
01791
01792 if(!propagateErr) propagateErr = "";
01793
01794 if(doConfirm)
01795 {
01796 DesktopContent.popUpVerification(
01797 "Do you want to reload the file from the server (and discard your changes)?",
01798 localDoIt
01799 );
01800 return;
01801 }
01802 else
01803 {
01804
01805 var keys = Object.keys(_fileHistoryStack);
01806 var filename = path + "." + extension;
01807 for(i;i<keys.length;++i)
01808 if(filename == keys[i])
01809 {
01810 Debug.log("Found " + filename + " in file history.");
01811
01812
01813
01814 var fileObj = {};
01815 fileObj.path = path;
01816 fileObj.extension = extension;
01817 fileObj.text = _fileHistoryStack[filename][0];
01818 fileObj.fileWasModified = _fileHistoryStack[filename][2];
01819 fileObj.fileLastSave = _fileHistoryStack[filename][3];
01820
01821 console.log("fileObj",fileObj);
01822
01823 CodeEditor.editor.handleFileContent(forPrimary,0,fileObj);
01824
01825 CodeEditor.editor.toggleDirectoryNav(forPrimary, false );
01826
01827
01828 if(!forPrimary && _viewMode == 0)
01829 CodeEditor.editor.toggleView();
01830
01831 return;
01832 }
01833
01834 localDoIt();
01835 }
01836
01837 function localDoIt()
01838 {
01839 CodeEditor.editor.toggleDirectoryNav(forPrimary,false );
01840
01841 DesktopContent.XMLHttpRequest("Request?RequestType=codeEditor" +
01842 "&option=getFileContent" +
01843 "&path=" + path +
01844 "&ext=" + extension
01845 , "" ,
01846 function(req)
01847 {
01848
01849 var err = DesktopContent.getXMLValue(req,"Error");
01850 if(err)
01851 {
01852 if(altPaths && altPaths.length &&
01853 altExtensions && altExtensions.length)
01854 {
01855
01856 CodeEditor.editor.openFile(forPrimary,
01857 altPaths.splice(0,1)[0],
01858 altExtensions.splice(0,1)[0],
01859 undefined , undefined,
01860 altPaths , altExtensions,
01861 propagateErr + err );
01862 }
01863 else
01864 Debug.log(propagateErr + err,Debug.HIGH_PRIORITY);
01865
01866
01867 return;
01868 }
01869
01870
01871 try
01872 {
01873 CodeEditor.editor.toggleDirectoryNav(forPrimary,0 );
01874 CodeEditor.editor.handleFileContent(forPrimary, req);
01875
01876
01877 if(!forPrimary && _viewMode == 0)
01878 CodeEditor.editor.toggleView();
01879
01880 if(gotoLine !== undefined)
01881 CodeEditor.editor.gotoLine(forPrimary,gotoLine);
01882 }
01883 catch(e)
01884 {
01885 Debug.log("Ignoring error handling file open: " + e);
01886 }
01887 console.log(DesktopContent._loadBox.style.display);
01888
01889 },
01890 0 , 0 , 1 );
01891 }
01892 }
01893
01894
01895
01896
01897 this.getLine = function(forPrimary)
01898 {
01899 Debug.log("getLine() forPrimary=" + forPrimary);
01900
01901
01902 var el = _eel[forPrimary];
01903 var cursor = CodeEditor.editor.getCursor(el);
01904 cursor.line = 1;
01905 if(cursor.startNodeIndex === undefined)
01906 {
01907 Debug.log("No cursor, so defaulting to top");
01908 return cursor;
01909 }
01910
01911
01912 var i,n,node,val;
01913 for(n=0; n<el.childNodes.length; ++n)
01914 {
01915 node = el.childNodes[n];
01916 val = node.textContent;
01917
01918
01919 for(i=0;i<val.length;++i)
01920 {
01921
01922 if(!cursor.focusAtEnd &&
01923 n == cursor.startNodeIndex &&
01924 i == cursor.startPos)
01925 break;
01926 else if(cursor.focusAtEnd &&
01927 n == cursor.endNodeIndex &&
01928 i == cursor.endPos)
01929 break;
01930
01931 if(val[i] == '\n')
01932 ++cursor.line;
01933 }
01934
01935
01936 if(!cursor.focusAtEnd &&
01937 n == cursor.startNodeIndex)
01938 {
01939 Debug.log("Found cursor at line " + cursor.line);
01940 break;
01941 }
01942 else if(cursor.focusAtEnd &&
01943 n == cursor.endNodeIndex)
01944 {
01945 Debug.log("Found cursor at line " + cursor.line);
01946 break;
01947 }
01948 }
01949
01950 return cursor;
01951 }
01952
01953
01954
01955 this.gotoLine = function(forPrimary,line,selectionCursor,topOfView)
01956 {
01957 line = line | 0;
01958 if(line < 1) line = 1;
01959 if(line > _numberOfLines[forPrimary])
01960 line = _numberOfLines[forPrimary];
01961 console.log("Goto line number ",line,selectionCursor);
01962
01963 if(topOfView)
01964 window.location.href = "#" + forPrimary + "L" + line;
01965
01966
01967
01968
01969
01970 var el = _eel[forPrimary];
01971
01972 if(line < 2)
01973 {
01974
01975
01976 var cursor = {
01977 "startNodeIndex": 0,
01978 "startPos":0,
01979 "endNodeIndex":0,
01980 "endPos":0,
01981 };
01982
01983
01984 if(selectionCursor)
01985 {
01986 cursor.endNodeIndex = selectionCursor.startNodeIndex;
01987 cursor.endPos = selectionCursor.startPos;
01988 cursor.focusAtEnd = selectionCursor.focusAtEnd;
01989 }
01990 CodeEditor.editor.setCursor(el,cursor,true );
01991
01992 return line;
01993 }
01994
01995 var i,n,node,el,val;
01996 var lineCount = 1;
01997 var found = false;
01998 var newLine = false;
01999
02000 var lastNode = 0;
02001 var lastPos = 0;
02002 for(n=0; n<el.childNodes.length; ++n)
02003 {
02004 node = el.childNodes[n];
02005 val = node.textContent;
02006
02007
02008 for(i=0;i<val.length;++i)
02009 {
02010 if(newLine)
02011 {
02012 lastNode = n;
02013 lastPos = i;
02014 }
02015
02016
02017 if(line == lineCount)
02018 {
02019
02020 Debug.log("Found line " + line);
02021 found = true;
02022 break;
02023 }
02024
02025 newLine = false;
02026 if(val[i] == '\n')
02027 {
02028 ++lineCount;
02029 newLine = true;
02030 }
02031 }
02032 if(found) break;
02033 }
02034
02035
02036
02037 var cursor = {
02038 "startNodeIndex":lastNode,
02039 "startPos":lastPos,
02040 "endNodeIndex":lastNode,
02041 "endPos":lastPos,
02042 };
02043
02044
02045
02046 if(selectionCursor)
02047 {
02048 cursor.focusAtEnd = selectionCursor.focusAtEnd;
02049
02050 if(lastNode < selectionCursor.startNodeIndex ||
02051 ( lastNode == selectionCursor.startNodeIndex &&
02052 lastPos < selectionCursor.startPos))
02053 {
02054 cursor.endNodeIndex = selectionCursor.startNodeIndex;
02055 cursor.endPos = selectionCursor.startPos;
02056 }
02057 else
02058 {
02059 cursor.startNodeIndex = selectionCursor.startNodeIndex;
02060 cursor.startPos = selectionCursor.startPos;
02061 }
02062
02063
02064 CodeEditor.editor.setCursor(el,cursor,
02065 true );
02066 return line;
02067 }
02068
02069
02070 CodeEditor.editor.setCursor(el,cursor,true );
02071
02072 return line;
02073
02074 }
02075
02076
02077
02078
02079
02080
02081
02082 this.handleFileContent = function(forPrimary,req,fileObj)
02083 {
02084 forPrimary = forPrimary?1:0;
02085
02086 Debug.log("handleFileContent forPrimary=" + forPrimary);
02087 console.log(req);
02088
02089 var path;
02090 var extension;
02091 var text;
02092 var fileWasModified, fileLastSave;
02093
02094 if(req)
02095 {
02096 path = DesktopContent.getXMLValue(req,"path");
02097 extension = DesktopContent.getXMLValue(req,"ext");
02098 text = DesktopContent.getXMLValue(req,"content");
02099 fileWasModified = false;
02100 fileLastSave = 0;
02101 }
02102 else
02103 {
02104 path = fileObj.path;
02105 extension = fileObj.extension;
02106 text = fileObj.text;
02107 fileWasModified = fileObj.fileWasModified;
02108 fileLastSave = fileObj.fileLastSave;
02109 }
02110
02111
02112
02113 text = text.replace(new RegExp(
02114 String.fromCharCode(160),'g'),' ');
02115
02116
02117
02118 _filePath[forPrimary] = path;
02119 _fileExtension[forPrimary] = extension;
02120 _fileWasModified[forPrimary] = fileWasModified;
02121 _fileLastSave[forPrimary] = fileLastSave;
02122
02123 _undoStack[forPrimary] = [];
02124 _undoStackLatestIndex[forPrimary] = -1;
02125
02126 var el = _eel[forPrimary];
02127
02128
02129 DesktopContent.showLoading(function()
02130 {
02131 try
02132 {
02133 el.textContent = text;
02134 CodeEditor.editor.displayFileHeader(forPrimary);
02135 }
02136 catch(e)
02137 { Debug.log("Ignoring error: " + e); }
02138 });
02139
02140 }
02141
02142
02143
02144 this.setCursor = function(el,inCursor,scrollIntoView)
02145 {
02146 if(inCursor.startNodeIndex !== undefined)
02147 {
02148
02149 var cursor = {
02150 "startNodeIndex": inCursor.startNodeIndex,
02151 "startPos": inCursor.startPos,
02152 "endNodeIndex": inCursor.endNodeIndex,
02153 "endPos": inCursor.endPos,
02154 "focusAtEnd": inCursor.focusAtEnd,
02155 };
02156
02157
02158 var scrollEndIntoView = cursor.focusAtEnd?true:false;
02159
02160 try
02161 {
02162 console.log("set cursor",cursor,"scrollIntoView=",scrollIntoView,
02163 "scrollEndIntoView=",scrollEndIntoView);
02164
02165 var range = document.createRange();
02166
02167 var firstEl = el.childNodes[cursor.startNodeIndex];
02168
02169
02170
02171 var secondEl = el.childNodes[cursor.endNodeIndex];
02172
02173
02174
02175 if(scrollIntoView)
02176 {
02177 Debug.log("scrollIntoView");
02178
02179
02180
02181
02182
02183
02184
02185
02186 Debug.log("inserting scroll 2nd element");
02187 try
02188 {
02189
02190 var val = secondEl.textContent;
02191 var newNode1 = document.createTextNode(
02192 val.substr(0,cursor.endPos));
02193
02194 el.insertBefore(newNode1,secondEl);
02195
02196 var newNode = document.createElement("label");
02197 newNode.textContent = val[cursor.endPos];
02198 el.insertBefore(newNode,secondEl);
02199
02200 secondEl.textContent = val.substr(cursor.endPos+1);
02201
02202 newNode.scrollIntoViewIfNeeded();
02203
02204 el.removeChild(newNode);
02205 el.removeChild(newNode1);
02206 secondEl.textContent = val;
02207 }
02208 catch(e)
02209 {
02210 Debug.log("Failed to scroll to inserted 2nd element: " + e);
02211 try
02212 {
02213 secondEl.scrollIntoViewIfNeeded();
02214 }
02215 catch(e)
02216 {
02217 Debug.log("Failed to scroll 2nd element: " + e);
02218 }
02219 }
02220
02221
02222 Debug.log("inserting scroll 1st element");
02223 try
02224 {
02225
02226
02227 if(!scrollEndIntoView)
02228 {
02229
02230 firstEl = el.childNodes[cursor.startNodeIndex];
02231 var val = firstEl.textContent;
02232 var newNode1 = document.createTextNode(
02233 val.substr(0,cursor.startPos));
02234
02235 el.insertBefore(newNode1,firstEl);
02236
02237 var newNode = document.createElement("label");
02238 newNode.textContent = val[cursor.startPos];
02239 el.insertBefore(newNode,firstEl);
02240
02241 firstEl.textContent = val.substr(cursor.startPos+1);
02242
02243 newNode.scrollIntoViewIfNeeded();
02244
02245
02246 el.removeChild(newNode);
02247 el.removeChild(newNode1);
02248 firstEl.textContent = val;
02249 }
02250 else
02251 Debug.log("scrollEndIntoView only");
02252 }
02253 catch(e)
02254 {
02255 Debug.log("Failed to scroll to inserted 1st element: " + e);
02256 try
02257 {
02258 firstEl.scrollIntoViewIfNeeded();
02259 }
02260 catch(e)
02261 {
02262 Debug.log("Failed to scroll 1st element: " + e);
02263 }
02264 }
02265
02266
02267
02268
02269 }
02270
02271 if(firstEl.firstChild)
02272 firstEl = firstEl.firstChild;
02273 if(secondEl.firstChild)
02274 secondEl = secondEl.firstChild;
02275
02276 range.setStart(firstEl,
02277 cursor.startPos);
02278 range.setEnd(secondEl,
02279 cursor.endPos);
02280
02281
02282 var selection = window.getSelection();
02283 selection.removeAllRanges();
02284 selection.addRange(range);
02285
02286
02287 if(scrollEndIntoView)
02288 selection.extend(secondEl,cursor.endPos);
02289
02290
02291
02292 if(scrollIntoView)
02293 el.focus();
02294
02295
02296
02297 }
02298 catch(err)
02299 {
02300 console.log("set cursor err:",err);
02301 }
02302 }
02303 }
02304
02305
02306
02307 this.createCursorFromContentPosition = function(el,startPos,endPos)
02308 {
02309
02310 var cursor = {
02311 "startNodeIndex":undefined,
02312 "startPos":undefined,
02313 "endNodeIndex":undefined,
02314 "endPos":undefined
02315 };
02316
02317
02318 var sum = 0;
02319 var oldSum = 0;
02320
02321 try
02322 {
02323
02324 for(i=0;i<el.childNodes.length;++i)
02325 {
02326 sum += el.childNodes[i].textContent.length;
02327
02328 if(cursor.startNodeIndex === undefined &&
02329 startPos >= oldSum &&
02330 startPos < sum)
02331 {
02332
02333 cursor.startNodeIndex = i;
02334 cursor.startPos = startPos - oldSum;
02335 }
02336 if(endPos >= oldSum &&
02337 endPos < sum)
02338 {
02339
02340 cursor.endNodeIndex = i;
02341 cursor.endPos = endPos - oldSum;
02342 break;
02343 }
02344
02345 oldSum = sum;
02346 }
02347
02348 console.log("createCursorFromContentPosition:",cursor);
02349
02350 }
02351 catch(err)
02352 {
02353 console.log("get cursor err:",err);
02354 }
02355 return cursor;
02356
02357 }
02358
02359
02360
02361 this.getCursor = function(el)
02362 {
02363
02364 var cursor = {
02365 "startNodeIndex":undefined,
02366 "startPos":undefined,
02367 "endNodeIndex":undefined,
02368 "endPos":undefined,
02369 "startPosInContent":undefined,
02370 "endPosInContent":undefined,
02371 "focusAtEnd":undefined
02372 };
02373
02374 var sum = 0;
02375 try
02376 {
02377 var selection = window.getSelection();
02378 var range = selection.getRangeAt(0);
02379 var focusNode = selection.focusNode;
02380 var extentNode = selection.extentNode;
02381
02382 cursor.startPos = range.startOffset;
02383 cursor.endPos = range.endOffset;
02384
02385
02386 for(i=0;i<el.childNodes.length;++i)
02387 {
02388 if(cursor.startNodeIndex === undefined &&
02389 (
02390 el.childNodes[i] == range.startContainer ||
02391 el.childNodes[i] == range.startContainer.parentNode ||
02392 el.childNodes[i] == range.startContainer.parentNode.parentNode ||
02393 el.childNodes[i] == range.startContainer.parentNode.parentNode.parentNode) )
02394 {
02395 cursor.startNodeIndex = i;
02396 cursor.startPosInContent = sum + cursor.startPos;
02397
02398 if(focusNode == range.startContainer ||
02399 extentNode == range.startContainer)
02400 cursor.focusAtEnd = false;
02401 }
02402
02403 if(el.childNodes[i] == range.endContainer ||
02404 el.childNodes[i] == range.endContainer.parentNode ||
02405 el.childNodes[i] == range.endContainer.parentNode.parentNode ||
02406 el.childNodes[i] == range.startContainer.parentNode.parentNode.parentNode)
02407 {
02408 cursor.endNodeIndex = i;
02409 cursor.endPosInContent = sum + cursor.endPos;
02410
02411 if(cursor.focusAtEnd == undefined &&
02412 (focusNode == range.endContainer ||
02413 extentNode == range.endContainer))
02414 cursor.focusAtEnd = true;
02415
02416 break;
02417 }
02418
02419 sum += el.childNodes[i].textContent.length;
02420 }
02421
02422
02423
02424
02425 }
02426 catch(err)
02427 {
02428 console.log("get cursor err:",err);
02429 }
02430 return cursor;
02431 }
02432
02433
02434
02435
02436 var _DECORATION_RED = "rgb(202, 52, 52)";
02437 var _DECORATION_BLUE = "rgb(64, 86, 206)";
02438 var _DECORATION_GREEN = "rgb(33, 175, 60)";
02439 var _DECORATION_BLACK = "rgb(5, 5, 5)";
02440 var _DECORATION_GRAY = "rgb(162, 179, 158)";
02441 var _DECORATIONS = {
02442 "txt": {
02443 "ADD_SUBDIRECTORY" : _DECORATION_RED,
02444 "include_directories" : _DECORATION_RED,
02445 "simple_plugin" : _DECORATION_RED,
02446 "set" : _DECORATION_RED,
02447 "install_headers" : _DECORATION_RED,
02448 "install_source" : _DECORATION_RED,
02449 "enable_testing" : _DECORATION_RED,
02450 "CMAKE_MINIMUM_REQUIRED": _DECORATION_RED,
02451 "include" : _DECORATION_RED,
02452 "create_doxygen_documentation": _DECORATION_RED,
02453 },
02454 "c++": {
02455 "#define" : _DECORATION_RED,
02456 "#undef" : _DECORATION_RED,
02457 "#include" : _DECORATION_RED,
02458 "#ifndef" : _DECORATION_RED,
02459 "#else" : _DECORATION_RED,
02460 "#endif" : _DECORATION_RED,
02461 "using" : _DECORATION_RED,
02462 "namespace" : _DECORATION_RED,
02463 "class" : _DECORATION_RED,
02464 "public" : _DECORATION_RED,
02465 "private" : _DECORATION_RED,
02466 "protected" : _DECORATION_RED,
02467 "static" : _DECORATION_RED,
02468 "virtual" : _DECORATION_RED,
02469 "override" : _DECORATION_RED,
02470 "const" : _DECORATION_RED,
02471 "void" : _DECORATION_RED,
02472 "bool" : _DECORATION_RED,
02473 "unsigned" : _DECORATION_RED,
02474 "int" : _DECORATION_RED,
02475 "uint64_t" : _DECORATION_RED,
02476 "uint32_t" : _DECORATION_RED,
02477 "uint16_t" : _DECORATION_RED,
02478 "uint8_t" : _DECORATION_RED,
02479 "long" : _DECORATION_RED,
02480 "float" : _DECORATION_RED,
02481 "double" : _DECORATION_RED,
02482 "return" : _DECORATION_RED,
02483 "char" : _DECORATION_RED,
02484 "if" : _DECORATION_RED,
02485 "else" : _DECORATION_RED,
02486 "for" : _DECORATION_RED,
02487 "while" : _DECORATION_RED,
02488 "do" : _DECORATION_RED,
02489 "switch" : _DECORATION_RED,
02490 "case" : _DECORATION_RED,
02491 "default" : _DECORATION_RED,
02492 "try" : _DECORATION_RED,
02493 "catch" : _DECORATION_RED,
02494 "this" : _DECORATION_RED,
02495 "true" : _DECORATION_RED,
02496 "false" : _DECORATION_RED,
02497
02498
02499
02500 "std" : _DECORATION_GREEN,
02501 "ots" : _DECORATION_GREEN,
02502 "string" : _DECORATION_GREEN,
02503 "set" : _DECORATION_GREEN,
02504 "vector" : _DECORATION_GREEN,
02505 "pair" : _DECORATION_GREEN,
02506 "get" : _DECORATION_GREEN,
02507 "map" : _DECORATION_GREEN,
02508 "endl" : _DECORATION_GREEN,
02509 "runtime_error" : _DECORATION_GREEN,
02510 "memcpy" : _DECORATION_GREEN,
02511 "cout" : _DECORATION_GREEN,
02512 },
02513 "js": {
02514 "this" : _DECORATION_RED,
02515 "var" : _DECORATION_RED,
02516 "return" : _DECORATION_RED,
02517 "function" : _DECORATION_RED,
02518 "if" : _DECORATION_RED,
02519 "else" : _DECORATION_RED,
02520 "for" : _DECORATION_RED,
02521 "while" : _DECORATION_RED,
02522 "do" : _DECORATION_RED,
02523 "switch" : _DECORATION_RED,
02524 "case" : _DECORATION_RED,
02525 "default" : _DECORATION_RED,
02526 "try" : _DECORATION_RED,
02527 "catch" : _DECORATION_RED,
02528 "new" : _DECORATION_RED,
02529 "instanceof" : _DECORATION_RED,
02530 "true" : _DECORATION_RED,
02531 "false" : _DECORATION_RED,
02532
02533 "Debug" : _DECORATION_GREEN,
02534 "DesktopContent" : _DECORATION_GREEN,
02535 "HIGH_PRIORITY" : _DECORATION_GREEN,
02536 "WARN_PRIORITY" : _DECORATION_GREEN,
02537 "INFO_PRIORITY" : _DECORATION_GREEN,
02538 "LOW_PRIORITY" : _DECORATION_GREEN,
02539
02540 "Math" : _DECORATION_GREEN,
02541 "String" : _DECORATION_GREEN,
02542 "window" : _DECORATION_GREEN,
02543 "document" : _DECORATION_GREEN,
02544 "textContent" : _DECORATION_GREEN,
02545 "innerHTML" : _DECORATION_GREEN,
02546 },
02547 "sh" : {
02548 "if" : _DECORATION_RED,
02549 "then" : _DECORATION_RED,
02550 "else" : _DECORATION_RED,
02551 "fi" : _DECORATION_RED,
02552 "for" : _DECORATION_RED,
02553 "in" : _DECORATION_RED,
02554 "while" : _DECORATION_RED,
02555 "do" : _DECORATION_RED,
02556 "done" : _DECORATION_RED,
02557 "switch" : _DECORATION_RED,
02558 "case" : _DECORATION_RED,
02559 "default" : _DECORATION_RED,
02560 "export" : _DECORATION_RED,
02561
02562 "echo" : _DECORATION_GREEN,
02563 "cd" : _DECORATION_GREEN,
02564 "cp" : _DECORATION_GREEN,
02565 "rm" : _DECORATION_GREEN,
02566 "cat" : _DECORATION_GREEN,
02567 "wget" : _DECORATION_GREEN,
02568 "chmod" : _DECORATION_GREEN,
02569 "sleep" : _DECORATION_GREEN,
02570 }
02571 };
02572 this.updateDecorations = function(forPrimary,forceDisplayComplete,forceDecorations)
02573 {
02574 forPrimary = forPrimary?1:0;
02575
02576 Debug.log("updateDecorations forPrimary=" + forPrimary + " forceDisplayComplete=" + forceDisplayComplete);
02577
02578 var el = _eel[forPrimary];
02579 var elTextObj = {"text":el.textContent,"time":Date.now()};
02580 var wasSnapshot = CodeEditor.editor.updateFileSnapshot(forPrimary,
02581 elTextObj);
02582
02583 if(wasSnapshot || forceDisplayComplete)
02584 CodeEditor.editor.updateOutline(forPrimary,elTextObj);
02585
02586 if(!forceDecorations && !wasSnapshot)
02587 {
02588 Debug.log("unchanged, skipping decorations");
02589
02590 return;
02591 }
02592
02593
02594 var i, j;
02595 var val;
02596
02597
02598 var cursor = CodeEditor.editor.getCursor(el);
02599
02600
02601
02602 CodeEditor.editor.updateLastSave(forPrimary);
02603
02604
02605 var n;
02606 var decor, fontWeight;
02607 var specialString;
02608 var commentString = "#";
02609 if(_fileExtension[forPrimary][0] == 'c' ||
02610 _fileExtension[forPrimary][0] == 'C' ||
02611 _fileExtension[forPrimary][0] == 'h' ||
02612 _fileExtension[forPrimary][0] == 'j')
02613 commentString = "//";
02614
02615 var fileDecorType = "txt";
02616 if( _fileExtension[forPrimary] == 'html' ||
02617 _fileExtension[forPrimary] == 'js')
02618 fileDecorType = "js";
02619 else if(_fileExtension[forPrimary][0] == 'c' ||
02620 _fileExtension[forPrimary][0] == 'C' ||
02621 _fileExtension[forPrimary][0] == 'h' ||
02622 _fileExtension[forPrimary][0] == 'j')
02623 fileDecorType = "c++";
02624 else if(_fileExtension[forPrimary] == 'sh' ||
02625 _fileExtension[forPrimary] == 'py')
02626 fileDecorType = "sh";
02627
02628 var newNode;
02629 var node;
02630
02631 var startOfWord = -1;
02632 var startOfString = -1;
02633 var stringQuoteChar;
02634 var escapeCount;
02635 var startOfComment = -1;
02636 var firstSpecialStringStartHandling = true;
02637 var firstSpecialStringEndHandling = true;
02638 var endPositionCache;
02639
02640 var done = false;
02641
02642 var eatNode;
02643 var eatVal;
02644 var closedString;
02645
02646 var prevChar;
02647
02649 function localInsertLabel(startPos, isQuote)
02650 {
02651
02652
02653 newNode = document.createTextNode(val.substr(0,startPos));
02654 el.insertBefore(newNode,node);
02655
02656 newNode = document.createElement("label");
02657 newNode.style.fontWeight = fontWeight;
02658 newNode.style.color = decor;
02659 newNode.textContent = specialString;
02660
02661 el.insertBefore(newNode,node);
02662
02663 if(isQuote)
02664 {
02665 var str = newNode.textContent;
02666 str = str.substr(str.indexOf('.')+1);
02667
02668
02669 if(str.length > 0 && str.length <= 4 &&
02670 (
02671 str[0] == 'c' ||
02672 str[0] == 'C' ||
02673 str[0] == 'h' ||
02674 str == "txt" ||
02675 str == "py" ||
02676 str == "sh"
02677 ))
02678 {
02679 Debug.log("is quote " + str);
02680
02681 newNode.onmouseover = function(e)
02682 {
02683 window.clearTimeout(_fileStringHoverTimeout);
02684
02685 var x = this.offsetWidth + this.offsetLeft + 64;
02686 var y = this.offsetTop;
02687 e.stopPropagation();
02688
02689
02690 if(_fileStringHoverEl.parentNode)
02691 {
02692 _fileStringHoverEl.parentNode.removeChild(_fileStringHoverEl);
02693 }
02694 else
02695 {
02696
02697 _fileStringHoverEl = document.createElement("div");
02698 _fileStringHoverEl.setAttribute("id","fileStringHoverEl");
02699 _fileStringHoverEl.setAttribute("contentEditable","false");
02700 _fileStringHoverEl.onmouseover = function(e)
02701 {
02702 window.clearTimeout(_fileStringHoverTimeout);
02703 e.stopPropagation();
02704 };
02705 }
02706
02707 _fileStringHoverEl.style.display = 'none';
02708
02709 var str = "";
02710 var name = this.textContent;
02711
02712
02713 name = name.substr(1,name.length-2);
02714 var nameArr = name.split('/');
02715 if(nameArr.length == 0)
02716 {
02717 Debug.log("empty name array, error! name = " + name);
02718 return;
02719 }
02720 else if(nameArr.length > 1 && nameArr[0] == "" &&
02721 nameArr[1] == "WebPath")
02722 {
02723 name = "/otsdaq_utilities/WebGUI" +
02724 name.substr(("/WebPath").length);
02725 }
02726 else if(nameArr[0] != "")
02727 {
02728
02729 var i = nameArr[0].indexOf('-');
02730 if(i > 0)
02731 {
02732 var repo = "";
02733 if(nameArr[0] != "otsdaq-core")
02734 {
02735 nameArr[0] = nameArr[0].substr(0,i) + '_'
02736 + nameArr[0].substr(i+1);
02737 }
02738 else
02739 nameArr[0] = "otsdaq";
02740
02741 name = "/" + nameArr[0] + "/" + name;
02742 }
02743 else
02744 {
02745 Debug.log("Confused by name array, error! name = " + name);
02746 return;
02747 }
02748 }
02749
02750
02751 Debug.log("name " + name);
02752
02753
02754
02755 str += htmlOpen("a",
02756 {
02757 "title":"Open file in this editor pane: \n" +
02758 "srcs" + name,
02759 "onclick":"CodeEditor.editor.openFile(" +
02760 (forPrimary) + ",\"" +
02761 name + "\", \"" +
02762 name.substr(name.indexOf('.')+1) + "\"" +
02763 ");",
02764 },
02765 "<div " +
02766 "style='float: left; padding: 1px 0 1px 6px;'>" +
02767 "<div " +
02768 "style='border:1px solid rgb(99, 98, 98); border-radius: 2px; width: 9px;" +
02769 "height: 9px; '></div></div>"
02770 , true );
02771
02772 str += htmlOpen("a",
02773 {
02774 "title":"Open file in the other editor pane of the split-view: \n" +
02775 "srcs" + name,
02776 "onclick":"CodeEditor.editor.openFile(" +
02777 (!forPrimary) + ",\"" +
02778 name + "\", \"" +
02779 name.substr(name.indexOf('.')+1) + "\"" +
02780 ");",
02781 },
02782 "<div " +
02783 "style='float: left; padding: 0;'>" +
02784 "<img class='dirNavFileNewWindowImgNewPane' " +
02785 "src='/WebPath/images/windowContentImages/CodeEditor-openInOtherPane.png'></div>"
02786 , true );
02787
02788 str += htmlOpen("a",
02789 {
02790 "title":"Open file in a new browser tab: \n" +
02791 "srcs" + name,
02792 "onclick":"DesktopContent.openNewBrowserTab(" +
02793 "\"Code Editor\",\"\"," +
02794 "\"/WebPath/html/CodeEditor.html?startFilePrimary=" +
02795 name + "\",0 /*unique*/);' ",
02796 },
02797 "<div " +
02798 "style='float: left; padding: 0 6px 0 0;'>" +
02799 "<img class='dirNavFileNewWindowImgNewWindow' " +
02800 "src='/WebPath/images/windowContentImages/CodeEditor-openInNewWindow.png'></div>"
02801 , true );
02802
02803 _fileStringHoverEl.innerHTML = str;
02804
02805 this.parentNode.appendChild(_fileStringHoverEl);
02806
02807
02808 _fileStringHoverEl.style.left = x + "px";
02809 _fileStringHoverEl.style.top = y + "px";
02810
02811 _fileStringHoverEl.style.display = 'block';
02812
02813 }
02814 }
02815 }
02816
02817
02818 node.textContent = val.substr(i);
02819
02820
02821
02822 if(cursor.startNodeIndex !== undefined)
02823 {
02824 if(n < cursor.startNodeIndex)
02825 {
02826
02827 cursor.startNodeIndex += 2;
02828 cursor.endNodeIndex += 2;
02829 }
02830 else
02831 {
02832
02833
02834
02835 if(n == cursor.startNodeIndex)
02836 {
02837
02838 if(cursor.startPos < startPos)
02839 {
02840
02841
02842 }
02843 else if(cursor.startPos < i)
02844 {
02845
02846 ++cursor.startNodeIndex;
02847 cursor.startPos -= startPos;
02848 }
02849 else
02850 {
02851
02852 cursor.startNodeIndex += 2;
02853 if(val[cursor.startPos-1] == '\r') --cursor.startPos;
02854 cursor.startPos -= i;
02855 }
02856 }
02857
02858
02859 if(n == cursor.endNodeIndex)
02860 {
02861
02862 if(cursor.endPos < startPos)
02863 {
02864
02865
02866 }
02867 else if(cursor.endPos < i)
02868 {
02869
02870 ++cursor.endNodeIndex;
02871 cursor.endPos -= startPos;
02872 }
02873 else
02874 {
02875
02876 cursor.endNodeIndex += 2;
02877 if(val[cursor.endPos-1] == '\r') --cursor.endPos;
02878 cursor.endPos -= i;
02879
02880 }
02881 }
02882 else if(n < cursor.endNodeIndex)
02883 {
02884 cursor.endNodeIndex += 2;
02885 }
02886
02887 }
02888 }
02889
02890 n += 1;
02891
02892 }
02893
02894 for(n=0;!done && n<el.childNodes.length;++n)
02895 {
02896 node = el.childNodes[n];
02897 val = node.textContent;
02898
02899 if(node.nodeName == "LABEL" ||
02900 node.nodeName == "FONT" ||
02901 node.nodeName == "SPAN" ||
02902 node.nodeName == "PRE")
02903 {
02904
02905
02906
02907 if((_DECORATIONS[fileDecorType][val] === undefined &&
02908 (val[0] != commentString[0] ||
02909 val.indexOf('\n') >= 0) &&
02910 val[0] != '"') ||
02911
02912 (n+1 >= cursor.startNodeIndex && n-1 <= cursor.endNodeIndex))
02913 {
02914
02915
02916
02917 newNode = document.createTextNode(val);
02918 el.insertBefore(newNode,node);
02919 el.removeChild(node);
02920
02921
02922
02923 --n;
02924 continue;
02925 }
02926
02927 }
02928 else if(node.nodeName == "DIV" ||
02929 node.nodeName == "BR")
02930 {
02931
02932
02933 eatVal = node.innerHTML;
02934
02935
02936 i = 1;
02937 if(node.nodeName == "DIV")
02938 {
02939 if(n > 0)
02940 {
02941 specialString = el.childNodes[n-1].textContent;
02942 if(specialString[specialString.length-1] == '\n')
02943 --i;
02944 }
02945
02946 if(eatVal.indexOf("<br>") == 0 ||
02947 eatVal[0] == '\n')
02948 ++i;
02949 }
02950
02951 if(i == 2)
02952 val = "\n\n" + val;
02953 else if(i == 1)
02954 val = "\n" + val;
02955
02956
02957
02958 newNode = document.createTextNode(val);
02959 el.insertBefore(newNode,node);
02960 el.removeChild(node);
02961
02962
02963 if(n == cursor.startNodeIndex)
02964 cursor.startPos += i;
02965 if(n == cursor.endNodeIndex)
02966 cursor.endPos += i;
02967
02968 --n;
02969 continue;
02970
02971 }
02972 else if(node.nodeName == "#text")
02973 {
02974 if(n > 0 &&
02975 el.childNodes[n-1].nodeName == "#text")
02976 {
02977
02978 n -= 2;
02979 continue;
02980 }
02981
02982
02983 if(n + 1 < el.childNodes.length &&
02984 el.childNodes[n+1].nodeName == "#text")
02985 {
02986
02987
02988
02989
02990
02991 if(cursor.startNodeIndex !== undefined)
02992 {
02993 if(n+1 < cursor.startNodeIndex)
02994 {
02995
02996 cursor.startNodeIndex -= 1;
02997 cursor.endNodeIndex -= 1;
02998 }
02999 else
03000 {
03001
03002
03003
03004 if(n+1 == cursor.startNodeIndex)
03005 {
03006
03007 --cursor.startNodeIndex;
03008 cursor.startPos += val.length;
03009 }
03010
03011
03012 if(n+1 == cursor.endNodeIndex)
03013 {
03014
03015 --cursor.endNodeIndex;
03016 cursor.endPos += val.length;
03017 }
03018 else if(n+1 < cursor.endNodeIndex)
03019 {
03020
03021 --cursor.endNodeIndex;
03022 }
03023 }
03024 }
03025
03026
03027 newNode = el.childNodes[n+1];
03028 val += newNode.textContent;
03029 newNode.textContent = val;
03030 el.removeChild(node);
03031
03032 --n;
03033 continue;
03034 }
03035
03036 startOfWord = -1;
03037
03038 for(i=0;i<val.length;++i)
03039 {
03040
03041
03042
03043
03044
03045 if(startOfComment == -1 && (
03046 startOfString != -1 ||
03047 (prevChar != '\\' && val[i] == '"') ||
03048 (prevChar != '\\' && val[i] == "'")
03049 ))
03050 {
03051 if(startOfString == -1 &&
03052 (val[i] == '"' || val[i] == "'"))
03053 {
03054 startOfString = i;
03055 stringQuoteChar = val[i];
03056
03057 firstSpecialStringStartHandling = true;
03058 firstSpecialStringEndHandling = true;
03059 }
03060 else if(prevChar != '\\' && val[i] == stringQuoteChar)
03061 {
03062 ++i;
03063 specialString = val.substr(startOfString,i-startOfString);
03064
03065
03066 decor = _DECORATION_BLUE;
03067 fontWeight = "normal";
03068 localInsertLabel(startOfString, true );
03069 startOfString = -1;
03070
03071 break;
03072 }
03073 }
03074 else if(startOfString == -1 && (
03075 startOfComment != -1 ||
03076 (i+commentString.length-1 < val.length &&
03077 val.substr(i,commentString.length) ==
03078 commentString)))
03079 {
03080 if(startOfComment == -1 && val[i] == commentString[0])
03081 {
03082 startOfComment = i;
03083 firstSpecialStringStartHandling = true;
03084 firstSpecialStringEndHandling = true;
03085 }
03086 else if(val[i] == '\n')
03087 {
03088
03089 specialString = val.substr(startOfComment,i-startOfComment);
03090
03091
03092 decor = _DECORATION_GRAY;
03093 fontWeight = "normal";
03094 localInsertLabel(startOfComment);
03095 startOfComment = -1;
03096
03097 break;
03098 }
03099 }
03100 else if(
03101 (val[i] >= 'a' && val[i] <= 'z') ||
03102 (val[i] >= 'A' && val[i] <= 'Z') ||
03103 (val[i] >= '0' && val[i] <= '9') ||
03104 (val[i] == '_' || val[i] == '-') ||
03105 val[i] == '#')
03106 {
03107 if(startOfWord == -1)
03108 startOfWord = i;
03109
03110 }
03111 else if(startOfWord != -1)
03112 {
03113 specialString = val.substr(startOfWord,i-startOfWord);
03114 decor = _DECORATIONS[fileDecorType][specialString];
03115
03116
03117 if(decor)
03118 {
03119
03120 fontWeight = "bold";
03121 localInsertLabel(startOfWord);
03122 startOfWord = -1;
03123
03124 break;
03125 }
03126 else
03127 startOfWord = -1;
03128 }
03129
03130
03131 if(prevChar == '\\' && val[i] == '\\')
03132 {
03133 ++escapeCount;
03134 if(escapeCount%2 == 0)
03135 prevChar = '';
03136 else
03137 prevChar = '\\';
03138 }
03139 else
03140 {
03141 escapeCount = 1;
03142 prevChar = val[i];
03143 }
03144 }
03145
03146
03147
03148
03149
03151
03152 if(startOfString != -1 || startOfComment != -1)
03153 {
03154 console.log("In string/comment crossing Nodes!");
03155
03156
03157 closedString = false;
03158 for(++n;n<el.childNodes.length;++n)
03159 {
03160 eatNode = el.childNodes[n];
03161 eatVal = eatNode.textContent;
03162
03163
03164
03165 if(cursor.startNodeIndex !== undefined)
03166 {
03167 if(firstSpecialStringStartHandling)
03168 firstSpecialStringStartHandling = false;
03169
03170 if(firstSpecialStringEndHandling)
03171 {
03172
03173
03174 endPositionCache = cursor.endPos;
03175 firstSpecialStringEndHandling = false;
03176 }
03177
03178 if(n < cursor.startNodeIndex)
03179 {
03180
03181 cursor.startNodeIndex -= 1;
03182 cursor.endNodeIndex -= 1;
03183 }
03184 else
03185 {
03186
03187
03188
03189 if(n == cursor.startNodeIndex)
03190 {
03191
03192 --cursor.startNodeIndex;
03193 cursor.startPos += val.length;
03194 }
03195
03196
03197 if(n == cursor.endNodeIndex)
03198 {
03199
03200 --cursor.endNodeIndex;
03201 cursor.endPos += val.length;
03202 }
03203 else if(n < cursor.endNodeIndex)
03204 {
03205
03206 --cursor.endNodeIndex;
03207 }
03208 }
03209 }
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235
03236
03237
03238
03239
03240
03241
03242
03243
03244
03245
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281 val += eatVal;
03282 el.removeChild(eatNode);
03283 --n;
03284
03285
03286
03287 for(i;i<val.length;++i)
03288 {
03289
03290 if(startOfString != -1 &&
03291 (prevChar != '\\' && val[i] == '"'))
03292 {
03293 Debug.log("Closing node crossed string.");
03294
03295 ++i;
03296 specialString = val.substr(startOfString,i-startOfString);
03297
03298
03299 decor = _DECORATION_BLUE;
03300 fontWeight = "normal";
03301 localInsertLabel(startOfString,true );
03302 startOfString = -1;
03303 closedString = true;
03304 break;
03305 }
03306
03307
03308 if(startOfComment != -1 && val[i] == '\n')
03309 {
03310 Debug.log("Closing node crossed comment.");
03311
03312
03313
03314 specialString = val.substr(startOfComment,i-startOfComment);
03315
03316
03317 decor = _DECORATION_GRAY;
03318 fontWeight = "normal";
03319 localInsertLabel(startOfComment);
03320 startOfComment = -1;
03321
03322 closedString = true;
03323 break;
03324
03325 }
03326
03327
03328 if(prevChar == '\\' && val[i] == '\\')
03329 {
03330 ++escapeCount;
03331 if(escapeCount%2 == 0)
03332 prevChar = '';
03333 else
03334 prevChar = '\\';
03335 }
03336 else
03337 {
03338 escapeCount = 1;
03339 prevChar = val[i];
03340 }
03341
03342 }
03343
03344 if(closedString) break;
03345
03346 }
03347
03348 if(!closedString && startOfString != -1)
03349 {
03350 Debug.log("String is never closed!");
03351 specialString = val.substr(startOfString,i-startOfString);
03352
03353
03354 decor = _DECORATION_BLUE;
03355 --n;
03356 localInsertLabel(startOfString, true );
03357 startOfString = -1;
03358 }
03359 if(!closedString && startOfComment != -1)
03360 {
03361 Debug.log("Comment is never closed!");
03362 specialString = val.substr(startOfComment,i-startOfComment);
03363
03364
03365 decor = _DECORATION_GRAY;
03366 --n;
03367 localInsertLabel(startOfComment);
03368 startOfComment = -1;
03369 }
03370
03371 if(n < cursor.endNodeIndex)
03372 {
03373
03374
03375 firstSpecialStringEndHandling = true;
03376 cursor.endPos = endPositionCache;
03377 }
03378
03379
03380 }
03381
03382 }
03383 else
03384 {
03385 console.log("unknown node.nodeName",node.nodeName);
03386 throw("node error!");
03387 }
03388 }
03389
03390
03391 CodeEditor.editor.setCursor(el,cursor);
03392
03393 CodeEditor.editor.updateDualView(forPrimary);
03394
03395 }
03396
03397
03398
03399 this.autoIndent = function(forPrimary, cursor)
03400 {
03401 if(!cursor || cursor.startNodeIndex === undefined)
03402 {
03403 Debug.log("Invalid text selection for auto-indent. Please select text in the text editor.",
03404 Debug.HIGH_PRIORITY);
03405 return;
03406 }
03407 forPrimary = forPrimary?1:0;
03408
03409 Debug.log("autoIndent " + forPrimary);
03410
03411 DesktopContent.showLoading(localDoIt);
03412 return;
03413
03414
03415
03416
03417
03418
03420 function localDoIt()
03421 {
03422
03423
03424
03425
03426
03427
03428
03429
03430 var el = _eel[forPrimary];
03431 var node,val;
03432 var found = false;
03433 var n,i;
03434
03435
03436 for(n=cursor.startNodeIndex;n>=0; --n)
03437 {
03438 node = el.childNodes[n];
03439 val = node.textContent;
03440
03441 for(i=(n==cursor.startNodeIndex?cursor.startPos-1:
03442 val.length-1); i>=0; --i)
03443 {
03444 if(val[i] == '\n')
03445 {
03446
03447 found = true;
03448 break;
03449 }
03450 }
03451 if(found) break;
03452 }
03453
03454
03455 console.log("at leading newline - n",n,"i",i);
03456
03457 if(n < 0) n = 0;
03458 if(i < 0) i = 0;
03459 else ++i;
03460
03461 cursor.startNodeIndex = n;
03462 cursor.startPos = i;
03463
03464
03465
03466 var preText = "";
03467 var text = "";
03468 var postText = "";
03469
03470 for(n=0; n<el.childNodes.length; ++n)
03471 {
03472 val = el.childNodes[n].textContent;
03473 if(n < cursor.startNodeIndex)
03474 preText += val;
03475 else if(n == cursor.startNodeIndex)
03476 {
03477 preText += val.substr(0,cursor.startPos);
03478
03479 if(n < cursor.endNodeIndex)
03480 text += val.substr(cursor.startPos);
03481 else
03482 {
03483 text += val.substr(cursor.startPos,
03484 cursor.endPos-cursor.startPos);
03485 postText += val.substr(cursor.endPos);
03486 }
03487 }
03488 else if(n < cursor.endNodeIndex)
03489 text += val;
03490 else if(n == cursor.endNodeIndex)
03491 {
03492 text += val.substr(0,cursor.endPos);
03493 postText += val.substr(cursor.endPos);
03494 }
03495 else
03496 postText += val;
03497 }
03498
03499
03500
03501
03502
03503 var fileExtension = _fileExtension[forPrimary];
03504 if(1
03505
03506
03507
03508
03509
03510 )
03511 {
03512
03513 var x = 0;
03514 for(i=0;i<text.length;++i)
03515 if(text[i] == ' ')
03516 ++x;
03517 else if(text[i] == '\t')
03518 x += _TAB_SIZE - (x+_TAB_SIZE)%_TAB_SIZE;
03519 else
03520 break;
03521 Debug.log("Whitespace size =" + x + " tabs=" + ((x/_TAB_SIZE)|0));
03522
03523
03524 var tabStr = "";
03525 for(n=0;n<((x/_TAB_SIZE)|0);++n)
03526 tabStr += '\t';
03527
03528
03529 newText = "";
03530 i = -1;
03531
03532 var nextTabStr;
03533
03534 var lastChar,firstChar;
03535 var prevLastChar,prevFirstChar;
03536
03537 var inCmdTabStr = "";
03538 var nextInCmdTabStr = "";
03539 var isCmdTabStr = "";
03540 var nextIsCmdTabStr = "";
03541
03542
03543
03544 var foundComment;
03545 var firstColonCommand = false;
03546 var lastColonCommand = false;
03547 var foundDoubleQuote,foundSingleQuote;
03548 var tradeInCmdStack = [];
03549 var tradeIsCmdStack = [];
03550
03551 do
03552 {
03553
03554
03555
03556 lastChar = '';
03557 firstChar = '';
03558
03559 foundComment = false;
03560 foundDoubleQuote = false;
03561 foundSingleQuote = false;
03562
03563 for(n=i+1;n<text.length;++n)
03564 {
03565 if(text[n] == '\n')
03566 break;
03567
03568 if(foundComment)
03569 continue;
03570
03571 if(!foundSingleQuote && text[n] == '"')
03572 foundDoubleQuote = !foundDoubleQuote;
03573 else if(!foundDoubleQuote && text[n] == "'")
03574 foundSingleQuote = !foundSingleQuote;
03575 else if(text[n] == '/' && n+1 < text.length &&
03576 text[n+1] == '/')
03577 {
03578 foundComment = true;
03579 continue;
03580 }
03581
03582 if(foundDoubleQuote || foundSingleQuote)
03583 continue;
03584
03585 if(text[n] != ' ' && text[n] != '\t')
03586 {
03587 lastChar = text[n];
03588 if(firstChar == '')
03589 firstChar = text[n];
03590 }
03591
03592
03593 if(text[n] == '(')
03594 inCmdTabStr += '\t';
03595 else if(text[n] == ')')
03596 inCmdTabStr = inCmdTabStr.substr(0, inCmdTabStr.length-1);
03597 else if(inCmdTabStr.length == 0 &&
03598 text[n] == ';')
03599 {
03600 inCmdTabStr = "";
03601 isCmdTabStr = "";
03602 firstColonCommand = false;
03603 lastColonCommand = false;
03604 }
03605
03606 }
03607
03608 nextTabStr = tabStr;
03609
03610
03611 if(firstChar == '}')
03612 {
03613 nextIsCmdTabStr = "";
03614
03615
03616 if(tradeInCmdStack.length &&
03617 tradeInCmdStack[tradeInCmdStack.length-1][0] ==
03618 tabStr.length)
03619 {
03620
03621 inCmdTabStr = tradeInCmdStack.pop()[1];
03622 nextInCmdTabStr = inCmdTabStr;
03623 isCmdTabStr = tradeIsCmdStack.pop();
03624 tabStr = tabStr.substr(0,tabStr.length-1);
03625 }
03626
03627
03628 isCmdTabStr = "";
03629 firstColonCommand = false;
03630
03631 tabStr = tabStr.substr(0,tabStr.length-1);
03632 nextTabStr = tabStr;
03633 }
03634 else if(lastChar == ':' &&
03635 (firstChar == 'p' ||
03636 firstChar == 'd' ||
03637 firstChar == 'c'))
03638 {
03639 nextIsCmdTabStr = "";
03640
03641
03642 isCmdTabStr = "";
03643 firstColonCommand = false;
03644 lastColonCommand = false;
03645 nextTabStr = tabStr.substr(0,tabStr.length-1);
03646 }
03647 else if(firstChar == ':')
03648 {
03649
03650 nextIsCmdTabStr = "";
03651 isCmdTabStr = "";
03652 firstColonCommand = true;
03653 }
03654 else if(firstChar == '#' ||
03655 firstChar == '{')
03656 {
03657
03658 if(lastColonCommand)
03659 tabStr = tabStr.substr(0,tabStr.length-1);
03660
03661
03662
03663 if(nextInCmdTabStr.length != 0 ||
03664 nextIsCmdTabStr.length != 1 ||
03665 prevLastChar != ',')
03666 {
03667
03668 nextIsCmdTabStr = "";
03669 isCmdTabStr = "";
03670 }
03671 }
03672 else if(!firstColonCommand &&
03673 !lastColonCommand &&
03674 lastChar != '' &&
03675 lastChar != ';' &&
03676 firstChar != '"' &&
03677 firstChar != "'")
03678 isCmdTabStr = '\t';
03679 else if(lastColonCommand &&
03680 prevLastChar == ',' &&
03681 inCmdTabStr.length == 0)
03682 {
03683
03684 lastColonCommand = false;
03685 tabStr = tabStr.substr(0,tabStr.length-1);
03686 isCmdTabStr = "\t";
03687 nextIsCmdTabStr = "\t";
03688 }
03689 else
03690 firstColonCommand = false;
03691
03692
03693 if(lastChar == ';')
03694 {
03695 inCmdTabStr = "";
03696 isCmdTabStr = "";
03697 firstColonCommand = false;
03698 lastColonCommand = false;
03699 }
03700
03701 console.log(
03702 "firstChar = " + firstChar +
03703 "lastChar = " + lastChar +
03704 "prevFirstChar = " + prevFirstChar +
03705 "prevLastChar = " + prevLastChar +
03706 " ... nextTab = " +
03707 tabStr.length +
03708 " + " +
03709 inCmdTabStr.length +
03710 " + " +
03711 isCmdTabStr.length +
03712 " ... nowTab = " +
03713 nextTabStr.length +
03714 " + " +
03715 nextInCmdTabStr.length +
03716 " + " +
03717 nextIsCmdTabStr.length +
03718 " stack=" +
03719 tradeInCmdStack.length +
03720 " " + firstColonCommand +
03721 " " + lastColonCommand);
03722
03723 if(i >= 0)
03724 newText += text[i];
03725 newText += nextTabStr + nextInCmdTabStr + nextIsCmdTabStr;
03726
03727 newText += text.substr(i+1,n-(i+1)).trimLeft();
03728
03729
03730
03731 if(lastChar == '{')
03732 {
03733 tabStr += '\t';
03734 isCmdTabStr = "";
03735
03736 if(inCmdTabStr.length)
03737 {
03738 tabStr += '\t';
03739
03740 tradeInCmdStack.push([tabStr.length,inCmdTabStr]);
03741 tradeIsCmdStack.push(isCmdTabStr);
03742
03743 inCmdTabStr = "";
03744 isCmdTabStr = "";
03745 }
03746 }
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757 nextInCmdTabStr = inCmdTabStr;
03758 nextIsCmdTabStr = isCmdTabStr;
03759
03760 if(lastChar != '')
03761 prevLastChar = lastChar;
03762 if(firstChar != '')
03763 prevFirstChar = firstChar;
03764
03765 i = n;
03766
03767 } while(i+1<text.length);
03768
03769
03770
03771 if(text[i] == '\n') newText += '\n';
03772
03773
03774 }
03775 else
03776 {
03777 Debug.log("Unknown operation to auto-indent file with extension " +
03778 fileExtension,Debug.HIGH_PRIORITY);
03779 return;
03780 }
03781
03782
03783 el.textContent = preText + newText + postText;
03784
03785 _fileWasModified[forPrimary] = true;
03786
03787 CodeEditor.editor.updateDecorations(forPrimary,
03788 false ,
03789 true );
03790
03791 }
03792 }
03793
03794
03795
03796 this.updateDualView = function(forPrimary)
03797 {
03798 forPrimary = forPrimary?1:0;
03799
03800 Debug.log("updateDualView " + forPrimary);
03801
03802
03803
03804 if(_filePath[0] == _filePath[1] &&
03805 _fileExtension[0] == _fileExtension[1])
03806 {
03807 var val,node, newNode;
03808 var el = _eel[forPrimary];
03809
03810 Debug.log("Update dual view");
03811
03812 _fileLastSave[(!forPrimary)?1:0] = _fileLastSave[forPrimary];
03813 _fileWasModified[(!forPrimary)?1:0] = _fileWasModified[forPrimary];
03814 CodeEditor.editor.updateLastSave(!forPrimary);
03815
03816
03817
03818 var elAlt = _eel[(!forPrimary)?1:0];
03819 elAlt.innerHTML = "";
03820 for(i=0;i<el.childNodes.length;++i)
03821 {
03822 node = el.childNodes[i];
03823 val = node.textContent;
03824 if(node.nodeName == "LABEL")
03825 {
03826 newNode = document.createElement("label");
03827 newNode.style.fontWeight = node.style.fontWeight;
03828 newNode.style.color = node.style.color;
03829 newNode.textContent = val;
03830 }
03831 else if(node.nodeName == "#text")
03832 {
03833 newNode = document.createTextNode(val);
03834 }
03835 else
03836 Debug.log("Skipping unknown node " + node.nodeName);
03837 elAlt.appendChild(newNode);
03838 }
03839 }
03840
03841 }
03842
03843
03844
03845
03846 this.updateOutline = function(forPrimary,elTextObj)
03847 {
03848 forPrimary = forPrimary?1:0;
03849
03850 Debug.log("updateOutline " + forPrimary);
03851
03852 var starti;
03853 var endi;
03854 var strLength;
03855 var str;
03856 var endPi, startCi;
03857 var newLinei;
03858 var localNewLineCount;
03859
03860 var newLineCount = 0;
03861 var outline = [];
03862 outline.push([1,"Top"]);
03863 var i,j,k;
03864 var fail, found;
03865
03866 var isCcSource = _fileExtension[forPrimary][0] == 'c' ||
03867 _fileExtension[forPrimary][0] == 'C';
03868 var isJsSource = _fileExtension[forPrimary] == "js" ||
03869 _fileExtension[forPrimary] == "html";
03870
03871 var indicatorIndex = 0;
03872 var indicator = "";
03873 if(isCcSource) indicator = "::";
03874 if(isJsSource) indicator = "function";
03875
03876 for(i=0;i<elTextObj.text.length;++i)
03877 {
03878 if(elTextObj.text[i] == '\n')
03879 {
03880 ++newLineCount;
03881 indicatorIndex = 0;
03882 continue;
03883 }
03884
03885
03886 if(elTextObj.text[i] == indicator[indicatorIndex])
03887 {
03888 ++indicatorIndex;
03889 if(indicatorIndex == indicator.length)
03890 {
03891
03892
03893
03894
03895 if(isCcSource)
03896 str = localHandleCcOutline();
03897 else if(isJsSource)
03898 str = localHandleJsOutline();
03899
03900 if(str)
03901 {
03902
03903 outline.push([newLineCount+1,
03904 str +
03905 "()"]);
03906 }
03907 }
03908 }
03909 else
03910 indicatorIndex = 0;
03911
03912 }
03913
03914 ++newLineCount;
03915
03916 Debug.log("Number of lines " + newLineCount);
03917 console.log("Done with outline", outline);
03918
03919
03920 str = "";
03921 for(i=0;i<newLineCount;++i)
03922 {
03923 str += "<a name='" + forPrimary + "L" + (i+1) + "'></a>";
03924 str += (i+1);
03925 str += "<br>";
03926 }
03927 document.getElementById("editableBoxLeftMargin" + forPrimary).innerHTML = str;
03928
03929 _numberOfLines[forPrimary] = newLineCount;
03930
03931
03932 if(!isCcSource && !isJsSource)
03933 {
03934
03935 i = (newLineCount/2)|0;
03936 if(i > 40)
03937 {
03938 outline.push([i,"Middle"]);
03939 }
03940 }
03941 outline.push([newLineCount,"Bottom"]);
03942
03943 var text;
03944
03945 str = "";
03946 str += "<center>";
03947 str += "<table><td>"
03948 str += "Outline: ";
03949 str += "</td><td>";
03950 str += htmlOpen("select",
03951 {
03952 "class":"textEditorOutlineSelect",
03953 "id":"textEditorOutlineSelect" + forPrimary,
03954 "style":"text-align-last: center; width: 100%;",
03955 "title":"Jump to a section of code.",
03956 "onchange":
03957 "CodeEditor.editor.handleOutlineSelect(" + forPrimary + ");",
03958 "onclick":
03959 "CodeEditor.editor.stopUpdateHandling(event);",
03960 },0 , false );
03961 str += "<option value='0'>Jump to a Line Number (Ctrl + L)</option>";
03962
03963 found = false;
03964 for(i=0;i<outline.length;++i)
03965 {
03966 str += "<option value='" + (outline[i][0]-2) + "'>";
03967 text = "#" + outline[i][0];
03968 str += text;
03969
03970
03971 found = (outline[i][1].indexOf("local") == 0);
03972
03973 for(j=text.length;j<(found?20:12);++j)
03974 str += " ";
03975 str += outline[i][1];
03976 str += "</option>";
03977 }
03978 str += "</select>";
03979 str += "</td></table>";
03980 str += "</center>";
03981 try
03982 {
03983 document.getElementById("textEditorOutline" + forPrimary).innerHTML = str;
03984 }
03985 catch(e)
03986 {
03987 Debug.log("Ignoring missing outline element. Assuming header not shown.");
03988 return;
03989 }
03990
03992
03993 function localHandleCcOutline()
03994 {
03995 if(startCi && i < startCi)
03996 return undefined;
03997
03998 starti = i-1;
03999
04000 endi = -1;
04001 startCi = -1;
04002 endPi = -1;
04003
04004
04005
04006
04007
04008
04009 for(j=i+2;j<elTextObj.text.length;++j)
04010 {
04011 if(elTextObj.text[j] == ';' ||
04012 elTextObj.text[j] == '+' ||
04013 elTextObj.text[j] == '"' ||
04014 elTextObj.text[j] == "'")
04015 return undefined;
04016 if(endi < 0)
04017 {
04018 if(elTextObj.text[j] == '(')
04019 endi = j++;
04020 }
04021 else if(startCi < 0)
04022 {
04023 if(elTextObj.text[j] == '{')
04024 {
04025 startCi = j--;
04026 break;
04027 }
04028 }
04029 }
04030
04031
04032
04033 if(endi < 0 || startCi < 0)
04034 {
04035 return undefined;
04036 }
04037
04038
04039
04040 for(j;j>endi;--j)
04041 {
04042 if(elTextObj.text[j] == ')')
04043 {
04044 endPi = j;
04045 break;
04046 }
04047 }
04048
04049 if(endPi < 0)
04050 {
04051 return undefined;
04052 }
04053
04054
04055
04056 return elTextObj.text.substr(starti+2,endi-starti-2).replace(/\s+/g,'');
04057
04058 }
04059
04061
04062 function localHandleJsOutline()
04063 {
04064 if(elTextObj.text[i + 1] == '(')
04065 {
04066
04067
04068 found = false;
04069
04070
04071 for(j=i-1-("function").length;j>=0;--j)
04072 {
04073 if(elTextObj.text[j] == '=')
04074 {
04075
04076 found = true;
04077 k = j;
04078 }
04079 else if(!(elTextObj.text[j] == ' ' || elTextObj.text[j] == '\t' ||
04080 (elTextObj.text[j] == '=' && !found)))
04081 break;
04082 }
04083
04084 if(found)
04085 {
04086
04087 for(j;j>=0;--j)
04088 {
04089 if(elTextObj.text[j] == ' ' || elTextObj.text[j] == '\t' ||
04090 elTextObj.text[j] == '\n')
04091 {
04092
04093 return elTextObj.text.substr(j+1,k-j-1).trim();
04094 }
04095 }
04096 }
04097 }
04098 else
04099 {
04100
04101
04102
04103 for(j=i+2;j<elTextObj.text.length;++j)
04104 {
04105 if(elTextObj.text[j] == '\n')
04106 break;
04107 else if(elTextObj.text[j] == '(')
04108 {
04109
04110 return elTextObj.text.substr(i+2,j-(i+2)).trim();
04111 }
04112 }
04113 }
04114
04115 return undefined;
04116 }
04117
04118 }
04119
04120
04121
04122 this.handleOutlineSelect = function(forPrimary)
04123 {
04124 forPrimary = forPrimary?1:0;
04125
04126 Debug.log("handleOutlineSelect() " + forPrimary);
04127
04128 var val = document.getElementById("textEditorOutlineSelect" + forPrimary).value | 0;
04129 if(val < 1) val = 1;
04130 console.log("line val",val);
04131
04132 CodeEditor.editor.gotoLine(forPrimary,val,
04133 undefined ,
04134 true );
04135
04136 }
04137
04138
04139
04140 var TABKEY = 9;
04141 this.keyDownHandler = function(e,forPrimary,shortcutsOnly)
04142 {
04143 forPrimary = forPrimary?1:0;
04144
04145 var keyCode = e.keyCode;
04146
04147 CodeEditor.editor.stopUpdateHandling();
04148
04149
04150 if(keyCode == 16 )
04151 return;
04152
04153
04154 if(_commandKeyDown)
04155 return;
04156
04157 var c = e.key;
04158
04159
04160
04161
04162 CodeEditor.editor.startUpdateHandling(forPrimary);
04163
04164 var el = _eel[forPrimary];
04165 var cursor;
04166 var cursorSelection = false;
04167
04168
04169
04170 if(!shortcutsOnly)
04171 {
04172 cursor = CodeEditor.editor.getCursor(el);
04173
04174 cursorSelection = (cursor.startNodeIndex !== undefined &&
04175 (cursor.startNodeIndex != cursor.endNodeIndex ||
04176 cursor.startPos != cursor.endPos));
04177
04178 if(!cursorSelection)
04179 _lastPageUpDownLine = -1;
04180
04182 function localInsertCharacter(c)
04183 {
04184 Debug.log("Inserting character... " + c);
04185
04186 var node,val;
04187 var found;
04188
04189
04190
04191
04192
04193
04194
04195
04196
04197 if(cursor.endNodeIndex > cursor.startNodeIndex)
04198 {
04199
04200 val = el.childNodes[cursor.endNodeIndex].textContent;
04201 val = val.substr(cursor.endPos);
04202 el.childNodes[cursor.endNodeIndex].textContent = val;
04203 --cursor.endNodeIndex;
04204 while(cursor.endNodeIndex > cursor.startNodeIndex)
04205 {
04206
04207 el.removeChild(el.childNodes[cursor.endNodeIndex]);
04208 --cursor.endNodeIndex;
04209 }
04210
04211 cursor.endPos = el.childNodes[cursor.startNodeIndex].textContent.length;
04212 }
04213
04214 var whiteSpaceString = "";
04215 var postWhiteSpaceString = "";
04216 var text = el.childNodes[cursor.startNodeIndex].textContent;
04217 var preCharString = text.substr(0,cursor.startPos);
04218 var cursorPosDelta = 0;
04219
04220 if(c == '\n')
04221 {
04222
04223
04224
04225 var firstChar = '';
04226
04227
04228 found = false;
04229 for(n=cursor.startNodeIndex;n>=0; --n)
04230 {
04231 node = el.childNodes[n];
04232 val = node.textContent;
04233
04234 for(i=(n==cursor.startNodeIndex?cursor.startPos-1:
04235 val.length-1); i>=0; --i)
04236 {
04237 if(val[i] == '\n')
04238 {
04239
04240 found = true;
04241 break;
04242 }
04243 else if(firstChar == '' &&
04244 val[i] != '\t' && val[i] != ' ')
04245 firstChar = val[i];
04246 }
04247 if(found) break;
04248 }
04249
04250
04251 console.log("at leading newline - n",n,"i",i,"firstChar",firstChar);
04252 if(n < 0) n = 0;
04253 if(i < 0) i = 0;
04254 else ++i;
04255
04256
04257 found = false;
04258 for(n; n<el.childNodes.length; ++n)
04259 {
04260 node = el.childNodes[n];
04261 val = node.textContent;
04262
04263 for(i;i<val.length;++i)
04264 {
04265
04266 if((val[i] != '\t' && val[i] != ' ') ||
04267 (n == cursor.startNodeIndex &&
04268 i >= cursor.startPos))
04269 {
04270 found = true;
04271 break;
04272 }
04273
04274 whiteSpaceString += val[i];
04275 }
04276
04277 if(found || n == cursor.startNodeIndex) break;
04278
04279 i = 0;
04280 }
04281
04282 if(firstChar == '{')
04283 {
04284 postWhiteSpaceString += "\n" + whiteSpaceString + "}";
04285 whiteSpaceString += '\t';
04286 postWhiteSpaceString += text.substr(cursor.endPos);
04287 }
04288 else
04289 {
04290 val = text.substr(cursor.endPos);
04291 i = val.indexOf('\n');
04292 if(i >= 0)
04293 {
04294
04295 postWhiteSpaceString += val.substr(0,
04296 i).trimLeft();
04297 postWhiteSpaceString += val.substr(i);
04298 }
04299 else
04300 postWhiteSpaceString += val.trimLeft();
04301 }
04302
04303 }
04304 else if(c == '}')
04305 {
04306
04307
04308
04309
04310 var openCount = 1;
04311 var foundFirstNewLine = false;
04312
04313
04314 found = false;
04315 for(n=cursor.startNodeIndex;n>=0; --n)
04316 {
04317 node = el.childNodes[n];
04318 val = node.textContent;
04319
04320 for(i=(n==cursor.startNodeIndex?cursor.startPos-1:
04321 val.length-1); i>=0; --i)
04322 {
04323 if(val[i] == '{')
04324 {
04325
04326 --openCount;
04327
04328 if(openCount == 0)
04329 {
04330 Debug.log("Found matching bracket n=" + n +
04331 " i=" + i);
04332 found = true;
04333 break;
04334 }
04335
04336 }
04337 else if(val[i] == '}')
04338 ++openCount;
04339 else if(!foundFirstNewLine &&
04340 val[i] == '\n')
04341 {
04342 foundFirstNewLine = true;
04343
04344 Debug.log("pre-deleted white space preCharString=" +
04345 preCharString.length + " " + preCharString);
04346
04347
04348 var nn = n;
04349 var ii = i+1;
04350 for(nn;nn<el.childNodes.length;++nn)
04351 {
04352 if(nn < cursor.startNodeIndex)
04353 {
04354
04355 el.childNodes[nn].textContent = "";
04356 }
04357 else if(nn == cursor.startNodeIndex)
04358 {
04359
04360 preCharString = el.childNodes[nn].textContent.substr(
04361 0,ii);
04362 break;
04363 }
04364 ii = 0;
04365 }
04366
04367 Debug.log("deleted white space preCharString=" +
04368 preCharString.length + " " + preCharString);
04369 }
04370 else if(!foundFirstNewLine && val[i] != ' ' &&
04371 val[i] != '\t')
04372 {
04373 Debug.log("Found character between } and new line, so doing nothing.");
04374 return false;
04375 }
04376 }
04377 if(found) break;
04378 }
04379
04380
04381
04382 console.log("at closing bracket - n",n,"i",i);
04383
04384 if(n < 0 || i < 0)
04385 preCharString = preCharString.trimRight();
04386 else
04387 {
04388
04389 var matchingWhiteSpace = "";
04390 found = false;
04391 var firstTime = true;
04392
04393 for(n;n>=0; --n)
04394 {
04395 node = el.childNodes[n];
04396 val = node.textContent;
04397
04398 for(i=(firstTime?i:
04399 val.length-1); i>=0; --i)
04400 {
04401 if(val[i] == '\n')
04402 {
04403
04404 found = true;
04405 break;
04406 }
04407 else if(val[i] == ' ' ||
04408 val[i] == '\t')
04409 matchingWhiteSpace += val[i];
04410 else
04411 matchingWhiteSpace = "";
04412 }
04413 if(found) break;
04414
04415 firstTime = false;
04416 }
04417 }
04418
04419
04420 preCharString += matchingWhiteSpace;
04421 Debug.log("matching white space preCharString=" +
04422 preCharString.length + " " + preCharString);
04423
04424 postWhiteSpaceString += text.substr(cursor.endPos);
04425
04426 }
04427 else
04428 postWhiteSpaceString += text.substr(cursor.endPos);
04429
04430 val = preCharString + c +
04431 whiteSpaceString +
04432 postWhiteSpaceString;
04433
04434 el.childNodes[cursor.startNodeIndex].textContent = val;
04435
04436
04437 console.log("cursorPosDelta",cursorPosDelta);
04438
04439 cursor.startPos = c.length + preCharString.length + whiteSpaceString.length;
04440 cursor.endNodeIndex = cursor.startNodeIndex;
04441 cursor.endPos = cursor.startPos;
04442
04443 console.log("cursor after newline",cursor);
04444
04445 CodeEditor.editor.setCursor(el,cursor,true );
04446
04447 _fileWasModified[forPrimary] = true;
04448
04449 return true;
04450 }
04451
04452 if(keyCode == 13)
04453 {
04454
04455
04456
04457
04458
04459
04460
04461
04462 localInsertCharacter('\n');
04463 e.preventDefault();
04464
04465
04466 return;
04467 }
04468 else if(keyCode == 36)
04469 {
04470
04471 e.preventDefault();
04472
04473
04474
04475
04476
04477
04478
04479 var i,n,node,val;
04480 var found = false;
04481
04482 var lastNonWhitespacePos = cursor.startPos;
04483 var lastNonWhitespaceNodeIndex = cursor.startNodeIndex;
04484 var lastPos = cursor.startPos;
04485 var lastNodeIndex = cursor.startNodeIndex;
04486
04487
04488 for(n=cursor.startNodeIndex; n>=0; --n)
04489 {
04490 node = el.childNodes[n];
04491 val = node.textContent;
04492
04493 for(i=(n==cursor.startNodeIndex?
04494 cursor.startPos-1:val.length-1);i>=0;--i)
04495 {
04496 if(val[i] == '\n')
04497 {
04498 found = true;
04499 break;
04500 }
04501 else if(!(val[i] == ' ' ||
04502 val[i] == '\t'))
04503 {
04504 lastNonWhitespacePos = i;
04505 lastNonWhitespaceNodeIndex = n;
04506 }
04507
04508 lastPos = i;
04509 lastNodeIndex = n;
04510 }
04511 if(found) break;
04512 }
04513 console.log("lastNonWhitespacePos",lastNonWhitespacePos);
04514 console.log("lastNonWhitespaceNodeIndex",lastNonWhitespaceNodeIndex);
04515
04516 if(lastNonWhitespacePos == cursor.startPos &&
04517 lastNonWhitespaceNodeIndex == cursor.startNodeIndex)
04518 {
04519
04520 lastNonWhitespacePos = lastPos;
04521 lastNonWhitespaceNodeIndex = lastNodeIndex;
04522 }
04523
04524
04525 if(lastNonWhitespacePos == lastPos &&
04526 lastNonWhitespaceNodeIndex == lastNodeIndex)
04527 document.getElementById("textEditorBody" + forPrimary).scrollLeft = 0;
04528
04529 cursor.startNodeIndex = lastNonWhitespaceNodeIndex
04530 cursor.startPos = lastNonWhitespacePos;
04531
04532 if(!e.shiftKey)
04533 {
04534 cursor.endNodeIndex = cursor.startNodeIndex;
04535 cursor.endPos = cursor.startPos;
04536 }
04537
04538
04539 CodeEditor.editor.setCursor(el,cursor,true );
04540
04541 return;
04542 }
04543 else if(keyCode == 35)
04544 {
04545
04546
04547 e.preventDefault();
04548
04549
04550
04551
04552
04553
04554
04555
04556 var i,n,node,val;
04557 var found = false;
04558
04559 var wantNext = false;
04560 var lastNonWhitespacePos = cursor.startPos;
04561 var lastNonWhitespaceNodeIndex = cursor.startNodeIndex;
04562
04563
04564 for(n=cursor.startNodeIndex; n<el.childNodes.length; ++n)
04565 {
04566 node = el.childNodes[n];
04567 val = node.textContent;
04568
04569 for(i=(n==cursor.startNodeIndex?
04570 cursor.startPos:0);i<val.length;++i)
04571 {
04572 if(wantNext)
04573 {
04574 lastNonWhitespacePos = i;
04575 lastNonWhitespaceNodeIndex = n;
04576 }
04577
04578 if(val[i] == '\n')
04579 {
04580 found = true;
04581 break;
04582 }
04583 else if(!(val[i] == ' ' ||
04584 val[i] == '\t'))
04585 wantNext = true;
04586 else
04587 wantNext = false;
04588 }
04589 if(found) break;
04590 }
04591 console.log("lastNonWhitespacePos",lastNonWhitespacePos);
04592 console.log("lastNonWhitespaceNodeIndex",lastNonWhitespaceNodeIndex);
04593
04594 if(lastNonWhitespacePos == cursor.startPos &&
04595 lastNonWhitespaceNodeIndex == cursor.startNodeIndex)
04596 {
04597
04598 lastNonWhitespacePos = i;
04599 lastNonWhitespaceNodeIndex = n;
04600 }
04601
04602 cursor.endNodeIndex = lastNonWhitespaceNodeIndex
04603 cursor.endPos = lastNonWhitespacePos;
04604
04605 if(!e.shiftKey)
04606 {
04607 cursor.startNodeIndex = cursor.endNodeIndex;
04608 cursor.startPos = cursor.endPos;
04609 }
04610
04611
04612 CodeEditor.editor.setCursor(el,cursor,true );
04613 return;
04614 }
04615 }
04616
04617
04618
04619 if(keyCode == 33)
04620 {
04621
04622 e.preventDefault();
04623 e.stopPropagation();
04624
04625
04626
04627
04628
04629
04630 var N = 50;
04631
04632 var gotoLineCursor = {};
04633
04634
04635 if(_lastPageUpDownLine == -1)
04636 {
04637 var cursorWithLine = CodeEditor.editor.getLine(forPrimary);
04638
04639 _startPageUpDownNodeIndex = cursorWithLine.startNodeIndex;
04640 _startPageUpDownPos = cursorWithLine.startPos;
04641
04642 _startPageUpDownLine = cursorWithLine.line;
04643 _lastPageUpDownLine = _startPageUpDownLine;
04644 }
04645
04646 gotoLineCursor.startNodeIndex = _startPageUpDownNodeIndex;
04647 gotoLineCursor.startPos = _startPageUpDownPos;
04648
04649
04650 _lastPageUpDownLine -= N;
04651 gotoLineCursor.focusAtEnd = (_lastPageUpDownLine > _startPageUpDownLine);
04652
04653 Debug.log("Page up to line " + _lastPageUpDownLine + " dir=" +
04654 gotoLineCursor.focusAtEnd);
04655
04656 _lastPageUpDownLine = CodeEditor.editor.gotoLine(forPrimary,_lastPageUpDownLine,
04657 e.shiftKey?gotoLineCursor:undefined);
04658
04659 return;
04660 }
04661 else if(keyCode == 34)
04662 {
04663
04664 e.preventDefault();
04665 e.stopPropagation();
04666
04667
04668
04669
04670
04671
04672 var N = 50;
04673
04674 var gotoLineCursor = {};
04675
04676
04677 if(_lastPageUpDownLine == -1)
04678 {
04679 var cursorWithLine = CodeEditor.editor.getLine(forPrimary);
04680
04681 _startPageUpDownNodeIndex = cursorWithLine.startNodeIndex;
04682 _startPageUpDownPos = cursorWithLine.startPos;
04683
04684 _startPageUpDownLine = cursorWithLine.line;
04685 _lastPageUpDownLine = _startPageUpDownLine;
04686 }
04687
04688 gotoLineCursor.startNodeIndex = _startPageUpDownNodeIndex;
04689 gotoLineCursor.startPos = _startPageUpDownPos;
04690
04691
04692 _lastPageUpDownLine += N;
04693 gotoLineCursor.focusAtEnd = (_lastPageUpDownLine > _startPageUpDownLine);
04694
04695 Debug.log("Page down to line " + _lastPageUpDownLine + " dir=" +
04696 gotoLineCursor.focusAtEnd);
04697
04698 _lastPageUpDownLine = CodeEditor.editor.gotoLine(forPrimary,_lastPageUpDownLine,
04699 e.shiftKey?gotoLineCursor:undefined);
04700
04701 return;
04702 }
04703 else if(keyCode == 13)
04704 {
04705
04706
04707
04708
04709 if(CodeEditor.editor.findAndReplaceLastButton[forPrimary] > 0)
04710 {
04711 e.preventDefault();
04712 e.stopPropagation();
04713
04714 Debug.log("Launch find and replace action " +
04715 CodeEditor.editor.findAndReplaceLastButton[forPrimary]);
04716 CodeEditor.editor.doFindAndReplaceAction(forPrimary,
04717 CodeEditor.editor.findAndReplaceLastButton[forPrimary]);
04718 return;
04719 }
04720 }
04721 else if(keyCode == 27)
04722 {
04723
04724
04725
04726
04727 if(CodeEditor.editor.findAndReplaceLastButton[forPrimary] > 0)
04728 {
04729 e.preventDefault();
04730 e.stopPropagation();
04731
04732
04733 CodeEditor.editor.displayFileHeader(forPrimary);
04734 return;
04735 }
04736 }
04737
04738
04739
04740
04741
04742 if(e.ctrlKey)
04743 {
04744 if(keyCode == 83)
04745 {
04746 CodeEditor.editor.saveFile(forPrimary,true );
04747 e.preventDefault();
04748 return;
04749 }
04750 else if(keyCode == 68)
04751 {
04752 CodeEditor.editor.toggleDirectoryNav(forPrimary);
04753 e.preventDefault();
04754 return;
04755 }
04756 else if(keyCode == 66)
04757 {
04758 CodeEditor.editor.build();
04759 e.preventDefault();
04760 return;
04761 }
04762 else if(keyCode == 70)
04763 {
04764 CodeEditor.editor.showFindAndReplace(forPrimary);
04765 e.preventDefault();
04766 return;
04767 }
04768 else if(keyCode == 73)
04769 {
04770 CodeEditor.editor.autoIndent(forPrimary, cursor);
04771 e.preventDefault();
04772 return;
04773 }
04774 else if(keyCode == 78)
04775 {
04776 CodeEditor.editor.build(true );
04777 e.preventDefault();
04778 return;
04779 }
04780 else if(keyCode == 48)
04781 {
04782 CodeEditor.editor.openFile(forPrimary,
04783 _filePath[forPrimary],
04784 _fileExtension[forPrimary],
04785 true );
04786 e.preventDefault();
04787 return;
04788 }
04789 else if(keyCode == 50)
04790 {
04791 CodeEditor.editor.toggleView();
04792 e.preventDefault();
04793 return;
04794 }
04795 else if(keyCode == 85)
04796 {
04797 CodeEditor.editor.undo(forPrimary, e.shiftKey );
04798 e.preventDefault();
04799 return;
04800 }
04801 else if(keyCode == 76 ||
04802 keyCode == 71)
04803 {
04804 DesktopContent.popUpVerification(
04805 "Goto line number: ",
04806
04807 function(line)
04808 {
04809 Debug.log("Going to line... " + line);
04810 CodeEditor.editor.gotoLine(forPrimary,line);
04811 }, undefined,
04812 undefined,
04813 undefined,
04814 undefined,
04815 true,
04816 undefined,
04817 undefined,
04818 "Go");
04819
04820 e.preventDefault();
04821 return;
04822 }
04823 else if(keyCode == 49)
04824 {
04825 CodeEditor.editor.openRelatedFile(forPrimary);
04826 e.preventDefault();
04827 return;
04828 }
04829
04830 }
04831 if(shortcutsOnly)
04832 return;
04833
04834
04835
04836 var rectangularTAB = false;
04837 var blockCOMMENT = false;
04838
04839
04840
04841
04842 if(e.ctrlKey)
04843 {
04844
04845 if(keyCode == 84 ||
04846 keyCode == 89)
04847 {
04848 rectangularTAB = true;
04849 e.preventDefault();
04850
04851 }
04852 else if(keyCode == 191)
04853 {
04854 blockCOMMENT = true;
04855 e.preventDefault();
04856
04857 }
04858 else
04859 return;
04860 }
04861
04862
04863
04864
04865 if(keyCode == TABKEY || rectangularTAB ||
04866 blockCOMMENT)
04867 {
04868 _fileWasModified[forPrimary] = true;
04869 CodeEditor.editor.updateLastSave(forPrimary);
04870 e.preventDefault();
04871
04872
04873
04874
04875
04876 var i,j,k;
04877
04878 if(cursorSelection)
04879 {
04880
04881 Debug.log("special key selected lines " + cursor.startNodeIndex + " - " +
04882 cursor.endNodeIndex);
04883
04884
04886
04887 if(rectangularTAB)
04888 {
04889 Debug.log("Rectangular TAB");
04890
04891
04892
04893
04894
04895
04896
04897
04898
04899 var node,val;
04900 var found = false;
04901 var x = 0;
04902
04903
04904 for(n=cursor.startNodeIndex;n>=0; --n)
04905 {
04906 node = el.childNodes[n];
04907 val = node.textContent;
04908
04909 for(i=(n==cursor.startNodeIndex?cursor.startPos-1:
04910 val.length-1); i>=0; --i)
04911 {
04912 if(val[i] == '\n')
04913 {
04914
04915 found = true;
04916 break;
04917 }
04918 }
04919 if(found) break;
04920 }
04921
04922 console.log("at leading newline - n",n,"i",i);
04923
04924
04925 found = false;
04926 for(n; n<el.childNodes.length; ++n)
04927 {
04928 node = el.childNodes[n];
04929 val = node.textContent;
04930
04931 for(i;i<val.length;++i)
04932 {
04933
04934 if(n == cursor.startNodeIndex &&
04935 i == cursor.startPos)
04936 {
04937 found = true;
04938
04939
04940 var prelength = val.length;
04941
04942 if(e.shiftKey)
04943 {
04944 if(i-1 >= 0 && val[i-1] == '\t')
04945 node.textContent = val.substr(0,i-1) + val.substr(i);
04946 }
04947 else
04948 {
04949 node.textContent = val.substr(0,i) + "\t" + val.substr(i);
04950
04951 }
04952
04953
04954
04955 cursor.startPos += node.textContent.length - prelength;
04956 break;
04957 }
04958
04959
04960 if(val[i] == '\t')
04961 x += _TAB_SIZE - (x+_TAB_SIZE)%_TAB_SIZE;
04962 else
04963 ++x;
04964 }
04965
04966 if(found) break;
04967
04968 i = 0;
04969 }
04970
04971 console.log("x",x);
04972
04973
04974
04975
04976 var xcnt = -1;
04977 for(n=cursor.startNodeIndex; n<el.childNodes.length; ++n)
04978 {
04979 node = el.childNodes[n];
04980 val = node.textContent;
04981
04982 for(i=(n==cursor.startNodeIndex?cursor.startPos:
04983 0);i<val.length;++i)
04984 {
04985
04986 if(val[i] == '\n')
04987 {
04988
04989 xcnt = 0;
04990 }
04991 else if(xcnt == x)
04992 {
04993
04994 xcnt = -1;
04995
04996 if(e.shiftKey)
04997 {
04998 if(i-1 < val.length && val[i-1] == '\t')
04999 {
05000 val = val.substr(0,i-1) + val.substr(i);
05001 node.textContent = val;
05002 }
05003 }
05004 else
05005 {
05006 val = val.substr(0,i) + "\t" + val.substr(i);
05007 node.textContent = val;
05008 }
05009
05010 }
05011 else if(xcnt != -1)
05012 {
05013 if(val[i] == '\t')
05014 xcnt += _TAB_SIZE - (xcnt+_TAB_SIZE)%_TAB_SIZE;
05015 else
05016 ++xcnt;
05017 }
05018 }
05019
05020 if(n == cursor.endNodeIndex)
05021 break;
05022 }
05023
05024
05025
05026
05027 CodeEditor.editor.setCursor(el,cursor,true );
05028
05029
05030
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052
05053
05054
05055
05056 return;
05057 }
05058
05059
05060
05061
05062
05064
05065
05066
05067
05068
05069
05070 var node,val;
05071 var found = false;
05072 var specialStr = '\t';
05073 if(blockCOMMENT)
05074 {
05075 if(_fileExtension[forPrimary][0] == 'c' ||
05076 _fileExtension[forPrimary][0] == 'C' ||
05077 _fileExtension[forPrimary][0] == 'h' ||
05078 _fileExtension[forPrimary][0] == 'H' ||
05079 _fileExtension[forPrimary][0] == 'j')
05080 specialStr = "//";
05081 else
05082 specialStr = "#";
05083 }
05084
05085 for(n=cursor.startNodeIndex; n>=0; --n)
05086 {
05087 node = el.childNodes[n];
05088 val = node.textContent;
05089
05090 for(i=(n==cursor.startNodeIndex?cursor.startPos-1:
05091 val.length-1); i>=0; --i)
05092 {
05093 if(val[i] == '\n')
05094 {
05095
05096 found = true;
05097 break;
05098 }
05099
05100 }
05101
05102 if(found) break;
05103 }
05104
05105
05106 found = false;
05107 var prevCharIsNewLine = false;
05108 var lookForNewLineIndex;
05109
05110 for(; n<el.childNodes.length &&
05111 n <= cursor.endNodeIndex; ++n)
05112 {
05113 node = el.childNodes[n];
05114 val = node.textContent;
05115
05116 lookForNewLineIndex = 0;
05117 for(;i<val.length;++i)
05118 {
05119 if(n == cursor.endNodeIndex && i >= cursor.endPos)
05120 {
05121
05122 found = true;
05123 break;
05124 }
05125
05126 if(val[i] == '\n' ||
05127 (i == 0 && prevCharIsNewLine))
05128 {
05129 if(i == 0 && prevCharIsNewLine) --i;
05130
05131 if(e.shiftKey)
05132 {
05133 var didDelete = false;
05134 if(i + specialStr.length < val.length &&
05135 (
05136
05137
05138 (j=val.indexOf(specialStr,i+1)) == i+1 ||
05139 (
05140 (
05141 (k=val.indexOf('\n',i+1)) < 0 ||
05142 k > j
05143 ) &&
05144 (
05145 j >= 0 &&
05146 val.substr(i+1,j-(i+1)).trim().length == 0
05147 )
05148 )
05149 )
05150 )
05151 {
05152 val = val.substr(0,j) +
05153 val.substr(j+specialStr.length);
05154 node.textContent = val;
05155 didDelete = true;
05156 lookForNewLineIndex = j+specialStr.length;
05157 }
05158 else if(specialStr == '\t')
05159 {
05160
05161 if((specialStr = " ") &&
05162 i + specialStr.length < val.length &&
05163 val.indexOf(specialStr,i+1) == i+1)
05164 {
05165 val = val.substr(0,i+1) +
05166 val.substr(i+1+specialStr.length);
05167 node.textContent = val;
05168 didDelete = true;
05169 }
05170 else if((specialStr = " ") &&
05171 i + specialStr.length < val.length &&
05172 val.indexOf(specialStr,i+1) == i+1)
05173 {
05174 val = val.substr(0,i+1) +
05175 val.substr(i+1+specialStr.length);
05176 node.textContent = val;
05177 didDelete = true;
05178 }
05179 else if((specialStr = " ") &&
05180 i + specialStr.length < val.length &&
05181 val.indexOf(specialStr,i+1) == i+1)
05182 {
05183 val = val.substr(0,i+1) +
05184 val.substr(i+1+specialStr.length);
05185 node.textContent = val;
05186 didDelete = true;
05187 }
05188 else if((specialStr = " ") &&
05189 i + specialStr.length < val.length &&
05190 val.indexOf(specialStr,i+1) == i+1)
05191 {
05192 val = val.substr(0,i+1) +
05193 val.substr(i+1+specialStr.length);
05194 node.textContent = val;
05195 didDelete = true;
05196 }
05197
05198 specialStr = '\t';
05199 }
05200
05201
05202 if(didDelete)
05203 {
05204
05205 if(n == cursor.startNodeIndex &&
05206 i < cursor.startPos)
05207 {
05208 cursor.startPos -= specialStr.length;
05209 }
05210 if(n == cursor.endNodeIndex &&
05211 i < cursor.endPos)
05212 {
05213 cursor.endPos -= specialStr.length;
05214 }
05215
05216
05217
05218 if(n == cursor.endNodeIndex &&
05219 cursor.endPos >= val.length)
05220 {
05221 ++cursor.endNodeIndex;
05222 cursor.endPos = 0;
05223 }
05224
05225
05226
05227
05228
05229
05230
05231
05232
05233
05234
05235 }
05236
05237 }
05238 else
05239 {
05240 val = val.substr(0,i+1) + specialStr + val.substr(i+1);
05241 node.textContent = val;
05242 }
05243
05244 if(i == -1 && prevCharIsNewLine) ++i;
05245 }
05246 }
05247 i = 0;
05248
05249 if(found) break;
05250
05251 if(e.shiftKey)
05252 {
05253
05254 j = val.lastIndexOf('\n');
05255 if(j >= lookForNewLineIndex &&
05256 (
05257 j == val[val.length-1] ||
05258 val.substr(j+1).trim().length == 0
05259 ))
05260 prevCharIsNewLine = true;
05261 else if(j < 0 && prevCharIsNewLine &&
05262 val.trim().length == 0)
05263 prevCharIsNewLine = true;
05264 else
05265 prevCharIsNewLine = false;
05266 }
05267 else
05268 prevCharIsNewLine = (val.length &&
05269 val[val.length-1] == '\n');
05270 }
05271
05272
05273 CodeEditor.editor.setCursor(el,cursor,true );
05274
05275
05276
05279
05280
05281
05282
05283
05284
05285
05286
05287
05288
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302 }
05303 else if(!blockCOMMENT)
05304 {
05305 if(e.shiftKey)
05306 {
05307 if(cursor.startNodeIndex !== undefined)
05308 {
05309 try
05310 {
05311 var node,val,i;
05312 i = cursor.startPos;
05313 node = el.childNodes[cursor.startNodeIndex];
05314 val = node.textContent;
05315
05316
05317
05318 if(val[i-1] == '\t')
05319 {
05320 node.textContent = val.substr(0,i-1) + val.substr(i);
05321
05322
05323 var range = document.createRange();
05324 range.setStart(node,i-1);
05325 range.setEnd(node,i-1);
05326
05327 var selection = window.getSelection();
05328 selection.removeAllRanges();
05329 selection.addRange(range);
05330 }
05331 }
05332 catch(err)
05333 {
05334 console.log(err);
05335 return;
05336 }
05337 }
05338 else
05339 Debug.log("No cursor for reverse tab.");
05340 }
05341 else
05342 document.execCommand('insertHTML', false, '	');
05343 }
05344
05345 return;
05346
05347 }
05348 else if(cursorSelection)
05349 {
05350 Debug.log("cursorSelection handling for speed-up");
05351
05352
05353
05354
05355
05356
05357
05358
05359
05360 console.log("cursorSelection char",keyCode,c);
05361
05362 if(e.key.length > 1)
05363 {
05364 if( keyCode != 46 &&
05365 keyCode != 8)
05366 return;
05367 c = '';
05368 }
05369
05370 e.preventDefault();
05371 e.stopPropagation();
05372 localInsertCharacter(c);
05373 }
05374 else
05375 {
05376 if(c == '}')
05377 {
05378 if(localInsertCharacter(c))
05379 {
05380
05381 e.preventDefault();
05382 e.stopPropagation();
05383 }
05384 }
05385 }
05386
05387 }
05388
05389
05390
05391
05392 this.updateLastSave = function(forPrimary)
05393 {
05394 forPrimary = forPrimary?1:0;
05395
05396 var el = document.getElementById("textEditorLastSave" + forPrimary);
05397 if(!el) return;
05398
05399 Debug.log("updateLastSave() forPrimary=" + forPrimary);
05400 var str = "";
05401 if(_fileWasModified[forPrimary])
05402 str += "<label style='color:red'>Unsaved changes!</label> ";
05403 else
05404 str += "Unmodified. ";
05405
05406 if(_fileLastSave[forPrimary])
05407 {
05408 var now = new Date();
05409 var d = new Date(_fileLastSave[forPrimary]);
05410 var tstr = d.toLocaleTimeString();
05411 tstr = tstr.substring(0,tstr.lastIndexOf(' ')) +
05412 (tstr[tstr.length-2]=='A'?"am":"pm");
05413
05414 var diff = ((now.getTime() - d.getTime())/1000)|0;
05415 var diffStr = "";
05416
05417 if(diff < 5)
05418 diffStr = "(just now) ";
05419 else if(diff < 10)
05420 diffStr = "(5 seconds ago) ";
05421 else if(diff < 20)
05422 diffStr = "(15 seconds ago) ";
05423 else if(diff < 40)
05424 diffStr = "(30 seconds ago) ";
05425 else if(diff < 50)
05426 diffStr = "(45 seconds ago) ";
05427 else if(diff < 120)
05428 diffStr = "(one minute ago) ";
05429 else if(diff < 15*60)
05430 diffStr = "(" + ((diff/60)|0) + " minutes ago) ";
05431 else if(diff < 20*60)
05432 diffStr = "(15 minutes ago) ";
05433 else if(diff < 40*60)
05434 diffStr = "(30 minutes ago) ";
05435 else if(diff < 50*60)
05436 diffStr = "(45 minutes ago) ";
05437 else if(diff < 90*60)
05438 diffStr = "(an hour ago) ";
05439 else
05440 diffStr = "(" + (Math.round(diff/60/60)) + " hours ago) ";
05441
05442
05443 str += "Last save was " + diffStr + tstr;
05444 }
05445 el.innerHTML = str;
05446 }
05447
05448
05449
05450 this.handleFileNameMouseMove = function(forPrimary,doNotStartTimer)
05451 {
05452 forPrimary = forPrimary?1:0;
05453
05454
05455
05456 if(_fileNameEditing[forPrimary]) return;
05457
05458 var el = document.getElementById("fileButtonContainerShowHide" + forPrimary);
05459 el.style.display = "block";
05460
05461 window.clearTimeout(_fileNameMouseMoveTimerHandle);
05462
05463 if(doNotStartTimer) return;
05464
05465 _fileNameMouseMoveTimerHandle = window.setTimeout(
05466 function()
05467 {
05468 el.style.display = "none";
05469 }
05470 ,1000);
05471
05472 }
05473
05474
05475
05476 this.startEditFileName = function(forPrimary)
05477 {
05478 forPrimary = forPrimary?1:0;
05479
05480 if(_fileNameEditing[forPrimary]) return;
05481 _fileNameEditing[forPrimary] = true;
05482
05483
05484 document.getElementById("fileButtonContainerShowHide" + forPrimary).style.display = "none";
05485
05486
05487 console.log("startEditFileName " + forPrimary);
05488
05489 var el = document.getElementById("fileNameDiv" + forPrimary);
05490
05491 var keys = Object.keys(_fileHistoryStack);
05492 var initVal = keys[document.getElementById("fileNameHistorySelect" +
05493 forPrimary).value|0].trim();
05494
05495 var _OK_CANCEL_DIALOG_STR = "";
05496
05497 _OK_CANCEL_DIALOG_STR += "<div title='' style='padding:5px;background-color:#eeeeee;border:1px solid #555555;position:relative;z-index:2000;" +
05498 "width:105px;height:20px;margin: 4px -122px -32px -120px; font-size: 16px; white-space:nowrap; text-align:center;'>";
05499 _OK_CANCEL_DIALOG_STR += "<a class='popUpOkCancel' onclick='" +
05500 "CodeEditor.editor.editCellOK(" + forPrimary +
05501 "); event.stopPropagation();' onmouseup='event.stopPropagation();' title='Accept Changes' style='color:green'>" +
05502 "<b style='color:green;font-size: 16px;'>OK</b></a> | " +
05503 "<a class='popUpOkCancel' onclick='" +
05504 "CodeEditor.editor.editCellCancel(" + forPrimary +
05505 "); event.stopPropagation();' onmouseup='event.stopPropagation();' title='Discard Changes' style='color:red'>" +
05506 "<b style='color:red;font-size: 16px;'>Cancel</b></a>";
05507 _OK_CANCEL_DIALOG_STR += "</div>";
05508
05509
05510 var str = "";
05511 str += htmlOpen("input",
05512 {
05513 "type":"text",
05514 "style":"text-align:center;margin:-4px -2px -4px -1px;width:90%;" +
05515 " height:" + (el.offsetHeight>20?el.offsetHeight:20) + "px",
05516 "value": initVal,
05517 "onclick":"event.stopPropagation();",
05518 },0 , true );
05519
05520
05521
05522
05523
05524
05525
05526 str += _OK_CANCEL_DIALOG_STR;
05527
05528 el.innerHTML = str;
05529
05530
05531 el = el.getElementsByTagName("input")[0];
05532 var startPos = initVal.lastIndexOf('/')+1;
05533 var endPos = initVal.lastIndexOf('.');
05534 if(endPos < 0) endPos = initVal.length;
05535 el.setSelectionRange(startPos, endPos);
05536 el.focus();
05537
05538 }
05539
05540
05541
05542 this.editCellOK = function(forPrimary)
05543 {
05544 forPrimary = forPrimary?1:0;
05545
05546 var val = document.getElementById("fileNameDiv" + forPrimary).getElementsByTagName("input")[0].value;
05547 console.log("editCellOK " + forPrimary + " = " + val);
05548 _fileNameEditing[forPrimary] = false;
05549
05550 var extPos = val.lastIndexOf('.');
05551
05552
05553
05554 _filePath[forPrimary] = val.substr(0,extPos);
05555 _fileExtension[forPrimary] = extPos > 0?val.substr(extPos+1):"";
05556
05557
05558
05559
05560
05561
05562
05563
05564
05565
05566
05567
05568
05569
05570 _fileWasModified[forPrimary] = true;
05571 _fileLastSave[forPrimary] = 0;
05572 CodeEditor.editor.updateLastSave(forPrimary);
05573
05574
05575
05576
05577
05578
05579
05580
05581
05582
05583 _fileHistoryStack[_filePath[forPrimary] + "." +
05584 _fileExtension[forPrimary]] = [
05585 _eel[forPrimary].textContent,
05586 Date.now(),
05587 _fileWasModified[forPrimary],
05588 _fileLastSave[forPrimary]];
05589 console.log("_fileHistoryStack",_fileHistoryStack);
05590
05591 CodeEditor.editor.updateFileHistoryDropdowns();
05592
05593 }
05594
05595
05596
05597 this.editCellCancel = function(forPrimary)
05598 {
05599 forPrimary = forPrimary?1:0;
05600
05601 Debug.log("editCellCancel " + forPrimary);
05602 _fileNameEditing[forPrimary] = false;
05603
05604
05605 CodeEditor.editor.updateFileHistoryDropdowns(forPrimary);
05606
05607 }
05608
05609
05610
05611
05612
05613
05614 this.updateFileHistoryDropdowns = function(forPrimarySelect)
05615 {
05616 Debug.log("updateFileHistoryDropdowns forPrimarySelect=" + forPrimarySelect);
05617
05618 var el;
05619 var str = "";
05620 var i;
05621
05622
05623 var keys = Object.keys(_fileHistoryStack);
05624
05625 var currentFile;
05626 for(var forPrimary=0;forPrimary<2;++forPrimary)
05627 {
05628 if(forPrimarySelect !== undefined &&
05629 forPrimarySelect != forPrimary) continue;
05630
05631 currentFile = _filePath[forPrimary] + "." + _fileExtension[forPrimary];
05632 str = "";
05633 str += htmlOpen("select",
05634 {
05635 "class":"fileNameHistorySelect",
05636 "id":"fileNameHistorySelect" + forPrimary,
05637 "style":"width:100%;" +
05638 "text-align-last: center;",
05639 "title":"The current file is\n" + currentFile,
05640 "onchange":
05641 "CodeEditor.editor.handleFileNameHistorySelect(" +
05642 forPrimary + ");",
05643 "onclick":"CodeEditor.editor.stopUpdateHandling(event);",
05644 "onfocus":"CodeEditor.editor.lastFileNameHistorySelectIndex = this.value;" +
05645 "this.value = -1;",
05646 "onblur":"this.value = CodeEditor.editor.lastFileNameHistorySelectIndex;",
05647
05648 },0 , false );
05649
05650
05651 for(i=0;i<keys.length;++i)
05652 {
05653
05654
05655 str += "<option value='" + i + "' ";
05656 if(currentFile == keys[i])
05657 str += "selected";
05658 str += ">";
05659 if(_fileHistoryStack[keys[i]][2])
05660 str += "*MODIFIED* ";
05661 str += keys[i];
05662 str += "</option>";
05663 }
05664
05665 str += "</select>";
05666
05667 try
05668 {
05669 el = document.getElementById("fileNameDiv" + forPrimary);
05670 el.innerHTML = str;
05671 }
05672 catch(e)
05673 {
05674 Debug.log("Ignoring error since file forPrimary=" +
05675 forPrimary + " is probably not opened: " +
05676 e);
05677 }
05678 }
05679
05680 }
05681
05682
05683
05684
05685 this.handleFileNameHistorySelect = function(forPrimary)
05686 {
05687 forPrimary = forPrimary?1:0;
05688
05689 var selectedFileIndex = document.getElementById("fileNameHistorySelect" + forPrimary).value | 0;
05690 Debug.log("updateFileHistoryDropdowns " + forPrimary +
05691 "selected=" + selectedFileIndex);
05692
05693 var keys = Object.keys(_fileHistoryStack);
05694 var selectedFileName = keys[selectedFileIndex];
05695
05696 Debug.log("selectedFileName " + selectedFileName);
05697
05698
05699
05700
05701 var fileObj = {};
05702 var fileArr = selectedFileName.split('.');
05703
05704
05705 if(fileArr[0] == _filePath[forPrimary] &&
05706 fileArr[1] == _fileExtension[forPrimary])
05707 {
05708 CodeEditor.editor.openFile(forPrimary,
05709 _filePath[forPrimary],
05710 _fileExtension[forPrimary],
05711 true );
05712 return;
05713 }
05714
05715 fileObj.path = fileArr[0];
05716 fileObj.extension = fileArr[1];
05717 fileObj.text = _fileHistoryStack[selectedFileName][0];
05718 fileObj.fileWasModified = _fileHistoryStack[selectedFileName][2];
05719 fileObj.fileLastSave = _fileHistoryStack[selectedFileName][3];
05720
05721 console.log("fileObj",fileObj);
05722
05723 CodeEditor.editor.handleFileContent(forPrimary,0,fileObj);
05724
05725 }
05726
05727
05728
05729
05730 this.showFindAndReplace = function(forPrimary)
05731 {
05732 forPrimary = forPrimary?1:0;
05733 _activePaneIsPrimary = forPrimary;
05734
05735 Debug.log("showFindAndReplace forPrimary=" + forPrimary + " activePane=" + _activePaneIsPrimary);
05736
05737 CodeEditor.editor.findAndReplaceLastButton[forPrimary] = 1;
05738
05739
05740 var el = _eel[forPrimary];
05741 var cursor = _findAndReplaceCursorInContent[forPrimary] =
05742 CodeEditor.editor.getCursor(el);
05743
05744
05745 el = document.getElementById("textEditorHeader" + forPrimary);
05746 var str = "";
05747
05748 str += "<center>";
05749
05750 str += "<table style='margin-top: 2px;'>";
05751
05752
05753
05754 str += "<tr><td style='text-align:right'>";
05755 str += "Find:";
05756 str += "</td><td>";
05757 str += htmlOpen("input",
05758 {
05759 "type":"text",
05760 "id":"findAndReplaceFind" + forPrimary,
05761 "style":"text-align:left; width:90%;" +
05762 " height:" + (20) + "px",
05763 "value": CodeEditor.editor.findAndReplaceFind[forPrimary],
05764 "onclick":"event.stopPropagation();",
05765 "onchange":"CodeEditor.editor.findAndReplaceFind[" +
05766 forPrimary + "] = this.value;" +
05767 "CodeEditor.editor.showFindAndReplaceSelection(" +
05768 forPrimary + ");",
05769 },0 , true );
05770
05771 str += "</td><td>";
05772
05773
05774 str += htmlOpen("select",
05775 {
05776 "id":"findAndReplaceScope" + forPrimary,
05777 "style":"width:100%;" +
05778 "text-align-last: center;",
05779 "title":"Choose the scope for Replace All",
05780 "onclick":"event.stopPropagation();" ,
05781 "onchange":"CodeEditor.editor.findAndReplaceScope[" +
05782 forPrimary + "] = this.value;" +
05783 "CodeEditor.editor.showFindAndReplaceSelection(" +
05784 forPrimary + ");",
05785
05786 },0 , false );
05787 str += "<option value='0'>All Lines</option>";
05788 str += "<option value='1' " + (CodeEditor.editor.findAndReplaceScope[forPrimary] ==
05789 1?"selected":"") + ">Selected Lines</option>";
05790 str += "</select>";
05791
05792 str += "</td><td>";
05793
05794
05795 str += htmlOpen("input",
05796 {
05797 "type":"checkbox",
05798 "id":"findAndReplaceCaseSensitive" + forPrimary,
05799 "title":"Toggle case sensitive search",
05800 "onclick":"event.stopPropagation();",
05801 "style":"margin-left:10px;",
05802 "onchange":"CodeEditor.editor.findAndReplaceCaseSensitive[" +
05803 forPrimary + "] = this.checked;" +
05804 "CodeEditor.editor.showFindAndReplaceSelection(" +
05805 forPrimary + ");",
05806
05807 },
05808 htmlOpen("a",
05809 {
05810 "title":"Toggle case sensitive search",
05811 "style":"margin-left:5px;",
05812 "onclick":"event.stopPropagation();" +
05813 "var el = document.getElementById(\"findAndReplaceCaseSensitive" +
05814 forPrimary + "\"); el.checked = !el.checked;" +
05815 "CodeEditor.editor.findAndReplaceCaseSensitive[" +
05816 forPrimary + "] = el.checked;" +
05817 "CodeEditor.editor.showFindAndReplaceSelection(" +
05818 forPrimary + ");",
05819
05820 },
05821 "Case sensitive" , true
05822 ), true );
05823
05824 str += "</td></tr>";
05825
05826
05827 str += "<tr><td style='text-align:right'>";
05828 str += "Replace with:";
05829 str += "</td><td>";
05830 str += htmlOpen("input",
05831 {
05832 "type":"text",
05833 "id":"findAndReplaceReplace" + forPrimary,
05834 "style":"text-align:left; width:90%;" +
05835 " height:" + (20) + "px",
05836 "value": CodeEditor.editor.findAndReplaceReplace[forPrimary],
05837 "onclick":"event.stopPropagation();",
05838 "onchange":"CodeEditor.editor.findAndReplaceReplace[" +
05839 forPrimary + "] = this.value; " +
05840 "CodeEditor.editor.showFindAndReplaceSelection(" +
05841 forPrimary + ");",
05842 },0 , true );
05843
05844 str += "</td><td>";
05845
05846
05847 str += htmlOpen("select",
05848 {
05849 "id":"findAndReplaceDirection" + forPrimary,
05850 "style":"width:100%;" +
05851 "text-align-last: center;",
05852 "title":"Choose the search direction for the Find & Replace",
05853 "onclick":"event.stopPropagation();",
05854 "onchange":"CodeEditor.editor.findAndReplaceDirection[" +
05855 forPrimary + "] = this.value;" +
05856 "CodeEditor.editor.showFindAndReplaceSelection(" +
05857 forPrimary + ");",
05858
05859 },0 , false );
05860 str += "<option value='0'>Search Forward</option>";
05861 str += "<option value='1' " + (CodeEditor.editor.findAndReplaceDirection[forPrimary] ==
05862 1?"selected":"") +
05863 ">Search Backward</option>";
05864 str += "</select>";
05865
05866 str += "</td><td>";
05867
05868
05869 str += htmlOpen("input",
05870 {
05871 "type":"checkbox",
05872 "id":"findAndReplaceWholeWord" + forPrimary,
05873 "title":"Toggle whole word search",
05874 "onclick":"event.stopPropagation();",
05875 "style":"margin-left:10px;",
05876 "onchange":"CodeEditor.editor.findAndReplaceWholeWord[" +
05877 forPrimary + "] = this.checked;" +
05878 "CodeEditor.editor.showFindAndReplaceSelection(" +
05879 forPrimary + ");",
05880
05881 },
05882 htmlOpen("a",
05883 {
05884 "style":"margin-left:5px;",
05885 "title":"Toggle whole word search",
05886 "onclick":"event.stopPropagation();" +
05887 "var el = document.getElementById(\"findAndReplaceWholeWord" +
05888 forPrimary + "\"); el.checked = !el.checked;" +
05889 "CodeEditor.editor.findAndReplaceWholeWord[" +
05890 forPrimary + "] = el.checked;" +
05891 "CodeEditor.editor.showFindAndReplaceSelection(" +
05892 forPrimary + ");",
05893 },
05894 "Whole word" , true
05895 ), true );
05896
05897 str += "</td></tr>";
05898
05899
05900
05901 str += "<tr><td colspan='4' style='text-align:center'>";
05902 str += htmlOpen("div",
05903 {
05904 "id": "findAndReplaceWrapped" + forPrimary,
05905 "style": "text-align:right; margin: 4px; width:115px;" +
05906 "color: red; float: left;",
05907 },0 , true );
05908 str += "<div style='float:left;'>";
05909 str += htmlOpen("input",
05910 {
05911 "type": "button",
05912 "value": "Find",
05913
05914 "style": "text-align:center; margin: 4px;" ,
05915 "onclick": "event.stopPropagation();" +
05916 "CodeEditor.editor.doFindAndReplaceAction(" + forPrimary + ",1)",
05917 },0 , true );
05918
05919 str += htmlOpen("input",
05920 {
05921 "type": "button",
05922 "value": "Replace",
05923
05924 "style": "text-align:center; margin: 4px;" ,
05925 "onclick": "event.stopPropagation();" +
05926 "CodeEditor.editor.doFindAndReplaceAction(" + forPrimary + ",2)",
05927 },0 , true );
05928
05929 str += htmlOpen("input",
05930 {
05931 "type": "button",
05932 "value": "Replace & Find",
05933
05934 "style": "text-align:center; margin: 4px;" ,
05935 "onclick": "event.stopPropagation();" +
05936 "CodeEditor.editor.doFindAndReplaceAction(" + forPrimary + ",3)",
05937 },0 , true );
05938
05939 str += htmlOpen("input",
05940 {
05941 "type": "button",
05942 "value": "Replace All",
05943
05944 "style": "text-align:center; margin: 4px;" ,
05945 "onclick": "event.stopPropagation();" +
05946 "CodeEditor.editor.doFindAndReplaceAction(" + forPrimary + ",4)",
05947 },0 , true );
05948
05949 str += htmlOpen("input",
05950 {
05951 "type": "button",
05952 "value": "Cancel",
05953 "title": "Close find and replace controls.",
05954 "style": "text-align:center; margin: 4px;" ,
05955
05956 "onclick": "event.stopPropagation();" +
05957 "CodeEditor.editor.displayFileHeader(" + forPrimary + ")",
05958 },0 , true );
05959
05960 str += "</div>";
05961 str += "</td></tr>";
05962
05963 str += "</table>";
05964 str += "</center>";
05965
05966 el.innerHTML = str;
05967
05968 el = document.getElementById("findAndReplaceFind" + forPrimary);
05969 el.setSelectionRange(0, el.value.length);
05970 el.focus();
05971
05972 el = document.getElementById("findAndReplaceCaseSensitive" + forPrimary);
05973 el.checked = CodeEditor.editor.findAndReplaceCaseSensitive[forPrimary];
05974
05975 el = document.getElementById("findAndReplaceWholeWord" + forPrimary);
05976 el.checked = CodeEditor.editor.findAndReplaceWholeWord[forPrimary];
05977
05978 }
05979
05980
05981
05982
05983 this.showFindAndReplaceSelection = function(forPrimary)
05984 {
05985 forPrimary = forPrimary?1:0;
05986 Debug.log("showFindAndReplaceSelection forPrimary=" + forPrimary);
05987
05988 var el = _eel[forPrimary];
05989 var cursor = CodeEditor.editor.getCursor(el);
05990
05991 if(cursor.startPosInContent !== undefined)
05992 CodeEditor.editor.setCursor(el,
05993 cursor,
05994 true );
05995 else if(
05996 CodeEditor.editor.findAndReplaceLastButton[forPrimary] > 0 &&
05997 _findAndReplaceCursorInContent[forPrimary] !== undefined)
05998 CodeEditor.editor.setCursor(el,
05999 _findAndReplaceCursorInContent[forPrimary],
06000 true );
06001
06002
06003 }
06004
06005
06006
06007
06008
06009
06010
06011
06012 this.doFindAndReplaceAction = function(forPrimary,action)
06013 {
06014 forPrimary = forPrimary?1:0;
06015 action = action | 0;
06016
06017 CodeEditor.editor.findAndReplaceLastButton[forPrimary] = action;
06018
06019 var find = document.getElementById("findAndReplaceFind" + forPrimary).value;
06020 var originalFind = find;
06021 if(!find || find == "")
06022 {
06023 Debug.log("Illegal empty string to find.", Debug.HIGH_PRIORITY);
06024 return;
06025 }
06026 var replace = CodeEditor.editor.findAndReplaceReplace[forPrimary];
06027 var scope = CodeEditor.editor.findAndReplaceScope[forPrimary]|0;
06028 var direction = CodeEditor.editor.findAndReplaceDirection[forPrimary]|0;
06029 if(action == 4)
06030 direction = 0;
06031 var caseSensitive = CodeEditor.editor.findAndReplaceCaseSensitive[forPrimary]?1:0;
06032 var wholeWord = CodeEditor.editor.findAndReplaceWholeWord[forPrimary]?1:0;
06033
06034 Debug.log("doFindAndReplaceAction forPrimary=" + forPrimary +
06035 " action=" + action +
06036 " find=" + find +
06037 " replace=" + replace +
06038 " scope=" + scope +
06039 " direction=" + direction +
06040 " caseSensitive=" + caseSensitive +
06041 " wholeWord=" + wholeWord);
06042
06043
06044
06045
06046
06047
06048
06049
06050
06051
06052 var el = _eel[forPrimary];
06053 var originalText = el.textContent;
06054
06055 if(caseSensitive)
06056 text = originalText;
06057 else
06058 {
06059 text = originalText.toLowerCase();
06060 find = find.toLowerCase();
06061 }
06062
06063 var i = direction?text.length:-1;
06064 var j = text.length-1;
06065
06066 var cursor = CodeEditor.editor.getCursor(el);
06067
06068
06069 if(cursor.startPosInContent !== undefined &&
06070 (action == 4 ||
06071 document.getElementById("findAndReplaceWrapped" + forPrimary).textContent == ""))
06072 i = cursor.startPosInContent;
06073 else if(_findAndReplaceCursorInContent[forPrimary] !== undefined &&
06074 _findAndReplaceCursorInContent[forPrimary].startPosInContent !== undefined &&
06075 _findAndReplaceCursorInContent[forPrimary].startPosInContent >= 0 &&
06076 (action == 4 ||
06077 document.getElementById("findAndReplaceWrapped" + forPrimary).textContent == ""))
06078 {
06079 i = _findAndReplaceCursorInContent[forPrimary].startPosInContent;
06080
06081 if(action == 4)
06082 CodeEditor.editor.setCursor(el,
06083 _findAndReplaceCursorInContent[forPrimary],
06084 true );
06085 }
06086
06087
06088 document.getElementById("findAndReplaceWrapped" + forPrimary).innerHTML = "";
06089
06090 Debug.log("Starting position: " + i);
06091
06092 if(scope == 1)
06093 {
06094 if(cursor.endPosInContent !== undefined)
06095 j = cursor.endPosInContent;
06096 else if(_findAndReplaceCursorInContent[forPrimary] !== undefined &&
06097 _findAndReplaceCursorInContent[forPrimary].endPosInContent != undefined &&
06098 _findAndReplaceCursorInContent[forPrimary].endPosInContent >= 0)
06099 j = _findAndReplaceCursorInContent[forPrimary].endPosInContent;
06100
06101 Debug.log("Ending position: " + j);
06102 }
06103 else if(action == 4)
06104 i = -1;
06105
06106 var replaceCount = 0;
06107 var done;
06108 var found = false;
06109 do
06110 {
06111 done = true;
06112
06114
06115 switch(action)
06116 {
06117 case 2:
06118 case 3:
06119 if(i > 0 && i + find.length <= text.length)
06120 found = true;
06121 case 4:
06122
06123 if(found)
06124 {
06125 Debug.log("Replacing");
06126 ++replaceCount;
06127
06128
06129 originalText =
06130 originalText.substr(0,i) +
06131 replace +
06132 originalText.substr(i+find.length);
06133
06134
06135 if(caseSensitive)
06136 text = originalText;
06137 else
06138 text = originalText.toLowerCase();
06139 }
06140
06141 break;
06142 case 1:
06143 break;
06144 default:
06145 Debug.log("Unrecognized action! " + action, Debug.HIGH_PRIORITY);
06146 return;
06147 }
06148
06149
06151
06152 switch(action)
06153 {
06154 case 1:
06155 case 3:
06156 case 4:
06157
06158 if(direction == 0)
06159 i = text.indexOf(find,i+1);
06160 else if(direction == 1)
06161 i = text.lastIndexOf(find,i-1);
06162
06163 if(wholeWord)
06164 {
06165
06166 if(i>0 && (
06167 (text[i-1] >= 'a' && text[i-1] <= 'z') ||
06168 (text[i-1] >= 'A' && text[i-1] <= 'Z') ||
06169 (text[i-1] >= '0' && text[i-1] <= '9') ||
06170 text[i-1] == '_'
06171 ))
06172 {
06173
06174 done = false;
06175 }
06176 else if(i>0 && i+find.length<text.length && (
06177 (text[i+find.length] >= 'a' && text[i+find.length] <= 'z') ||
06178 (text[i+find.length] >= 'A' && text[i+find.length] <= 'Z') ||
06179 (text[i+find.length] >= '0' && text[i+find.length] <= '9') ||
06180 text[i+find.length] == '_'
06181 ))
06182 {
06183
06184 done = false;
06185 }
06186 }
06187
06188 console.log(i);
06189
06190 if(done)
06191 {
06192 if(i >= 0)
06193 {
06194 found = true;
06195
06196
06197 if(action == 4)
06198 {
06199
06200 if(i + find.length < j)
06201 done = false;
06202
06203 }
06204 }
06205 else
06206 {
06207 found = false;
06208 document.getElementById("findAndReplaceWrapped" + forPrimary).innerHTML = "Reached end";
06209 }
06210 }
06211 else
06212 found = false;
06213
06214 break;
06215 case 2:
06216 break;
06217 default:
06218 Debug.log("Unrecognized action! " + action, Debug.HIGH_PRIORITY);
06219 return;
06220 }
06221
06222
06223 } while(!done);
06224
06225
06227
06228 switch(action)
06229 {
06230 case 2:
06231 case 3:
06232 case 4:
06233
06234
06235
06236 el.textContent = originalText;
06237 CodeEditor.editor.updateDecorations(forPrimary);
06238
06239
06240 if(action == 3)
06241 {
06242 _findAndReplaceCursorInContent[forPrimary] =
06243 CodeEditor.editor.createCursorFromContentPosition(el,
06244 i, i + find.length);
06245 CodeEditor.editor.setCursor(
06246 el,
06247 _findAndReplaceCursorInContent[forPrimary],
06248 true );
06249 }
06250
06251
06252 break;
06253 case 1:
06254
06255
06256 _findAndReplaceCursorInContent[forPrimary] =
06257 CodeEditor.editor.createCursorFromContentPosition(el,
06258 i, i + find.length)
06259 CodeEditor.editor.setCursor(
06260 el,
06261 _findAndReplaceCursorInContent[forPrimary],
06262 true );
06263
06264 break;
06265 default:
06266 Debug.log("Unrecognized action! " + action, Debug.HIGH_PRIORITY);
06267 return;
06268 }
06269
06270
06271
06272
06273 if(action == 4)
06274 document.getElementById("findAndReplaceWrapped" + forPrimary).innerHTML =
06275 replaceCount + " Replaced";
06276
06277
06278 }
06279
06280
06281
06282 this.displayFileHeader = function(forPrimary)
06283 {
06284 forPrimary = forPrimary?1:0;
06285
06286 var forceDisplayComplete = false;
06287 if(CodeEditor.editor.findAndReplaceLastButton[forPrimary] != -1)
06288 {
06289 CodeEditor.editor.findAndReplaceLastButton[forPrimary] = -1;
06290 forceDisplayComplete = true;
06291 }
06292
06293 Debug.log("displayFileHeader forPrimary=" + forPrimary);
06294
06295
06296 var el = document.getElementById("textEditorHeader" + forPrimary);
06297
06298
06299 var path = _filePath[forPrimary];
06300 var extension = _fileExtension[forPrimary];
06301
06302
06303
06304 var str = "";
06305
06306
06307 str += htmlOpen("div",
06308 {
06309 "onmousemove" :
06310 "CodeEditor.editor.handleFileNameMouseMove(" + forPrimary + ");",
06311 },0 , false );
06312 str += "<center>";
06313
06314
06315 str += htmlOpen("div",
06316 {
06317 "class":"fileButtonContainer",
06318 "id":"fileButtonContainer" + forPrimary,
06319
06320 },0 , false );
06321 str += htmlOpen("div",
06322 {
06323 "class":"fileButtonContainerShowHide",
06324 "id":"fileButtonContainerShowHide" + forPrimary,
06325 "onmousemove":
06326 "event.stopPropagation(); " +
06327 "CodeEditor.editor.handleFileNameMouseMove(" + forPrimary +
06328 ",1 /*doNotStartTimer*/);",
06329
06330 },0 , false );
06331 str += htmlOpen("div",
06332 {
06333 "class":"fileButton",
06334 "id":"fileRenameButton" + forPrimary,
06335 "title": "Change the filename\n" + path + "." + extension,
06336 "onclick":
06337 "event.stopPropagation(); " +
06338 "CodeEditor.editor.startEditFileName(" + forPrimary + ");",
06339 },0 , true );
06340 str += htmlOpen("div",
06341 {
06342 "class":"fileButton",
06343 "id":"fileDownloadButton" + forPrimary,
06344 "title": "Download the file content from\n" + path + "." + extension,
06345 "onclick":
06346 "event.stopPropagation(); " +
06347 "CodeEditor.editor.download(" + forPrimary + ");",
06348 },
06349
06350 "<div class='fileDownloadButtonBgChild' style='display: block; margin-left: 0px; margin-top: 1px; height:7px; width: 6px; background-color: rgb(202, 204, 210);'></div>" +
06351 "<div class='fileDownloadButtonBorderChild' style='display: block; width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; border-top: 8px solid rgb(202, 204, 210);'></div>" +
06352 "<div class='fileDownloadButtonBgChild' style='position: relative; top: 2px; width: 12px; height: 2px; display: block; background-color: rgb(202, 204, 210);'></div>"
06353 , true );
06354 str += htmlOpen("div",
06355 {
06356 "class":"fileButton",
06357 "id":"fileUploadButton" + forPrimary,
06358 "title": "Upload file content to\n" + path + "." + extension,
06359 "onclick":
06360 "event.stopPropagation(); " +
06361 "CodeEditor.editor.upload(" + forPrimary + ");",
06362 },
06363
06364 "<div class='fileDownloadButtonBorderChild' style='display: block; width: 0; height: 0; border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 8px solid rgb(202, 204, 210);'></div>" +
06365 "<div class='fileDownloadButtonBgChild' style='display: block; margin-left: 0px; height:7px; width: 6px; background-color: rgb(202, 204, 210);'></div>" +
06366 "<div class='fileDownloadButtonBgChild' style='position: relative; top: 3px; width: 12px; height: 2px; display: block; background-color: rgb(202, 204, 210);'></div>"
06367 , true );
06368 str += htmlOpen("div",
06369 {
06370 "class":"fileButton fileUndoButton",
06371 "id":"fileUndoButton" + forPrimary,
06372 "title": "Undo to rewind to last recorded checkpoint for\n" + path + "." + extension,
06373 "style": "color: rgb(202, 204, 210);" +
06374 "padding: 0 5px 0;" +
06375 "font-size: 17px;" +
06376 "font-weight: bold;",
06377 "onclick":
06378 "event.stopPropagation(); " +
06379 "CodeEditor.editor.undo(" + forPrimary + ");",
06380 },
06381
06382 "↩"
06383 , true );
06384 str += htmlOpen("div",
06385 {
06386 "class":"fileButton fileUndoButton",
06387 "id":"fileRedoButton" + forPrimary,
06388 "title": "Redo to fast-forward to last recorded checkpoint for\n" + path + "." + extension,
06389 "style": "color: rgb(202, 204, 210);" +
06390 "padding: 0 5px 0;" +
06391 "font-size: 17px;" +
06392 "font-weight: bold;",
06393 "onclick":
06394 "event.stopPropagation(); " +
06395 "CodeEditor.editor.undo(" + forPrimary + ",1 /*redo*/);",
06396 },
06397
06398 "↪"
06399 , true );
06400
06401
06402
06403 str += "</div>";
06404 str += "</div>";
06405
06406 str += htmlClearDiv();
06407
06408
06409 str += "<table><tr><td>";
06410
06411 str += htmlOpen("a",
06412 {
06413 "title":"Open file in a new browser tab: \n" +
06414 "srcs" + path + "." + extension,
06415 "onclick":"DesktopContent.openNewBrowserTab(" +
06416 "\"Code Editor\",\"\"," +
06417 "\"/WebPath/html/CodeEditor.html?startFilePrimary=" +
06418 path + "." + extension + "\",0 /*unique*/);' ",
06419 },
06420 "<img class='dirNavFileNewWindowImgNewWindow' " +
06421 "src='/WebPath/images/windowContentImages/CodeEditor-openInNewWindow.png'>"
06422 , true );
06423
06424
06425 str += htmlOpen("a",
06426 {
06427 "title":"Open file in the other editor pane of the split-view: \n" +
06428 "srcs" + path + "." + extension,
06429 "onclick":"CodeEditor.editor.openFile(" +
06430 (!forPrimary) + ",\"" +
06431 path + "\", \"" +
06432 extension + "\"" +
06433 ");",
06434 },
06435 "<img class='dirNavFileNewWindowImgNewPane' " +
06436 "src='/WebPath/images/windowContentImages/CodeEditor-openInOtherPane.png'>"
06437 , true );
06438 str += "</td><td>";
06439
06440
06441 str += htmlOpen("div",
06442 {
06443 "class":"fileNameDiv",
06444 "id":"fileNameDiv" + forPrimary,
06445 "style":"margin: 0 5px 0 5px",
06446 },0 , false );
06447 str += "<a onclick='CodeEditor.editor.openFile(" + forPrimary +
06448 ",\"" + path + "\",\"" + extension + "\",true /*doConfirm*/);' " +
06449 "title='Click to reload \n" + path + "." + extension + "' " +
06450 ">" +
06451 path + "." + extension + "</a>";
06452 str += "</div>";
06453
06454 str += "</td></tr></table>";
06455 str += "</center>";
06456 str += "</div>";
06457
06458 str += htmlClearDiv();
06459
06460
06461 str += "<div class='textEditorLastSave' id='textEditorLastSave" +
06462 forPrimary + "'>Unmodified</div>";
06463
06464 str += htmlClearDiv();
06465
06466 str += "<div class='textEditorOutline' id='textEditorOutline" +
06467 forPrimary + "'>Outline:</div>";
06468
06469 el.innerHTML = str;
06470
06471 CodeEditor.editor.updateDecorations(forPrimary,forceDisplayComplete);
06472 CodeEditor.editor.updateFileHistoryDropdowns();
06473
06474 }
06475
06476
06477
06478
06479
06480
06481
06482 this.updateFileSnapshot = function(forPrimary,textObj , ignoreTimeDelta)
06483 {
06484 forPrimary = forPrimary?1:0;
06485
06486 Debug.log("updateFileSnapshot forPrimary=" + forPrimary);
06487
06488
06489 var addSnapshot = false;
06490
06491 if(_undoStackLatestIndex[forPrimary] != -1)
06492 {
06493
06494
06495 if((ignoreTimeDelta ||
06496 2*1000 < textObj.time - _undoStack[forPrimary][_undoStackLatestIndex[forPrimary]][1]) &&
06497 _undoStack[forPrimary][_undoStackLatestIndex[forPrimary]][0] != textObj.text)
06498 addSnapshot = true;
06499 }
06500 else
06501 addSnapshot = true;
06502
06503
06504 if(addSnapshot)
06505 {
06506 ++_undoStackLatestIndex[forPrimary];
06507 if(_undoStackLatestIndex[forPrimary] >= _undoStack_MAX_SIZE)
06508 _undoStackLatestIndex[forPrimary] = 0;
06509
06510 _undoStack[forPrimary][_undoStackLatestIndex[forPrimary]] =
06511 [textObj.text,
06512 textObj.time];
06513
06514 console.log("snapshot added to stack",_undoStack[forPrimary]);
06515
06516
06517
06518
06519
06520
06521
06522 _fileHistoryStack[_filePath[forPrimary] + "." +
06523 _fileExtension[forPrimary]] = [
06524 textObj.text,
06525 textObj.time,
06526 _fileWasModified[forPrimary],
06527 _fileLastSave[forPrimary]];
06528 console.log("_fileHistoryStack",_fileHistoryStack);
06529
06530 CodeEditor.editor.updateFileHistoryDropdowns();
06531 }
06532
06533 return addSnapshot;
06534
06535 }
06536
06537
06538
06539
06540 this.startUpdateHandling = function(forPrimary)
06541 {
06542 _updateHandlerTargetPane[forPrimary] = true;
06543
06544 window.clearTimeout(_updateTimerHandle);
06545 _updateTimerHandle = window.setTimeout(
06546 CodeEditor.editor.updateTimeoutHandler,
06547 _UPDATE_DECOR_TIMEOUT );
06548
06549 }
06550
06551
06552
06553
06554 this.stopUpdateHandling = function(event)
06555 {
06556 if(event) event.stopPropagation();
06557 window.clearTimeout(_updateTimerHandle);
06558 }
06559
06560
06561
06562
06563 this.updateTimeoutHandler = function()
06564 {
06565 if(_updateHandlerTargetPane[0])
06566 {
06567 CodeEditor.editor.updateDecorations(0 );
06568 _updateHandlerTargetPane[0] = false;
06569 }
06570 if(_updateHandlerTargetPane[1])
06571 {
06572 CodeEditor.editor.updateDecorations(1 );
06573 _updateHandlerTargetPane[1] = false;
06574 }
06575 }
06576
06577
06578
06579
06580 this.doubleClickHandler = function(forPrimary)
06581 {
06582 forPrimary = forPrimary?1:0;
06583
06584 Debug.log("doubleClickHandler forPrimary=" + forPrimary);
06585
06586
06587
06588
06589
06590 var el = _eel[forPrimary];
06591 var cursor = CodeEditor.editor.getCursor(el);
06592
06593 if(!cursor || cursor.startNodeIndex === undefined)
06594 return;
06595
06596 var n = cursor.startNodeIndex;
06597 var c = el.childNodes[n].textContent[
06598 cursor.startPos];
06599
06600 var openCount = 0;
06601
06602 if(c != '{' && c != '}')
06603 {
06604 if(cursor.startPos == 0)
06605 {
06606
06607 do
06608 {
06609 --n;
06610 } while(n >= 0 && el.childNodes[n].textContent.length);
06611
06612 if(n < 0) return;
06613 c = el.childNodes[n].textContent[
06614 el.childNodes[n].textContent.length-1];
06615 }
06616 else
06617 c = el.childNodes[n].textContent[
06618 cursor.startPos-1];
06619
06620 if(c == '{')
06621 openCount = 1;
06622 }
06623
06624 Debug.log("character before cursor " + c);
06625
06626 if(c != '{' && c != '}') return;
06627
06628 var i;
06629 var found = false;
06630 var foundDoubleQuote = false;
06631 var foundSingleQuote = false;
06632 var foundComment = false;
06633
06634 if(c == '}')
06635 {
06636
06637 cursor.endNodeIndex = -1;
06638 cursor.endPos = -1;
06639
06640
06641
06642
06643
06644 var openCountSave = openCount;
06645 var prelimFound = false;
06646
06647 for(n;n>=0; --n)
06648 {
06649 node = el.childNodes[n];
06650 val = node.textContent;
06651 for(i=(n==cursor.startNodeIndex?cursor.startPos-1:
06652 val.length-1); i>=0; --i)
06653 {
06654 if(cursor.endNodeIndex == -1)
06655 {
06656 cursor.endNodeIndex = n;
06657 cursor.endPos = i;
06658 }
06659
06660 if(val[i] == '\n')
06661 {
06662 foundSingleQuote = false;
06663 foundDoubleQuote = false;
06664 openCountSave = openCount;
06665
06666 if(prelimFound)
06667 {
06668 Debug.log("confirmed found open count match ni " + n + " " + i);
06669 found = true;
06670 break;
06671 }
06672 }
06673
06674 if(!foundSingleQuote && val[i] == '"')
06675 foundDoubleQuote = !foundDoubleQuote;
06676 else if(!foundDoubleQuote && val[i] == "'")
06677 foundSingleQuote = !foundSingleQuote;
06678 else if(val[i]== '/' && i-1 >= 0 &&
06679 val[i-1] == '/')
06680 {
06681
06682 openCount = openCountSave;
06683 if(openCount > 0)
06684 prelimFound = false;
06685
06686 --i;
06687 continue;
06688 }
06689
06690 if(foundDoubleQuote || foundSingleQuote ||
06691 prelimFound)
06692 continue;
06693
06694 if(val[i] == '}')
06695 ++openCount;
06696 else if(val[i] == '{')
06697 {
06698 --openCount;
06699 if(openCount <= 0)
06700 {
06701 prelimFound = true;
06702 Debug.log("found open count match ni " + n + " " + i);
06703
06704
06705
06706 }
06707 }
06708
06709 cursor.startNodeIndex = n;
06710 cursor.startPos = i;
06711 }
06712
06713 if(found) break;
06714 }
06715
06716 }
06717 else
06718 {
06719
06720
06721 i = cursor.startPos;
06722 for(n=cursor.startNodeIndex;n<el.childNodes.length; ++n)
06723 {
06724 node = el.childNodes[n];
06725 val = node.textContent;
06726
06727 for(; i<val.length; ++i)
06728 {
06729 if(val[i] == '\n')
06730 {
06731 foundSingleQuote = false;
06732 foundDoubleQuote = false;
06733 foundComment = false;
06734 }
06735
06736 if(foundComment)
06737 continue;
06738
06739 if(!foundSingleQuote && val[i] == '"')
06740 foundDoubleQuote = !foundDoubleQuote;
06741 else if(!foundDoubleQuote && val[i] == "'")
06742 foundSingleQuote = !foundSingleQuote;
06743 else if(val[i]== '/' && i+1 < val.length &&
06744 val[i+1] == '/')
06745 {
06746 foundComment = true;
06747 continue;
06748 }
06749
06750 if(foundDoubleQuote || foundSingleQuote)
06751 continue;
06752
06753 if(val[i] == '{')
06754 ++openCount;
06755 else if(val[i] == '}')
06756 {
06757 --openCount;
06758 if(openCount <= 0)
06759 {
06760 found = true;
06761 Debug.log("found open count match ni " + n + " " + i);
06762 break;
06763 }
06764 }
06765
06766 cursor.endNodeIndex = n;
06767 cursor.endPos = i;
06768 }
06769
06770 if(found) break;
06771
06772 i = 0;
06773
06774 }
06775 }
06776
06777
06778 CodeEditor.editor.setCursor(el,cursor);
06779
06780 }
06781
06782
06783
06784
06785 this.download = function(forPrimary)
06786 {
06787 forPrimary = forPrimary?1:0;
06788
06789 Debug.log("download forPrimary=" + forPrimary);
06790
06791 var dataStr = "data:text/plain;charset=utf-8," +
06792 encodeURIComponent(_eel[forPrimary].textContent);
06793
06794 var filename = _filePath[forPrimary];
06795 var i = filename.lastIndexOf('/');
06796 if(i >= 0)
06797 filename = filename.substr(i+1);
06798 filename += "." + _fileExtension[forPrimary];
06799
06800 Debug.log("Downloading to filename " + filename);
06801
06802 var link = document.createElement("a");
06803 link.setAttribute("href", dataStr);
06804 link.setAttribute("style", "display:none");
06805 link.setAttribute("download", filename);
06806 document.body.appendChild(link);
06807
06808 link.click();
06809
06810 link.parentNode.removeChild(link);
06811
06812 }
06813
06814
06815
06816 this.upload = function(forPrimary)
06817 {
06818 forPrimary = forPrimary?1:0;
06819
06820 Debug.log("upload forPrimary=" + forPrimary);
06821
06822 _fileUploadString = "";
06823
06824 var str = "";
06825
06826 var el = document.getElementById("popUpDialog");
06827 if(!el)
06828 {
06829 el = document.createElement("div");
06830 el.setAttribute("id", "popUpDialog");
06831 }
06832 el.style.display = "none";
06833
06834
06835 var w = 400;
06836 var h = 205;
06837 DesktopContent.setPopUpPosition(el,w ,h );
06838
06839 var str = "<a id='" +
06840 "popUpDialog" +
06841 "-header' onclick='var el = document.getElementById(" +
06842 "\"popUpDialog\"); if(el) el.parentNode.removeChild(el); return false;'>Cancel</a><br><br>";
06843
06844 str += "<div id='popUpDialog-div'>";
06845
06846 str += "Please choose the file to upload which has the text content to place in the open source file:<br><br>" +
06847 _filePath[forPrimary] + "." + _fileExtension[forPrimary] +
06848 "<br><br>";
06849
06850 str += "<center>";
06851
06852 str += "<input type='file' id='popUpDialog-fileUpload' " +
06853 "accept='";
06854 for(var i=0;i<_ALLOWED_FILE_EXTENSIONS.length;++i)
06855 str += (i?", ":"") + "." + _ALLOWED_FILE_EXTENSIONS[i];
06856 str += "' enctype='multipart/form-data' />";
06857 str += "<br><br>";
06858
06859 var onmouseupJS = "";
06860 onmouseupJS += "document.getElementById(\"popUpDialog-submitButton\").disabled = true;";
06861 onmouseupJS += "CodeEditor.editor.uploadTextFromFile(" + forPrimary + ");";
06862
06863 str += "<input id='popUpDialog-submitButton' disabled type='button' onmouseup='" +
06864 onmouseupJS + "' " +
06865 "value='Upload File' title='" +
06866 "Upload the chosen file text content to\n" +
06867 _filePath[forPrimary] + "." + _fileExtension[forPrimary] +
06868 "'/>";
06869
06870 el.innerHTML = str;
06871 document.body.appendChild(el);
06872 el.style.display = "block";
06873
06874 document.getElementById('popUpDialog-fileUpload').addEventListener(
06875 'change', function(evt) {
06876 var files = evt.target.files;
06877 var file = files[0];
06878 var reader = new FileReader();
06879 reader.onload = function() {
06880
06881 _fileUploadString = this.result;
06882 Debug.log("_fileUploadString = " + _fileUploadString);
06883 document.getElementById('popUpDialog-submitButton').disabled = false;
06884 }
06885 reader.readAsText(file);
06886 }, false);
06887 }
06888
06889
06890
06891 this.uploadTextFromFile = function(forPrimary)
06892 {
06893 forPrimary = forPrimary?1:0;
06894
06895 Debug.log("uploadTextFromFile forPrimary=" + forPrimary);
06896
06897
06898 document.getElementById('popUpDialog-submitButton').disabled = false;
06899
06900 Debug.log("uploadTextFromFile _fileUploadString = " + _fileUploadString);
06901
06902
06903
06904 DesktopContent.showLoading(function()
06905 {
06906 try
06907 {
06908
06909
06910 _fileUploadString = _fileUploadString.replace(new RegExp(
06911 String.fromCharCode(160),'g'),' ');
06912 _fileUploadString = "hi";
06913 var el = _eel[forPrimary];
06914 el.textContent = _fileUploadString;
06915 CodeEditor.editor.displayFileHeader(forPrimary);
06916 }
06917 catch(e)
06918 {
06919 Debug.log("There was an error uploading the text: " + e,
06920 Debug.HIGH_PRIORITY);
06921 return;
06922 }
06923 Debug.log("Source upload complete! (You can use undo to go back) ",
06924 Debug.INFO_PRIORITY);
06925
06926
06927 var el = document.getElementById("popUpDialog");
06928 if(el) el.parentNode.removeChild(el);
06929
06930 });
06931
06932 }
06933
06934 }
06935
06936
06937
06938
06939
06940
06941
06942
06943
06944