/* ====================================================================
* Copyright (c) 2003-2006, Martin Hauner
* http://subcommander.tigris.org
*
* Subcommander is licensed as described in the file doc/COPYING, which
* you should have received as part of this distribution.
* ====================================================================
*/
// sc
#include "Tab.h"
#include "util/utf8.h"
/**
* \brief construct a Tab object.
*
* \param tabWidth use tabwidth spaces for a single tab in the column
* calculations.
*/
Tab::Tab( unsigned int tabWidth )
: _tabwidth(tabWidth)
{
}
/**
* \brief calc the number of columns in a string.
* A CRLF counts as a single column.
*
* \param s an utf-8 encoded 0 terminated string.
*/
unsigned int Tab::calcColumns( const char* s )
{
unsigned int chars = 0;
if( ! s )
{
return 0;
}
while( *s )
{
if( *s == '\t' && (chars % _tabwidth == 0) )
{
chars += _tabwidth;
}
else if( *s == '\r' || *s == '\n' )
{
// on any line end marker we are done
break;
}
else
{
chars += 1;
}
s = utf8::next8( s );
}
return chars;
}
/**
* \brief calc next column, on tab jump tabwidth.
* A CRLF counts as a single column.
*
* \param s an utf-8 encoded 0 terminated string.
* \param pos current column position.
*/
int Tab::calcColumnForNextChar( const char* s, int pos )
{
int col = 0;
if( ! s )
{
return pos;
}
while( *s && col <= pos )
{
if( *s == '\t' && (col % _tabwidth == 0) )
{
col += _tabwidth;
}
else
{
col += 1;
// on any line end marker we are done
// next col is after end of line
if( *s == '\r' || *s == '\n' )
{
break;
}
}
s = utf8::next8( s );
}
return col;
}
/**
* \brief calc prev column, on tab jump tabwidth.
* A CRLF counts as a single column.
*
* \param s an utf-8 encoded 0 terminated string.
* \param pos current column position.
*/
int Tab::calcColumnForPrevChar( const char* s, int pos )
{
int col = 0;
if( ! s )
{
return pos;
}
while( *s && col < pos )
{
int plus = 0;
if( *s == '\t' && (col % _tabwidth == 0) )
{
plus = _tabwidth;
}
else if( *s == '\r' || *s == '\n' )
{
// shouldn't happen
}
else
{
plus = 1;
}
if( col + plus >= pos )
{
break;
}
col += plus;
s = utf8::next8( s );
}
return col;
}
/**
* \brief calc the character offset for the character at the given column.
* A CRLF counts as a single column.
*
* \param s an utf-8 encoded 0 terminated string.
* \param col the column for which we calculate the character offset.
*/
int Tab::calcCharOffsetForColumn( const char* s, int col )
{
int pos = 0;
int chr = 0;
if( ! s )
{
return pos;
}
while( *s && pos < col )
{
if( *s == '\t' && (pos % _tabwidth == 0) )
{
pos += _tabwidth;
}
else if( *s == '\r' || *s == '\n' )
{
// shouldn't happen
break;
}
else
{
pos += 1;
}
s = utf8::next8( s );
chr++;
}
return chr;
}
/**
* \brief calc the nearest column position for the given column.
* This is used if you click into the space of a tab to position
* a cursor at the column where the tab begins or the tab ends.
*
* \param s an utf-8 encoded 0 terminated string.
* \param col the column for which we calculate the new column.
*/
int Tab::calcColumnForColumn( const char* s, int col )
{
int ncol = 0;
if( ! s )
{
return 0;
}
while( *s && ncol <= col )
{
int add = 0;
if( *s == '\t' && (ncol % _tabwidth == 0) )
{
add = _tabwidth;
}
else if( *s == '\r' || *s == '\n' )
{
// count CRLF as one column
}
else
{
add = 1;
}
if( ncol + add > col )
{
break;
}
ncol += add;
s = utf8::next8( s );
}
return ncol;
}
syntax highlighted by Code2HTML, v. 0.9.1