#include "caret.h"
#include <assert.h>
#include "WindowOp.h"
void createCaret( HWND hwnd, PData data )
{
CreateCaret(hwnd, NULL, 1, getCharHeight(hwnd) + 1);
data->isCaretCreated = TRUE;
}
void destroyCaret( HWND hwnd, PData data )
{
assert(data->isCaretCreated);
HideCaret(hwnd);
DestroyCaret();
data->isCaretCreated = FALSE;
}
void showCaret( HWND hwnd, PData data )
{
int caretX;
int caretY;
if (!data->isCaretCreated)
createCaret(hwnd, data);
getCaretXY(hwnd, data, &caretX, &caretY);
SetCaretPos( caretX, caretY );
ShowCaret(hwnd);
}
void getCaretXY( HWND hwnd, PData data, int *caretX, int *caretY )
{
int chX, chY;
int pxX, pxY;
int curBlockIdx;
int curLineIdx;
char const * line;
chX = data->nCaretCharBefore;
chY = 0;
curBlockIdx = data->nFirstBlock;
curLineIdx = data->nFirstLineInFirstBlock;
if (isLower( data->nFirstBlock, data->nFirstLineInFirstBlock, data->nCaretBlock, data->nCaretLineInBlock))
{
while (curBlockIdx != data->nCaretBlock || curLineIdx != data->nCaretLineInBlock)
{
nextLine(data, curBlockIdx, curLineIdx, &curBlockIdx, &curLineIdx);
chY++;
}
}
else
{
while (curBlockIdx != data->nCaretBlock || curLineIdx != data->nCaretLineInBlock)
{
prevLine(data, curBlockIdx, curLineIdx, &curBlockIdx, &curLineIdx);
chY--;
}
}
line = data->text->blocks[data->nCaretBlock]->lines[data->nCaretLineInBlock];
pxX = (chX == 0 ? 0 : getLineLength(hwnd, line, data->nCaretCharBefore));
pxY = chY * getCharHeight(hwnd);
*caretX = pxX;
*caretY = pxY;
}
void updateCaret( HWND hwnd, PData data )
{
int caretX;
int caretY;
assert(data->isCaretCreated);
getCaretXY(hwnd, data, &caretX, &caretY);
SetCaretPos( caretX, caretY );
}
void saveCaretData( PData data, PCaretData cData )
{
int lineIdx;
cData->nBlock = data->nCaretBlock;
cData->nCharBefore = 0;
for (lineIdx = 0; lineIdx < data->nCaretLineInBlock; ++lineIdx)
{
cData->nCharBefore += (int)strlen(data->text->blocks[data->nCaretBlock]->lines[lineIdx]);
}
cData->nCharBefore += data->nCaretCharBefore;
}
void restoreFromCaretData( PData data, PCaretData cData )
{
int lineIdx;
int prevCharsCount;
PBlock block;
block = data->text->blocks[cData->nBlock];
data->nCaretBlock = cData->nBlock;
for (lineIdx = 0, prevCharsCount = 0;
lineIdx < block->linesCount && !(prevCharsCount <= cData->nCharBefore && cData->nCharBefore < prevCharsCount + (int)strlen(block->lines[lineIdx]));
lineIdx++)
{
prevCharsCount += (int)strlen(block->lines[lineIdx]);
}
if (lineIdx == block->linesCount)
{
data->nCaretLineInBlock = block->linesCount - 1;
data->nCaretCharBefore = (int)strlen(block->lines[block->linesCount - 1]);
}
else
{
data->nCaretLineInBlock = lineIdx;
data->nCaretCharBefore = cData->nCharBefore - prevCharsCount;
}
}
void moveCaretRight( HWND hwnd, PData data )
{
CaretData cData;
saveCaretData(data, &cData);
cData.nCharBefore++;
if (cData.nCharBefore > getBlockCharCount(data->text->blocks[cData.nBlock]))
{
if (cData.nBlock + 1 >= data->text->blockCount)
{
cData.nCharBefore--;
}
else
{
cData.nCharBefore = 0;
cData.nBlock++;
}
}
restoreFromCaretData(data, &cData);
}
void moveCaretLeft( HWND hwnd, PData data )
{
CaretData cData;
saveCaretData(data, &cData);
cData.nCharBefore--;
if (cData.nCharBefore < 0)
{
if (cData.nBlock - 1 < 0)
{
cData.nCharBefore++;
}
else
{
cData.nBlock--;
cData.nCharBefore = getBlockCharCount(data->text->blocks[cData.nBlock]);
}
}
restoreFromCaretData(data, &cData);
}