~kiwec/ke

ref: 337ac6f02307afffb7211dbf895ae4a61d43002f ke/src/Line.cpp -rw-r--r-- 3.1 KiB
337ac6f0 — Wolf Clément Fixed Gutter drawing and Data insertion 3 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "Line.hpp"
#include "Buffer.hpp"
#include "Document.hpp"
#include "Editor.hpp"
#include "Gutter.hpp"
#include <cmath>

void Line::calc_size() {
	auto ptr = begin();
	for(m_size = 0; ptr[m_size] != L'\n' && ptr[m_size] != L'\0'; m_size++);
}

void Line::clear_syntax() {
	for(auto ptr = syntax(); *ptr != L'\n' && *ptr != L'\0'; ptr++) {
		*ptr = 15;
	}
}

void Line::erase(uint start, uint size) {
	m_doc->erase(m_start + start, size);
}

void Line::erase_next() {
	if(is_last()) return;
	m_doc->erase(m_start + m_size, next().m_size + 1);
}

void Line::erase_prev() {
	if(is_first()) return;
	m_doc->erase(m_start - prev().m_size, prev().m_size + 1);
}

wchar_t Line::operator[](uint pos) const {
	return begin()[pos];
}

wchar_t* Line::begin() const {
	return &(*m_doc)[m_start];
}

wchar_t* Line::end() const {
	return begin() + m_size;
}

Line Line::next() const {
	assert(!is_last());

	return Line(m_doc, m_start + m_size + 1, m_number + 1);
}

Line Line::prev() const {
	assert(!is_first());

	auto offset = -2;
	auto ptr = begin();
	for(; m_start + offset > 0 && ptr[offset] != L'\n'; offset--);
	return Line(m_doc, m_start + offset, m_number - 1);
}

Line Line::make_next() {
	m_doc->insert(L"\n", 1, m_start + m_size);
	return Line(m_doc, m_start + m_size + 1, m_number + 1);
}

int Line::get_current_indentation() const {
	uint indent = 0;
	while(indent < length() && operator[](indent) == L'\t') {
		indent++;
	}
	return indent;
}

int Line::get_next_indentation() const {
	if(length() == 0) return 0;
	if(operator[](length() - 1) == '{') return get_current_indentation() + 1;
	return get_current_indentation();
}

bool Line::is_first() const {
	return m_number == 1;
}

bool Line::is_last() const {
	return m_number == m_doc->get_nb_lines();
}

void Line::insert(wchar_t c, uint pos) {
	m_doc->insert(&c, 1, m_start + pos);
}

void Line::insert(wchar_t* str, uint size, uint pos) {
	m_doc->insert(str, size, m_start + pos);
}

void Line::print(uint x, uint y, uint bg) const {
	printFrom(0, x, y, bg);
}

void Line::printFrom(uint start, uint x, uint y, uint bg) const {
	uint c = 0;
	uint8_t scolor;
	auto text = begin();
	uint synmax = length();
	for(uint i = 0; text[i] != L'\0'; i++) {
		// Fallback color in case syntax is not initialized
		if(i + 1 > synmax) scolor = 0;
		else scolor = syntax()[i];

		if(text[i] == L'\t') {
			if(c >= start) {
				for(uint j = 0; j < 4; j++) {
					tb_change_cell(x + c + j - start, y, ' ', scolor, bg);
				}
			}
			c += 4;
		}
		else {
			if(c >= start) {
				tb_change_cell(x + c - start, y, text[i], scolor, bg);
			}
			c++;
		}
	}
}

uint Line::height(Buffer& buf) const {
	double bufWidth = (double)(buf.max_line_width());
	double w = (double)width() + 1.f;
	return ceil(w / bufWidth);
}

syntax_t* Line::syntax() const {
	return &m_doc->syntax()[m_start];
}

std::unique_ptr<wchar_t[]> Line::text_copy() const {
	std::unique_ptr<wchar_t[]> copy(new wchar_t[m_size + 1]);
	memcpy(copy.get(), begin(), m_size);
	copy[m_size] = L'\0';
	return copy;
}

uint Line::width() const {
	uint x = 0;
	for(auto text = begin(); text != end(); text++) {
		if(*text == L'\t') {
			x += 4;
		}
		else {
			x++;
		}
	}

	return x;
}