inline iterator_range<Iterator> get_current_line(Iterator lower_bound, Iterator current, Iterator upper_bound) { Iterator first = get_line_start(lower_bound, current); Iterator last = get_line_start(current, upper_bound); if (last == current) last = upper_bound; return iterator_range<Iterator>(first, last); }
int get_nof_tabs_between(sptr_t edit, int start, int end) { int current_pos = get_line_start(edit,start); int max_tabs = 0; do { unsigned char current_char = (unsigned char)call_edit(edit,SCI_GETCHARAT,current_pos); bool current_char_ends_line = is_line_end(edit,current_pos); int tabs_on_line = 0; while (current_char != '\0' && !current_char_ends_line) { if (current_char == '\t') { tabs_on_line++; if (tabs_on_line > max_tabs) { max_tabs = tabs_on_line; } } current_pos = call_edit(edit,SCI_POSITIONAFTER,current_pos); current_char = (unsigned char)call_edit(edit,SCI_GETCHARAT,current_pos); current_char_ends_line = is_line_end(edit,current_pos); } } while (change_line(edit,current_pos,FORWARDS) && current_pos < end); return max_tabs; }
//============================================================================== int main() { std::string input(u8"Hallo äöüß\n¡Bye! ✿➂➿♫"); typedef boost::spirit::line_pos_iterator<std::string::const_iterator> source_iterator; typedef boost::u8_to_u32_iterator<source_iterator> iterator_type; source_iterator soi(input.begin()), eoi(input.end()); iterator_type first(soi), last(eoi); qi::rule<iterator_type, std::u32string()> string_u32 = +encoding::graph; qi::rule<iterator_type, std::string()> string = string_u32 [qi::_val = to_utf8_(qi::_1)]; std::vector<boost::iterator_range<iterator_type> > ast; // note the trick with `raw` to expose the iterators bool result = qi::phrase_parse(first, last, *qi::raw[ string ], encoding::space, ast); if (result) { for (auto const& range : ast) { source_iterator base_b(range.begin().base()), base_e(range.end().base()); auto lbound = get_line_start(soi, base_b); // RAW access to the base iterators: std::cout << "Fragment: '" << std::string(base_b, base_e) << "'\t" << "raw: L" << get_line(base_b) << ":" << get_column(lbound, base_b, /*tabs:*/4) << "-L" << get_line(base_e) << ":" << get_column(lbound, base_e, /*tabs:*/4); // "cooked" access: auto line = get_current_line(lbound, base_b, eoi); // std::cout << "Line: '" << line << "'\n"; // iterator_type is an alias for u8_to_u32_iterator<...> size_t cur_pos = 0, start_pos = 0, end_pos = 0; for(iterator_type it = line.begin(), _eol = line.end(); ; ++it, ++cur_pos) { if (it.base() == base_b) start_pos = cur_pos; if (it.base() == base_e) end_pos = cur_pos; if (it == _eol) break; } std::cout << "\t// in u32 code _units_: positions " << start_pos << "-" << end_pos << "\n"; } std::cout << "\n"; } else { std::cout << "Failure" << std::endl; } if (first!=last) { std::cout << "Remaining: '" << std::string(first, last) << "'\n"; } }
inline std::size_t get_column(Iterator lower_bound, Iterator current, std::size_t tabs) { std::size_t column = 1; Iterator first = get_line_start(lower_bound, current); for (Iterator i = first; i != current; ++i) { switch (*i) { case '\t': column += tabs - (column - 1) % tabs; break; default: ++column; } } return column; }
int get_block_boundary(sptr_t edit, int& location, direction which_dir) { int current_pos; int max_tabs = 0; bool orig_line = true; location = get_line_start(edit,location); do { int tabs_on_line = 0; current_pos = location; unsigned char current_char = (unsigned char)call_edit(edit,SCI_GETCHARAT,current_pos); bool current_char_ends_line = is_line_end(edit,current_pos); while (current_char != '\0' && !current_char_ends_line) { if (current_char == '\t') { tabs_on_line++; if (tabs_on_line > max_tabs) { max_tabs = tabs_on_line; } } current_pos = call_edit(edit,SCI_POSITIONAFTER,current_pos); current_char = (unsigned char)call_edit(edit,SCI_GETCHARAT,current_pos); current_char_ends_line = is_line_end(edit,current_pos); } if (tabs_on_line == 0 && !orig_line) { return max_tabs; } orig_line = false; } while (change_line(edit,location,which_dir)); return max_tabs; }