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;