2016-03-13 00:35:29 +00:00
|
|
|
(function(){
|
|
|
|
var ns = __namespace( "Components.Vim" );
|
|
|
|
|
|
|
|
/** @type {Dandelion} */
|
|
|
|
var Dand = __import( "Dandelion" );
|
|
|
|
/** @type {Dandelion.IDOMElement} */
|
|
|
|
var IDOMElement = __import( "Dandelion.IDOMElement" );
|
|
|
|
/** @type {Dandelion.IDOMObject} */
|
|
|
|
var IDOMObject = __import( "Dandelion.IDOMObject" );
|
|
|
|
/** @type {System.Cycle} */
|
|
|
|
var Cycle = __import( "System.Cycle" );
|
|
|
|
/** @type {System.Debug} */
|
|
|
|
var debug = __import( "System.Debug" );
|
|
|
|
|
|
|
|
var GetLine = function( buffs, l )
|
|
|
|
{
|
|
|
|
/** @type {Components.Vim.LineBuffer} */
|
|
|
|
var LineHead = buffs[0];
|
|
|
|
l ++;
|
|
|
|
|
|
|
|
for( var i = 0, line = LineHead;
|
|
|
|
line && i < l; i ++ )
|
|
|
|
{
|
|
|
|
LineHead = line;
|
|
|
|
while( line )
|
|
|
|
{
|
|
|
|
line = line.next;
|
|
|
|
if( line.br ) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return LineHead;
|
|
|
|
};
|
|
|
|
|
|
|
|
var LineOffset = function( buffs, l )
|
|
|
|
{
|
|
|
|
/** @type {Components.Vim.LineBuffer} */
|
|
|
|
var offset = 0;
|
|
|
|
|
2016-03-13 12:26:26 +00:00
|
|
|
LineLoop:
|
2016-03-13 00:35:29 +00:00
|
|
|
for( var i = 0, line = buffs[0];
|
|
|
|
line && i < l; i ++ )
|
|
|
|
{
|
|
|
|
while( line )
|
|
|
|
{
|
2016-03-13 12:26:26 +00:00
|
|
|
if( line.next && line.next.placeholder )
|
|
|
|
break LineLoop;
|
2016-03-13 00:35:29 +00:00
|
|
|
|
2016-03-14 15:28:30 +00:00
|
|
|
// Using toString because tab is 1 byte
|
|
|
|
// but variable width
|
|
|
|
offset += line.toString().length + 1;
|
2016-03-13 00:35:29 +00:00
|
|
|
line = line.next;
|
2016-03-14 15:28:30 +00:00
|
|
|
|
|
|
|
if( line && line.br ) break;
|
2016-03-13 00:35:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return offset;
|
|
|
|
};
|
|
|
|
|
2016-03-13 12:26:26 +00:00
|
|
|
var Cursor = function( feeder )
|
2016-03-13 00:35:29 +00:00
|
|
|
{
|
2016-03-13 12:26:26 +00:00
|
|
|
/** @type {Components.Vim.LineFeeder} */
|
|
|
|
this.feeder = feeder;
|
|
|
|
|
2016-03-13 18:15:24 +00:00
|
|
|
this.cols = feeder.firstBuffer.cols;
|
2016-03-13 00:35:29 +00:00
|
|
|
|
|
|
|
// The preferred X position
|
|
|
|
this.pX = 0;
|
|
|
|
|
|
|
|
// The displaying X position
|
|
|
|
this.X = 0;
|
|
|
|
|
|
|
|
// The current line resided
|
|
|
|
this.Y = 0;
|
|
|
|
|
|
|
|
// The resulting position
|
|
|
|
this.P = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Can only be 1, -1
|
|
|
|
// 0 will be treated as undefined
|
|
|
|
Cursor.prototype.moveX = function( d )
|
|
|
|
{
|
|
|
|
var x = this.pX;
|
|
|
|
|
|
|
|
var updatePx = Boolean( d );
|
|
|
|
if( updatePx ) x = this.X + d;
|
|
|
|
|
|
|
|
if( !d ) d = 1;
|
|
|
|
|
2016-03-13 12:26:26 +00:00
|
|
|
var buffs = this.feeder.lineBuffers;
|
2016-03-13 00:35:29 +00:00
|
|
|
|
|
|
|
/** @type {Components.Vim.LineBuffer} */
|
|
|
|
var line = GetLine( buffs, this.Y );
|
|
|
|
var content = line.visualLines.join( "\n" );
|
|
|
|
|
|
|
|
var c = content[ x ];
|
|
|
|
|
|
|
|
if( c == undefined )
|
|
|
|
{
|
|
|
|
x = d > 0 ? content.length - 1 : 0;
|
|
|
|
}
|
|
|
|
else if( c == "\n" )
|
|
|
|
{
|
|
|
|
x += d;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.X = x;
|
|
|
|
|
|
|
|
if( updatePx )
|
|
|
|
{
|
|
|
|
this.pX = x;
|
|
|
|
this.updatePosition();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
Cursor.prototype.lineStart = function()
|
|
|
|
{
|
|
|
|
this.pX = 0;
|
|
|
|
this.moveX();
|
|
|
|
this.updatePosition();
|
|
|
|
};
|
|
|
|
|
|
|
|
Cursor.prototype.lineEnd = function()
|
|
|
|
{
|
|
|
|
this.moveX( Number.MAX_VALUE );
|
|
|
|
};
|
|
|
|
|
|
|
|
Cursor.prototype.updatePosition = function()
|
|
|
|
{
|
2016-03-13 12:26:26 +00:00
|
|
|
this.P = this.X + LineOffset( this.feeder.lineBuffers, this.Y );
|
2016-03-13 18:15:24 +00:00
|
|
|
this.feeder.dispatcher.dispatchEvent( new BotanEvent( "VisualUpdate" ) );
|
2016-03-13 00:35:29 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Cursor.prototype.moveY = function( d )
|
|
|
|
{
|
2016-03-13 12:26:26 +00:00
|
|
|
var Y = this.Y;
|
2016-03-14 15:28:30 +00:00
|
|
|
var line;
|
2016-03-13 12:26:26 +00:00
|
|
|
|
|
|
|
Y += d;
|
2016-03-13 18:15:24 +00:00
|
|
|
if( Y < 0 )
|
|
|
|
{
|
|
|
|
Y = 0;
|
|
|
|
}
|
|
|
|
else if( this.feeder.moreAt < Y )
|
2016-03-13 12:26:26 +00:00
|
|
|
{
|
2016-03-13 18:15:24 +00:00
|
|
|
var feeder = this.feeder;
|
|
|
|
var lastLine = feeder.lastBuffer.lineNum;
|
2016-03-14 15:28:30 +00:00
|
|
|
var lineShift = Y - feeder.moreAt;
|
2016-03-13 18:15:24 +00:00
|
|
|
|
|
|
|
var i = 0;
|
|
|
|
while( true )
|
|
|
|
{
|
2016-03-14 15:28:30 +00:00
|
|
|
feeder.pan( undefined, lineShift + i );
|
2016-03-13 18:15:24 +00:00
|
|
|
|
2016-03-14 15:28:30 +00:00
|
|
|
// if it turns out to be the same line
|
|
|
|
// before after panning
|
|
|
|
// we keep scrolling it ( panning )
|
2016-03-13 18:15:24 +00:00
|
|
|
// until the entire line cosumes the screen
|
|
|
|
if( feeder.lastBuffer.lineNum == lastLine )
|
|
|
|
{
|
|
|
|
i ++;
|
|
|
|
}
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
|
2016-03-14 15:28:30 +00:00
|
|
|
// The line number cursor need to be in
|
|
|
|
Y = lastLine + lineShift;
|
|
|
|
|
|
|
|
// Calculate the visual line position
|
2016-03-13 18:15:24 +00:00
|
|
|
for( i = 0, line = feeder.firstBuffer;
|
|
|
|
line != feeder.lastBuffer;
|
|
|
|
line = line.next )
|
|
|
|
{
|
|
|
|
if( line.br ) i ++;
|
|
|
|
if( line.lineNum == Y ) break;
|
|
|
|
}
|
2016-03-13 12:26:26 +00:00
|
|
|
|
2016-03-13 18:15:24 +00:00
|
|
|
this.Y = i;
|
2016-03-13 12:26:26 +00:00
|
|
|
// Keep original position after panning
|
|
|
|
this.moveX();
|
|
|
|
this.updatePosition();
|
2016-03-13 18:15:24 +00:00
|
|
|
|
2016-03-13 19:33:36 +00:00
|
|
|
feeder.softReset();
|
|
|
|
|
2016-03-13 12:26:26 +00:00
|
|
|
return;
|
|
|
|
}
|
2016-03-14 15:28:30 +00:00
|
|
|
else if ( this.Y < Y )
|
|
|
|
{
|
|
|
|
// If panning is forward
|
|
|
|
// and next line does not exists
|
|
|
|
line = this.getLine().nextLine;
|
|
|
|
if( !line || line.placeholder )
|
|
|
|
{
|
|
|
|
// do nothing
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2016-03-13 12:26:26 +00:00
|
|
|
|
|
|
|
this.Y = Y;
|
|
|
|
|
2016-03-13 00:35:29 +00:00
|
|
|
this.moveX();
|
|
|
|
this.updatePosition();
|
|
|
|
};
|
|
|
|
|
2016-03-13 18:15:24 +00:00
|
|
|
Cursor.prototype.getLine = function()
|
|
|
|
{
|
|
|
|
var feeder = this.feeder;
|
|
|
|
var line = feeder.firstBuffer;
|
|
|
|
for( var i = 0;
|
|
|
|
line != feeder.lastBuffer;
|
|
|
|
line = line.next )
|
|
|
|
{
|
|
|
|
if( line.br ) i ++;
|
|
|
|
if( this.Y == i ) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return line;
|
|
|
|
};
|
|
|
|
|
2016-03-13 00:35:29 +00:00
|
|
|
__readOnly( Cursor.prototype, "position", function()
|
|
|
|
{
|
|
|
|
return {
|
|
|
|
start: this.P
|
|
|
|
, end: this.P + 1
|
|
|
|
};
|
|
|
|
} );
|
|
|
|
|
|
|
|
ns[ NS_EXPORT ]( EX_CLASS, "Cursor", Cursor );
|
|
|
|
})();
|