Skip to content

Commit

Permalink
Double-wide and double-high line support.
Browse files Browse the repository at this point in the history
  • Loading branch information
Timothy Johnson committed Sep 5, 2016
1 parent 8b11a99 commit 217e567
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 6 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ vala_precompile(VALA_C
src/TerminalOutput.vala
src/CharacterAttributes.vala
src/TerminalView.vala
src/TextView.vala
src/TerminalWidget.vala
src/NestingContainer.vala
src/Autocompletion.vala
Expand Down
49 changes: 49 additions & 0 deletions src/TerminalOutput.vala
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,36 @@ public class TerminalOutput : Gtk.TextBuffer {
line_updated(cursor_position.line);
break;

case TerminalStream.StreamElement.ControlSequenceType.DEC_DOUBLE_WIDTH_LINE:
Gtk.TextIter start, end;
get_iter_at_line(out start, cursor_position.line);
get_iter_at_line(out end, cursor_position.line);
end.forward_to_line_end();

// Add tag to entire line. Text drawn in TextView.draw_layer
apply_tag(tag_table.lookup("double-wide") ?? create_tag("double-wide", "invisible", true), start, end);
break;

case TerminalStream.StreamElement.ControlSequenceType.DEC_DOUBLE_HEIGHT_LINE_TOP_HALF:
Gtk.TextIter start, end;
get_iter_at_line(out start, cursor_position.line);
get_iter_at_line(out end, cursor_position.line);
end.forward_to_line_end();

// Add tag to entire line. Text drawn in TextView.draw_layer
apply_tag(tag_table.lookup("double-top") ?? create_tag("double-top", "invisible", true), start, end);
break;

case TerminalStream.StreamElement.ControlSequenceType.DEC_DOUBLE_HEIGHT_LINE_BOTTOM_HALF:
Gtk.TextIter start, end;
get_iter_at_line(out start, cursor_position.line);
get_iter_at_line(out end, cursor_position.line);
end.forward_to_line_end();

// Add tag to entire line. Text drawn in TextView.draw_layer
apply_tag(tag_table.lookup("double-bottom") ?? create_tag("double-bottom", "invisible", true), start, end);
break;

case TerminalStream.StreamElement.ControlSequenceType.BELL:
// TODO: Beep on the terminal window rather than the default display
Gdk.beep();
Expand Down Expand Up @@ -912,6 +942,25 @@ public class TerminalOutput : Gtk.TextBuffer {
foreach (var tag in tags)
apply_tag(tag, start, iter);

// If this is a double-wide or double-high line expand tag to the new line end
if (!start.ends_line())
{
var end = start;
end.forward_to_line_end();

var tag = tag_table.lookup("double-wide");
if (tag != null && start.ends_tag(tag))
apply_tag(tag, start, end);

tag = tag_table.lookup("double-top");
if (tag != null && start.ends_tag(tag))
apply_tag(tag, start, end);

tag = tag_table.lookup("double-bottom");
if (tag != null && start.ends_tag(tag))
apply_tag(tag, start, end);
}

start = iter;

// Printed text should overwrite previous content on the line
Expand Down
9 changes: 3 additions & 6 deletions src/TerminalView.vala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class TerminalView : Fixed {

var box = new Box (Orientation.VERTICAL, 5);
put (box, 0, 0);

size_allocate.connect((alloc) => {
var child = Gtk.Allocation ();
child.x = 0;
Expand Down Expand Up @@ -103,9 +103,6 @@ public class TerminalOutputView : ScrolledWindow {
this.terminal = terminal;

view = new TextView.with_buffer (terminal.terminal_output);
view.editable = false;
view.cursor_visible = false;
view.wrap_mode = WrapMode.CHAR;
view.motion_notify_event.connect(on_motion_notify_event);
view.button_press_event.connect(on_button_press_event);
view.has_tooltip = true;
Expand Down Expand Up @@ -377,7 +374,7 @@ public class TerminalOutputView : ScrolledWindow {
}

public void scroll_to_position(TerminalOutput.CursorPosition position = {-1, -1}) {
if (position.line == -1 && position.column == -1)
if (position.line == -1 && position.column == -1)
// Default: Scroll to end
vadjustment.value = vadjustment.upper;
else {
Expand Down Expand Up @@ -431,4 +428,4 @@ public class TerminalOutputView : ScrolledWindow {
// TODO: Use Utilities.schedule_execution here?
terminal.update_size();
}
}
}
127 changes: 127 additions & 0 deletions src/TextView.vala
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright © 2013–2014 Philipp Emanuel Weidmann <[email protected]>
* Copyright © 2015-2016 RedHatter <[email protected]>
*
* Nemo vir est qui mundum non reddat meliorem.
*
*
* This file is part of Final Term.
*
* Final Term is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Final Term is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Final Term. If not, see <http://www.gnu.org/licenses/>.
*/

using Gtk;
using Pango;

/**
* Custom TextView to draw double-wide and double-high text.
*/
public class TextView : Gtk.TextView {
public TextView.with_buffer (TextBuffer buffer) {
set_buffer(buffer);
editable = false;
cursor_visible = false;
wrap_mode = Gtk.WrapMode.CHAR;
}

public override void draw_layer (TextViewLayer layer, Cairo.Context cr) {
// Draw after text has been rendered
if (layer != TextViewLayer.BELOW)
return;

//TODO: Cache layout
var line = create_pango_layout(null);
TextIter iter;

// For each of the three types obtain the text using
// forward_to_tag_toggle, apply line styles, set clip, and draw with
// Cairo transforms

// Double-wide: scale x by a factor of 2
buffer.get_iter_at_line(out iter, 0);
var tag = buffer.tag_table.lookup("double-wide");
if (tag != null) {
while (next_segment(cr, tag, ref iter, line)) {
cr.scale(2.0, 1.0);
Pango.cairo_show_layout(cr, line);
cr.scale(0.5, 1.0);
}
}

// Double-high top half: scale both x and y by a factor of 2
buffer.get_iter_at_line(out iter, 0);
tag = buffer.tag_table.lookup("double-top");
if (tag != null) {
while (next_segment(cr, tag, ref iter, line)) {
cr.scale(2.0, 2.0);
Pango.cairo_show_layout(cr, line);
cr.scale(0.5, 0.5);
}
}

// Double-high bottom half: scale both x and y by a factor of 2 and
// shift y up one line
buffer.get_iter_at_line(out iter, 0);
tag = buffer.tag_table.lookup("double-bottom");
if (tag != null) {
while (next_segment(cr, tag, ref iter, line)) {
int line_height;
get_line_yrange (iter, null, out line_height);
cr.rel_move_to(0, -line_height);
cr.scale(2.0, 2.0);
Pango.cairo_show_layout(cr, line);
cr.scale(0.5, 0.5);
}
}
}

private bool next_segment (Cairo.Context cr, TextTag tag, ref TextIter iter, Pango.Layout line) {
if (!iter.forward_to_tag_toggle(tag))
return false; // No more segments

var start = iter;
iter.forward_to_tag_toggle(tag);

// Extract text
var text = buffer.get_text(start, iter, true);
line.set_text(text, -1);

// TODO: Set all attribues from tags

// Set color attribute
var color = get_default_attributes().appearance.fg_color;
var attr = Pango.attr_foreground_new(color.red, color.green, color.blue);
attr.start_index = 0;
attr.end_index = text.length;
var attr_list = new AttrList();
attr_list.change((owned) attr);
line.set_attributes(attr_list);

// Get position shifted by scroll
Gdk.Rectangle pos_rect;
get_cursor_locations(iter, out pos_rect, null);
pos_rect.y -= (int) get_vadjustment().value;
pos_rect.x -= (int) get_hadjustment().value;

// clip and move Cairo
int height;
line.get_pixel_size(null, out height);
cr.reset_clip();
cr.rectangle(pos_rect.x, pos_rect.y, get_allocated_width(), height);
cr.clip();
cr.move_to(pos_rect.x, pos_rect.y);

return true;
}
}

0 comments on commit 217e567

Please sign in to comment.