📄 textdocument.cpp
字号:
}
else
{
xpos ++;
}
}
longest = max(longest, xpos);*/
return 100;//longest;
}
//
// Return information about specified line
//
bool TextDocument::lineinfo_from_lineno(ULONG lineno, ULONG *lineoff_chars, ULONG *linelen_chars, ULONG *lineoff_bytes, ULONG *linelen_bytes)
{
if(lineno < m_nNumLines)
{
if(linelen_chars) *linelen_chars = m_pLineBuf_char[lineno+1] - m_pLineBuf_char[lineno];
if(lineoff_chars) *lineoff_chars = m_pLineBuf_char[lineno];
if(linelen_bytes) *linelen_bytes = m_pLineBuf_byte[lineno+1] - m_pLineBuf_byte[lineno];
if(lineoff_bytes) *lineoff_bytes = m_pLineBuf_byte[lineno];
return true;
}
else
{
return false;
}
}
//
// Perform a reverse lookup - file-offset to line number
//
bool TextDocument::lineinfo_from_offset(ULONG offset_chars, ULONG *lineno, ULONG *lineoff_chars, ULONG *linelen_chars, ULONG *lineoff_bytes, ULONG *linelen_bytes)
{
ULONG low = 0;
ULONG high = m_nNumLines-1;
ULONG line = 0;
if(m_nNumLines == 0)
{
if(lineno) *lineno = 0;
if(lineoff_chars) *lineoff_chars = 0;
if(linelen_chars) *linelen_chars = 0;
if(lineoff_bytes) *lineoff_bytes = 0;
if(linelen_bytes) *linelen_bytes = 0;
return false;
}
while(low <= high)
{
line = (high + low) / 2;
if(offset_chars >= m_pLineBuf_char[line] && offset_chars < m_pLineBuf_char[line+1])
{
break;
}
else if(offset_chars < m_pLineBuf_char[line])
{
high = line-1;
}
else
{
low = line+1;
}
}
if(lineno) *lineno = line;
if(lineoff_bytes) *lineoff_bytes = m_pLineBuf_byte[line];
if(linelen_bytes) *linelen_bytes = m_pLineBuf_byte[line+1] - m_pLineBuf_byte[line];
if(lineoff_chars) *lineoff_chars = m_pLineBuf_char[line];
if(linelen_chars) *linelen_chars = m_pLineBuf_char[line+1] - m_pLineBuf_char[line];
return true;
}
int TextDocument::getformat()
{
return m_nFileFormat;
}
ULONG TextDocument::size()
{
return m_nDocLength_bytes;
}
TextIterator TextDocument::iterate(ULONG offset_chars)
{
ULONG off_bytes = charoffset_to_byteoffset(offset_chars);
ULONG len_bytes = m_nDocLength_bytes - off_bytes;
//if(!lineinfo_from_offset(offset_chars, 0, linelen, &offset_bytes, &length_bytes))
// return TextIterator();
return TextIterator(off_bytes, len_bytes, this);
}
//
//
//
TextIterator TextDocument::iterate_line(ULONG lineno, ULONG *linestart, ULONG *linelen)
{
ULONG offset_bytes;
ULONG length_bytes;
if(!lineinfo_from_lineno(lineno, linestart, linelen, &offset_bytes, &length_bytes))
return TextIterator();
return TextIterator(offset_bytes, length_bytes, this);
}
TextIterator TextDocument::iterate_line_offset(ULONG offset_chars, ULONG *lineno, ULONG *linestart)
{
ULONG offset_bytes;
ULONG length_bytes;
if(!lineinfo_from_offset(offset_chars, lineno, linestart, 0, &offset_bytes, &length_bytes))
return TextIterator();
return TextIterator(offset_bytes, length_bytes, this);
}
ULONG TextDocument::lineno_from_offset(ULONG offset)
{
ULONG lineno = 0;
lineinfo_from_offset(offset, &lineno, 0, 0, 0, 0);
return lineno;
}
ULONG TextDocument::offset_from_lineno(ULONG lineno)
{
ULONG lineoff = 0;
lineinfo_from_lineno(lineno, &lineoff, 0, 0, 0);
return lineoff;
}
//
// Retrieve an entire line of text
//
ULONG TextDocument::getline(ULONG nLineNo, TCHAR *buf, ULONG buflen, ULONG *off_chars)
{
ULONG offset_bytes;
ULONG length_bytes;
ULONG offset_chars;
ULONG length_chars;
if(!lineinfo_from_lineno(nLineNo, &offset_chars, &length_chars, &offset_bytes, &length_bytes))
{
*off_chars = 0;
return 0;
}
gettext(offset_bytes, length_bytes, buf, &buflen);
*off_chars = offset_chars;
return buflen;
}
//
// Convert the RAW buffer in underlying file-format to UTF-16
//
//
// utf16len - [in/out] on input holds size of utf16str buffer,
// on output holds number of utf16 characters stored
//
// returns bytes processed from rawdata
//
size_t TextDocument::rawdata_to_utf16(BYTE *rawdata, size_t rawlen, TCHAR *utf16str, size_t *utf16len)
{
switch(m_nFileFormat)
{
// convert from ANSI->UNICODE
case NCP_ASCII:
return ascii_to_utf16(rawdata, rawlen, (UTF16 *)utf16str, utf16len);
case NCP_UTF8:
return utf8_to_utf16(rawdata, rawlen, (UTF16 *)utf16str, utf16len);
// already unicode, do a straight memory copy
case NCP_UTF16:
rawlen /= sizeof(TCHAR);
return copy_utf16((UTF16 *)rawdata, rawlen, (UTF16 *)utf16str, utf16len) * sizeof(TCHAR);
// need to convert from big-endian to little-endian
case NCP_UTF16BE:
rawlen /= sizeof(TCHAR);
return swap_utf16((UTF16 *)rawdata, rawlen, (UTF16 *)utf16str, utf16len) * sizeof(TCHAR);
// error! we should *never* reach this point
default:
*utf16len = 0;
return 0;
}
}
//
// Converts specified UTF16 string to the underlying RAW format of the text-document
// (i.e. UTF-16 -> UTF-8
// UTF-16 -> UTF-32 etc)
//
// returns number of WCHARs processed from utf16str
//
size_t TextDocument::utf16_to_rawdata(TCHAR *utf16str, size_t utf16len, BYTE *rawdata, size_t *rawlen)
{
switch(m_nFileFormat)
{
// convert from UTF16 -> ASCII
case NCP_ASCII:
return utf16_to_ascii((UTF16 *)utf16str, utf16len, rawdata, rawlen);
// convert from UTF16 -> UTF8
case NCP_UTF8:
return utf16_to_utf8((UTF16 *)utf16str, utf16len, rawdata, rawlen);
// already unicode, do a straight memory copy
case NCP_UTF16:
*rawlen /= sizeof(TCHAR);
utf16len = copy_utf16((UTF16 *)utf16str, utf16len, (UTF16 *)rawdata, rawlen);
*rawlen *= sizeof(TCHAR);
return utf16len;
// need to convert from big-endian to little-endian
case NCP_UTF16BE:
*rawlen /= sizeof(TCHAR);
utf16len = swap_utf16((UTF16 *)utf16str, utf16len, (UTF16 *)rawdata, rawlen);
*rawlen *= sizeof(TCHAR);
return utf16len;
// error! we should *never* reach this point
default:
*rawlen = 0;
return 0;
}
}
//
// Insert UTF-16 text at specified BYTE offset
//
// returns number of BYTEs stored
//
ULONG TextDocument::insert_raw(ULONG offset_bytes, TCHAR *text, ULONG length)
{
BYTE buf[0x100];
ULONG buflen;
ULONG copied;
ULONG rawlen = 0;
ULONG offset = offset_bytes+ m_nHeaderSize;
while(length)
{
buflen = 0x100;
copied = utf16_to_rawdata(text, length, buf, (size_t *)&buflen);
// do the piece-table insertion!
if(!m_seq.insert(offset, buf, buflen))
break;
text += copied;
length -= copied;
rawlen += buflen;
offset += buflen;
}
m_nDocLength_bytes = m_seq.size();
return rawlen;
}
ULONG TextDocument::replace_raw(ULONG offset_bytes, TCHAR *text, ULONG length, ULONG erase_chars)
{
BYTE buf[0x100];
ULONG buflen;
ULONG copied;
ULONG rawlen = 0;
ULONG offset = offset_bytes + m_nHeaderSize;
ULONG erase_bytes = count_chars(offset_bytes, erase_chars);
while(length)
{
buflen = 0x100;
copied = utf16_to_rawdata(text, length, buf, (size_t *)&buflen);
// do the piece-table replacement!
if(!m_seq.replace(offset, buf, buflen, erase_bytes))
break;
text += copied;
length -= copied;
rawlen += buflen;
offset += buflen;
erase_bytes = 0;
}
m_nDocLength_bytes = m_seq.size();
return rawlen;
}
//
// Erase is a little different. Need to work out how many
// bytes the specified number of UTF16 characters takes up
//
ULONG TextDocument::erase_raw(ULONG offset_bytes, ULONG length)
{
/*TCHAR buf[0x100];
ULONG buflen;
ULONG bytes;
ULONG erase_bytes = 0;
ULONG erase_offset = offset_bytes;
while(length)
{
buflen = min(0x100, length);
bytes = gettext(offset_bytes, 0x100, buf, &buflen);
erase_bytes += bytes;
offset_bytes += bytes;
length -= buflen;
}
// do the piece-table deletion!
if(m_seq.erase(erase_offset + m_nHeaderSize, erase_bytes))
{
m_nDocLength_bytes = m_seq.size();
return length;
}*/
ULONG erase_bytes = count_chars(offset_bytes, length);
if(m_seq.erase(offset_bytes + m_nHeaderSize, erase_bytes))
{
m_nDocLength_bytes = m_seq.size();
return length;
}
return 0;
}
//
// return number of bytes comprising 'length_chars' characters
// in the underlying raw file
//
ULONG TextDocument::count_chars(ULONG offset_bytes, ULONG length_chars)
{
switch(m_nFileFormat)
{
case NCP_ASCII:
return length_chars;
case NCP_UTF16:
case NCP_UTF16BE:
return length_chars * sizeof(WCHAR);
default:
break;
}
ULONG offset_start = offset_bytes;
while(length_chars && offset_bytes < m_nDocLength_bytes)
{
TCHAR buf[0x100];
ULONG charlen = min(length_chars, 0x100);
ULONG bytelen;
bytelen = gettext(offset_bytes, m_nDocLength_bytes - offset_bytes, buf, &charlen);
length_chars -= charlen;
offset_bytes += bytelen;
}
return offset_bytes - offset_start;
}
ULONG TextDocument::byteoffset_to_charoffset(ULONG offset_bytes)
{
switch(m_nFileFormat)
{
case NCP_ASCII:
return offset_bytes;
case NCP_UTF16:
case NCP_UTF16BE:
return offset_bytes / sizeof(WCHAR);
case NCP_UTF8:
case NCP_UTF32:
case NCP_UTF32BE:
// bug bug! need to implement this.
default:
break;
}
return 0;
}
ULONG TextDocument::charoffset_to_byteoffset(ULONG offset_chars)
{
switch(m_nFileFormat)
{
case NCP_ASCII:
return offset_chars;
case NCP_UTF16:
case NCP_UTF16BE:
return offset_chars * sizeof(WCHAR);
case NCP_UTF8:
case NCP_UTF32:
case NCP_UTF32BE:
default:
break;
}
ULONG lineoff_chars;
ULONG lineoff_bytes;
if(lineinfo_from_offset(offset_chars, 0, &lineoff_chars, 0, &lineoff_bytes, 0))
{
return count_chars(lineoff_bytes, offset_chars - lineoff_chars)
+ lineoff_bytes;
}
else
{
return 0;
}
}
//
// Insert text at specified character-offset
//
ULONG TextDocument::insert_text(ULONG offset_chars, TCHAR *text, ULONG length)
{
ULONG offset_bytes = charoffset_to_byteoffset(offset_chars);
return insert_raw(offset_bytes, text, length);
}
//
// Overwrite text at specified character-offset
//
ULONG TextDocument::replace_text(ULONG offset_chars, TCHAR *text, ULONG length, ULONG erase_len)
{
ULONG offset_bytes = charoffset_to_byteoffset(offset_chars);
return replace_raw(offset_bytes, text, length, erase_len);
}
//
// Erase text at specified character-offset
//
ULONG TextDocument::erase_text(ULONG offset_chars, ULONG length)
{
ULONG offset_bytes = charoffset_to_byteoffset(offset_chars);
return erase_raw(offset_bytes, length);
}
bool TextDocument::Undo(ULONG *offset_start, ULONG *offset_end)
{
ULONG start, length;
if(!m_seq.undo())
return false;
start = m_seq.event_index() - m_nHeaderSize;
length = m_seq.event_length();
*offset_start = byteoffset_to_charoffset(start);
*offset_end = byteoffset_to_charoffset(start+length);
m_nDocLength_bytes = m_seq.size();
return true;
}
bool TextDocument::Redo(ULONG *offset_start, ULONG *offset_end)
{
ULONG start, length;
if(!m_seq.redo())
return false;
start = m_seq.event_index() - m_nHeaderSize;
length = m_seq.event_length();
*offset_start = byteoffset_to_charoffset(start);
*offset_end = byteoffset_to_charoffset(start+length);
m_nDocLength_bytes = m_seq.size();
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -