edn/jni/edn/Buffer/BufferText.cpp

1415 lines
39 KiB
C++

/**
*******************************************************************************
* @file BufferText.cpp
* @brief Editeur De N'ours : Text Buffer (edit only ASCII text File) (header)
* @author Edouard DUPIN
* @date 19/01/2011
* @par Project
* Edn
*
* @par Copyright
* Copyright 2010 Edouard DUPIN, all right reserved
*
* This software is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY.
*
* Licence summary :
* You can modify and redistribute the sources code and binaries.
* You can send me the bug-fix
* You can not earn money with this Software (if the source extract from Edn
* represent less than 50% of original Sources)
* Term of the licence in in the file licence.txt.
*
*******************************************************************************
*/
#include <tools_debug.h>
#include <tools_globals.h>
#include <ClipBoard.h>
#include <BufferText.h>
#include <toolsMemory.h>
#include <etk/RegExp.h>
#include <etk/unicode.h>
#include <ewol/ewol.h>
#include <ewol/OObject.h>
#include <ewol/WidgetManager.h>
#include <ewol/Widget.h>
#include <ewol/Font.h>
#undef __class__
#define __class__ "BufferText"
const uint32_t nbLineAllocatedInBase = 300;
extern "C"
{
const char * g_pointerForTheDisplayLine[] = {"%1d", "%2d","%3d","%4d","%5d","%6d","%7d","%8d","%9d","%d"};
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::BasicInit(void)
{
NeedToCleanEndPage = true;
// set the first element that is displayed
m_displayStartBufferPos = 0;
// set the number of the lineNumber;
nbColoneForLineNumber = 1;
// init the link with the buffer manager
myColorManager = ColorizeManager::getInstance();
// Init Selection mode :
SelectionEnd();
//EDN_INFO("Init");
// new mode :
m_cursorPos = 0;
m_cursorPreferredCol = -1;
//m_cursorMode = CURSOR_DISPLAY_MODE_NORMAL;
m_displayStartPixelX = 0;
m_displayStartLineId = 0;
m_displaySize.x = 200;
m_displaySize.y = 20;
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::NameChange(void)
{
// Find HL system
//EDN_DEBUG("check name change");
if (true == HighlightManager::getInstance()->Exist(m_fileName)) {
Highlight * myHL = HighlightManager::getInstance()->Get(m_fileName);
// Set the new HL
if (NULL != myHL) {
m_EdnBuf.SetHLSystem(myHL);
}
}
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
BufferText::BufferText()
{
BasicInit();
SetModify(true);
EDN_INFO("New(Empty-Buffer)");
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
BufferText::BufferText(etk::File &fileName) : Buffer(fileName)
{
BasicInit();
NameChange();
EDN_INFO("Add Data from file(" << GetFileName() << ")");
FILE * myFile = NULL;
// try to open the file. if not existed, new file
myFile = fopen(fileName.GetCompleateName().c_str(), "r");
if (NULL != myFile) {
m_EdnBuf.DumpFrom(myFile);
// close the input file
fclose(myFile);
SetModify(false);
} else {
// fichier inexistant... creation d'un nouveaux
EDN_WARNING("No File ==> created a new one(" << GetFileName() << ")");
SetModify(true);
}
UpdateWindowsPosition();
ForceReDraw(true);
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::Save(void)
{
EDN_INFO("Save File : \"" << GetFileName() << "\"" );
FILE * myFile = NULL;
myFile = fopen(GetFileName().GetCompleateName().c_str(), "w");
if (NULL != myFile) {
m_EdnBuf.DumpIn(myFile);
fclose(myFile);
SetModify(false);
}
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
BufferText::~BufferText(void)
{
EDN_INFO("Delete(BufferText)");
}
void BufferText::SelectionStart(void)
{
// start a nex selection
SelectionCheckMode();
//EDN_DEBUG("SELECT_start");
}
void BufferText::SelectionEnd(void)
{
//EDN_DEBUG("SELECT_stop");
}
void BufferText::SelectionCheckMode(void)
{
/*
if (true == ewol::IsSetCtrl() ) {
} else {
}
*/
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::GetInfo(infoStatBuffer_ts &infoToUpdate)
{
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::SetLineDisplay(uint32_t lineNumber)
{
}
#define SEPARATION_SIZE_LINE_NUMBER (3)
void BufferText::DrawLineNumber(ewol::OObject2DTextColored* OOText, ewol::OObject2DColored* OOColored, int32_t sizeX, int32_t sizeY,char *myPrint, int32_t lineNumber, int32_t positionY)
{
char tmpLineNumber[50];
sprintf(tmpLineNumber, myPrint, lineNumber);
OOColored->SetColor(myColorManager->Get(COLOR_LIST_BG_2));
OOColored->Rectangle( 0, positionY, sizeX+0.5*SEPARATION_SIZE_LINE_NUMBER, sizeY);
OOText->SetColor(myColorManager->Get(COLOR_CODE_LINE_NUMBER));
OOText->TextAdd(1, positionY, tmpLineNumber, -1);
}
#define CURSOR_WIDTH (5)
#define CURSOR_THICKNESS (1.2)
void BufferText::CursorDisplay(ewol::OObject2DColored* OOColored, int32_t x, int32_t y, int32_t letterHeight, int32_t letterWidth)
{
color_ts & tmpppppp = ColorizeManager::getInstance()->Get(COLOR_CODE_CURSOR);
OOColored->SetColor(tmpppppp);
if (true == ewol::IsSetInsert()) {
OOColored->Rectangle( x, y, letterWidth, letterHeight);
} else {
OOColored->Line( (int32_t)(x-CURSOR_WIDTH), (int32_t)(y) , (int32_t)(x+CURSOR_WIDTH), (int32_t)(y) , CURSOR_THICKNESS);
OOColored->Line( (int32_t)(x-CURSOR_WIDTH), (int32_t)(y+letterHeight-CURSOR_THICKNESS), (int32_t)(x+CURSOR_WIDTH), (int32_t)(y+letterHeight-CURSOR_THICKNESS), CURSOR_THICKNESS);
OOColored->Line( (int32_t)(x) , (int32_t)(y) , (int32_t)(x) , (int32_t)(y+letterHeight-CURSOR_THICKNESS), CURSOR_THICKNESS);
}
}
/**
* @brief Update internal data of the pointer to display
*
* @param[in,out] ---
*
* @return ---
*
*/
/*
void BufferText::UpdatePointerNumber(void)
{
// get the number of line in the buffer
int32_t maxNumberLine = m_EdnBuf.NumberOfLines();
//int32_t maxNumberLine = 2096;
if (10 > maxNumberLine) { m_nbColoneForLineNumber = 1;
} else if (100 > maxNumberLine) { m_nbColoneForLineNumber = 2;
} else if (1000 > maxNumberLine) { m_nbColoneForLineNumber = 3;
} else if (10000 > maxNumberLine) { m_nbColoneForLineNumber = 4;
} else if (100000 > maxNumberLine) { m_nbColoneForLineNumber = 5;
} else if (1000000 > maxNumberLine) { m_nbColoneForLineNumber = 6;
} else if (1000000 > maxNumberLine) { m_nbColoneForLineNumber = 7;
} else if (10000000 > maxNumberLine) { m_nbColoneForLineNumber = 8;
} else if (100000000 > maxNumberLine) { m_nbColoneForLineNumber = 9;
} else { m_nbColoneForLineNumber = 10;
}
}
*/
int32_t BufferText::GetNumberOfLine(void)
{
return m_EdnBuf.CountLines();
}
// TODO : Remove this ... it is really bad...
static int32_t g_basicfontId = 0;
/**
* @brief Display the curent buffer with all the probematic imposed by the xharset and the user contraint.
*
* @param[in,out] drawer the basic user drawer of EDN.
*
* @return
*
*/
int32_t BufferText::Display(ewol::OObject2DTextColored* OOTextNormal,
ewol::OObject2DTextColored* OOTextBold,
ewol::OObject2DTextColored* OOTextItalic,
ewol::OObject2DTextColored* OOTextBoldItalic,
ewol::OObject2DColored* OOColored,
int32_t offsetX, int32_t offsetY,
int32_t sizeX, int32_t sizeY)
{
offsetX -= 40;
if (offsetX<0) {
offsetX = 0;
}
int32_t selStart, selEnd, selRectStart, selRectEnd;
bool selIsRect;
int32_t selHave;
int32_t fontId = OOTextNormal->GetFontID();
// TODO : Remove this ...
g_basicfontId = fontId;
int32_t letterWidth = ewol::GetWidth(fontId, "A");
int32_t letterHeight = ewol::GetHeight(fontId);
m_displayStartLineId = offsetY / letterHeight;
// update the display position with the scroll ofset :
m_displayStartBufferPos = m_EdnBuf.CountForwardNLines(0, m_displayStartLineId);
// update the number of element that can be displayed
m_displaySize.x = (sizeX/letterWidth) + 1 - nbColoneForLineNumber;
m_displaySize.y = (sizeY/letterHeight) + 1;
EDN_VERBOSE("main DIPLAY " << m_displaySize.x << " char * " << m_displaySize.y << " char");
selHave = m_EdnBuf.GetSelectionPos(SELECTION_PRIMARY, selStart, selEnd, selIsRect, selRectStart, selRectEnd);
colorInformation_ts * HLColor = NULL;
// get the number of line in the buffer
int32_t maxNumberLine = m_EdnBuf.NumberOfLines();
char *myPrint = NULL;
if (10 > maxNumberLine) { nbColoneForLineNumber = 1; myPrint = (char *)"%1d";
} else if (100 > maxNumberLine) { nbColoneForLineNumber = 2; myPrint = (char *)"%2d";
} else if (1000 > maxNumberLine) { nbColoneForLineNumber = 3; myPrint = (char *)"%3d";
} else if (10000 > maxNumberLine) { nbColoneForLineNumber = 4; myPrint = (char *)"%4d";
} else if (100000 > maxNumberLine) { nbColoneForLineNumber = 5; myPrint = (char *)"%5d";
} else if (1000000 > maxNumberLine) { nbColoneForLineNumber = 6; myPrint = (char *)"%6d";
} else if (1000000 > maxNumberLine) { nbColoneForLineNumber = 7; myPrint = (char *)"%7d";
} else if (10000000 > maxNumberLine) { nbColoneForLineNumber = 8; myPrint = (char *)"%8d";
} else if (100000000 > maxNumberLine) { nbColoneForLineNumber = 9; myPrint = (char *)"%9d";
} else { nbColoneForLineNumber = 10; myPrint = (char *)"%d";
}
uint32_t y = 0;
int32_t iii, new_i;
// Get color :
Colorize * myColor = myColorManager->Get("normal");
Colorize * myColorSel = myColorManager->Get("SelectedText");
color_ts & myColorSpace = myColorManager->Get(COLOR_CODE_SPACE);
color_ts & myColorTab = myColorManager->Get(COLOR_CODE_TAB);
Colorize * selectColor = NULL;
ewol::OObject2DTextColored* OOTextSelected = NULL;
int mylen = m_EdnBuf.Size();
int32_t x_base=nbColoneForLineNumber*letterWidth;
int32_t idX = 0;
OOColored->SetColor(myColorManager->Get(COLOR_CODE_BASIC_BG));
OOColored->Rectangle( 0, 0, sizeX, sizeY);
int displayLines = 0;
// Regenerate the colorizing if necessary ...
displayHLData_ts m_displayLocalSyntax;
m_EdnBuf.HightlightGenerateLines(m_displayLocalSyntax, m_displayStartBufferPos, m_displaySize.y);
//GTimeVal timeStart;
//g_get_current_time(&timeStart);
uniChar_t displayChar[MAX_EXP_CHAR_LEN];
memset(displayChar, 0, sizeof(uniChar_t)*MAX_EXP_CHAR_LEN);
// draw the lineNumber :
int32_t currentLineID = m_displayStartLineId+1;
EDN_VERBOSE("Start display of text buffer [" << m_displayStartBufferPos<< ".." << mylen << "]");
EDN_VERBOSE("cursor Pos : " << m_cursorPos << "start at pos=" << m_displayStartBufferPos);
DrawLineNumber(OOTextNormal, OOColored, x_base, sizeY, myPrint, currentLineID, y);
int32_t pixelX = x_base + SEPARATION_SIZE_LINE_NUMBER;
clipping_ts drawClipping;
drawClipping.x = 0;
drawClipping.y = 0;
drawClipping.w = sizeX;
drawClipping.h = sizeY;
clipping_ts drawClippingTextArea;
drawClippingTextArea.x = pixelX;
drawClippingTextArea.y = 0;
drawClippingTextArea.w = sizeX - drawClipping.x;
drawClippingTextArea.h = sizeY;
for (iii=m_displayStartBufferPos; iii<mylen && displayLines < m_displaySize.y ; iii = new_i) {
//EDN_DEBUG("diplay element=" << iii);
int displaywidth;
uint32_t currentChar = '\0';
new_i = iii;
displaywidth = m_EdnBuf.GetExpandedChar(new_i, idX, displayChar, currentChar);
int32_t drawSize = 0;
//EDN_INFO("diplay element=" << new_i);
if (currentChar!='\n') {
selectColor = myColor;
HLColor = m_EdnBuf.GetElementColorAtPosition(m_displayLocalSyntax, iii);
if (NULL != HLColor) {
if (NULL != HLColor->patern) {
selectColor = HLColor->patern->GetColor();
}
}
bool haveBg = false;
if( true == selHave
&& selStart <= iii
&& selEnd > iii)
{
selectColor = myColorSel;
OOColored->SetColor(selectColor->GetBG());
haveBg = selectColor->HaveBg();
} else {
if( ' ' == currentChar
&& true == globals::IsSetDisplaySpaceChar() )
{
OOColored->SetColor(myColorSpace);
haveBg = true;
} else if( '\t' == currentChar
&& true == globals::IsSetDisplaySpaceChar() )
{
OOColored->SetColor(myColorTab);
haveBg = true;
} else {
OOColored->SetColor(selectColor->GetBG());
haveBg = selectColor->HaveBg();
}
}
coord2D_ts textPos;
textPos.x = pixelX-offsetX;
textPos.y = y;
if (true == selectColor->GetItalic() ) {
if (true == selectColor->GetBold() ) {
OOTextSelected = OOTextBoldItalic;
} else {
OOTextSelected = OOTextItalic;
}
} else {
if (true == selectColor->GetBold() ) {
OOTextSelected = OOTextBold;
} else {
OOTextSelected = OOTextNormal;
}
}
OOTextSelected->SetColor(selectColor->GetFG());
drawSize = OOTextSelected->TextAdd(textPos, drawClippingTextArea, displayChar);
if (true == haveBg ) {
OOColored->Rectangle(textPos.x, y, drawSize, letterHeight, drawClippingTextArea);
}
}
idX += displaywidth;
// display cursor :
if (m_cursorPos == iii) {
// display the cursor:
CursorDisplay(OOColored, pixelX, y, letterHeight, letterWidth);
}
pixelX += drawSize;
// move to next line ...
if (currentChar=='\n') {
idX =0;
pixelX = x_base + SEPARATION_SIZE_LINE_NUMBER;
y += letterHeight;
displayLines++;
currentLineID++;
DrawLineNumber(OOTextNormal, OOColored, x_base, sizeY, myPrint, currentLineID, y);
}
}
// special case : the cursor is at the end of the buffer...
if (m_cursorPos == iii) {
CursorDisplay(OOColored, pixelX, y, letterHeight, letterWidth);
}
//GTimeVal timeStop;
//g_get_current_time(&timeStop);
//EDN_DEBUG("Display Generation = " << timeStop.tv_usec - timeStart.tv_usec << " micro-s");
return ERR_NONE;
}
int32_t BufferText::GetMousePosition(int32_t width, int32_t height)
{
int32_t letterWidth = ewol::GetWidth(g_basicfontId, "9");
int32_t letterHeight = ewol::GetHeight(g_basicfontId);
int32_t lineOffset = height / letterHeight;
//******************************* get the X position : *******************************************
// get the number of line in the buffer
int32_t maxNumberLine = m_EdnBuf.NumberOfLines();
if (10 > maxNumberLine) { nbColoneForLineNumber = 1;
} else if (100 > maxNumberLine) { nbColoneForLineNumber = 2;
} else if (1000 > maxNumberLine) { nbColoneForLineNumber = 3;
} else if (10000 > maxNumberLine) { nbColoneForLineNumber = 4;
} else if (100000 > maxNumberLine) { nbColoneForLineNumber = 5;
} else if (1000000 > maxNumberLine) { nbColoneForLineNumber = 6;
} else if (1000000 > maxNumberLine) { nbColoneForLineNumber = 7;
} else if (10000000 > maxNumberLine) { nbColoneForLineNumber = 8;
} else if (100000000 > maxNumberLine) { nbColoneForLineNumber = 9;
} else { nbColoneForLineNumber = 10;
}
int32_t iii, new_i;
int mylen = m_EdnBuf.Size();
int32_t x_base=nbColoneForLineNumber*letterWidth + SEPARATION_SIZE_LINE_NUMBER;
int32_t idX = 0;
uniChar_t displayChar[MAX_EXP_CHAR_LEN];
memset(displayChar, 0, sizeof(uniChar_t)*MAX_EXP_CHAR_LEN);
int32_t pixelX = x_base;
int32_t startLinePosition = m_EdnBuf.CountForwardNLines(m_displayStartBufferPos, lineOffset);
if (width <= pixelX) {
EDN_DEBUG(" Element : Befor the start of the line ... ==> END");
return startLinePosition;
}
EDN_VERBOSE("Get id element : x=" << width << "px y=" << height << "px");
EDN_VERBOSE(" line offset = " << lineOffset);
for (iii=startLinePosition; iii<mylen; iii = new_i) {
int displaywidth;
uint32_t currentChar = '\0';
new_i = iii;
displaywidth = m_EdnBuf.GetExpandedChar(new_i, idX, displayChar, currentChar);
if (currentChar!='\n') {
int32_t drawSize = ewol::GetWidth(g_basicfontId, displayChar);
EDN_VERBOSE(" Element : " << currentChar << "=\"" << (char)currentChar << "\" display offset=" << pixelX << "px width=" << drawSize << "px");
pixelX += drawSize;
if (width <= pixelX) {
EDN_VERBOSE(" Find IT ==> END");
// find position ...
break;
}
} else {
EDN_VERBOSE(" Element : \"\\n\" display width=---px ==> end of line ==> END");
// end of line ... exit cycle
break;
}
idX += displaywidth;
}
EDN_VERBOSE("BufferText::GetMousePosition(" << width << "," << height << "); ==> " << iii );
return iii;
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
// TODO : Simplify selection ....
void BufferText::MouseEvent(int32_t width, int32_t height)
{
if (true == ewol::IsSetShift() ) {
MouseSelectFromCursorTo(width, height);
} else {
// Get the caracter mouse position
int32_t newPos = GetMousePosition(width, height);
// move the cursor
SetInsertPosition(newPos);
// if a preferred column wasn't aleady established, establish it
/*if (m_cursorPreferredCol < 0) {
m_cursorPreferredCol = posX;
}*/
m_EdnBuf.Unselect(SELECTION_PRIMARY);
ForceReDraw(true);
UpdateWindowsPosition();
}
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
* @todo : Set the move up and DOWN...
*
*/
// TODO : Simplify selection ....
void BufferText::MouseSelectFromCursorTo(int32_t width, int32_t height)
{
// Get the caracter mouse position
int32_t newPos = GetMousePosition(width, height);
int32_t selStart, selEnd, selRectStart, selRectEnd;
bool selIsRect;
int32_t selHave = m_EdnBuf.GetSelectionPos(SELECTION_PRIMARY, selStart, selEnd, selIsRect, selRectStart, selRectEnd);
//EDN_DEBUG("BufferText:: " << selHave << " = BufGetSelectionPos(SELECTION_PRIMARY," << selStart << "," << selEnd << "," << selIsRect << "," << selRectStart << "," << selRectEnd << ");" );
int32_t rememberCursorPos = m_cursorPos;
// move the cursor
SetInsertPosition(newPos);
// if a preferred column wasn't aleady established, establish it
/*if (m_cursorPreferredCol < 0) {
m_cursorPreferredCol = posX;
}*/
if (false == selHave) {
m_EdnBuf.Select(SELECTION_PRIMARY, rememberCursorPos, m_cursorPos);
} else {
if (rememberCursorPos == selStart) {
m_EdnBuf.Select(SELECTION_PRIMARY, m_cursorPos, selEnd);
} else {
m_EdnBuf.Select(SELECTION_PRIMARY, selStart, m_cursorPos);
}
}
ForceReDraw(true);
UpdateWindowsPosition();
}
/**
* @brief double click : select the data around the selection
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::MouseEventDouble(void)
{
int32_t beginPos, endPos;
if (true == m_EdnBuf.SelectAround(m_cursorPos, beginPos, endPos)) {
m_EdnBuf.Select(SELECTION_PRIMARY, beginPos, endPos);
m_cursorPos = endPos;
ForceReDraw(true);
}
// no else
}
/**
* @brief triple click select all the line
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::MouseEventTriple(void)
{
m_EdnBuf.Select(SELECTION_PRIMARY, m_EdnBuf.StartOfLine(m_cursorPos), m_EdnBuf.EndOfLine(m_cursorPos));
m_cursorPos = m_EdnBuf.EndOfLine(m_cursorPos);
ForceReDraw(true);
}
void BufferText::RemoveLine(void)
{
int32_t start = m_EdnBuf.StartOfLine(m_cursorPos);
int32_t stop = m_EdnBuf.EndOfLine(m_cursorPos);
m_EdnBuf.Remove(start, stop+1);
SetInsertPosition(start);
SetModify(true);
}
void BufferText::SelectAll(void)
{
m_EdnBuf.Select(SELECTION_PRIMARY, 0, m_EdnBuf.Size());
m_cursorPos = m_EdnBuf.Size();
ForceReDraw(true);
}
void BufferText::SelectNone(void)
{
m_EdnBuf.Unselect(SELECTION_PRIMARY);
ForceReDraw(true);
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::ScrollDown(void)
{
MoveUpDown(3);
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::ScrollUp(void)
{
MoveUpDown(-3);
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::MoveUpDown(int32_t ofset)
{
if (ofset >= 0) {
int32_t nbLine = m_EdnBuf.NumberOfLines();
if (m_displayStartLineId+ofset+3 > nbLine) {
m_displayStartLineId = nbLine-3;
} else {
m_displayStartLineId += ofset;
}
m_displayStartBufferPos = m_EdnBuf.CountForwardNLines(0, m_displayStartLineId);
} else {
ofset *= -1;
if (m_displayStartLineId < ofset) {
m_displayStartLineId = 0;
m_displayStartBufferPos = 0;
} else {
m_displayStartLineId -= ofset;
m_displayStartBufferPos = m_EdnBuf.CountForwardNLines(0, m_displayStartLineId);
}
}
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::ForceReDraw(bool allElement)
{
NeedToCleanEndPage = true;
}
void BufferText::SetInsertPosition(int32_t newPos, bool insertChar)
{
int32_t SelectionStart, SelectionEnd, SelectionRectStart, SelectionRectEnd;
bool SelectionIsRect;
bool haveSelectionActive = m_EdnBuf.GetSelectionPos(SELECTION_PRIMARY, SelectionStart, SelectionEnd, SelectionIsRect, SelectionRectStart, SelectionRectEnd);
int32_t rememberCursorPos = m_cursorPos;
//EDN_DEBUG("newPos=" << newPos);
// unselect buffer:
m_EdnBuf.Unselect(SELECTION_PRIMARY);
/* make sure new position is ok, do nothing if it hasn't changed */
if (newPos != m_cursorPos) {
if (newPos < 0){
newPos = 0;
}
if (newPos > m_EdnBuf.Size()) {
newPos = m_EdnBuf.Size();
}
m_cursorPos = newPos;
}
m_cursorPreferredCol = -1;
// special case when insert char ...
if (true == insertChar) {
return;
}
if( false == haveSelectionActive
&& true == ewol::IsSetShift() )
{
// new selection
m_EdnBuf.Select(SELECTION_PRIMARY, rememberCursorPos, m_cursorPos);
} else if( true == ewol::IsSetShift()
&& true == haveSelectionActive)
{
// update selection
if (rememberCursorPos == SelectionStart) {
m_EdnBuf.Select(SELECTION_PRIMARY, m_cursorPos, SelectionEnd);
} else {
m_EdnBuf.Select(SELECTION_PRIMARY, SelectionStart, m_cursorPos);
}
}
}
bool BufferText::TextDMoveUp(int32_t offset)
{
int32_t lineStartPos, column, prevLineStartPos, newPos;
// Find the position of the start of the line.
lineStartPos = m_EdnBuf.StartOfLine(m_cursorPos);
// check if we can go up ...
if (lineStartPos == 0) {
return false;
}
// Decide what column to move to, if there's a preferred column use that
if (m_cursorPreferredCol >= 0) {
column = m_cursorPreferredCol;
} else {
column = m_EdnBuf.CountDispChars(lineStartPos, m_cursorPos);
}
// Get the previous line
prevLineStartPos = m_EdnBuf.CountBackwardNLines(lineStartPos, offset);
//EDN_INFO("Move Line UP result : prevLineStartPos=" << prevLineStartPos);
// Get the display char position
newPos = m_EdnBuf.CountForwardDispChars(prevLineStartPos, column);
//EDN_INFO("Move to colomn : column=" << column << " newPos=" << newPos);
// move the cursor
SetInsertPosition(newPos);
// if a preferred column wasn't aleady established, establish it
if (m_cursorPreferredCol < 0) {
m_cursorPreferredCol = column;
}
return true;
}
bool BufferText::TextDMoveDown(int32_t offset)
{
int32_t lineStartPos, column, nextLineStartPos, newPos;
// check if we are not at the end of Buffer
if (m_cursorPos == m_EdnBuf.Size() ) {
return false;
}
// Find the position of the start of the line.
lineStartPos = m_EdnBuf.StartOfLine(m_cursorPos);
if (m_cursorPreferredCol >= 0) {
column = m_cursorPreferredCol;
} else {
column = m_EdnBuf.CountDispChars(lineStartPos, m_cursorPos);
}
// get the next line :
nextLineStartPos = m_EdnBuf.CountForwardNLines(lineStartPos, offset);
//EDN_INFO("Move Line DOWN result : nextLineStartPos=" << nextLineStartPos);
// Get the display char position
newPos = m_EdnBuf.CountForwardDispChars(nextLineStartPos, column);
//EDN_INFO("Move to colomn : column=" << column << " newPos=" << newPos);
SetInsertPosition(newPos);
// if a preferred column wasn't aleady established, establish it
if (m_cursorPreferredCol < 0) {
m_cursorPreferredCol = column;
}
return true;
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::cursorMove(ewol::eventKbMoveType_te moveTypeEvent)
{
bool needUpdatePosition = true;
// check selection event ...
/*
if (true == ewol::IsSetShift() ) {
if ( CURSOR_MODE_NORMAL == cursorMode) {
SelectionStart();
} else {
SelectionCheckMode();
}
} else {
SelectionEnd();
}
*/
switch(moveTypeEvent) {
case ewol::EVENT_KB_MOVE_TYPE_LEFT:
//EDN_INFO("keyEvent : <LEFT>");
if (m_cursorPos > 0) {
SetInsertPosition(m_cursorPos - 1);
}
break;
case ewol::EVENT_KB_MOVE_TYPE_RIGHT:
//EDN_INFO("keyEvent : <RIGHT>");
if (m_cursorPos < m_EdnBuf.Size() ) {
SetInsertPosition(m_cursorPos + 1);
}
break;
case ewol::EVENT_KB_MOVE_TYPE_UP:
//EDN_INFO("keyEvent : <UP>");
TextDMoveUp(1);
break;
case ewol::EVENT_KB_MOVE_TYPE_DOWN:
//EDN_INFO("keyEvent : <DOWN>");
// check if we have enought line ...
TextDMoveDown(1);
break;
case ewol::EVENT_KB_MOVE_TYPE_PAGE_UP:
//EDN_INFO("keyEvent : <PAGE-UP>");
TextDMoveUp(m_displaySize.y);
break;
case ewol::EVENT_KB_MOVE_TYPE_PAGE_DOWN:
//EDN_INFO("keyEvent : <PAGE-DOWN>");
TextDMoveDown(m_displaySize.y);
break;
case ewol::EVENT_KB_MOVE_TYPE_START:
//EDN_INFO("keyEvent : <Start of line>");
SetInsertPosition(m_EdnBuf.StartOfLine(m_cursorPos) );
break;
case ewol::EVENT_KB_MOVE_TYPE_END:
//EDN_INFO("keyEvent : <End of line>");
SetInsertPosition(m_EdnBuf.EndOfLine(m_cursorPos) );
break;
default:
//LastUpDownCursorPosition = -1;
needUpdatePosition = false;
break;
}
if ( true == needUpdatePosition) {
UpdateWindowsPosition();
}
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::UpdateWindowsPosition(bool centerPage)
{
if (centerPage == false) {
/*
// Display position (Y mode):
//EDN_INFO("BufferText::UpdateWindowsPosition() m_displayStart(" << m_displayStartPixelX << "px," << m_displayStartLineId << "id) m_displaySize(" << m_displaySize.x << "," <<m_displaySize.y << ")");
position_ts cursorPosition;
cursorPosition.y = m_EdnBuf.CountLines(0, m_cursorPos);
int32_t lineStartPos = m_EdnBuf.StartOfLine(m_cursorPos);
cursorPosition.x = m_EdnBuf.CountDispChars(lineStartPos, m_cursorPos);
//EDN_INFO("BufferText::UpdateWindowsPosition() curent cursor position : (" << cursorPosition.x << "," << cursorPosition.y << ")");
if (m_displayStartLineId > (int32_t)cursorPosition.y - globals::getNbLineBorder() ) {
m_displayStartLineId = cursorPosition.y - globals::getNbLineBorder();
if (m_displayStartLineId < 0) {
m_displayStartLineId = 0;
ForceReDraw(true);
}
} else if (m_displayStartLineId + m_displaySize.y <= (int32_t)cursorPosition.y + globals::getNbLineBorder() ) {
m_displayStartLineId = cursorPosition.y - m_displaySize.y + globals::getNbLineBorder() + 1;
ForceReDraw(true);
}
// Display position (X mode):
//EDN_INFO("cursorPosition X : " << cursorPosition.y << " windows " << m_displayStartLineId << "=>" << m_displayStartPixelX + m_displaySize.x);
if (m_displayStartPixelX > cursorPosition.x - globals::getNbColoneBorder() ) {
m_displayStartPixelX = cursorPosition.x - globals::getNbColoneBorder();
if (m_displayStartPixelX < 0) {
m_displayStartPixelX = 0;
ForceReDraw(true);
}
} else if (m_displayStartPixelX + m_displaySize.x <= cursorPosition.x + globals::getNbColoneBorder() ) {
m_displayStartPixelX = cursorPosition.x - m_displaySize.x + globals::getNbColoneBorder() + 1;
ForceReDraw(true);
}
//update the buffer position ID :
m_displayStartBufferPos = m_EdnBuf.CountForwardNLines(0, m_displayStartLineId);
*/
} else {
// center the line at the middle of the screen :
position_ts cursorPosition;
//EDN_DEBUG(" -------------------------------------------------");
cursorPosition.y = m_EdnBuf.CountLines(0, m_cursorPos);
//EDN_DEBUG(" cursor position : " << m_cursorPos << " ==> ligne=" << cursorPosition.y);
cursorPosition.x = 0;
m_displayStartPixelX = 0;
//EDN_DEBUG(" display size : " << m_displaySize.y);
m_displayStartLineId = cursorPosition.y - m_displaySize.y/2;
m_displayStartLineId = edn_max(m_displayStartLineId, 0);
m_displayStartBufferPos = m_EdnBuf.CountForwardNLines(0, m_displayStartLineId);
ForceReDraw(true);
//EDN_DEBUG(" display start : " << m_displayStartPixelX << "x" << m_displayStartLineId);
//EDN_DEBUG(" -------------------------------------------------");
}
}
/**
* @brief
*
* @param[in,out] ---
*
* @return ---
*
*/
void BufferText::AddChar(uniChar_t unicodeData)
{
int32_t SelectionStart, SelectionEnd, SelectionRectStart, SelectionRectEnd;
bool SelectionIsRect;
bool haveSelectionActive = m_EdnBuf.GetSelectionPos(SELECTION_PRIMARY, SelectionStart, SelectionEnd, SelectionIsRect, SelectionRectStart, SelectionRectEnd);
if (unicodeData == 0x09) {
if (false == haveSelectionActive) {
etk::VectorType<int8_t> tmpVect;
tmpVect.PushBack(0x09);
m_EdnBuf.Insert(m_cursorPos, tmpVect);
SetInsertPosition(m_cursorPos+1, true);
} else {
// Indent depend of the multiline in the selection ...
// count the number of line :
int32_t nbSelectedLines = m_EdnBuf.CountLines(SelectionStart, SelectionEnd);
if (0 == nbSelectedLines) {
etk::VectorType<int8_t> tmpVect;
tmpVect.PushBack(0x09);
m_EdnBuf.ReplaceSelected(SELECTION_PRIMARY, tmpVect);
SetInsertPosition(SelectionStart+tmpVect.Size(), true);
} else {
if (true == ewol::IsSetShift() ) {
m_cursorPos = m_EdnBuf.UnIndent(SELECTION_PRIMARY);
} else {
m_cursorPos = m_EdnBuf.Indent(SELECTION_PRIMARY);
}
}
}
} else if (unicodeData == '\n') {
etk::VectorType<int8_t> tmpVect;
if (true == ewol::IsSetShift()) {
tmpVect.PushBack('\r');
} else {
tmpVect.PushBack('\n');
// if Auto indent Enable ==> we get the start of the previous line and add it to tne new one
if (true == globals::IsSetAutoIndent() ) {
int32_t l_lineStart;
// Get the begin of the line or the begin of the line befor selection
if (false == haveSelectionActive) {
l_lineStart = m_EdnBuf.StartOfLine(m_cursorPos);
} else {
l_lineStart = m_EdnBuf.StartOfLine(SelectionStart);
}
// add same characters in the temporar buffer
for (int32_t kk=l_lineStart; kk<m_cursorPos; kk++) {
if (' ' == m_EdnBuf[kk]) {
tmpVect.PushBack(' ');
} else if('\t' == m_EdnBuf[kk]) {
tmpVect.PushBack('\t');
} else {
break;
}
}
}
}
// Set temporary buffer in the real buffer
if (false == haveSelectionActive) {
m_EdnBuf.Insert(m_cursorPos, tmpVect);
SetInsertPosition(m_cursorPos+tmpVect.Size(), true);
} else {
m_EdnBuf.ReplaceSelected(SELECTION_PRIMARY, tmpVect);
SetInsertPosition(SelectionStart+tmpVect.Size(), true);
}
} else if (unicodeData == 0x7F ) {
//EDN_INFO("keyEvent : <Suppr> pos=" << m_cursorPos);
if (false == haveSelectionActive) {
m_EdnBuf.Remove(m_cursorPos, m_cursorPos+1);
} else {
m_EdnBuf.RemoveSelected(SELECTION_PRIMARY);
SetInsertPosition(SelectionStart, true);
}
} else if (unicodeData == 0x08) {
//EDN_INFO("keyEvent : <Del> pos=" << m_cursorPos);
if (false == haveSelectionActive) {
m_EdnBuf.Remove(m_cursorPos-1, m_cursorPos);
SetInsertPosition(m_cursorPos-1, true);
} else {
m_EdnBuf.RemoveSelected(SELECTION_PRIMARY);
SetInsertPosition(SelectionStart, true);
}
} else {
// normal adding char ...
if (true == m_EdnBuf.GetUTF8Mode()) {
char tmpUTF8[16];
unicode::convertUnicodeToUtf8(unicodeData, tmpUTF8);
etk::VectorType<int8_t> tmpVect;
int32_t localOfset = strlen(tmpUTF8);
tmpVect.PushBack((int8_t*)tmpUTF8, localOfset);
if (false == haveSelectionActive) {
m_EdnBuf.Insert(m_cursorPos, tmpVect);
SetInsertPosition(m_cursorPos+localOfset, true);
} else {
m_EdnBuf.ReplaceSelected(SELECTION_PRIMARY, tmpVect);
SetInsertPosition(SelectionStart+localOfset, true);
}
} else {
// convert in the Good ISO format :
char output_ISO;
unicode::convertUnicodeToIso(m_EdnBuf.GetCharsetType(), unicodeData, output_ISO);
//printf(" insert : \"%s\"==> 0x%08x=%d ", UTF8data, (unsigned int)output_ISO, (int)output_ISO);
etk::VectorType<int8_t> tmpVect;
tmpVect.PushBack(output_ISO);
if (false == haveSelectionActive) {
m_EdnBuf.Insert(m_cursorPos, tmpVect);
SetInsertPosition(m_cursorPos+1, true);
} else {
m_EdnBuf.ReplaceSelected(SELECTION_PRIMARY, tmpVect);
SetInsertPosition(SelectionStart+1, true);
}
}
}
SetModify(true);
UpdateWindowsPosition();
}
int32_t BufferText::FindLine(etk::String &data)
{
if ( 0 == data.Size()) {
EDN_WARNING("no search data");
return 0;
}
EDN_INFO("Search data line : \"" << data << "\"");
etk::VectorType<int8_t> mVectSearch;
mVectSearch = data.GetVector();
//EDN_INFO("search data Forward : startSearchPos=" << startSearchPos );
int32_t foundPos;
bool findSomething = m_EdnBuf.SearchForward(0, mVectSearch, &foundPos, true);
// if find data :
if (true == findSomething) {
return m_EdnBuf.CountLines(0, foundPos);
} else {
return 0;
}
}
void BufferText::JumpAtLine(int32_t newLine)
{
int32_t positionLine = m_EdnBuf.CountForwardNLines(0, newLine);
m_EdnBuf.Unselect(SELECTION_PRIMARY);
EDN_DEBUG("jump at the line : " << newLine );
SetInsertPosition(positionLine);
UpdateWindowsPosition(true);
}
/**
* @brief Get the current line (to know where to jump)
*
* @param ---
*
* @return Return the current line number
*
*/
int32_t BufferText::GetCurrentLine(void)
{
return m_EdnBuf.CountLines(0, m_cursorPos);
}
void BufferText::Search(etk::String &data, bool back, bool caseSensitive, bool wrap, bool regExp)
{
EDN_INFO("Search data : \"" << data << "\"");
int32_t SelectionStart, SelectionEnd, SelectionRectStart, SelectionRectEnd;
bool SelectionIsRect;
bool haveSelectionActive = m_EdnBuf.GetSelectionPos(SELECTION_PRIMARY, SelectionStart, SelectionEnd, SelectionIsRect, SelectionRectStart, SelectionRectEnd);
int32_t startSearchPos = m_cursorPos;
if (true == haveSelectionActive) {
if (false == back) {
startSearchPos = SelectionEnd;
} else {
startSearchPos = SelectionStart;
}
}
if ( 0 == data.Size()) {
EDN_WARNING("no search data");
return;
}
etk::VectorType<int8_t> mVectSearch;
mVectSearch = data.GetVector();
if (false == back) {
//EDN_INFO("search data Forward : startSearchPos=" << startSearchPos );
int32_t foundPos;
bool findSomething = m_EdnBuf.SearchForward(startSearchPos, mVectSearch, &foundPos, caseSensitive);
if( false == findSomething
&& true == wrap)
{
//EDN_INFO("WrapMode !!! 0 ==> end");
findSomething = m_EdnBuf.SearchForward(0, mVectSearch, &foundPos, caseSensitive);
}
// if find data :
if (true == findSomething) {
// select new position
int32_t endSelectionPos = foundPos+mVectSearch.Size();
SetInsertPosition(endSelectionPos);
m_EdnBuf.Select(SELECTION_PRIMARY, foundPos, endSelectionPos);
UpdateWindowsPosition();
}
} else {
//EDN_INFO("search data Backward : " << data.GetDirectPointer() );
int32_t foundPos;
bool findSomething = m_EdnBuf.SearchBackward(startSearchPos, mVectSearch, &foundPos, caseSensitive);
if( false == findSomething
&& true == wrap)
{
//EDN_INFO("WrapMode !!! end ==> 0");
findSomething = m_EdnBuf.SearchBackward(m_EdnBuf.Size(), mVectSearch, &foundPos, caseSensitive);
}
// if find data :
if (true == findSomething) {
// select new position
int32_t endSelectionPos = foundPos+mVectSearch.Size();
SetInsertPosition(foundPos);
m_EdnBuf.Select(SELECTION_PRIMARY, foundPos, endSelectionPos);
UpdateWindowsPosition();
}
}
// NOTE : Need to be use in the highligner and the current buffer when we select Regular Expression ...
/*
// Test avec le truc de regExp :
char * myBuf = m_EdnBuf.GetRange(0, m_EdnBuf.Size());
regexp *compiledRE;
char *compileMsg;
compiledRE = CompileRE(data.GetDirectPointer(), &compileMsg, REDFLT_STANDARD);
if (compiledRE == NULL) {
EDN_ERROR("RegExpression : \"" << data.GetDirectPointer() << "\" error named : \"" << compileMsg << "\"" );
} else {
EDN_DEBUG("RegExpression : \"" << data.GetDirectPointer() << "\" OK ... ");
if (true == ExecRE(compiledRE, NULL, myBuf, NULL, false, '\0', '\0', NULL, NULL)) {
EDN_INFO(" ==> top_branch=" << compiledRE->top_branch << "; extentpBW=" << (int32_t)(compiledRE->extentpBW - myBuf) << "; extentpFW=" << (int32_t)(compiledRE->extentpFW - myBuf));
} else {
EDN_INFO(" ==> not fined ... ");
}
}
// free copy of buffer ...
if (myBuf != NULL) {
free(myBuf);
}
*/
}
void BufferText::Replace(etk::String &data)
{
int32_t SelectionStart, SelectionEnd, SelectionRectStart, SelectionRectEnd;
bool SelectionIsRect;
bool haveSelectionActive = m_EdnBuf.GetSelectionPos(SELECTION_PRIMARY, SelectionStart, SelectionEnd, SelectionIsRect, SelectionRectStart, SelectionRectEnd);
if (true == haveSelectionActive) {
// Replace Data :
etk::VectorType<int8_t> myData = data.GetVector();
m_EdnBuf.ReplaceSelected(SELECTION_PRIMARY, myData);
SetInsertPosition(SelectionStart + myData.Size());
}
SetModify(true);
}
/**
* @brief request a copy of the selection in the named clipBoard ID
*
* @param[in] clipboardID Id of the buffer we want to get data [0..10] (0 copy normal / 10 middle button)
*
* @return ---
*
*/
void BufferText::Copy(int8_t clipboardID)
{
etk::VectorType<int8_t> mVect;
// get the curent selected data
if (true == m_EdnBuf.SelectHasSelection(SELECTION_PRIMARY) ) {
m_EdnBuf.GetSelectionText(SELECTION_PRIMARY, mVect);
}
// copy data in the click board :
ClipBoard::Set(clipboardID, mVect);
}
/**
* @brief Request a copy and a remove of the curent selection in the named clipBoard ID
*
* @param[in] clipboardID Id of the buffer we want to get data [0..10] (0 copy normal / 10 middle button)
*
* @return ---
*
*/
void BufferText::Cut(int8_t clipboardID)
{
int32_t SelectionStart, SelectionEnd, SelectionRectStart, SelectionRectEnd;
bool SelectionIsRect;
bool haveSelectionActive = m_EdnBuf.GetSelectionPos(SELECTION_PRIMARY, SelectionStart, SelectionEnd, SelectionIsRect, SelectionRectStart, SelectionRectEnd);
// copy data
Copy(clipboardID);
// remove data :
if (true == haveSelectionActive ) {
EDN_INFO("REMOVE SELECTION");
m_EdnBuf.RemoveSelected(SELECTION_PRIMARY);
m_cursorPos = SelectionStart;
}
UpdateWindowsPosition();
ForceReDraw(true);
SetModify(true);
}
/**
* @brief request the past of a specific clipboard on the curent position or selection
*
* @param[in] clipboardID Id of the buffer we want to get data [0..10] (0 copy normal / 10 middle button)
*
* @return ---
*
*/
void BufferText::Paste(int8_t clipboardID)
{
etk::VectorType<int8_t> mVect;
// copy data from the click board :
ClipBoard::Get(clipboardID, mVect);
int32_t SelectionStart, SelectionEnd, SelectionRectStart, SelectionRectEnd;
bool SelectionIsRect;
bool haveSelectionActive = m_EdnBuf.GetSelectionPos(SELECTION_PRIMARY, SelectionStart, SelectionEnd, SelectionIsRect, SelectionRectStart, SelectionRectEnd);
if (true == haveSelectionActive ) {
// replace data
m_EdnBuf.ReplaceSelected(SELECTION_PRIMARY, mVect );
m_cursorPos = SelectionStart + mVect.Size();
} else {
// insert data
m_EdnBuf.Insert(m_cursorPos, mVect);
m_cursorPos += mVect.Size();
}
UpdateWindowsPosition();
ForceReDraw(true);
SetModify(true);
}
void BufferText::Undo(void)
{
int32_t newPos = m_EdnBuf.Undo();
if (newPos >= 0) {
SetInsertPosition(newPos, true);
UpdateWindowsPosition();
ForceReDraw(true);
SetModify(true);
}
}
void BufferText::Redo(void)
{
int32_t newPos = m_EdnBuf.Redo();
if (newPos >= 0) {
SetInsertPosition(newPos, true);
UpdateWindowsPosition();
ForceReDraw(true);
SetModify(true);
}
}
void BufferText::SetCharset(unicode::charset_te newCharset)
{
m_EdnBuf.SetCharsetType(newCharset);
ForceReDraw(true);
}