+unsigned Text::get_line_length(unsigned i) const
+{
+ if(i>=lines.size())
+ throw InvalidParameterValue("Invalid line number");
+ return lines[i].length;
+}
+
+void Text::offset_to_coords(unsigned offs, unsigned &row, unsigned &col) const
+{
+ if(lines.empty())
+ {
+ row=0;
+ col=0;
+ return;
+ }
+
+ for(unsigned i=0; i<lines.size(); ++i)
+ if(offs>=lines[i].start && offs<=lines[i].start+lines[i].length)
+ {
+ row=i;
+ col=offs-lines[i].start;
+ return;
+ }
+}
+
+unsigned Text::coords_to_offset(unsigned row, unsigned col) const
+{
+ if(row>=lines.size())
+ return text.size();
+
+ return lines[row].start+min(col, lines[row].length);
+}
+
+Geometry Text::coords_to_geometry(unsigned row, unsigned col) const
+{
+ if(row>=lines.size())
+ row=lines.size()-1;
+ const Line &line=lines[row];
+ if(col>line.length)
+ col=line.length;
+
+ const GL::Font *font=style->get_font();
+ float font_size=font->get_default_size();
+ unsigned line_height=static_cast<unsigned>((font->get_ascent()-font->get_descent())*font_size);
+ unsigned line_spacing=static_cast<unsigned>(font_size*6/5);
+ unsigned height=line_height+(lines.size()-1)*line_spacing;
+ int y_offset=static_cast<int>(-font->get_descent()*font_size);
+
+ Geometry geom;
+ geom.w=line.width;
+ geom.h=height;
+ geom.x=static_cast<unsigned>(font->get_string_width(text.substr(line.start, col))*font_size);
+ geom.y=(lines.size()-1-row)*line_spacing+y_offset;
+
+ return geom;
+}
+