File indexing completed on 2024-05-19 04:00:11
0001 /* 0002 This file is part of the Kate project within KDE. 0003 SPDX-FileCopyrightText: 2013-2018 Dominik Haumann <dhaumann@kde.org> 0004 0005 SPDX-License-Identifier: MIT 0006 */ 0007 0008 require("cursor.js"); 0009 0010 function DocumentCursor(doc, lineOrCursor, column) { 0011 0012 if (arguments.length === 1) { 0013 if (doc instanceof DocumentCursor) { 0014 return doc.clone(); 0015 } else { 0016 this.document = doc; 0017 this.line = 0; 0018 this.column = 0; 0019 } 0020 } else if (arguments.length === 2 && typeof lineOrCursor == "object") { 0021 this.document = doc; 0022 this.line = lineOrCursor.line; 0023 this.column = lineOrCursor.column; 0024 } else if (arguments.length === 3 && typeof lineOrCursor == "number" 0025 && typeof column == "number") { 0026 this.document = doc; 0027 this.line = parseInt(lineOrCursor, 10); 0028 this.column = parseInt(column, 10); 0029 } else { 0030 throw "Wrong usage of DocumentCursor constructor"; 0031 } 0032 } 0033 0034 DocumentCursor.prototype.clone = function() { 0035 return new DocumentCursor(this.document, this.line, this.column); 0036 } 0037 0038 DocumentCursor.prototype.setPosition = function(line, column) { 0039 this.line = line; 0040 this.column = column; 0041 } 0042 0043 DocumentCursor.prototype.isValid = function() { 0044 return (this.line >= 0) && (this.column >= 0); 0045 } 0046 0047 DocumentCursor.prototype.compareTo = function(other) { 0048 if (this.line > other.line || (this.line === other.line && this.column > other.column)) { 0049 return 1; 0050 } 0051 if (this.line < other.line || (this.line === other.line && this.column < other.column)) { 0052 return -1; 0053 } 0054 return 0; 0055 } 0056 0057 DocumentCursor.prototype.equals = function(other) { 0058 return (this.document === other.document && this.line === other.line && this.column === other.column); 0059 } 0060 0061 DocumentCursor.prototype.toString = function() { 0062 if (this.isValid()) { 0063 return "DocumentCursor(" + this.line+ "," + this.column+ ")"; 0064 } else { 0065 return "DocumentCursor()"; 0066 } 0067 } 0068 0069 DocumentCursor.invalid = function(doc) { 0070 return new DocumentCursor(doc, -1, -1); 0071 } 0072 0073 0074 0075 0076 DocumentCursor.prototype.isValidTextPosition = function() { 0077 return this.document.isValidTextPosition(this.line, this.column); 0078 } 0079 0080 DocumentCursor.prototype.atStartOfLine = function() { 0081 return this.isValidTextPosition() && this.column === 0; 0082 } 0083 0084 DocumentCursor.prototype.atEndOfLine = function() { 0085 return this.isValidTextPosition() && this.column === this.document.lineLength(this.line); 0086 } 0087 0088 DocumentCursor.prototype.atStartOfDocument = function() { 0089 return this.line === 0 && this.column === 0; 0090 } 0091 0092 DocumentCursor.prototype.atEndOfDocument = function() { 0093 return this.isValid() && (this.line === this.document.lines() - 1) && this.column === this.document.lineLength(this.line); 0094 } 0095 0096 DocumentCursor.prototype.gotoNextLine = function() { 0097 var ok = this.isValid() && (this.line + 1 < this.document.lines()); 0098 if (ok) { 0099 this.line = this.line + 1; 0100 this.column = 0; 0101 } 0102 return ok; 0103 } 0104 0105 DocumentCursor.prototype.gotoPreviousLine = function() { 0106 var ok = this.line > 0 && this.column >= 0; 0107 if (ok) { 0108 this.line = this.line - 1; 0109 this.column = 0; 0110 } 0111 return ok; 0112 } 0113 0114 DocumentCursor.prototype.move = function(nChars, wrapAtEol) { 0115 // validity checks 0116 if (typeof wrapAtEol != "boolean") { 0117 wrapAtEol = true; 0118 } 0119 0120 if (!this.isValid()) { 0121 return false; 0122 } 0123 0124 var c = new Cursor(this.line, this.column); 0125 0126 // cache lineLength to minimize calls of KTextEditor::DocumentPrivate::lineLength(), as 0127 // results in locating the correct block in the text buffer every time, 0128 // which is relatively slow 0129 var lineLength = this.document.lineLength(c.line); 0130 0131 // special case: cursor position is not in valid text, then the algo does 0132 // not work for Wrap mode. Hence, catch this special case by setting 0133 // c.column() to the lineLength() 0134 if (nChars > 0 && wrapAtEol && c.column > lineLength) { 0135 c.column = lineLength; 0136 } 0137 0138 while (nChars !== 0) { 0139 if (nChars > 0) { 0140 if (wrapAtEol) { 0141 var advance = Math.min(lineLength - c.column, nChars); 0142 0143 if (nChars > advance) { 0144 if (c.line + 1 >= this.document.lines()) { 0145 return false; 0146 } 0147 0148 c.line += 1; 0149 c.column = 0; 0150 nChars -= advance + 1; // +1 because of end-of-line wrap 0151 0152 // advanced one line, so cache correct line length again 0153 lineLength = this.document.lineLength(c.line); 0154 } else { 0155 c.column += nChars; 0156 nChars = 0; 0157 } 0158 } else { // NoWrap 0159 c.column = c.column + nChars; 0160 nChars = 0; 0161 } 0162 } else { 0163 var back = Math.min(c.column, -nChars); 0164 if (-nChars > back) { 0165 if (c.line === 0) { 0166 return false; 0167 } 0168 0169 c.line -= 1; 0170 lineLength = this.document.lineLength(c.line); 0171 c.column = lineLength; 0172 nChars += back + 1; // +1 because of wrap-around at start-of-line 0173 } else { 0174 c.column += nChars; 0175 nChars = 0; 0176 } 0177 } 0178 } 0179 0180 this.line = c.line; 0181 this.column = c.column; 0182 return true; 0183 } 0184 0185 DocumentCursor.prototype.toCursor = function() { 0186 return new Cursor(this.line, this.column); 0187 } 0188 0189 DocumentCursor.prototype.toVirtualCursor = function() { 0190 return document.toVirtualCursor(this); 0191 } 0192 0193 // kate: indent-width 2; replace-tabs on;