git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7296 c06c8d41-db1a-0410-9941-cceddc491573
MK7MCWBPFRJSUWVXZ43LPFJ5Y2AYZZCREDYBT7AWJUMTQ2ET5AZQC
MADTICUXDKQB7EKTXG7J2OIJGUM7A437FRWIBRA3BIVEKXEXHO6AC
Q3B3UVMYEVC4YJUPYVSNTR4DJH4E6J4JJDHZNT5LNOCHCPPMEMXAC
BUM7LKOC3TMIMFUQLZYCT7SNYP6UKXAJ2KFQPB3XWMN4B2W4DRXQC
MV5USMLTBKVRWBAD67UFJ2BS4Y5HEOMYASRSB44DS24BBMRP75RQC
SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
25CH7HH4LKXFIZ75YNMXS3TSXO6O27DYSOPLOD45K4OCNFWLS4LQC
B7EE54F23AM4BECQ7GENNC4MHIPH6YVMOXOGZAQUZJKDJYGL7RAQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
2PAHDAPDO6PN4FNGB5N7CQNEGHSE3NOGPXYZMIAOJC4VW34FRVOAC
BWAQ3FHBBM6G3K3KYP75CRTR343RDQZJRYX5ZGYUEXYBAC3APDLAC
4XGOVPFCU6KZIYHKWCHUTZY6G5S326DKBG3UREPR34Q4TSDD3TAAC
text_start = heading_indent;
height += m_font_entry->char_height();
}
else if (m_entries[i].tile)
{
m_entries[i].sx = tile_ident;
text_start = text_indent;
int entry_height =
std::max(max_tile_height, m_font_entry->char_height());
height += entry_height;
text_height += (entry_height - m_font_entry->char_height()) / 2;
m_entries[i].ex = m_entries[i].sx + text_width;
m_entries[i].sy = height;
m_entries[i].ey = m_entries[i].sy + text_height;
m_font_buf.add(m_entries[i].text, text_start, text_height);
int entry_height;
if (m_entries[i].tile)
{
m_entries[i].sx = entry_start + tile_indent;
entry_height = std::max(max_tile_height, text_height);
// Currently, menus only support one texture at a time.
tex = m_entries[i].texture;
ASSERT(m_entries[i].texture == tex || tex == TEX_MAX);
m_tile_buf.set_tex(&m_image->m_textures[tex]);
m_tile_buf.add(m_entries[i].tile, m_entries[i].sx,
m_entries[i].sy);
}
else
{
m_entries[i].sx = text_sx;
entry_height = text_height;
}
int text_sy = m_entries[i].sy;
text_sy += (entry_height - m_font_entry->char_height()) / 2;
if (text_sx + text_width > entry_start + column_width)
{
// [enne] - Ugh, hack. Maybe MenuEntry could specify the
// presence and length of this substring?
std::string unfm = m_entries[i].text.tostring();
bool let = (unfm[1] >= 'a' && unfm[1] <= 'z'
|| unfm[1] >= 'A' && unfm[1] <= 'Z');
bool plus = (unfm[3] == '-' || unfm[3] == '+');
formatted_string text;
if (let && plus && unfm[0] == ' ' && unfm[2] == ' '
&& unfm[4] == ' ')
{
formatted_string header = m_entries[i].text.substr(0, 5);
m_font_buf.add(header, text_sx, text_sy);
text_sx += m_font_entry->string_width(header);
text = m_entries[i].text.substr(5);
}
else
{
text += m_entries[i].text;
}
int w = entry_start + column_width - text_sx;
int h = m_font_entry->char_height() * 2;
formatted_string split = m_font_entry->split(text, w, h);
int string_height = m_font_entry->string_height(split);
if (string_height > entry_height)
{
text_sy = m_entries[i].sy;
}
m_font_buf.add(split, text_sx, text_sy);
m_entries[i].ex = entry_start + column_width;
entry_height = std::max(entry_height, string_height);
}
else
{
m_entries[i].ex = entry_start + column_width;
m_font_buf.add(m_entries[i].text, text_sx, text_sy);
}
m_entries[i].ey = m_entries[i].sy + entry_height;
prev_height = m_entries[i].sy;
height = std::max(height, m_entries[i].ey);
column = (column + 1) % max_columns;
}
unsigned int string_width(const formatted_string &str);
unsigned int string_height(const char *text);
unsigned int string_height(const formatted_string &str);
// Try to split this string to fit in w x h pixel area.
formatted_string split(const formatted_string &str, unsigned int max_width,
unsigned int max_height);
}
unsigned int FTFont::string_height(const formatted_string &str)
{
std::string temp = str.tostring();
return string_height(temp.c_str());
}
unsigned int FTFont::string_height(const char *text)
{
int height = 1;
for (const char *itr = text; (*itr); itr++)
{
if (*itr == '\n')
height++;
}
return char_height() * height;
}
}
int FTFont::find_index_before_width(const char *text, int max_width)
{
int width = std::max(-m_min_offset, 0);
for (int i = 0; text[i]; i++)
{
char c = text[i];
width += m_glyphs[c].advance;
int adjust = std::max(0, m_glyphs[c].width - m_glyphs[c].advance);
if (width + adjust > max_width)
return i;
}
return -1;
}
formatted_string FTFont::split(const formatted_string &str,
unsigned int max_width, unsigned int max_height)
{
int max_lines = max_height / char_height();
if (max_lines < 1)
return formatted_string();
formatted_string ret;
ret += str;
std::string base = str.tostring();
int num_lines = 0;
char *line = &base[0];
while (true)
{
int line_end = find_index_before_width(line, max_width);
if (line_end == -1)
break;
int space_idx = 0;
for (char *search = &line[line_end]; search > line; search--)
{
if (*search == ' ')
{
space_idx = search - line;
break;
}
}
if (++num_lines >= max_lines || !space_idx)
{
int ellipses;
if (space_idx && (space_idx - line_end > 2))
ellipses = space_idx;
else
ellipses = line_end - 2;
size_t idx = &line[ellipses] - &base[0];
ret[idx] = '.';
ret[idx+1] = '.';
return ret.substr(0, idx + 2);
}
else
{
line[space_idx] = '\n';
ret[&line[space_idx] - &base[0]] = '\n';
}
line = &line[space_idx+1];
}
return ret;
InvMenu(int mflags = MF_MULTISELECT)
: Menu(mflags, "inventory"), type(MT_INVLIST), pre_select(NULL),
title_annotate(NULL)
{
}
InvMenu(int mflags = MF_MULTISELECT);
char &formatted_string::operator [] (size_t idx)
{
size_t rel_idx = idx;
int size = ops.size();
for (int i = 0; i < size; ++i)
{
if (ops[i] != FSOP_TEXT)
continue;
size_t len = ops[i].text.length();
if (rel_idx >= len)
rel_idx -= len;
else
return ops[i].text[rel_idx];
}
ASSERT(!"Invalid index");
char *invalid = NULL;
return *invalid;
}