[wrap] start support for word wrapping and fix a variety of glitches

pull/69/head
Timothy Stack 11 years ago
parent 50d50fb5a8
commit c3d51190c8

@ -189,6 +189,10 @@ public:
} }
}; };
void invalidate() {
this->cleanup();
};
/** @param gpd The sink to send results to. */ /** @param gpd The sink to send results to. */
void set_control(grep_proc_control *gpc) void set_control(grep_proc_control *gpc)
{ {

@ -325,6 +325,9 @@ COMMANDS
Enable a inactive 'filter-in' or 'filter-out' Enable a inactive 'filter-in' or 'filter-out'
expression. expression.
disable-word-wrap Disable word wrapping in the log and text file views.
enable-word-wrap Enable word wrapping in the log and text file views.
open <filename>[:<line>] open <filename>[:<line>]
Open the given file within lnav and, if it is a Open the given file within lnav and, if it is a
text file, switch to the text view and jump to text file, switch to the text view and jump to
@ -348,7 +351,7 @@ COMMANDS
session <cmd> Add the given command to the session file session <cmd> Add the given command to the session file
(~/.lnav/session). Any commands listed in the session file (~/.lnav/session). Any commands listed in the session file
are executed on startup. Only the highlight and are executed on startup. Only the highlight, word-wrap, and
filter-related commands can be added to the session file. filter-related commands can be added to the session file.
create-logline-table <table-name> create-logline-table <table-name>

@ -148,6 +148,10 @@ public:
int row, int row,
string_attrs_t &value_out); string_attrs_t &value_out);
size_t text_size_for_line(textview_curses &tc, int row, bool raw) {
return 0;
};
int value_for_row(vis_line_t row) int value_for_row(vis_line_t row)
{ {
int grow = row / (this->buckets_per_group() + 1); int grow = row / (this->buckets_per_group() + 1);

@ -86,9 +86,14 @@ public:
// if false is returned, the merge is complete // if false is returned, the merge is complete
bool get_top(owner_t *&owner, iterator_t& iterator) bool get_top(owner_t *&owner, iterator_t& iterator)
{ {
owner = top_node_ptr_mbr->owner_ptr; if (top_node_ptr_mbr->has_iterator) {
iterator = top_node_ptr_mbr->current_iterator; owner = top_node_ptr_mbr->owner_ptr;
return iterator != top_node_ptr_mbr->end_iterator; iterator = top_node_ptr_mbr->current_iterator;
return iterator != top_node_ptr_mbr->end_iterator;
}
else {
return false;
}
} }
private: private:
@ -422,6 +427,7 @@ void kmerge_tree_c<T, owner_t, iterator_t, comparitor>::compare_nodes(kmerge_tre
node_rec* parent_ptr = node_ptr->parent_ptr; node_rec* parent_ptr = node_ptr->parent_ptr;
parent_ptr->owner_ptr = winner_ptr->owner_ptr; parent_ptr->owner_ptr = winner_ptr->owner_ptr;
parent_ptr->has_iterator = winner_ptr->has_iterator;
parent_ptr->current_iterator = winner_ptr->current_iterator; parent_ptr->current_iterator = winner_ptr->current_iterator;
parent_ptr->end_iterator = winner_ptr->end_iterator; parent_ptr->end_iterator = winner_ptr->end_iterator;
parent_ptr->source_node_ptr = winner_ptr; parent_ptr->source_node_ptr = winner_ptr;

@ -49,6 +49,7 @@ listview_curses::listview_curses()
lv_height(0), lv_height(0),
lv_needs_update(true), lv_needs_update(true),
lv_show_scrollbar(true), lv_show_scrollbar(true),
lv_word_wrap(false),
lv_mouse_y(-1), lv_mouse_y(-1),
lv_mouse_mode(LV_MODE_NONE) lv_mouse_mode(LV_MODE_NONE)
{ } { }
@ -102,12 +103,12 @@ bool listview_curses::handle_key(int ch)
case 'b': case 'b':
case KEY_BACKSPACE: case KEY_BACKSPACE:
case KEY_PPAGE: case KEY_PPAGE:
this->shift_top(-height); this->shift_top(-(this->rows_available(this->lv_top, RD_UP) - vis_line_t(1)));
break; break;
case ' ': case ' ':
case KEY_NPAGE: case KEY_NPAGE:
this->shift_top(height); this->shift_top(this->rows_available(this->lv_top, RD_DOWN) - vis_line_t(1));
break; break;
case KEY_HOME: case KEY_HOME:
@ -115,10 +116,9 @@ bool listview_curses::handle_key(int ch)
break; break;
case KEY_END: { case KEY_END: {
vis_line_t tail_bottom(this->get_inner_height() - height + 1);
vis_line_t last_line(this->get_inner_height() - 1); vis_line_t last_line(this->get_inner_height() - 1);
vis_line_t tail_bottom(this->get_top_for_last_row());
tail_bottom = max(vis_line_t(0), tail_bottom);
if (this->get_top() == last_line) if (this->get_top() == last_line)
this->set_top(tail_bottom); this->set_top(tail_bottom);
else if (tail_bottom <= this->get_top()) else if (tail_bottom <= this->get_top())
@ -155,7 +155,7 @@ bool listview_curses::handle_key(int ch)
void listview_curses::do_update(void) void listview_curses::do_update(void)
{ {
if (this->lv_window != NULL && this->lv_needs_update) { if (this->lv_window != NULL && this->lv_needs_update) {
vis_line_t y(this->lv_y), height, bottom, lines, row; vis_line_t y(this->lv_y), height, bottom, row;
attr_line_t overlay_line; attr_line_t overlay_line;
vis_line_t overlay_height(0); vis_line_t overlay_height(0);
struct line_range lr; struct line_range lr;
@ -168,19 +168,13 @@ void listview_curses::do_update(void)
} }
this->get_dimensions(height, width); this->get_dimensions(height, width);
lr.lr_start = this->lv_left;
lr.lr_end = this->lv_left + width;
row_count = this->get_inner_height(); row_count = this->get_inner_height();
if (this->lv_top >= (int)row_count) {
this->lv_top = max(vis_line_t(0), vis_line_t(row_count) - height);
}
row = this->lv_top; row = this->lv_top;
lines = min(height - overlay_height,
vis_line_t(row_count) - this->lv_top);
bottom = y + height; bottom = y + height;
for (; y < bottom; ++y) { while (y < bottom) {
lr.lr_start = this->lv_left;
lr.lr_end = this->lv_left + width;
if (this->lv_overlay_source != NULL && if (this->lv_overlay_source != NULL &&
this->lv_overlay_source->list_value_for_overlay( this->lv_overlay_source->list_value_for_overlay(
*this, *this,
@ -188,24 +182,31 @@ void listview_curses::do_update(void)
overlay_line)) { overlay_line)) {
this->mvwattrline(this->lv_window, y, 0, overlay_line, lr); this->mvwattrline(this->lv_window, y, 0, overlay_line, lr);
overlay_line.clear(); overlay_line.clear();
++y;
} }
else if (lines > 0) { else if (row < row_count) {
attr_line_t al; attr_line_t al;
this->lv_source->listview_value_for_row(*this, row, al); this->lv_source->listview_value_for_row(*this, row, al);
this->mvwattrline(this->lv_window, y, 0, al, lr); do {
--lines; this->mvwattrline(this->lv_window, y, 0, al, lr);
lr.lr_start += width;
lr.lr_end += width;
++y;
} while (this->lv_word_wrap && y < bottom && lr.lr_start < al.length());
++row; ++row;
} }
else { else {
wmove(this->lv_window, y, 0); wmove(this->lv_window, y, 0);
wclrtoeol(this->lv_window); wclrtoeol(this->lv_window);
++y;
} }
} }
if (this->lv_show_scrollbar) { if (this->lv_show_scrollbar) {
double progress = 1.0; double progress = 1.0;
double coverage = 1.0; double coverage = 1.0;
vis_line_t lines;
if (this->get_inner_height() > 0) { if (this->get_inner_height() > 0) {
progress = (double)this->lv_top / (double)row_count; progress = (double)this->lv_top / (double)row_count;

@ -66,6 +66,9 @@ public:
vis_line_t row, vis_line_t row,
attr_line_t &value_out) = 0; attr_line_t &value_out) = 0;
virtual size_t listview_size_for_row(const listview_curses &lv,
vis_line_t row) = 0;
virtual std::string listview_source_name(const listview_curses &lv) { virtual std::string listview_source_name(const listview_curses &lv) {
return ""; return "";
}; };
@ -149,6 +152,49 @@ public:
void set_show_scrollbar(bool ss) { this->lv_show_scrollbar = ss; }; void set_show_scrollbar(bool ss) { this->lv_show_scrollbar = ss; };
bool get_show_scrollbar() const { return this->lv_show_scrollbar; }; bool get_show_scrollbar() const { return this->lv_show_scrollbar; };
void set_word_wrap(bool ww) { this->lv_word_wrap = ww; };
bool get_word_wrap() const { return this->lv_word_wrap; };
enum row_direction_t {
RD_UP = -1,
RD_DOWN = 1,
};
vis_line_t rows_available(vis_line_t line, row_direction_t dir) {
unsigned long width;
vis_line_t height;
vis_line_t retval(0);
this->get_dimensions(height, width);
if (this->lv_word_wrap) {
size_t row_count = this->lv_source->listview_rows(*this);
while ((height > 0) && (line >= 0) && (line < row_count)) {
size_t len = this->lv_source->listview_size_for_row(*this, line);
do {
len -= std::min(width, len);
--height;
} while (len > 0);
line += vis_line_t(dir);
++retval;
}
}
else {
switch (dir) {
case RD_UP:
retval = std::min(height, line + vis_line_t(1));
break;
case RD_DOWN:
retval = std::min(height,
vis_line_t(this->lv_source->listview_rows(*this) - line));
break;
}
}
return retval;
};
/** @param win The curses window this view is attached to. */ /** @param win The curses window this view is attached to. */
void set_window(WINDOW *win) { this->lv_window = win; }; void set_window(WINDOW *win) { this->lv_window = win; };
@ -192,12 +238,24 @@ public:
/** @return The line number that is displayed at the bottom. */ /** @return The line number that is displayed at the bottom. */
vis_line_t get_bottom() vis_line_t get_bottom()
{ {
vis_line_t retval, height; vis_line_t retval = this->lv_top;
unsigned long width;
this->get_dimensions(height, width); retval += vis_line_t(this->rows_available(retval, RD_DOWN) - 1);
retval = std::min(this->lv_top + height - vis_line_t(1),
vis_line_t(this->get_inner_height() - 1)); return retval;
};
vis_line_t get_top_for_last_row() {
vis_line_t retval(0);
if (this->get_inner_height() > 0) {
vis_line_t last_line(this->get_inner_height() - 1);
retval = last_line - vis_line_t(this->rows_available(last_line, RD_UP) - 1);
if ((retval + 1) < this->get_inner_height()) {
++retval;
}
}
return retval; return retval;
}; };
@ -259,7 +317,10 @@ public:
*/ */
unsigned int shift_left(int offset) unsigned int shift_left(int offset)
{ {
if (offset < 0 && this->lv_left < (unsigned int)-offset) { if (this->lv_word_wrap) {
alerter::singleton().chime();
}
else if (offset < 0 && this->lv_left < (unsigned int)-offset) {
this->set_left(0); this->set_left(0);
} }
else { else {
@ -353,6 +414,7 @@ protected:
* is needed. * is needed.
*/ */
bool lv_show_scrollbar; /*< Draw the scrollbar in the view. */ bool lv_show_scrollbar; /*< Draw the scrollbar in the view. */
bool lv_word_wrap;
struct timeval lv_mouse_time; struct timeval lv_mouse_time;
int lv_scroll_accel; int lv_scroll_accel;

@ -529,10 +529,9 @@ void rebuild_indexes(bool force)
logfile_sub_source &lss = lnav_data.ld_log_source; logfile_sub_source &lss = lnav_data.ld_log_source;
textview_curses & log_view = lnav_data.ld_views[LNV_LOG]; textview_curses & log_view = lnav_data.ld_views[LNV_LOG];
textview_curses & text_view = lnav_data.ld_views[LNV_TEXT]; textview_curses & text_view = lnav_data.ld_views[LNV_TEXT];
vis_line_t old_bottom(0), height(0); vis_line_t old_bottom(0);
content_line_t top_content = content_line_t(-1); content_line_t top_content = content_line_t(-1);
unsigned long width;
bool scroll_down; bool scroll_down;
size_t old_count; size_t old_count;
time_t old_time; time_t old_time;
@ -552,9 +551,8 @@ void rebuild_indexes(bool force)
bool new_data = false; bool new_data = false;
size_t new_count; size_t new_count;
text_view.get_dimensions(height, width); old_bottom = text_view.get_top_for_last_row();
old_bottom = text_view.get_top() + height; scroll_down = text_view.get_top() >= old_bottom;
scroll_down = (size_t)old_bottom > tss->text_line_count();
for (iter = tss->tss_files.begin(); for (iter = tss->tss_files.begin();
iter != tss->tss_files.end(); ) { iter != tss->tss_files.end(); ) {
@ -619,15 +617,14 @@ void rebuild_indexes(bool force)
text_view.reload_data(); text_view.reload_data();
new_count = tss->text_line_count(); new_count = tss->text_line_count();
if (scroll_down && new_count >= (size_t)old_bottom) { if (scroll_down && text_view.get_top_for_last_row() > text_view.get_top()) {
text_view.set_top(vis_line_t(new_count - height + 1)); text_view.set_top(text_view.get_top_for_last_row());
} }
} }
old_time = lnav_data.ld_top_time; old_time = lnav_data.ld_top_time;
log_view.get_dimensions(height, width); old_bottom = log_view.get_top_for_last_row();
old_bottom = log_view.get_top() + height; scroll_down = log_view.get_top() >= old_bottom;
scroll_down = (size_t)old_bottom > old_count;
if (force) { if (force) {
old_count = 0; old_count = 0;
} }
@ -638,8 +635,8 @@ void rebuild_indexes(bool force)
log_view.reload_data(); log_view.reload_data();
if (scroll_down && new_count >= (size_t)old_bottom) { if (scroll_down && log_view.get_top_for_last_row() > log_view.get_top()) {
log_view.set_top(vis_line_t(new_count - height + 1)); log_view.set_top(log_view.get_top_for_last_row());
} }
else if (!scroll_down && force) { else if (!scroll_down && force) {
content_line_t new_top_content = content_line_t(-1); content_line_t new_top_content = content_line_t(-1);
@ -658,6 +655,9 @@ void rebuild_indexes(bool force)
start_line = force ? grep_line_t(0) : grep_line_t(-1); start_line = force ? grep_line_t(0) : grep_line_t(-1);
if (force) { if (force) {
if (lnav_data.ld_search_child[LNV_LOG].get() != NULL) {
lnav_data.ld_search_child[LNV_LOG]->get_grep_proc()->invalidate();
}
log_view.match_reset(); log_view.match_reset();
} }
@ -707,6 +707,10 @@ public:
value_out = this->tds_lines[row]; value_out = this->tds_lines[row];
}; };
size_t text_size_for_line(textview_curses &tc, int row, bool raw) {
return this->tds_lines[row].length();
};
private: private:
vector<string> tds_lines; vector<string> tds_lines;
}; };
@ -1981,7 +1985,7 @@ void execute_search(lnav_view_t view, const std::string &regex)
} }
gc.reset(); gc.reset();
fprintf(stderr, "start search for: %s\n", regex.c_str()); fprintf(stderr, "start search for: '%s'\n", regex.c_str());
if (regex.empty()) { if (regex.empty()) {
lnav_data.ld_bottom_source.grep_error(""); lnav_data.ld_bottom_source.grep_error("");

@ -592,6 +592,36 @@ static string com_disable_filter(string cmdline, vector<string> &args)
return retval; return retval;
} }
static string com_enable_word_wrap(string cmdline, vector<string> &args)
{
string retval = "";
if (args.size() == 0) {
}
else {
lnav_data.ld_views[LNV_LOG].set_word_wrap(true);
lnav_data.ld_views[LNV_TEXT].set_word_wrap(true);
}
return retval;
}
static string com_disable_word_wrap(string cmdline, vector<string> &args)
{
string retval = "";
if (args.size() == 0) {
}
else {
lnav_data.ld_views[LNV_LOG].set_word_wrap(false);
lnav_data.ld_views[LNV_TEXT].set_word_wrap(false);
}
return retval;
}
static std::vector<string> custom_logline_tables; static std::vector<string> custom_logline_tables;
static string com_create_logline_table(string cmdline, vector<string> &args) static string com_create_logline_table(string cmdline, vector<string> &args)
@ -656,14 +686,16 @@ static string com_session(string cmdline, vector<string> &args)
string retval = "error: expecting a command to save to the session file"; string retval = "error: expecting a command to save to the session file";
if (args.size() == 0) {} if (args.size() == 0) {}
else if (args.size() > 2) { else if (args.size() >= 2) {
/* XXX put these in a map */ /* XXX put these in a map */
if (args[1] != "highlight" && if (args[1] != "highlight" &&
args[1] != "enable-word-wrap" &&
args[1] != "disable-word-wrap" &&
args[1] != "filter-in" && args[1] != "filter-in" &&
args[1] != "filter-out" && args[1] != "filter-out" &&
args[1] != "enable-filter" && args[1] != "enable-filter" &&
args[1] != "disable-filter") { args[1] != "disable-filter") {
retval = "error: only the highlight and filter commands are " retval = "error: only the highlight, filter, and word-wrap commands are "
"supported"; "supported";
} }
else if (getenv("HOME") == NULL) { else if (getenv("HOME") == NULL) {
@ -1130,6 +1162,8 @@ void init_lnav_commands(readline_context::command_map_t &cmd_map)
cmd_map["write-csv-to"] = com_save_to; cmd_map["write-csv-to"] = com_save_to;
cmd_map["enable-filter"] = com_enable_filter; cmd_map["enable-filter"] = com_enable_filter;
cmd_map["disable-filter"] = com_disable_filter; cmd_map["disable-filter"] = com_disable_filter;
cmd_map["enable-word-wrap"] = com_enable_word_wrap;
cmd_map["disable-word-wrap"] = com_disable_word_wrap;
cmd_map["create-logline-table"] = com_create_logline_table; cmd_map["create-logline-table"] = com_create_logline_table;
cmd_map["delete-logline-table"] = com_delete_logline_table; cmd_map["delete-logline-table"] = com_delete_logline_table;
cmd_map["open"] = com_open; cmd_map["open"] = com_open;

@ -225,6 +225,20 @@ public:
return retval; return retval;
}; };
size_t line_length(iterator ll) {
iterator next_line = ll + 1;
size_t retval;
if (next_line == this->end()) {
retval = this->lf_index_size - ll->get_offset();
}
else {
retval = next_line->get_offset() - ll->get_offset() - 1;
}
return retval;
};
void read_full_message(iterator ll, std::string &msg_out, int max_lines=50); void read_full_message(iterator ll, std::string &msg_out, int max_lines=50);
/** /**

@ -170,8 +170,6 @@ void logfile_sub_source::text_value_for_line(textview_curses &tc,
{ {
content_line_t line(0); content_line_t line(0);
size_t tab;
assert(row >= 0); assert(row >= 0);
assert((size_t)row < this->lss_index.size()); assert((size_t)row < this->lss_index.size());
@ -189,10 +187,6 @@ void logfile_sub_source::text_value_for_line(textview_curses &tc,
this->lss_token_value = this->lss_token_value =
this->lss_token_file->read_line(this->lss_token_line); this->lss_token_file->read_line(this->lss_token_line);
while ((tab = this->lss_token_value.find('\t')) != string::npos) {
this->lss_token_value = this->lss_token_value.replace(tab, 1, 8, ' ');
}
this->lss_token_date_end = 0; this->lss_token_date_end = 0;
value_out = this->lss_token_value; value_out = this->lss_token_value;
if (this->lss_flags & F_SCRUB) { if (this->lss_flags & F_SCRUB) {

@ -130,6 +130,14 @@ public:
int row, int row,
string_attrs_t &value_out); string_attrs_t &value_out);
size_t text_size_for_line(textview_curses &tc, int row, bool raw) {
content_line_t line = this->lss_index[row];
logfile *lf = this->find(line);
logfile::iterator ll = lf->begin() + line;
return lf->line_length(ll) + (this->lss_flags & F_TIME_OFFSET ? 13 : 0);
};
void text_mark(bookmark_type_t *bm, int line, bool added) void text_mark(bookmark_type_t *bm, int line, bool added)
{ {
content_line_t cl = this->lss_index[line]; content_line_t cl = this->lss_index[line];

@ -450,8 +450,9 @@ static void load_time_bookmarks(void)
continue; continue;
} }
if (part_name == NULL) if (part_name == NULL) {
continue; continue;
}
if (!dts.scan(log_time, NULL, &log_tm, log_tv)) { if (!dts.scan(log_time, NULL, &log_tm, log_tv)) {
continue; continue;
@ -530,7 +531,7 @@ static void load_time_bookmarks(void)
lss.find(lf->get_filename().c_str(), base_content_line); lss.find(lf->get_filename().c_str(), base_content_line);
fprintf(stderr, "checking bookmarks for %s\n", lf->get_filename().c_str()); fprintf(stderr, "checking time offsets for %s\n", lf->get_filename().c_str());
logfile::iterator line_iter = lf->begin(); logfile::iterator line_iter = lf->begin();
@ -687,7 +688,7 @@ static int read_last_search(yajlpp_parse_context *ypc, const unsigned char *str,
ypc->get_path_fragment(-2)); ypc->get_path_fragment(-2));
view_index = view_name - lnav_view_strings; view_index = view_name - lnav_view_strings;
if (view_index < LNV__MAX) { if (view_index < LNV__MAX && !regex.empty()) {
execute_search((lnav_view_t)view_index, regex); execute_search((lnav_view_t)view_index, regex);
lnav_data.ld_views[view_index].set_follow_search(false); lnav_data.ld_views[view_index].set_follow_search(false);
} }
@ -786,6 +787,7 @@ static void save_time_bookmarks(void)
auto_mem<sqlite3_stmt> stmt(sqlite3_finalize); auto_mem<sqlite3_stmt> stmt(sqlite3_finalize);
if (sqlite3_open(db_path.c_str(), db.out()) != SQLITE_OK) { if (sqlite3_open(db_path.c_str(), db.out()) != SQLITE_OK) {
fprintf(stderr, "error: unable to open bookmark DB -- %s\n", db_path.c_str());
return; return;
} }
@ -813,7 +815,7 @@ static void save_time_bookmarks(void)
stmt.out(), stmt.out(),
NULL) != SQLITE_OK) { NULL) != SQLITE_OK) {
fprintf(stderr, fprintf(stderr,
"error: could not prepare bookmark replace statemnt -- %s\n", "error: could not prepare bookmark delete statemnt -- %s\n",
sqlite3_errmsg(db)); sqlite3_errmsg(db));
return; return;
} }
@ -1065,7 +1067,7 @@ static void save_time_bookmarks(void)
} }
if (sqlite3_bind_int64(stmt.in(), 6, offset.tv_usec) != SQLITE_OK) { if (sqlite3_bind_int64(stmt.in(), 6, offset.tv_usec) != SQLITE_OK) {
fprintf(stderr, "error: could not bind offset_sec -- %s\n", fprintf(stderr, "error: could not bind offset_usec -- %s\n",
sqlite3_errmsg(db.in())); sqlite3_errmsg(db.in()));
return; return;
} }

@ -410,7 +410,7 @@ void sql_strftime(char *buffer, size_t buffer_size, time_t time, int millis)
gmtime_r(&time, &gmtm); gmtime_r(&time, &gmtm);
snprintf(buffer, buffer_size, snprintf(buffer, buffer_size,
"% 4d-%02d-%02dT%02d:%02d:%02d.%03d", "%4d-%02d-%02dT%02d:%02d:%02d.%03d",
gmtm.tm_year + 1900, gmtm.tm_year + 1900,
gmtm.tm_mon + 1, gmtm.tm_mon + 1,
gmtm.tm_mday, gmtm.tm_mday,

@ -81,6 +81,16 @@ public:
value_out[lr].insert(make_string_attr("file", this->current_file())); value_out[lr].insert(make_string_attr("file", this->current_file()));
}; };
size_t text_size_for_line(textview_curses &tc, int line, bool raw) {
size_t retval = 0;
if (!this->tss_files.empty()) {
retval = this->current_file()->line_length(this->current_file()->begin() + line);
}
return retval;
};
logfile *current_file(void) const logfile *current_file(void) const
{ {
if (this->tss_files.empty()) { if (this->tss_files.empty()) {

@ -69,6 +69,8 @@ public:
std::string &value_out, std::string &value_out,
bool raw = false) = 0; bool raw = false) = 0;
virtual size_t text_size_for_line(textview_curses &tc, int line, bool raw = false) = 0;
/** /**
* Inform the source that the given line has been marked/unmarked. This * Inform the source that the given line has been marked/unmarked. This
* callback function can be used to translate between between visible line * callback function can be used to translate between between visible line
@ -350,6 +352,10 @@ public:
vis_line_t line, vis_line_t line,
attr_line_t &value_out); attr_line_t &value_out);
size_t listview_size_for_row(const listview_curses &lv, vis_line_t row) {
return this->tc_sub_source->text_size_for_line(*this, row);
};
std::string listview_source_name(const listview_curses &lv) { std::string listview_source_name(const listview_curses &lv) {
return this->tc_sub_source == NULL ? "" : return this->tc_sub_source == NULL ? "" :
this->tc_sub_source->text_source_name(*this); this->tc_sub_source->text_source_name(*this);

@ -213,6 +213,8 @@ public:
/** @return The attributes for the string. */ /** @return The attributes for the string. */
string_attrs_t &get_attrs() { return this->al_attrs; }; string_attrs_t &get_attrs() { return this->al_attrs; };
size_t length() const { return this->al_string.length(); };
void operator=(const std::string &rhs) { this->al_string = rhs; }; void operator=(const std::string &rhs) { this->al_string = rhs; };
/** Clear the string and the attributes for the string. */ /** Clear the string and the attributes for the string. */

@ -69,6 +69,10 @@ public:
} }
}; };
size_t listview_size_for_row(const listview_curses &lv, vis_line_t row) {
return 100;
};
bool attrline_next_token(const view_curses &vc, bool attrline_next_token(const view_curses &vc,
int line, int line,
struct line_range &lr, struct line_range &lr,

Loading…
Cancel
Save