1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
/*
* Copyright (c) 1997 - 2010 Hansjrg Malthaner
*
* This file is part of the Simutrans project under the artistic licence.
* (see licence.txt)
*/
#include <string.h>
#include "gui_fixedwidth_textarea.h"
#include "../../dataobj/translator.h"
#include "../../utils/cbuffer_t.h"
gui_fixedwidth_textarea_t::gui_fixedwidth_textarea_t(cbuffer_t* buf_, const sint16 width, const koord reserved_area_)
{
buf = buf_;
set_width(width);
set_reserved_area(reserved_area_);
}
void gui_fixedwidth_textarea_t::recalc_size()
{
calc_display_text(koord::invalid, false);
}
void gui_fixedwidth_textarea_t::set_width(const sint16 width)
{
if( width>0 ) {
// height is simply reset to 0 as it requires recalculation anyway
gui_komponente_t::set_groesse( koord(width, 0) );
}
}
void gui_fixedwidth_textarea_t::set_reserved_area(const koord area)
{
if( area.x>=0 && area.y>=0 ) {
reserved_area = area;
}
}
void gui_fixedwidth_textarea_t::set_groesse(koord groesse)
{
// y-component (height) in groesse is deliberately ignored
set_width(groesse.x);
}
/* calculates the height of the text that flows around the world_view
* if draw is true, it will also draw the text
* borrowed from ding_infowin_t::calc_draw_info() with adaptation
*/
void gui_fixedwidth_textarea_t::calc_display_text(const koord offset, const bool draw)
{
const bool unicode = translator::get_lang()->utf_encoded;
KOORD_VAL x=0, word_x=0, y = 0;
const char* text(*buf);
const utf8 *p = (const utf8 *)text;
const utf8 *line_start = p;
const utf8 *word_start = p;
const utf8 *line_end = p;
// also in unicode *c==0 is end
while(*p!=0 || p!=line_end) {
// force at end of text or newline
const KOORD_VAL max_width = ( y<reserved_area.y ) ? get_groesse().x-reserved_area.x : get_groesse().x;
// smaller than the allowd width?
do {
// end of line?
size_t len = 0;
uint16 next_char = unicode ? utf8_to_utf16(p, &len) : *p++;
p += len;
if(next_char==0 || next_char=='\n') {
line_end = p-1;
if( next_char == 0 ) {
p--;
}
word_start = p;
word_x = 0;
break;
}
// Space: Maybe break here
else if( next_char==' ' || (next_char >= 0x3000 && next_char<0xFE70) ) {
// ignore space at start of line
if(next_char!=' ' || x>0) {
x += (KOORD_VAL)display_get_char_width( next_char );
}
word_start = p;
word_x = 0;
}
else {
// normal char: retrieve and calculate width
int ch_width = display_get_char_width( next_char );
x += ch_width;
word_x += ch_width;
}
} while( x<max_width );
// spaces at the end can be omitted
line_end = word_start;
if(line_end==line_start) {
// too long word for a single line => break the word
word_start = line_end = p;
word_x = 0;
}
else if(word_start[-1]==' ' || word_start[-1]=='\n') {
line_end --;
}
// start of new line or end of text
if(draw && (line_end-line_start)!=0) {
display_text_proportional_len_clip( offset.x, offset.y+y, (const char *)line_start, ALIGN_LEFT | DT_DIRTY | DT_CLIP, COL_BLACK, (size_t)(line_end - line_start) );
}
y += LINESPACE;
// back to start of new line
line_start = word_start;
x = word_x;
word_x = 0;
}
// reset component height where necessary
if( y!=get_groesse().y ) {
gui_komponente_t::set_groesse( koord(get_groesse().x, y) );
}
}
void gui_fixedwidth_textarea_t::zeichnen(koord offset)
{
calc_display_text(offset + get_pos(), true);
}
|