@@ -100,20 +100,6 @@ impl EditorView {
100 let mut spans = Vec::new();
100 let mut spans = Vec::new();
101 let mut visual_x = 0;
101 let mut visual_x = 0;
102 let mut line = 0u16;
102 let mut line = 0u16;
103− let visible_selections: Vec<Range> = if is_focused {
109− // TODO: limit selection to one in viewport
110− // .filter(|range| !range.is_empty()) // && range.overlaps(&Range::new(start, end + 1))
114− // don't render selections on unfocused windows
118 'outer: for event in highlights {
104 'outer: for event in highlights {
119 match event.unwrap() {
105 match event.unwrap() {
@@ -174,26 +160,6 @@ impl EditorView {
174 let grapheme = Cow::from(grapheme);
160 let grapheme = Cow::from(grapheme);
175 let width = grapheme_width(&grapheme) as u16;
161 let width = grapheme_width(&grapheme) as u16;
177− // TODO: this should really happen as an after pass
178− let style = if visible_selections
180− .any(|range| range.contains(char_index))
183− style.clone().bg(Color::Rgb(128, 47, 0))
188− let style = if visible_selections
190− .any(|range| range.head == char_index)
192− style.clone().bg(Color::Rgb(255, 255, 255))
197 // ugh, improve with a traverse method
163 // ugh, improve with a traverse method
198 // or interleave highlight spans with selection and diagnostic spans
164 // or interleave highlight spans with selection and diagnostic spans
199 let is_diagnostic = view.doc.diagnostics.iter().any(|diagnostic| {
165 let is_diagnostic = view.doc.diagnostics.iter().any(|diagnostic| {
@@ -206,8 +172,6 @@ impl EditorView {
209− // TODO: paint cursor heads except primary
211 surface.set_string(
175 surface.set_string(
212 viewport.x + visual_x,
176 viewport.x + visual_x,
213 viewport.y + line,
177 viewport.y + line,
@@ -224,18 +188,102 @@ impl EditorView {
191+ // render selections
194+ let text = view.doc.text().slice(..);
196+ let start = text.line_to_char(view.first_line);
197+ let end = text.line_to_char(last_line + 1);
198+ Range::new(start, end)
200+ let cursor_style = Style::default().bg(Color::Rgb(255, 255, 255));
203+ let selection_style = Style::default().bg(Color::Rgb(128, 47, 0));
205+ for selection in view
211+ .filter(|range| range.overlaps(&screen))
213+ // TODO: render also if only one of the ranges is in viewport
214+ let mut start = view.screen_coords_at_pos(&text, selection.anchor);
215+ let mut end = view.screen_coords_at_pos(&text, selection.head);
218+ if let Some(end) = end {
221+ viewport.x + end.col as u16,
222+ viewport.y + end.row as u16,
230+ if selection.head < selection.anchor {
231+ std::mem::swap(&mut start, &mut end);
233+ let start = start.unwrap_or_else(|| Position::new(0, 0));
234+ let end = end.unwrap_or_else(|| {
235+ Position::new(viewport.height as usize, viewport.width as usize)
238+ if start.row == end.row {
241+ viewport.x + start.col as u16,
242+ viewport.y + start.row as u16,
243+ (end.col - start.col) as u16,
251+ viewport.x + start.col as u16,
252+ viewport.y + start.row as u16,
253+ // text.line(view.first_line).len_chars() as u16 - start.col as u16,
254+ viewport.width - start.col as u16,
259+ for i in start.row + 1..end.row {
263+ viewport.y + i as u16,
264+ // text.line(view.first_line + i).len_chars() as u16,
272+ Rect::new(viewport.x, viewport.y + end.row as u16, end.col as u16, 1),
227 let style: Style = theme.get("ui.linenr");
281 let style: Style = theme.get("ui.linenr");
228 let warning: Style = theme.get("warning");
282 let warning: Style = theme.get("warning");
229 let last_line = view.last_line();
283 let last_line = view.last_line();
230 for (i, line) in (view.first_line..last_line).enumerate() {
284 for (i, line) in (view.first_line..last_line).enumerate() {
231 if view.doc.diagnostics.iter().any(|d| d.line == line) {
285 if view.doc.diagnostics.iter().any(|d| d.line == line) {
232− surface.set_stringn(
286+ surface.set_stringn(viewport.x - OFFSET, viewport.y + i as u16, "●", 1, warning);
233− viewport.x + 0 - OFFSET,
234− viewport.y + i as u16,
241 surface.set_stringn(
289 surface.set_stringn(