← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~nha/widelands/fonthandler into lp:widelands

 

Nicolai Hähnle has proposed merging lp:~nha/widelands/fonthandler into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)
Related bugs:
  #594688 Cursor is not rendered in text fields in opengl mode
  https://bugs.launchpad.net/bugs/594688
  #594693 Images not rendered in richtext fields in opengl mode
  https://bugs.launchpad.net/bugs/594693

For more details, see:
https://code.launchpad.net/~nha/widelands/fonthandler/+merge/47929

I've been doing some cleanups of this branch, and I'd like to get it merged soonish. It doesn't yet do everything that I originally set out to do, but I think it's in a usable state.

The fundamental change of how the Font_Handler works is that we no longer want to cache entire pages of text, but instead only cache individual pre-rendered lines as pictures. The advantage is that very long multiline texts do not have to be rendered all at once, and we limit the size of pictures generated in this way. We also do not have to re-render texts when the caret moves, and we can more naturally integrate more complex graphics in richtext fields in OpenGL mode. However, that last part - refactoring richtext support - has not been implemented yet.

Visible changes:
1. The caret now works in OpenGL mode (yay!)
2. Font rendering now uses proper alpha-rendering
3. Multi-line texts no longer have ridiculously large spacing between lines in the new renderer. However, since Multiline_Textarea refactoring is pending the richtext changes, this is not yet the case everywhere, but only in Multiline_Editbox and those place that call draw_multiline directly (e.g. game tips).

If you have some spare minutes to test, I'd appreciate bug reports. If I don't hear anything, I'm going to merge this in the next few days (probably Wednesday).


-- 
https://code.launchpad.net/~nha/widelands/fonthandler/+merge/47929
Your team Widelands Developers is requested to review the proposed merge of lp:~nha/widelands/fonthandler into lp:widelands.
=== added file 'src/graphic/font.cc'
--- src/graphic/font.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/font.cc	2011-01-30 15:33:06 +0000
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2002-2011 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include "font.h"
+
+#include <map>
+
+#include "constants.h"
+#include "io/filesystem/layered_filesystem.h"
+
+namespace {
+
+struct FontDescr {
+	std::string name;
+	int size;
+
+	bool operator<(const FontDescr & o) const {
+		return
+			size < o.size ||
+			(size == o.size && name < o.name);
+	}
+};
+
+typedef std::map<FontDescr, UI::Font *> FontMap;
+
+FontMap g_fontmap;
+
+} // anonymous namespace
+
+
+namespace UI {
+
+/**
+ * Open a font file and load the corresponding font.
+ */
+Font::Font(const std::string & name, int size)
+{
+	// Load the TrueType Font
+	std::string filename = "fonts/";
+	filename += name;
+
+	//  We must keep this File Read open, otherwise the following calls are
+	//  crashing. do not know why...
+	m_fontfile.Open(*g_fs, filename.c_str());
+
+	SDL_RWops * const ops = SDL_RWFromMem(m_fontfile.Data(0), m_fontfile.GetSize());
+	if (!ops)
+		throw wexception("could not load font!: RWops Pointer invalid");
+
+	m_font = TTF_OpenFontIndexRW(ops, 1, size, 0);
+	if (!m_font)
+		throw wexception("could not load font!: %s", TTF_GetError());
+
+	// Compute the line skip based on some glyphs by sampling some letters,
+	// special characters, and accented/umlauted versions of capital A
+	// It seems more reasonable to use TTF_FontLineSkip(), but the fonts
+	// we use claim to have a very excessive line skip.
+	static uint16_t glyphs[] = {'A', '_', '@', ',', 'q', 'y', '"', 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5};
+	int32_t minminy = 0;
+	int32_t maxmaxy = 0;
+
+	for (unsigned int idx = 0; idx < sizeof(glyphs) / sizeof(glyphs[0]); ++idx) {
+		int miny, maxy;
+		if (TTF_GlyphMetrics(m_font, glyphs[idx], 0, 0, &miny, &maxy, 0) < 0)
+			continue; // error, e.g. glyph not found
+
+		if (miny < minminy)
+			minminy = miny;
+		if (maxy > maxmaxy)
+			maxmaxy = maxy;
+	}
+
+	m_computed_lineskip = maxmaxy - minminy + 1;
+}
+
+/**
+ * Free all resources associated with this font.
+ */
+Font::~Font()
+{
+	TTF_CloseFont(m_font);
+	m_font = 0;
+}
+
+/**
+ * \return the maximum height of glyphs of this font.
+ */
+uint32_t Font::height() const
+{
+	return TTF_FontHeight(m_font);
+}
+
+/**
+ * \return the number of pixels between lines in this font (from baseline to baseline).
+ */
+uint32_t Font::lineskip() const
+{
+	return m_computed_lineskip;
+}
+
+/**
+ * Return the font for the given name and size.
+ *
+ * \note Fonts are cached and need not be freed explicitly. \see shutdown
+ */
+Font * Font::get(const std::string & name, int size)
+{
+	FontDescr descr;
+	descr.name = name;
+	descr.size = size;
+
+	FontMap::iterator it = g_fontmap.find(descr);
+	if (it == g_fontmap.end()) {
+		Font * font = new Font(name, size);
+		it = g_fontmap.insert(std::make_pair(descr, font)).first;
+	}
+
+	//TODO: get rid of this nasty hack
+	//This is required until Font_Handler completely switches to the new render_line()-based functionality
+	TTF_SetFontStyle(it->second->get_ttf_font(), TTF_STYLE_BOLD);
+
+	return it->second;
+}
+
+/**
+ * Free all registered fonts.
+ */
+void Font::shutdown()
+{
+	while (!g_fontmap.empty()) {
+		delete g_fontmap.begin()->second;
+		g_fontmap.erase(g_fontmap.begin());
+	}
+}
+
+/**
+ * Compute the bare width (without caret padding) of the given string.
+ */
+uint32_t TextStyle::calc_bare_width(const std::string & text) const
+{
+	int w, h;
+	TTF_SizeUTF8(font->get_ttf_font(), text.c_str(), &w, &h);
+	return w;
+}
+
+
+/*
+=============================
+
+Default fonts and styles
+
+=============================
+*/
+
+Font * Font::ui_big()
+{
+	Font * font = 0;
+	if (!font)
+		font = Font::get(UI_FONT_BIG);
+	return font;
+}
+
+Font * Font::ui_small()
+{
+	Font * font = 0;
+	if (!font)
+		font = Font::get(UI_FONT_SMALL);
+	return font;
+}
+
+Font * Font::ui_ultrasmall()
+{
+	Font * font = 0;
+	if (!font)
+		font = Font::get(UI_FONT_ULTRASMALL);
+	return font;
+}
+
+const TextStyle & TextStyle::ui_big()
+{
+	static TextStyle style;
+	static bool init = false;
+
+	if (!init) {
+		style.font = Font::ui_big();
+		style.fg = UI_FONT_CLR_FG;
+		style.bold = true;
+		init = true;
+	}
+
+	return style;
+}
+
+const TextStyle & TextStyle::ui_small()
+{
+	static TextStyle style;
+	static bool init = false;
+
+	if (!init) {
+		style.font = Font::ui_small();
+		style.fg = UI_FONT_CLR_FG;
+		style.bold = true;
+		init = true;
+	}
+
+	return style;
+}
+
+const TextStyle & TextStyle::ui_ultrasmall()
+{
+	static TextStyle style;
+	static bool init = false;
+
+	if (!init) {
+		style.font = Font::ui_ultrasmall();
+		style.fg = UI_FONT_CLR_FG;
+		style.bold = true;
+		init = true;
+	}
+
+	return style;
+}
+
+} // namespace UI

=== added file 'src/graphic/font.h'
--- src/graphic/font.h	1970-01-01 00:00:00 +0000
+++ src/graphic/font.h	2011-01-30 15:33:06 +0000
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2002-2011 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef FONT_H
+#define FONT_H
+
+#include <boost/shared_ptr.hpp>
+
+#include <SDL_ttf.h>
+
+#include "io/fileread.h"
+#include "rgbcolor.h"
+
+namespace UI {
+
+/**
+ * Margin around text that is kept to make space for the caret.
+ */
+#define LINE_MARGIN 1
+
+
+/**
+ * Wrapper object around a font.
+ *
+ * Fonts in our sense are defined by the general font shape (given by the font
+ * name) and the size of the font.
+ */
+struct Font {
+	static void shutdown();
+	static Font * get(const std::string & name, int size);
+	static Font * ui_big();
+	static Font * ui_small();
+	static Font * ui_ultrasmall();
+
+	uint32_t height() const;
+	uint32_t lineskip() const;
+
+	TTF_Font * get_ttf_font() const {return m_font;}
+
+private:
+	Font(const std::string & name, int size);
+	~Font();
+
+	FileRead m_fontfile;
+	TTF_Font * m_font;
+	uint32_t m_computed_lineskip;
+};
+
+/**
+ * Text style combines font with other characteristics like color
+ * and style (italics, bold).
+ */
+struct TextStyle {
+	TextStyle() :
+		font(0),
+		fg(255, 255, 255),
+		bold(false),
+		italics(false),
+		underline(false)
+	{}
+
+	static TextStyle makebold(Font * font, RGBColor fg) {
+		TextStyle ts;
+		ts.font = font;
+		ts.bold = true;
+		ts.fg = fg;
+		return ts;
+	}
+
+	static const TextStyle & ui_big();
+	static const TextStyle & ui_small();
+	static const TextStyle & ui_ultrasmall();
+	uint32_t calc_bare_width(const std::string & text) const;
+
+	Font * font;
+	RGBColor fg;
+	bool bold : 1;
+	bool italics : 1;
+	bool underline : 1;
+
+	bool operator== (const TextStyle & o) const {
+		return
+			font == o.font && fg == o.fg &&
+			bold == o.bold && italics == o.italics && underline == o.underline;
+	}
+	bool operator!= (const TextStyle & o) const {
+		return !(*this == o);
+	}
+};
+
+} // namespace UI
+
+#endif // FONT_H

=== modified file 'src/graphic/font_handler.cc'
--- src/graphic/font_handler.cc	2010-11-27 16:23:39 +0000
+++ src/graphic/font_handler.cc	2011-01-30 15:33:06 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2010 by the Widelands Development Team
+ * Copyright (C) 2002-2011 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -22,7 +22,7 @@
 #include "font_handler.h"
 
 #include "io/filesystem/filesystem.h"
-#include "font_loader.h"
+#include "font.h"
 #include "helper.h"
 #include "log.h"
 #include "wexception.h"
@@ -32,30 +32,68 @@
 #include "rendertarget.h"
 #include "surface.h"
 #include "graphic/render/surface_sdl.h"
+#include "wordwrap.h"
 
 #include <SDL_image.h>
 #include <SDL_ttf.h>
 
 #include <algorithm>
 #include <iostream>
+#include <boost/concept_check.hpp>
+#include <boost/concept_check.hpp>
+#include <scripting/pdep/llimits.h>
 
 namespace UI {
 
-#define LINE_MARGIN 1
+/// The global unique \ref Font_Handler object
+Font_Handler * g_fh = 0;
+
+/**
+ * The line cache stores unprocessed rendered lines of text.
+ */
+struct LineCacheEntry {
+	/*@{*/
+	TextStyle style;
+	std::string text;
+	/*@}*/
+
+	/*@{*/
+	PictureID picture;
+	uint32_t width;
+	uint32_t height;
+	/*@}*/
+};
+
+typedef std::list<LineCacheEntry> LineCache;
+
+static const unsigned MaxLineCacheSize = 500;
+
+/**
+ * Internal data of the \ref Font_Handler.
+ */
+struct Font_Handler::Data {
+	LineCache linecache;
+
+	const LineCacheEntry & get_line(const TextStyle & style, const std::string & text);
+
+private:
+	void render_line(LineCacheEntry & lce);
+};
 
 /**
  * Plain Constructor
  */
-Font_Handler::Font_Handler() {
+Font_Handler::Font_Handler() :
+	d(new Data)
+{
 	if (TTF_Init() == -1)
 		throw wexception
 			("True Type library did not initialize: %s\n", TTF_GetError());
-	m_font_loader = new Font_Loader();
 }
 
 
 Font_Handler::~Font_Handler() {
-	delete m_font_loader;
+	Font::shutdown();
 	TTF_Quit();
 }
 
@@ -66,7 +104,7 @@
 uint32_t Font_Handler::get_fontheight
 	(std::string const & name, int32_t const size)
 {
-	TTF_Font * const f = m_font_loader->get_font(name, size);
+	TTF_Font * const f = Font::get(name, size)->get_ttf_font();
 	const int32_t fontheight = TTF_FontHeight(f);
 	if (fontheight < 0)
 		throw wexception
@@ -75,6 +113,124 @@
 	return fontheight;
 }
 
+/**
+ * Get a cache entry for the given text (without linebreaks!) rendered
+ * in the given style.
+ *
+ * If there is no pre-existing cache entry, a new one is created.
+ */
+const LineCacheEntry & Font_Handler::Data::get_line(const UI::TextStyle & style, const std::string & text)
+{
+	for (LineCache::iterator it = linecache.begin(); it != linecache.end(); ++it) {
+		if (it->style != style || it->text != text)
+			continue;
+
+		// Found a hit, move to front
+		if (it != linecache.begin())
+			linecache.splice(linecache.begin(), linecache, it);
+		return *it;
+	}
+
+	// Cache miss; render a new picture
+	LineCache::iterator it = linecache.insert(linecache.begin(), LineCacheEntry());
+	it->style = style;
+	it->text = text;
+	render_line(*it);
+
+	while (linecache.size() > MaxLineCacheSize)
+		linecache.pop_back();
+
+	return *it;
+}
+
+/**
+ * Render the picture of a \ref LineCacheEntry whose key data has
+ * already been filled in.
+ */
+void Font_Handler::Data::render_line(LineCacheEntry & lce)
+{
+	//static int count = 0;
+	//log("render_line(%s): %i\n", lce.text.c_str(), ++count);
+
+	TTF_Font * font = lce.style.font->get_ttf_font();
+	SDL_Color sdl_fg = {lce.style.fg.r(), lce.style.fg.g(), lce.style.fg.b(), 0};
+
+	// Work around an Issue in SDL_TTF that dies when the surface
+	// has zero width
+	int width = 0;
+	if (TTF_SizeUTF8(font, lce.text.c_str(), &width, 0) < 0 or !width) {
+		lce.width = 0;
+		lce.height = TTF_FontHeight(font);
+		return;
+	}
+
+	int32_t font_style = TTF_STYLE_NORMAL;
+	if (lce.style.bold)
+		font_style |= TTF_STYLE_BOLD;
+	if (lce.style.italics)
+		font_style |= TTF_STYLE_ITALIC;
+	if (lce.style.underline)
+		font_style |= TTF_STYLE_UNDERLINE;
+	TTF_SetFontStyle(font, font_style);
+
+	SDL_Surface * text_surface = TTF_RenderUTF8_Blended(font, lce.text.c_str(), sdl_fg);
+	if (!text_surface) {
+		log
+			("Font_Handler::render_line, an error : %s\n",
+			 TTF_GetError());
+		log("Text was: '%s'\n", lce.text.c_str());
+		return;
+	}
+
+	lce.picture = g_gr->convert_sdl_surface_to_picture(text_surface, true);
+	lce.width = lce.picture->get_w();
+	lce.height = lce.picture->get_h();
+}
+
+/**
+ * Draw unwrapped, single-line text (i.e. no line breaks).
+ */
+void Font_Handler::draw_text
+	(RenderTarget & dst,
+	 const TextStyle & style,
+	 Point dstpoint,
+	 const std::string & text,
+	 Align align,
+	 uint32_t caret)
+{
+	const LineCacheEntry & lce = d->get_line(style, text);
+
+	do_align(align, dstpoint.x, dstpoint.y, lce.width + 2 * LINE_MARGIN, lce.height);
+
+	if (lce.picture && lce.picture->valid())
+		dst.blit(Point(dstpoint.x + LINE_MARGIN, dstpoint.y), lce.picture);
+
+	if (caret <= text.size())
+		draw_caret(dst, style, dstpoint, text, caret);
+}
+
+/**
+ * Draw multi-line text, optionally with wrapping.
+ *
+ * @note Consider using @ref WordWrap directly, if the same multi-line
+ * text is going to be rendered many times.
+ */
+void Font_Handler::draw_multiline
+	(RenderTarget & dst,
+	 const TextStyle & style,
+	 Point dstpoint,
+	 const std::string & text,
+	 Align align,
+	 uint32_t wrap,
+	 uint32_t caret)
+{
+	WordWrap ww(style, wrap);
+
+	ww.wrap(text);
+	ww.draw(dst, dstpoint, align, caret);
+}
+
+
 /*
  * Draw this string, if it is not cached, create the cache for it.
  *
@@ -85,7 +241,7 @@
  * windows ...) this is the death, for a whole new surface is rendered
  * with everything that has been written so far.
  */
-// TODO: rename this to draw text
+// TODO: get rid of this (depends on refactor of Multiline_Textarea)
 void Font_Handler::draw_string
 	(RenderTarget & dst,
 	 std::string const & fontname,
@@ -95,50 +251,27 @@
 	 Align               const align,
 	 uint32_t            const wrap,
 	 Widget_Cache        const widget_cache,
-	 PictureID         *       widget_cache_id,
-	 uint32_t            const caret,
-	 bool                const transparent)
+	 PictureID         *       widget_cache_id)
 {
-	TTF_Font & font = *m_font_loader->get_font(fontname, fontsize);
+	TTF_Font & font = *Font::get(fontname, fontsize)->get_ttf_font();
 	//Width and height of text, needed for alignment
 	uint32_t w, h;
 	PictureID picid;
 	//log("Font_Handler::draw_string(%s)\n", text.c_str());
 	//Fontrender takes care of caching
 	if (widget_cache == Widget_Cache_None) {
-		// look if text is cached
-		_Cache_Infos  ci =
-			{g_gr->get_no_picture(), text, &font, fg, bg, caret, 0, 0};
-
-		std::list<_Cache_Infos>::iterator i =
-			find(m_cache.begin(), m_cache.end(), ci);
-
-		if (i != m_cache.end())  {
-			// Ok, it is cached, blit it and done
-			picid = i->picture_id;
-			w = i->w;
-			h = i->h;
-			if (i != m_cache.begin()) {
-				m_cache.push_front (*i);
-				m_cache.erase (i);
-			}
+		TextStyle style;
+		style.font = Font::get(fontname, fontsize);
+		style.fg = fg;
+		style.bold = true;
+
+		if (wrap == std::numeric_limits<uint32_t>::max() && text.find('\n') == std::string::npos) {
+			draw_text(dst, style, dstpoint, text, align);
 		} else {
-			//not cached, create a new surface and cache it
-			ci.picture_id =
-				create_text_surface
-					(font, fg, bg, text, align, wrap, 0, caret, transparent);
-			g_gr->get_picture_size(ci.picture_id, ci.w, ci.h);
-			ci.f = &font;
-			m_cache.push_front (ci);
-
-			while (m_cache.size() > CACHE_ARRAY_SIZE)
-				m_cache.pop_back();
-
-			//Set for alignment and blitting
-			picid = ci.picture_id;
-			w = ci.w;
-			h = ci.h;
+			draw_multiline(dst, style, dstpoint, text, align, wrap);
 		}
+
+		return;
 	} else if (widget_cache == Widget_Cache_Use) {
 		//  Widget gave us an explicit picid.
 		g_gr->get_picture_size(*widget_cache_id, w, h);
@@ -147,8 +280,10 @@
 		// We need to (re)create the picid for the widget.
 		// The old picture is freed automatically
 		*widget_cache_id =
-			create_text_surface
-				(font, fg, bg, text, align, wrap, 0, caret, transparent);
+			convert_sdl_surface
+				(*create_sdl_text_surface
+				 (font, fg, bg, text, align, wrap, 0),
+				 bg, true);
 		g_gr->get_picture_size(*widget_cache_id, w, h);
 		picid = *widget_cache_id;
 	}
@@ -157,32 +292,13 @@
 }
 
 /*
-* Creates a Widelands surface of the given text, checks if multiline or not
-*/
-PictureID Font_Handler::create_text_surface
-	(TTF_Font & font, RGBColor const fg, RGBColor const bg,
-	 std::string const & text, Align const align,
-	 uint32_t            const wrap,
-	 uint32_t            const linespacing,
-	 uint32_t            const caret,
-	 bool                const transparent)
-{
-	return
-		convert_sdl_surface
-			(*create_sdl_text_surface
-			 	(font, fg, bg, text, align, wrap, linespacing, caret),
-			 bg, transparent);
-}
-
-/*
  * This function renders a short (single line) text surface
  */
 SDL_Surface * Font_Handler::create_single_line_text_surface
 	(TTF_Font & font,
 	 RGBColor const fg, RGBColor const bg,
 	 std::string       text,
-	 Align,
-	 uint32_t    const caret)
+	 Align)
 {
 	// render this block in a SDL Surface
 	SDL_Color sdl_fg = {fg.r(), fg.g(), fg.b(), 0};
@@ -215,10 +331,6 @@
 		SDL_Rect r; r.x = LINE_MARGIN, r.y = 0;
 		SDL_BlitSurface(text_surface, 0, surface, &r);
 		SDL_FreeSurface(text_surface);
-		if (caret != std::numeric_limits<uint32_t>::max()) {
-			std::string const text_caret_pos = text.substr(0, caret);
-			render_caret(font, *surface, text_caret_pos);
-		}
 		return surface;
 	} else {
 		log
@@ -242,8 +354,7 @@
 	 std::string const & text,
 	 Align       const align,
 	 uint32_t            const wrap,
-	 uint32_t            const linespacing,
-	 uint32_t                  caret)
+	 uint32_t            const linespacing)
 {
 	assert(wrap != std::numeric_limits<uint32_t>::max());
 	assert(2 * LINE_MARGIN < wrap);
@@ -256,9 +367,6 @@
 	SDL_Color sdl_fg = {fg.r(), fg.g(), fg.b(), 0};
 	SDL_Color sdl_bg = {bg.r(), bg.g(), bg.b(), 0};
 
-	uint32_t cur_text_pos = 0;
-	uint32_t i = 0;
-
 	std::string const lines = word_wrap_text(font, text, wrap);
 	std::string::size_type const lines_size = lines.size();
 	struct {std::string::size_type pos; bool done;} j = {0, false};
@@ -298,17 +406,6 @@
 			SDL_Rect r; r.x = LINE_MARGIN, r.y = 0;
 			SDL_BlitSurface(text_surface, 0, surface, &r);
 			SDL_FreeSurface(text_surface);
-			if (caret != std::numeric_limits<uint32_t>::max()) {
-				uint32_t const new_text_pos = cur_text_pos + line_size;
-				if (new_text_pos >= caret - i) {
-					int32_t const caret_line_pos = caret - cur_text_pos - i;
-					line.resize(caret_line_pos);
-					render_caret(font, *surface, line);
-					caret = std::numeric_limits<uint32_t>::max();
-				} else
-					cur_text_pos = new_text_pos;
-				++i;
-			}
 
 			m_rendered_lines.push_back(surface);
 			global_surface_height += surface->h + linespacing;
@@ -333,35 +430,31 @@
 
 }
 
-void Font_Handler::render_caret
-	(TTF_Font          & font,
-	 SDL_Surface       & line,
-	 std::string const & text_caret_pos)
+/**
+ * Draw the caret for the given text rendered exactly at the given point
+ * (including \ref LINE_MARGIN).
+ */
+void Font_Handler::draw_caret
+	(RenderTarget & dst,
+	 const TextStyle & style,
+	 Point dstpoint,
+	 const std::string & text,
+	 uint32_t caret)
 {
-	int32_t caret_x, caret_y;
-
-	TTF_SizeUTF8(&font, text_caret_pos.c_str(), &caret_x, &caret_y);
-	caret_x += LINE_MARGIN;
-
-	//TODO: Implement caret rendering for opengl
-	if (!g_opengl)
-	{
-		PictureID caret = g_gr->get_picture(PicMod_Game, "pics/caret.png");
-		upcast(SurfaceSDL, sdlsurf, caret.get());
-		assert(sdlsurf);
-		SDL_Surface * const caret_surf_sdl = sdlsurf->get_sdl_surface();
-
-		SDL_Rect r;
-		r.x = caret_x - caret_surf_sdl->w;
-		r.y = (caret_y - caret_surf_sdl->h) / 2;
-
-		SDL_BlitSurface(caret_surf_sdl, 0, &line, &r);
-	} else {
-		log("WARNING: Should render caret here but it is not implemented\n");
-	}
-
+	std::string sub = text.substr(0, caret);
+	int caret_x, caret_y;
+
+	TTF_SizeUTF8(style.font->get_ttf_font(), sub.c_str(), &caret_x, &caret_y);
+
+	PictureID caretpic = g_gr->get_picture(PicMod_UI, "pics/caret.png");
+	Point caretpt;
+	caretpt.x = dstpoint.x + caret_x + LINE_MARGIN - caretpic->get_w();
+	caretpt.y = dstpoint.y + (caret_y - caretpic->get_h()) / 2;
+
+	dst.blit(caretpt, caretpic);
 }
 
+
 /*
 * Renders a string into a SDL surface
 * Richtext works with this method, because whole richtext content
@@ -376,7 +469,7 @@
 	 int32_t             const style,
 	 uint32_t            const linespacing)
 {
-	TTF_Font & font = *m_font_loader->get_font(fontname, fontsize);
+	TTF_Font & font = *Font::get(fontname, fontsize)->get_ttf_font();
 	TTF_SetFontStyle(&font, style);
 	return
 		create_sdl_text_surface(font, fg, bg, text, align, wrap, linespacing);
@@ -390,15 +483,14 @@
 	 std::string const & text,
 	 Align               const align,
 	 uint32_t            const wrap,
-	 uint32_t            const linespacing,
-	 uint32_t            const caret)
+	 uint32_t            const linespacing)
 {
 	return
 		wrap != std::numeric_limits<uint32_t>::max()  ?
 		create_static_long_text_surface
-			(font, fg, bg, text, align, wrap, linespacing, caret)
+			(font, fg, bg, text, align, wrap, linespacing)
 		:
-		create_single_line_text_surface(font, fg, bg, text, align, caret);
+		create_single_line_text_surface(font, fg, bg, text, align);
 }
 
 /*
@@ -834,6 +926,7 @@
 void Font_Handler::flush_cache()
 {
 	m_cache.clear();
+	d->linecache.clear();
 }
 
 //Inserts linebreaks into a text, so it doesn't get bigger than max_width
@@ -918,50 +1011,11 @@
 {
 	return
 		word_wrap_text
-			(*m_font_loader->get_font(fontname, fontsize),
+			(*Font::get(fontname, fontsize)->get_ttf_font(),
 			 unwrapped_text,
 			 max_width);
 }
 
-
-//calculates size of a given text
-void Font_Handler::get_size
-	(std::string const & fontname, int32_t const fontsize,
-	 std::string text,
-	 uint32_t & w, uint32_t & h,
-	 uint32_t const wrap)
-{
-	TTF_Font & font = *m_font_loader->get_font(fontname, fontsize);
-
-	if (wrap < std::numeric_limits<uint32_t>::max())
-		text = word_wrap_text(font, text, wrap);
-
-	w = 0;
-	h = 0;
-	std::string::size_type const text_size = text.size();
-	struct {std::string::size_type pos; bool done;} j = {0, false};
-	for (; not j.done;)
-	{
-		std::string::size_type line_end = text.find('\n', j.pos);
-		if (line_end == std::string::npos) {
-			line_end = text_size;
-			j.done = true;
-		}
-		std::string::size_type line_size = line_end - j.pos;
-		std::string line = text.substr(j.pos, line_size);
-
-		int32_t line_w, line_h;
-		TTF_SizeUTF8(&font, line.empty() ? " " : line.c_str(), &line_w, &line_h);
-
-		if (static_cast<int32_t>(w) < line_w)
-			w = line_w;
-		h += line_h;
-
-		j.pos = line_end + 1;
-	}
-	w += 2 * LINE_MARGIN;
-}
-
 //calcultes linewidth of a given text
 int32_t Font_Handler::calc_linewidth(TTF_Font & font, std::string const & text)
 {
@@ -970,4 +1024,33 @@
 	return w;
 }
 
-}
+/**
+ * Compute the total size of the given text, when wrapped to the given
+ * maximum width and rendered in the given text style.
+ */
+void Font_Handler::get_size
+	(const TextStyle & textstyle,
+	 const std::string & text,
+	 uint32_t & w, uint32_t & h,
+	 uint32_t wrap)
+{
+	WordWrap ww(textstyle, wrap);
+	ww.wrap(text);
+	w = ww.width();
+	h = ww.height();
+}
+
+/**
+ * Calculates size of a given text.
+ */
+void Font_Handler::get_size
+	(std::string const & fontname, int32_t const fontsize,
+	 const std::string & text,
+	 uint32_t & w, uint32_t & h,
+	 uint32_t const wrap)
+{
+	// use bold style by default for historical reasons
+	get_size(TextStyle::makebold(Font::get(fontname, fontsize), RGBColor(255, 255, 255)), text, w, h, wrap);
+}
+
+} // namespace UI

=== modified file 'src/graphic/font_handler.h'
--- src/graphic/font_handler.h	2010-11-27 13:30:37 +0000
+++ src/graphic/font_handler.h	2011-01-30 15:33:06 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2009 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -29,6 +29,8 @@
 
 #include <SDL_ttf.h>
 
+#include <boost/scoped_ptr.hpp>
+
 #include <list>
 #include <cstring>
 #include <vector>
@@ -37,7 +39,7 @@
 
 namespace UI {
 struct Text_Block;
-struct Font_Loader;
+struct TextStyle;
 
 /** class Font_Handler
  *
@@ -46,6 +48,23 @@
 struct Font_Handler {
 	Font_Handler();
 	~Font_Handler();
+
+	void draw_text
+		(RenderTarget &,
+		 const TextStyle &,
+		 Point dstpoint,
+		 const std::string & text,
+		 Align align = Align_CenterLeft,
+		 uint32_t caret = std::numeric_limits<uint32_t>::max());
+	void draw_multiline
+		(RenderTarget &,
+		 const TextStyle &,
+		 Point dstpoint,
+		 const std::string & text,
+		 Align align = Align_CenterLeft,
+		 uint32_t wrap = std::numeric_limits<uint32_t>::max(),
+		 uint32_t caret = std::numeric_limits<uint32_t>::max());
+
 	void draw_string
 		(RenderTarget &,
 		 const std::string & font,
@@ -56,12 +75,16 @@
 		 Align               align           = Align_CenterLeft,
 		 uint32_t            wrap         = std::numeric_limits<uint32_t>::max(),
 		 Widget_Cache        widget_cache    = Widget_Cache_None,
-		 PictureID         * widget_cache_id = 0,
-		 uint32_t            caret        = std::numeric_limits<uint32_t>::max(),
-		 bool                transparent     = true);
+		 PictureID         * widget_cache_id = 0);
+
+	void get_size
+		(const TextStyle &,
+		 const std::string & text,
+		 uint32_t & w, uint32_t & h,
+		 uint32_t wrap = std::numeric_limits<uint32_t>::max());
 	void get_size
 		(std::string const & fontname, int32_t size,
-		 std::string text,
+		 const std::string & text,
 		 uint32_t & w, uint32_t & h,
 		 uint32_t wrap = std::numeric_limits<uint32_t>::max());
 	int32_t calc_linewidth(TTF_Font &, const std::string & text);
@@ -115,19 +138,12 @@
 private:
 	static const uint32_t CACHE_ARRAY_SIZE = 500;
 
-	Font_Loader           * m_font_loader;
 	std::list<_Cache_Infos> m_cache;
 
+	struct Data;
+	boost::scoped_ptr<Data> d;
+
 private:
-	PictureID create_text_surface
-		(TTF_Font &,
-		 RGBColor fg, RGBColor bg,
-		 std::string const & text,
-		 Align,
-		 uint32_t            wrap         = std::numeric_limits<uint32_t>::max(),
-		 uint32_t            line_spacing = 0,
-		 uint32_t            caret        = std::numeric_limits<uint32_t>::max(),
-		 bool transparent = true);
 	PictureID convert_sdl_surface
 		(SDL_Surface &, const RGBColor bg, bool transparent = false);
 	SDL_Surface * draw_string_sdl_surface
@@ -143,19 +159,16 @@
 		 std::string const & text,
 		 Align,
 		 uint32_t            wrap        = std::numeric_limits<uint32_t>::max(),
-		 uint32_t            linespacing = 0,
-		 uint32_t            caret       = std::numeric_limits<uint32_t>::max());
+		 uint32_t            linespacing = 0);
 	SDL_Surface * create_static_long_text_surface
 		(TTF_Font &, RGBColor fg, RGBColor bg,
 		 std::string const & text,
 		 Align,
 		 uint32_t            wrap        = std::numeric_limits<uint32_t>::max(),
-		 uint32_t            linespacing = 0,
-		 uint32_t            caret       = std::numeric_limits<uint32_t>::max());
+		 uint32_t            linespacing = 0);
 	SDL_Surface * create_single_line_text_surface
 		(TTF_Font &, RGBColor fg, RGBColor bg,
-		 std::string text, Align,
-		 uint32_t caret = std::numeric_limits<uint32_t>::max());
+		 std::string text, Align);
 	SDL_Surface * create_empty_sdl_surface(uint32_t w, uint32_t h);
 	SDL_Surface * join_sdl_surfaces
 		(uint32_t w, uint32_t h,
@@ -168,13 +181,16 @@
 	SDL_Surface * load_image(std::string file);
 	SDL_Surface * render_space
 		(Text_Block &, RGBColor bg, int32_t style = TTF_STYLE_NORMAL);
-	void render_caret
-		(TTF_Font &,
-		 SDL_Surface & line,
-		 const std::string & text_caret_pos);
+
+	void draw_caret
+		(RenderTarget &,
+		 const TextStyle &,
+		 Point dstpoint,
+		 const std::string & text,
+		 uint32_t caret);
 };
 
-extern Font_Handler * g_fh; // the default font
+extern Font_Handler * g_fh;
 
 }
 

=== removed file 'src/graphic/font_loader.cc'
--- src/graphic/font_loader.cc	2010-05-18 13:21:05 +0000
+++ src/graphic/font_loader.cc	1970-01-01 00:00:00 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2002, 2008-2009 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#include "font_loader.h"
-#include "font_handler.h"
-
-#include "io/fileread.h"
-#include "io/filesystem/layered_filesystem.h"
-
-#include "wexception.h"
-
-#include <SDL_ttf.h>
-
-#include <iostream>
-#include <string>
-#include <cstring>
-
-namespace UI {
-
-Font_Handler * g_fh = 0; // the font handler
-
-/*
-===============================================================================
-
-Font Loader IMPLEMENTATION
-
-===============================================================================
-*/
-
-
-/*
-* Opens a font file and returns a TTF_FONT* pointer.
-*/
-
-TTF_Font * Font_Loader::open_font(std::string const & name, int32_t const size)
-{
-	// Load the TrueType Font
-	std::string filename = "fonts/";
-	filename            += name;
-
-	//  We must keep this File Read open, otherwise the following calls are
-	//  crashing. do not know why...
-	FileRead & fr = *new FileRead();
-	fr.Open(*g_fs, filename.c_str());
-
-	m_freads.push_back(&fr);
-
-	SDL_RWops * const ops = SDL_RWFromMem(fr.Data(0), fr.GetSize());
-	if (!ops)
-		throw wexception("could not load font!: RWops Pointer invalid");
-
-	if (TTF_Font * const font = TTF_OpenFontIndexRW(ops, 1, size, 0))
-		return font;
-	else
-		throw wexception("could not load font!: %s", TTF_GetError());
-}
-
-/*
-* Looks for a font with given name and size in the font cache and returns it.
-* Ohterwise font will be loaded with open_font and chached.
-*/
-TTF_Font * Font_Loader::get_font(std::string const & name, int32_t const size)
-{
-	char buffer[5];
-	snprintf(buffer, sizeof(buffer), "%i", size);
-
-	const std::string key_name = name + '-' + buffer;
-	std::map<std::string, TTF_Font *>::iterator const it =
-		m_font_table.find(key_name);
-	if (it != m_font_table.end()) {
-		TTF_SetFontStyle(it->second, TTF_STYLE_BOLD);
-		return it->second;
-	}
-
-	TTF_Font * const font = open_font(name, size);
-
-	if (font) {
-		TTF_SetFontStyle(font, TTF_STYLE_BOLD);
-		m_font_table.insert(std::pair<std::string, TTF_Font *>(key_name, font));
-	}
-	return font;
-}
-
-/*
-* Clears the font cache.
-*/
-void Font_Loader::clear_fonts() {
-	for
-		(std::map<std::string, TTF_Font *>::iterator i = m_font_table.begin();
-		 i != m_font_table.end();
-		 ++i)
-		TTF_CloseFont(i->second);
-	m_font_table.clear();
-
-	for (uint32_t i = 0; i < m_freads.size(); ++i)
-		delete m_freads[i];
-	m_freads.clear();
-}
-
-
-Font_Loader::~Font_Loader() {
-	clear_fonts();
-}
-
-}

=== removed file 'src/graphic/font_loader.h'
--- src/graphic/font_loader.h	2010-05-12 10:16:44 +0000
+++ src/graphic/font_loader.h	1970-01-01 00:00:00 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2002-2004, 2006, 2008-2009 by the Widelands Development Team
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-#ifndef FONT_LOADER_H
-#define FONT_LOADER_H
-
-#include "io/fileread.h"
-
-#include <SDL_ttf.h>
-
-#include <map>
-#include <string>
-#include <cstring>
-#include <vector>
-
-namespace UI {
-
-/*
- * Font
- *
- * this represents a loaded font used by the FontHandler
- */
-struct Font_Loader {
-	Font_Loader() {};
-	~Font_Loader();
-	TTF_Font * open_font(const std::string & name, int32_t size);
-	TTF_Font * get_font (std::string const & name, int32_t size);
-	void clear_fonts();
-private:
-	std::map<std::string, TTF_Font *> m_font_table;
-	std::vector<FileRead *> m_freads;
-};
-
-}
-
-#endif

=== modified file 'src/graphic/render/render_sdl.cc'
--- src/graphic/render/render_sdl.cc	2010-11-27 16:23:39 +0000
+++ src/graphic/render/render_sdl.cc	2011-01-30 15:33:06 +0000
@@ -73,7 +73,7 @@
 	//log("SurfaceSDL::draw_rect()\n");
 	const uint32_t color = clr.map(format());
 
-	const Point bl = rc.bottom_left() - Point(1, 1);
+	const Point bl = rc.bottom_right() - Point(1, 1);
 
 	for (int32_t x = rc.x + 1; x < bl.x; ++x) {
 		set_pixel(x, rc.y, color);
@@ -126,7 +126,7 @@
 
 	//log("SurfaceSDL::brighten_rect()\n");
 
-	const Point bl = rc.bottom_left();
+	const Point bl = rc.bottom_right();
 
 	lock(IPixelAccess::Lock_Normal);
 

=== added file 'src/graphic/wordwrap.cc'
--- src/graphic/wordwrap.cc	1970-01-01 00:00:00 +0000
+++ src/graphic/wordwrap.cc	2011-01-30 15:33:06 +0000
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2002-2011 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * The original version of the word wrapping algorithm was taken
+ * from Wesnoth -- http://www.wesnoth.org
+ */
+
+#include "wordwrap.h"
+
+#include "font_handler.h"
+#include "log.h"
+#include "rendertarget.h"
+
+namespace UI {
+
+/**
+ * Initialize the wordwrap object with an unlimited line length
+ * and a default-constructed text style.
+ */
+WordWrap::WordWrap() :
+	m_wrapwidth(std::numeric_limits<uint32_t>::max())
+{
+}
+
+WordWrap::WordWrap(const TextStyle & style, uint32_t wrapwidth) :
+	m_style(style)
+{
+	m_wrapwidth = wrapwidth;
+
+	if (m_wrapwidth < std::numeric_limits<uint32_t>::max()) {
+		if (m_wrapwidth < 2 * LINE_MARGIN)
+			m_wrapwidth = 0;
+		else
+			m_wrapwidth -= 2 * LINE_MARGIN;
+	}
+}
+
+/**
+ * Set the text style for future wrapping operations.
+ */
+void WordWrap::set_style(const TextStyle & style)
+{
+	m_style = style;
+}
+
+/**
+ * Set the wrap width (i.e. line width limit in pixels) for future wrapping operations.
+ */
+void WordWrap::set_wrapwidth(uint32_t wrapwidth)
+{
+	m_wrapwidth = wrapwidth;
+}
+
+/**
+ * Return the wrap width. This can be larger than the actual @ref width of the final
+ * text.
+ */
+uint32_t WordWrap::wrapwidth() const
+{
+	return m_wrapwidth;
+}
+
+/**
+ * Perform the wrapping computations for the given text and fill in
+ * the private data containing the wrapped results.
+ */
+void WordWrap::wrap(const std::string & text)
+{
+	//static int count = 0;
+	//log("word_wrap_text(%u): %i\n", m_wrapwidth, ++count);
+
+	m_lines.clear();
+
+	std::string::size_type line_start = 0;
+
+	while (line_start <= text.size()) {
+		std::string::size_type next_line_start;
+		std::string::size_type line_end;
+
+		compute_end_of_line(text, line_start, line_end, next_line_start);
+
+		LineData ld;
+		ld.start = line_start;
+		ld.text = text.substr(line_start, line_end - line_start);
+		m_lines.push_back(ld);
+
+		line_start = next_line_start;
+	}
+}
+
+
+/**
+ * Compute the position where the line that starts at \p line_start
+ * ends.
+ */
+void WordWrap::compute_end_of_line
+	(const std::string & text,
+	 std::string::size_type line_start,
+	 std::string::size_type & line_end,
+	 std::string::size_type & next_line_start)
+{
+	std::string::size_type orig_end = text.find('\n', line_start);
+	if (orig_end == std::string::npos)
+		orig_end = text.size();
+
+	if (m_wrapwidth == std::numeric_limits<uint32_t>::max() || orig_end - line_start <= 1) {
+		// Special fast path when wrapping is disabled or
+		// original text line contains at most one character
+		line_end = orig_end;
+		next_line_start = orig_end + 1;
+		return;
+	}
+
+	// Optimism: perhaps the entire line fits?
+	if (m_style.calc_bare_width(text.substr(line_start, orig_end - line_start)) <= m_wrapwidth) {
+		line_end = orig_end;
+		next_line_start = orig_end + 1;
+		return;
+	}
+
+	// Okay, we really do need to wrap; get a first rough estimate using binary search
+	// Invariant: [line_start, end_lower) fits,
+	// but everything strictly longer than [line_start, end_upper) does not fit
+	// We force the lower bound to allow at least one character,
+	// otherwise the word wrap might get into an infinite loop.
+	std::string::size_type end_upper = orig_end - 1;
+	std::string::size_type end_lower = line_start + 1;
+
+	while (end_upper - end_lower > 4) {
+		std::string::size_type mid = end_lower + (end_upper - end_lower + 1) / 2;
+
+		if (m_style.calc_bare_width(text.substr(line_start, mid - line_start)) <= m_wrapwidth) {
+			end_lower = mid;
+		} else {
+			end_upper = mid - 1;
+		}
+	}
+
+	// Narrow it down to a word break
+	// Invariant: space points to a space character such that [line_start, space) fits
+	std::string::size_type space = end_lower;
+
+	while (space > line_start && text[space] != ' ')
+		--space;
+
+	for (;;) {
+		std::string::size_type nextspace = text.find(' ', space + 1);
+		if (nextspace > end_upper)
+			break; // we already know that this cannot possibly fit
+
+		// check whether the next word still fits
+		if (m_style.calc_bare_width(text.substr(line_start, nextspace - line_start)) > m_wrapwidth)
+			break;
+
+		space = nextspace;
+	}
+
+	if (space > line_start) {
+		line_end = space;
+		next_line_start = space + 1;
+		return;
+	}
+
+	// Nasty special case: the line starts with a single word that is too big to fit
+	// Continue the binary search until we narrowed down exactly how many characters fit
+	while (end_upper > end_lower) {
+		std::string::size_type mid = end_lower + (end_upper - end_lower + 1) / 2;
+
+		if (m_style.calc_bare_width(text.substr(line_start, mid - line_start)) <= m_wrapwidth)
+			end_lower = mid;
+		else
+			end_upper = mid - 1;
+	}
+
+	next_line_start = line_end = end_lower;
+}
+
+
+/**
+ * Compute the width (including border) of the word-wrapped text.
+ *
+ * \note This is rather inefficient right now.
+ */
+uint32_t WordWrap::width() const
+{
+	uint32_t width = 0;
+
+	for (uint32_t line = 0; line < m_lines.size(); ++line) {
+		uint32_t linewidth = m_style.calc_bare_width(m_lines[line].text);
+		if (linewidth > width)
+			width = linewidth;
+	}
+
+	return width + 2 * LINE_MARGIN;
+}
+
+/**
+ * Compute the total height of the word-wrapped text.
+ */
+uint32_t WordWrap::height() const
+{
+	uint32_t fontheight = m_style.font->height();
+	uint32_t lineskip = m_style.font->lineskip();
+
+	return fontheight + (m_lines.size() - 1) * lineskip;
+}
+
+/**
+ * Given an offset @p caret into the original text, compute the @p line that it
+ * appears in in the wrapped text, and also the @p pos within that line (as an offset).
+ */
+void WordWrap::calc_wrapped_pos(uint32_t caret, uint32_t & line, uint32_t & pos) const
+{
+	assert(m_lines.size());
+	assert(m_lines[0].start == 0);
+
+	uint32_t min = 0;
+	uint32_t max = m_lines.size() - 1;
+
+	while (max > min) {
+		uint32_t mid = min + (max - min + 1) / 2;
+
+		if (caret >= m_lines[mid].start)
+			min = mid;
+		else
+			max = mid - 1;
+	}
+
+	assert(caret >= m_lines[min].start);
+
+	line = min;
+	pos = caret - m_lines[min].start;
+}
+
+/**
+ * Return the starting offset of line number @p line in the original text.
+ */
+uint32_t WordWrap::line_offset(uint32_t line) const
+{
+	return m_lines[line].start;
+}
+
+/**
+ * Draw the word-wrapped text onto \p dst, anchored at \p where with the given alignment.
+ *
+ * \note This also draws the caret, if any.
+ */
+void WordWrap::draw(RenderTarget & dst, Point where, Align align, uint32_t caret)
+{
+	uint32_t fontheight = m_style.font->height();
+	uint32_t lineskip = m_style.font->lineskip();
+	uint32_t caretline, caretpos;
+
+	calc_wrapped_pos(caret, caretline, caretpos);
+
+	if ((align & Align_Vertical) != Align_Top) {
+		uint32_t h = height();
+
+		if ((align & Align_Vertical) == Align_VCenter)
+			where.y -= (h + 1) / 2;
+		else
+			where.y -= h;
+	}
+
+	++where.y;
+	for (uint32_t line = 0; line < m_lines.size(); ++line, where.y += lineskip) {
+		if (where.y >= dst.get_h() || int32_t(where.y + fontheight) <= 0)
+			continue;
+
+		g_fh->draw_text
+			(dst, m_style, where, m_lines[line].text, Align(align & Align_Horizontal),
+			 line == caretline ? caretpos : std::numeric_limits<uint32_t>::max());
+	}
+}
+
+
+} // namespace UI

=== added file 'src/graphic/wordwrap.h'
--- src/graphic/wordwrap.h	1970-01-01 00:00:00 +0000
+++ src/graphic/wordwrap.h	2011-01-30 15:33:06 +0000
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010-2011 by the Widelands Development Team
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef WORDWRAP_H
+#define WORDWRAP_H
+
+#include <string>
+
+#include "font.h"
+#include "point.h"
+#include "ui_basic/align.h"
+
+struct RenderTarget;
+
+namespace UI {
+
+/**
+ * Helper struct that provides word wrapping and related functionality.
+ */
+struct WordWrap {
+	WordWrap();
+	WordWrap(const TextStyle & style, uint32_t wrapwidth = std::numeric_limits<uint32_t>::max());
+
+	void set_style(const TextStyle & style);
+	void set_wrapwidth(uint32_t wrapwidth);
+
+	uint32_t wrapwidth() const;
+
+	void wrap(const std::string & text);
+
+	uint32_t width() const;
+	uint32_t height() const;
+
+	void draw
+		(RenderTarget & dst, Point where, Align align = Align_Left,
+		 uint32_t caret = std::numeric_limits<uint32_t>::max());
+
+	void calc_wrapped_pos(uint32_t caret, uint32_t & line, uint32_t & pos) const;
+	uint32_t nrlines() const {return m_lines.size();}
+	uint32_t line_offset(uint32_t line) const;
+
+private:
+	struct LineData {
+		/// Textual content of the line
+		std::string text;
+
+		/// Starting offset of this line within the original un-wrapped text
+		uint32_t start;
+	};
+
+	void compute_end_of_line
+		(const std::string & text,
+		 std::string::size_type line_start,
+		 std::string::size_type & line_end,
+		 std::string::size_type & next_line_start);
+
+	TextStyle m_style;
+	uint32_t m_wrapwidth;
+
+	std::vector<LineData> m_lines;
+};
+
+} // namespace UI
+
+#endif // WORDWRAP_H

=== modified file 'src/logic/building.cc'
--- src/logic/building.cc	2010-11-01 14:00:56 +0000
+++ src/logic/building.cc	2011-01-30 15:33:06 +0000
@@ -30,6 +30,7 @@
 #include "productionsite.h"
 #include "profile/profile.h"
 #include "graphic/rendertarget.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "sound/sound_handler.h"
 #include "tribe.h"
@@ -734,10 +735,8 @@
 
 	if (dpyflags & Interactive_Base::dfShowCensus) {
 		//  TODO make more here
-		UI::g_fh->draw_string
-			(dst,
-			 UI_FONT_SMALL,
-			 UI_FONT_SMALL_CLR,
+		UI::g_fh->draw_text
+			(dst, UI::TextStyle::ui_small(),
 			 pos - Point(0, 45),
 			 info_string(igbase.building_census_format()),
 			 UI::Align_Center);
@@ -749,10 +748,8 @@
 				(!iplayer->player().see_all() &&
 				 iplayer->player().is_hostile(*get_owner()))
 				return;
-		UI::g_fh->draw_string
-			(dst,
-			 UI_FONT_SMALL,
-			 UI_FONT_SMALL_CLR,
+		UI::g_fh->draw_text
+			(dst, UI::TextStyle::ui_small(),
 			 pos - Point(0, 35),
 			 info_string(igbase.building_statistics_format()),
 			 UI::Align_Center);

=== modified file 'src/rect.h'
--- src/rect.h	2010-05-24 16:07:20 +0000
+++ src/rect.h	2011-01-30 15:33:06 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2007 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -27,7 +27,7 @@
 	Rect(const Point p, const uint32_t W, const uint32_t H) throw ()
 		: Point(p), w(W), h(H)
 	{}
-	Point bottom_left() const {return *this + Point(w, h);}
+	Point bottom_right() const {return *this + Point(w, h);}
 
 	/**
 	 * Returns true if this rectangle contains the given point.

=== modified file 'src/ui_basic/button.cc'
--- src/ui_basic/button.cc	2010-12-30 17:01:47 +0000
+++ src/ui_basic/button.cc	2011-01-30 15:33:06 +0000
@@ -21,6 +21,7 @@
 
 #include "mouse_constants.h"
 
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/picture.h"
 #include "graphic/rendertarget.h"
@@ -37,26 +38,23 @@
 	 PictureID background_picture_id,
 	 std::string const & title_text,
 	 std::string const & tooltip_text,
-	 bool const _enabled, bool const flat,
-	 std::string const & fontname,
-	 uint32_t const      fontsize)
+	 bool const _enabled, bool const flat)
 	:
-	NamedPanel            (parent, name, x, y, w, h, tooltip_text),
-	m_highlighted         (false),
-	m_pressed             (false),
-	m_permpressed         (false),
-	m_enabled             (_enabled),
-	m_repeating           (false),
-	m_flat                (flat),
+	NamedPanel           (parent, name, x, y, w, h, tooltip_text),
+	m_highlighted   (false),
+	m_pressed       (false),
+	m_permpressed   (false),
+	m_enabled       (_enabled),
+	m_repeating     (false),
+	m_flat          (flat),
 	m_draw_flat_background(false),
-	m_title               (title_text),
-	m_pic_background      (background_picture_id),
-	m_pic_custom          (g_gr->get_no_picture()),
-	m_pic_custom_disabled (g_gr->get_no_picture()),
-	m_fontname            (fontname),
-	m_fontsize            (fontsize),
-	m_clr_down            (229, 161, 2),
-	m_draw_caret          (false)
+	m_title         (title_text),
+	m_pic_background(background_picture_id),
+	m_pic_custom    (g_gr->get_no_picture()),
+	m_pic_custom_disabled(g_gr->get_no_picture()),
+	m_font(UI::Font::ui_small()),
+	m_clr_down      (229, 161, 2),
+	m_draw_caret    (false)
 {
 	set_think(false);
 
@@ -72,25 +70,22 @@
 	 PictureID background_picture_id,
 	 const PictureID foreground_picture_id,
 	 const std::string & tooltip_text,
-	 bool const _enabled, bool const flat,
-	 const std::string & fontname,
-	 const uint32_t      fontsize)
+	 bool const _enabled, bool const flat)
 	:
-	NamedPanel            (parent, name, x, y, w, h, tooltip_text),
-	m_highlighted         (false),
-	m_pressed             (false),
-	m_permpressed         (false),
-	m_enabled             (_enabled),
-	m_repeating           (false),
-	m_flat                (flat),
+	NamedPanel      (parent, name, x, y, w, h, tooltip_text),
+	m_highlighted   (false),
+	m_pressed       (false),
+	m_permpressed   (false),
+	m_enabled       (_enabled),
+	m_repeating     (false),
+	m_flat          (flat),
 	m_draw_flat_background(false),
-	m_pic_background      (background_picture_id),
-	m_pic_custom          (foreground_picture_id),
-	m_pic_custom_disabled (g_gr->create_grayed_out_pic(foreground_picture_id)),
-	m_fontname            (fontname),
-	m_fontsize            (fontsize),
-	m_clr_down            (229, 161, 2),
-	m_draw_caret          (false)
+	m_pic_background(background_picture_id),
+	m_pic_custom    (foreground_picture_id),
+	m_pic_custom_disabled(g_gr->create_grayed_out_pic(foreground_picture_id)),
+	m_font(UI::Font::ui_small()),
+	m_clr_down      (229, 161, 2),
+	m_draw_caret    (false)
 {
 	set_think(false);
 
@@ -189,20 +184,17 @@
 			 	 (get_h() - static_cast<int32_t>(cph)) >> 1),
 			 m_enabled ? m_pic_custom : m_pic_custom_disabled);
 
-	} else if (m_title.length()) //  otherwise draw title string centered
-		UI::g_fh->draw_string
-			(dst,
-			 m_fontname,
-			 m_fontsize,
-			 m_enabled ? UI_FONT_CLR_FG : UI_FONT_CLR_DISABLED, UI_FONT_CLR_BG,
-			 Point(get_w() >> 1, get_h() >> 1),
-			 m_title,
-			 Align_Center,
-			 std::numeric_limits<uint32_t>::max(),
-			 Widget_Cache_None,
-			 0,
-			 m_draw_caret ? m_title.length() :
-			 std::numeric_limits<uint32_t>::max());
+	} else if (m_title.length()) {
+		//  otherwise draw title string centered
+		UI::TextStyle ts;
+		ts.font = m_font;
+		ts.bold = true;
+		ts.fg = m_enabled ? UI_FONT_CLR_FG : UI_FONT_CLR_DISABLED;
+		UI::g_fh->draw_text
+			(dst, ts, Point(get_w() / 2, get_h() / 2),
+			 m_title, Align_Center,
+			 m_draw_caret ? m_title.length() : std::numeric_limits<uint32_t>::max());
+	}
 
 	//  draw border
 	//  a pressed but not highlighted button occurs when the user has pressed

=== modified file 'src/ui_basic/button.h'
--- src/ui_basic/button.h	2010-12-30 17:01:47 +0000
+++ src/ui_basic/button.h	2011-01-30 15:33:06 +0000
@@ -31,6 +31,8 @@
 
 namespace UI {
 
+struct Font;
+
 /// This is simply a button. Override void clicked() to react to the click.
 /// This is all that is needed in most cases, but if there is a need to give a
 /// callback function to the button, there are some templates for that below.
@@ -43,9 +45,7 @@
 		 std::string const & title_text,
 		 std::string const & tooltip_text = std::string(),
 		 bool const _enabled = true,
-		 bool const flat    = false,
-		 std::string const & fontname = UI_FONT_NAME,
-		 uint32_t const      fontsize = UI_FONT_SIZE_SMALL);
+		 bool const flat    = false);
 	Button /// for pictorial buttons
 		(Panel * const parent,
 		 std::string const & name,
@@ -54,9 +54,7 @@
 		 const PictureID foreground_picture_id,
 		 std::string const & tooltip_text = std::string(),
 		 bool const _enabled = true,
-		 bool const flat     = false,
-		 const std::string & fontname = UI_FONT_NAME,
-		 const uint32_t      fontsize = UI_FONT_SIZE_SMALL);
+		 bool const flat     = false);
 	~Button();
 
 	void set_pic(PictureID picid);
@@ -67,10 +65,7 @@
 	void set_enabled(bool on);
 	void set_repeating(bool const on) {m_repeating = on;}
 	void set_draw_caret(bool draw_caret) {m_draw_caret = draw_caret;}
-	void set_font(std::string const & name, int32_t size) {
-		m_fontname = name;
-		m_fontsize = size;
-	}
+	void set_font(Font * font) {m_font = font;}
 	bool is_snap_target() const {return true;}
 
 	// Drawing and event handlers
@@ -108,8 +103,7 @@
 	PictureID   m_pic_background; //  background texture (picture ID)
 	PictureID   m_pic_custom;     //  custom icon on the button
 	PictureID   m_pic_custom_disabled;
-	std::string m_fontname;
-	uint32_t    m_fontsize;
+	Font * m_font;
 
 	RGBColor    m_clr_down; //  color of border while a flat button is "down"
 	bool        m_draw_caret;
@@ -127,9 +121,7 @@
 		 const std::string & title_text,
 		 std::string const & tooltip_text = std::string(),
 		 bool const _enabled = true,
-		 bool const flat     = false,
-		 const std::string & fontname = UI_FONT_NAME,
-		 const uint32_t      fontsize = UI_FONT_SIZE_SMALL)
+		 bool const flat     = false)
 		:
 		Button
 			(parent, name,
@@ -137,9 +129,7 @@
 			 background_pictute_id,
 			 title_text,
 			 tooltip_text,
-			 _enabled, flat,
-			 fontname,
-			 fontsize),
+			 _enabled, flat),
 		_callback_function     (callback_function)
 	{}
 	Callback_Button /// for pictorial buttons
@@ -151,9 +141,7 @@
 		 boost::function<void()> callback_function,
 		 std::string const & tooltip_text = std::string(),
 		 bool const _enabled = true,
-		 bool const flat     = false,
-		 const std::string & fontname = UI_FONT_NAME,
-		 const uint32_t      fontsize = UI_FONT_SIZE_SMALL)
+		 bool const flat     = false)
 		:
 		Button
 			(parent, name,
@@ -161,9 +149,7 @@
 			 background_pictute_id,
 			 foreground_picture_id,
 			 tooltip_text,
-			 _enabled, flat,
-			 fontname,
-			 fontsize),
+			 _enabled, flat),
 		_callback_function     (callback_function)
 	{}
 

=== modified file 'src/ui_basic/editbox.cc'
--- src/ui_basic/editbox.cc	2010-11-27 13:30:37 +0000
+++ src/ui_basic/editbox.cc	2011-01-30 15:33:06 +0000
@@ -21,6 +21,7 @@
 
 #include "mouse_constants.h"
 
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/rendertarget.h"
 #include "helper.h"
@@ -393,17 +394,13 @@
 
 	pos.x += m->scrolloffset;
 
-	UI::g_fh->draw_string
+	UI::g_fh->draw_text
 		(dst,
-		 m->fontname, m->fontsize, m->fontcolor, UI_FONT_CLR_BG,
+		 TextStyle::makebold(Font::get(m->fontname, m->fontsize), m->fontcolor),
 		 pos,
 		 m->text,
 		 align(),
-		 std::numeric_limits<uint32_t>::max(),
-		 Widget_Cache_None,
-		 0,
-		 has_focus() ? static_cast<int32_t>(m->caret) :
-		 std::numeric_limits<uint32_t>::max());
+		 has_focus() ? static_cast<int32_t>(m->caret) : std::numeric_limits<uint32_t>::max());
 }
 
 /**

=== modified file 'src/ui_basic/helpwindow.cc'
--- src/ui_basic/helpwindow.cc	2010-12-20 18:17:09 +0000
+++ src/ui_basic/helpwindow.cc	2011-01-30 15:33:06 +0000
@@ -23,6 +23,7 @@
 #include "i18n.h"
 #include "window.h"
 #include "button.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "wlapplication.h"
 
@@ -68,14 +69,14 @@
 	set_inner_size(in_width, in_height);
 	set_pos(Point((g_gr->get_xres() - out_width) / 2, (g_gr->get_yres() - out_height) / 2));
 
-	new Callback_Button
+	Button * btn = new Callback_Button
 		(this, "ok",
 		 in_width / 3, in_height - but_height * 3 / 2,
 		 in_width / 3, but_height,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&HelpWindow::pressedOk, boost::ref(*this)),
-		 _("OK"), std::string(), true, false,
-		 UI_FONT_NAME, (fontsize < 12 ? 12 : fontsize));
+		 _("OK"), std::string(), true, false);
+	btn->set_font(Font::get(UI_FONT_NAME, (fontsize < 12 ? 12 : fontsize)));
 
 	textarea->set_size(in_width - 10, in_height - 10 - (2 * but_height));
 }

=== modified file 'src/ui_basic/listselect.cc'
--- src/ui_basic/listselect.cc	2010-12-03 21:42:50 +0000
+++ src/ui_basic/listselect.cc	2011-01-30 15:33:06 +0000
@@ -20,6 +20,7 @@
 #include "listselect.h"
 
 #include "constants.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/offscreensurface.h"
 #include "graphic/rendertarget.h"
@@ -392,11 +393,9 @@
 		const RGBColor col = er.use_clr ? er.clr : UI_FONT_CLR_FG;
 
 		// Horizontal center the string
-		UI::g_fh->draw_string
+		UI::g_fh->draw_text
 			(dst,
-			 m_fontname, m_fontsize,
-			 col,
-			 RGBColor(107, 87, 55),
+			 TextStyle::makebold(Font::get(m_fontname, m_fontsize), col),
 			 Point
 			 	(x,
 			 	 y +
@@ -407,7 +406,6 @@
 			 m_align);
 
 		// Now draw pictures
-
 		if (er.picid != g_gr->get_no_picture()) {
 			uint32_t w, h;
 			g_gr->get_picture_size(er.picid, w, h);

=== modified file 'src/ui_basic/multilineeditbox.cc'
--- src/ui_basic/multilineeditbox.cc	2010-11-27 13:30:37 +0000
+++ src/ui_basic/multilineeditbox.cc	2011-01-30 15:33:06 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002-2004, 2006-2010 by the Widelands Development Team
+ * Copyright (C) 2002-2004, 2006-2011 by the Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -23,202 +23,394 @@
 #include "constants.h"
 #include "graphic/font_handler.h"
 #include "graphic/rendertarget.h"
+#include "graphic/wordwrap.h"
 #include "helper.h"
 #include "wlapplication.h"
-
-#include <SDL_keysym.h>
-
-#include <algorithm>
+#include <scripting/pdep/llimits.h>
 
 namespace UI {
+
+static const int32_t ms_darken_value = -20;
+static const int32_t ms_scrollbar_w = 24;
+
+struct Multiline_Editbox::Data {
+	Scrollbar scrollbar;
+
+	/// The text in the edit box
+	std::string text;
+
+	/// Position of the cursor inside the text.
+	/// 0 indicates that the cursor is before the first character,
+	/// text.size() inidicates that the cursor is after the last character.
+	uint32_t cursor_pos;
+
+	/// Font and style
+	TextStyle textstyle;
+
+	/// Maximum length of the text string, in bytes
+	uint32_t maxbytes;
+
+	/// Cached wrapping info; see @ref refresh_ww and @ref update
+	/*@{*/
+	bool ww_valid;
+	WordWrap ww;
+	/*@}*/
+
+	Data(Multiline_Editbox &);
+	void refresh_ww();
+
+	void update();
+
+	void scroll_cursor_into_view();
+	void set_cursor_pos(uint32_t cursor_pos);
+
+	uint32_t prev_char(uint32_t cursor);
+	uint32_t next_char(uint32_t cursor);
+	uint32_t snap_to_char(uint32_t cursor);
+
+	void erase_bytes(uint32_t start, uint32_t end);
+	void insert(uint32_t where, const std::string & s);
+
+	bool is_utf8_extended(char ch) const;
+	std::string unicode_to_utf8(uint16_t unicode) const;
+
+private:
+	Multiline_Editbox & owner;
+};
+
 /**
  * Initialize an editbox that supports multiline strings.
 */
 Multiline_Editbox::Multiline_Editbox
 	(Panel * parent,
 	 int32_t x, int32_t y, uint32_t w, uint32_t h,
-	 const char * text)
+	 const std::string & text)
 	:
-	Multiline_Textarea(parent, x, y, w, h, text, Align_Left, true),
-	m_cur_pos         (get_text().size()),
-	m_maxchars        (0xffff),
-	m_needs_update    (false)
+	Panel(parent, x, y, w, h),
+	d(new Data(*this))
 {
-	set_scrollmode(ScrollNormal);
 	set_handle_mouse(true);
 	set_can_focus(true);
 	set_think(false);
-}
-
-
-/**
- * A key event must be handled
-*/
-bool Multiline_Editbox::handle_key(bool const down, SDL_keysym const code) {
-	m_needs_update = true;
-
+
+	set_text(text);
+}
+
+Multiline_Editbox::Data::Data(Multiline_Editbox & o)
+:
+scrollbar(&o, o.get_w() - ms_scrollbar_w, 0, ms_scrollbar_w, o.get_h(), false),
+cursor_pos(0),
+textstyle(TextStyle::ui_small()),
+maxbytes(0xffff),
+ww_valid(false),
+owner(o)
+{
+	scrollbar.moved.set(&o, &Multiline_Editbox::scrollpos_changed);
+
+	scrollbar.set_pagesize(owner.get_h() - 2 * textstyle.font->height());
+	scrollbar.set_singlestepsize(textstyle.font->height());
+}
+
+/**
+ * Call this function whenever some part of the data changes that potentially
+ * requires some redrawing.
+ */
+void Multiline_Editbox::Data::update()
+{
+	ww_valid = false;
+	owner.update();
+}
+
+/**
+ * Return the text currently stored by the editbox.
+ */
+std::string const & Multiline_Editbox::get_text() const
+{
+	return d->text;
+}
+
+/**
+ * Replace the currently stored text with something else.
+ */
+void Multiline_Editbox::set_text(const std::string & text)
+{
+	if (text == d->text)
+		return;
+
+	d->text = text;
+	while (d->text.size() > d->maxbytes)
+		d->erase_bytes(d->prev_char(d->text.size()), d->text.size());
+
+	if (d->cursor_pos > d->text.size())
+		d->cursor_pos = d->text.size();
+
+	d->update();
+	d->scroll_cursor_into_view();
+
+	changed.call();
+}
+
+/**
+ * Set the text style.
+ */
+void Multiline_Editbox::set_textstyle(const UI::TextStyle & ts)
+{
+	if (d->textstyle == ts)
+		return;
+
+	d->textstyle = ts;
+	d->update();
+
+}
+
+/**
+ * Set the maximum number of bytes in the scrollbar text.
+ *
+ * This will shorten the currently stored text when necessary.
+ */
+void Multiline_Editbox::set_maximum_bytes(const uint32_t n)
+{
+	while (n < d->text.size())
+		d->erase_bytes(d->prev_char(d->text.size()), d->text.size());
+	d->maxbytes = n;
+
+	// do not need to update here, because erase() will
+	// update when necessary
+}
+
+/**
+ * Return the currently set maximum number of bytes.
+ */
+uint32_t Multiline_Editbox::get_maximum_bytes() const
+{
+	return d->maxbytes;
+}
+
+/**
+ * Return @c true iff the given character is an extended byte of
+ * a multi-byte UTF8 character.
+ */
+bool Multiline_Editbox::Data::is_utf8_extended(char ch) const
+{
+	return (ch & 0xc0) == 0x80;
+}
+
+/**
+ * Convert a unicode character into a multi-byte utf8 string.
+ */
+std::string Multiline_Editbox::Data::unicode_to_utf8(uint16_t unicode) const
+{
+	unsigned char buf[4];
+
+	memset(buf, 0, sizeof(buf));
+
+	if (unicode < 0x80) {
+		buf[0] = unicode;
+	} else if (unicode < 0x800) {
+		buf[0] = ((unicode & 0x7c0) >> 6) | 0xc0;
+		buf[1] = (unicode & 0x3f) | 0x80;
+	} else {
+		buf[0] = ((unicode & 0xf000) >> 12) | 0xe0;
+		buf[1] = ((unicode & 0xfc0) >> 6) | 0x80;
+		buf[2] = (unicode & 0x3f) | 0x80;
+	}
+
+	return reinterpret_cast<char *>(buf);
+}
+
+/**
+ * Erase the given range of bytes, adjust the cursor position, and update.
+ */
+void Multiline_Editbox::Data::erase_bytes(uint32_t start, uint32_t end)
+{
+	assert(start <= end);
+	assert(end <= text.size());
+
+	uint32_t nbytes = end - start;
+	text.erase(start, nbytes);
+	update();
+
+	if (cursor_pos >= end)
+		set_cursor_pos(cursor_pos - nbytes);
+	else if (cursor_pos > start)
+		set_cursor_pos(start);
+}
+
+/**
+ * Find the starting byte of the previous character
+ */
+uint32_t Multiline_Editbox::Data::prev_char(uint32_t cursor)
+{
+	assert(cursor <= text.size());
+
+	if (cursor == 0)
+		return cursor;
+
+	do {
+		--cursor;
+	} while (cursor > 0 && is_utf8_extended(text[cursor]));
+
+	return cursor;
+}
+
+/**
+ * Find the starting byte of the next character
+ */
+uint32_t Multiline_Editbox::Data::next_char(uint32_t cursor)
+{
+	assert(cursor <= text.size());
+
+	if (cursor >= text.size())
+		return cursor;
+
+	do {
+		++cursor;
+	} while (cursor < text.size() && is_utf8_extended(text[cursor]));
+
+	return cursor;
+}
+
+/**
+ * Return the starting offset of the (multi-byte) character that @p cursor points to.
+ */
+uint32_t Multiline_Editbox::Data::snap_to_char(uint32_t cursor)
+{
+	while (cursor > 0 && is_utf8_extended(text[cursor]))
+		--cursor;
+	return cursor;
+}
+
+/**
+ * This is called by the UI code whenever a key press or release arrives
+ */
+bool Multiline_Editbox::handle_key(bool const down, SDL_keysym const code)
+{
 	if (down) {
-		std::string txt =
-			UI::g_fh->word_wrap_text
-				(m_fontname, m_fontsize, get_text(), get_eff_w());
-		assert(m_cur_pos <= txt.size());
 		switch (code.sym) {
-
 		case SDLK_DELETE:
-			if (m_cur_pos < txt.size()) {
-				do {
-					++m_cur_pos;
-				} while
-						(m_cur_pos < txt.size() &&
-						 ((txt.at(m_cur_pos) & 0xc0) == 0x80));
-				// fallthrough - handle it like backspace
-			} else
-				break;
+			if (d->cursor_pos < d->text.size()) {
+				d->erase_bytes(d->cursor_pos, d->next_char(d->cursor_pos));
+				changed.call();
+			}
+			break;
 
 		case SDLK_BACKSPACE:
-			if (txt.size() and m_cur_pos) {
-				while ((txt.at(--m_cur_pos) & 0xc0) == 0x80) {
-					txt.erase(txt.begin() + m_cur_pos);
-					if (m_cur_pos == 0)
+			if (d->cursor_pos > 0) {
+				d->erase_bytes(d->prev_char(d->cursor_pos), d->cursor_pos);
+				changed.call();
+			}
+			break;
+
+		case SDLK_LEFT: {
+			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
+				uint32_t newpos = d->prev_char(d->cursor_pos);
+				while (newpos > 0 && isspace(d->text[newpos]))
+					newpos = d->prev_char(newpos);
+				while (newpos > 0) {
+					uint32_t prev = d->prev_char(newpos);
+					if (isspace(d->text[prev]))
 						break;
+					newpos = prev;
 				}
-				txt.erase(txt.begin() + m_cur_pos);
-				set_text(txt.c_str());
-			}
-			break;
-
-		case SDLK_LEFT:
-			if (0 < m_cur_pos) {
-				while ((txt.at(--m_cur_pos) & 0xc0) == 0x80) {};
-				if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-					for (uint32_t new_cur_pos = m_cur_pos;; m_cur_pos = new_cur_pos)
-						if (0 == new_cur_pos or isspace(txt.at(--new_cur_pos)))
-							break;
-			}
-			break;
+				d->set_cursor_pos(newpos);
+			} else {
+				d->set_cursor_pos(d->prev_char(d->cursor_pos));
+			}
+			break;
+		}
 
 		case SDLK_RIGHT:
-			if (m_cur_pos < txt.size()) {
-				do {
-					++m_cur_pos;
-					if (m_cur_pos >= txt.size()) {
-						break;
-					}
-
-				} while ((txt.at(m_cur_pos) & 0xc0) == 0x80);
-
-				if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-					for (uint32_t new_cur_pos = m_cur_pos;; ++new_cur_pos) {
-						assert ((new_cur_pos - 1) < txt.size());
-						if
-							(new_cur_pos == txt.size()
-							 or
-							 isspace(txt.at(new_cur_pos - 1)))
-						{
-							m_cur_pos = new_cur_pos;
-							break;
-						}
-					}
+			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
+				uint32_t newpos = d->next_char(d->cursor_pos);
+				while (newpos < d->text.size() && isspace(d->text[newpos]))
+					newpos = d->next_char(newpos);
+				while (newpos < d->text.size() && !isspace(d->text[newpos]))
+					newpos = d->next_char(newpos);
+				d->set_cursor_pos(newpos);
+			} else {
+				d->set_cursor_pos(d->next_char(d->cursor_pos));
 			}
 			break;
 
 		case SDLK_DOWN:
-			if (m_cur_pos < txt.size()) {
-				uint32_t begin_of_line = m_cur_pos;
-
-				assert(begin_of_line < txt.size());
-				if (txt.at(begin_of_line) == '\n')
-					--begin_of_line;
-				while (begin_of_line > 0 && txt.at(begin_of_line) != '\n')
-					--begin_of_line;
-				if (begin_of_line)
-					++begin_of_line;
-				uint32_t begin_of_next_line = m_cur_pos;
-				while
-					(begin_of_next_line < txt.size()
-					 &&
-					 txt.at(begin_of_next_line) != '\n')
-					++begin_of_next_line;
-				begin_of_next_line += begin_of_next_line == txt.size() ? -1 : 1;
-				uint32_t end_of_next_line = begin_of_next_line;
-				while
-					(end_of_next_line < txt.size() &&
-					 txt.at(end_of_next_line) != '\n')
-					++end_of_next_line;
-				m_cur_pos =
-					begin_of_next_line + m_cur_pos - begin_of_line
-					>
-					end_of_next_line ? end_of_next_line :
-					begin_of_next_line + m_cur_pos - begin_of_line;
-				// Care about unicode letters
-				while (m_cur_pos < txt.size() && (txt.at(m_cur_pos) & 0xc0) == 0x80)
-					++m_cur_pos;
+			if (d->cursor_pos < d->text.size()) {
+				d->refresh_ww();
+
+				uint32_t cursorline, cursorpos;
+				d->ww.calc_wrapped_pos(d->cursor_pos, cursorline, cursorpos);
+
+				if (cursorline + 1 < d->ww.nrlines()) {
+					uint32_t lineend = d->text.size();
+					if (cursorline + 2 < d->ww.nrlines())
+						lineend = d->prev_char(d->ww.line_offset(cursorline + 2));
+
+					uint32_t newpos = d->ww.line_offset(cursorline + 1) + cursorpos;
+					if (newpos > lineend)
+						newpos = lineend;
+					else
+						newpos = d->snap_to_char(newpos);
+					d->set_cursor_pos(newpos);
+				} else {
+					d->set_cursor_pos(d->text.size());
+				}
 			}
 			break;
 
 		case SDLK_UP:
-			if (m_cur_pos > 0) {
-				uint32_t begin_of_line = m_cur_pos;
-
-				if (begin_of_line >= txt.size()) {
-					begin_of_line = txt.size() - 1;
+			if (d->cursor_pos > 0) {
+				d->refresh_ww();
+
+				uint32_t cursorline, cursorpos;
+				d->ww.calc_wrapped_pos(d->cursor_pos, cursorline, cursorpos);
+
+				if (cursorline > 0) {
+					uint32_t newpos = d->ww.line_offset(cursorline-1) + cursorpos;
+					uint32_t lineend = d->prev_char(d->ww.line_offset(cursorline));
+
+					if (newpos > lineend)
+						newpos = lineend;
+					else
+						newpos = d->snap_to_char(newpos);
+					d->set_cursor_pos(newpos);
+				} else {
+					d->set_cursor_pos(0);
 				}
-				assert (begin_of_line < txt.size());
-				if (txt.at(begin_of_line) == '\n')
-					--begin_of_line;
-				while (begin_of_line > 0 && txt.at(begin_of_line) != '\n')
-					--begin_of_line;
-				if (begin_of_line)
-					++begin_of_line;
-				uint32_t end_of_last_line = begin_of_line;
-				if (begin_of_line)
-					--end_of_last_line;
-				uint32_t begin_of_lastline = end_of_last_line;
-				assert(begin_of_lastline < txt.size());
-				if (begin_of_lastline > 0 && txt.at(begin_of_lastline) == '\n')
-					--begin_of_lastline;
-				while (begin_of_lastline > 0 && txt.at(begin_of_lastline) != '\n')
-					--begin_of_lastline;
-				if (begin_of_lastline)
-					++begin_of_lastline;
-				m_cur_pos =
-					begin_of_lastline + (m_cur_pos - begin_of_line)
-					>
-					end_of_last_line ? end_of_last_line :
-					begin_of_lastline + (m_cur_pos - begin_of_line);
-				// Care about unicode letters
-				while (m_cur_pos < txt.size() && (txt.at(m_cur_pos) & 0xc0) == 0x80)
-					++m_cur_pos;
 			}
 			break;
 
 		case SDLK_HOME:
-			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-				m_cur_pos = 0;
-			else
-				while (0 < m_cur_pos) {
-					uint32_t const preceding_cur_pos = m_cur_pos - 1;
-					if (txt.at(preceding_cur_pos) == '\n')
-						break;
-					else
-						m_cur_pos = preceding_cur_pos;
-				}
+			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
+				d->set_cursor_pos(0);
+			} else {
+				d->refresh_ww();
+
+				uint32_t cursorline, cursorpos;
+				d->ww.calc_wrapped_pos(d->cursor_pos, cursorline, cursorpos);
+
+				d->set_cursor_pos(d->ww.line_offset(cursorline));
+			}
 			break;
 
 		case SDLK_END:
-			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL))
-				m_cur_pos = txt.size();
-			else
-				while (m_cur_pos < txt.size() and txt.at(m_cur_pos) != '\n')
-					++m_cur_pos;
+			if (code.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
+				d->set_cursor_pos(d->text.size());
+			} else {
+				d->refresh_ww();
+
+				uint32_t cursorline, cursorpos;
+				d->ww.calc_wrapped_pos(d->cursor_pos, cursorline, cursorpos);
+
+				if (cursorline + 1 < d->ww.nrlines())
+					d->set_cursor_pos(d->prev_char(d->ww.line_offset(cursorline + 1)));
+				else
+					d->set_cursor_pos(d->text.size());
+			}
 			break;
 
 		case SDLK_RETURN:
 		case SDLK_KP_ENTER:
-			if (txt.size() < m_maxchars) {
-				txt.insert(txt.begin() + m_cur_pos++, 1, '\n');
-				set_text(txt.c_str());
-			}
+			d->insert(d->cursor_pos, "\n");
+			changed.call();
 			break;
 
 		default:
@@ -226,33 +418,16 @@
 			// example ~ + o results in a o with a tilde over it. The ~ is reported
 			// as a 0 on keystroke, the o then as the unicode character. We simply
 			// ignore the 0.
-			if (is_printable(code) and code.unicode and txt.size() < m_maxchars) {
-				if (code.unicode < 0x80)         // 1 byte char
-					txt.insert(txt.begin() + m_cur_pos++, 1, code.unicode);
-				else if (code.unicode < 0x800) { // 2 byte char
-					txt.insert
-						(txt.begin() + m_cur_pos++,
-						 (((code.unicode & 0x7c0) >> 6) | 0xc0));
-					txt.insert
-						(txt.begin() + m_cur_pos++,
-						 ((code.unicode & 0x3f) | 0x80));
-				} else {                         // 3 byte char
-					txt.insert
-						(txt.begin() + m_cur_pos++,
-						 (((code.unicode & 0xf000) >> 12) | 0xe0));
-					txt.insert
-						(txt.begin() + m_cur_pos++,
-						 (((code.unicode & 0xfc0) >> 6) | 0x80));
-					txt.insert
-						(txt.begin() + m_cur_pos++,
-						 ((code.unicode & 0x3f) | 0x80));
+			if (is_printable(code) and code.unicode) {
+				std::string utf8 = d->unicode_to_utf8(code.unicode);
+
+				if (d->text.size() + utf8.size() <= d->maxbytes) {
+					d->insert(d->cursor_pos, utf8);
+					changed.call();
 				}
 			}
-			set_text(txt.c_str());
 			break;
 		}
-		set_text(txt.c_str());
-		changed.call();
 		return true;
 	}
 
@@ -267,11 +442,9 @@
 {
 	if (btn == SDL_BUTTON_LEFT and not has_focus()) {
 		focus();
-		Multiline_Textarea::set_text(get_text().c_str());
-		changed.call();
 		return true;
 	}
-	return Multiline_Textarea::handle_mousepress(btn, x, y);
+	return Panel::handle_mousepress(btn, x, y);
 }
 bool Multiline_Editbox::handle_mouserelease(const Uint8, int32_t, int32_t)
 {
@@ -280,75 +453,100 @@
 
 /**
  * Redraw the Editbox
-*/
+ */
 void Multiline_Editbox::draw(RenderTarget & dst)
 {
 	//  make the whole area a bit darker
 	dst.brighten_rect(Rect(Point(0, 0), get_w(), get_h()), ms_darken_value);
-	if (get_text().size()) {
-		UI::g_fh->draw_string
-			(dst,
-			 m_fontname,
-			 m_fontsize,
-			 m_fcolor,
-			 RGBColor(107, 87, 55),
-			 Point(get_halign(), 0 - m_textpos),
-			 get_text(),
-			 m_align,
-			 get_eff_w(),
-			 m_cache_mode,
-			 &m_cache_id,
-			 //  explicit cast is necessary to avoid a compiler warning
-			 has_focus() ? static_cast<int32_t>(m_cur_pos) :
-			 std::numeric_limits<uint32_t>::max());
-		draw_scrollbar();
-
-		uint32_t w; // just to run g_fh->get_size_from_cache
-		UI::g_fh->get_size_from_cache(m_cache_id, w, m_textheight);
-
-		m_cache_mode = Widget_Cache_Use;
-	}
-}
-
-/**
- * Set text function needs to take care of the current
- * position
- */
-void Multiline_Editbox::set_text(char const * const str)
-{
-	CalcLinePos();
-
-	Multiline_Textarea::set_text(str);
-}
-
-/**
- * Calculate the height position of the cursor and write it to m_textpos
- * so the scrollbar can follow the cursor.
- */
-void Multiline_Editbox::CalcLinePos()
-{
-	if (m_textheight < static_cast<uint32_t>(get_h())) {
-		m_textpos = 0;
-		return;
-	}
-
-	std::string const & str = get_text().c_str();
-	size_t leng = str.size();
-	uint32_t lbtt = 0; // linebreaks to top
-	uint32_t lbtb = 0; // linebreaks to bottom
-
-	for
-		(size_t i = 0;
-		 i < std::min(m_cur_pos, static_cast<uint32_t>(str.size() - 1));
-		 ++i)
-		if (str.at(i) == '\n')
-			++lbtt;
-	for (size_t i = m_cur_pos; i < leng; ++i)
-		if (str.at(i) == '\n')
-			++lbtb;
-
-	m_textpos = (lbtt == 0) & (lbtb == 0) ?
-		0 : (m_textheight - get_h()) * lbtt / (lbtb + lbtt);
-}
-
-}
+
+	d->refresh_ww();
+
+	d->ww.draw
+		(dst, Point(0, -int32_t(d->scrollbar.get_scrollpos())), Align_Left,
+		 has_focus() ? d->cursor_pos : std::numeric_limits<uint32_t>::max());
+}
+
+/**
+ * Insert the given string starting at cursor position @p where.
+ * Update the cursor so that it stays in the same place, but note that the cursor is "right-magnetic":
+ * If @p where is equal to the current cursor position, then the cursor is moved.
+ * This is usually what one wants.
+ */
+void Multiline_Editbox::Data::insert(uint32_t where, const std::string & s)
+{
+	text.insert(where, s);
+	update();
+
+	if (cursor_pos >= where)
+		set_cursor_pos(cursor_pos + s.size());
+}
+
+/**
+ * Change the position of the cursor, cause a display refresh and scroll the cursor
+ * into view when necessary.
+ */
+void Multiline_Editbox::Data::set_cursor_pos(uint32_t newpos)
+{
+	assert(newpos <= text.size());
+
+	if (cursor_pos == newpos)
+		return;
+
+	cursor_pos = newpos;
+	owner.update();
+
+	scroll_cursor_into_view();
+}
+
+/**
+ * Ensure that the cursor is visible.
+ */
+void Multiline_Editbox::Data::scroll_cursor_into_view()
+{
+	refresh_ww();
+
+	uint32_t cursorline, cursorpos;
+	ww.calc_wrapped_pos(cursor_pos, cursorline, cursorpos);
+
+	int32_t lineheight = textstyle.font->height();
+	int32_t lineskip = textstyle.font->lineskip();
+	int32_t top = cursorline * lineskip;
+
+	if (top < int32_t(scrollbar.get_scrollpos())) {
+		scrollbar.set_scrollpos(top - lineheight);
+		owner.update();
+	} else if (top + lineheight > int32_t(scrollbar.get_scrollpos()) + owner.get_h()) {
+		scrollbar.set_scrollpos(top - owner.get_h() + 2 * lineheight);
+		owner.update();
+	}
+}
+
+/**
+ * Callback function called by the scrollbar.
+ */
+void Multiline_Editbox::scrollpos_changed(int32_t)
+{
+	update();
+}
+
+/**
+ * Re-wrap the string and update the scrollbar range accordingly.
+ */
+void Multiline_Editbox::Data::refresh_ww()
+{
+	if (int32_t(ww.wrapwidth()) != owner.get_w() - ms_scrollbar_w)
+		ww_valid = false;
+	if (ww_valid)
+		return;
+
+	ww.set_style(textstyle);
+	ww.set_wrapwidth(owner.get_w() - ms_scrollbar_w);
+
+	ww.wrap(text);
+	ww_valid = true;
+
+	int32_t textheight = ww.height();
+	scrollbar.set_steps(textheight - owner.get_h());
+}
+
+} // namespace UI

=== modified file 'src/ui_basic/multilineeditbox.h'
--- src/ui_basic/multilineeditbox.h	2009-09-30 18:31:29 +0000
+++ src/ui_basic/multilineeditbox.h	2011-01-30 15:33:06 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2002, 2006, 2008-2009 by Widelands Development Team
+ * Copyright (C) 2002, 2006, 2008-2011 by Widelands Development Team
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -20,41 +20,44 @@
 #ifndef UI_MULTILINEEDITBOX_H
 #define UI_MULTILINEEDITBOX_H
 
-#include "multilinetextarea.h"
+#include "panel.h"
 #include "m_signal.h"
 
+#include <boost/scoped_ptr.hpp>
+
 namespace UI {
-struct Scrollbar;
+
+struct TextStyle;
 
 /**
- * This behaves like an editbox, but looks like
- * a multiline textarea
- *
- * Shift + del or Shift + backspace deletes all text
+ * A panel that allows entering multi-line string, i.e. like a hybrid between
+ * @ref Editbox and @ref Multiline_Textarea
  */
-struct Multiline_Editbox : public Multiline_Textarea {
+struct Multiline_Editbox : public Panel {
 	Multiline_Editbox
-		(Panel *, int32_t x, int32_t y, uint32_t w, uint32_t h, char const *);
+		(Panel *, int32_t x, int32_t y, uint32_t w, uint32_t h, const std::string & text);
 
 	Signal changed;
 
+	std::string const & get_text() const;
+	void set_text(std::string const &);
+	void set_textstyle(const TextStyle &);
+
+	void set_maximum_bytes(uint32_t n);
+	uint32_t get_maximum_bytes() const;
+
+protected:
 	void draw(RenderTarget &);
-	void set_maximum_chars(int32_t const n) {m_maxchars = n;}
-	int32_t get_maximum_chars() {return m_maxchars;}
 
 	bool handle_mousepress  (Uint8 btn, int32_t x, int32_t y);
 	bool handle_mouserelease(Uint8 btn, int32_t x, int32_t y);
 	bool handle_key(bool down, SDL_keysym);
-	void set_text(char const *);
 
 private:
-	void CalcLinePos();
-	static const int32_t ms_darken_value = -20;
-	uint32_t m_cur_pos;
-	uint32_t m_char_pos;
-	uint32_t m_line_pos;
-	uint32_t m_maxchars;
-	bool     m_needs_update;
+	void scrollpos_changed(int32_t);
+
+	struct Data;
+	boost::scoped_ptr<Data> d;
 };
 
 }

=== modified file 'src/ui_basic/multilinetextarea.h'
--- src/ui_basic/multilinetextarea.h	2010-09-25 08:11:16 +0000
+++ src/ui_basic/multilinetextarea.h	2011-01-30 15:33:06 +0000
@@ -31,10 +31,6 @@
 /**
  * This defines an area, where a text can easily be printed.
  * The textarea transparently handles explicit line-breaks and word wrapping.
- *
- * Do not use it blindly for big texts: the font handler needs to re-break the
- * entire text whenever the textarea is drawn, this is a trade-off which greatly
- * simplifies this class.
  */
 struct Multiline_Textarea : public Panel {
 	enum ScrollMode {

=== modified file 'src/ui_basic/panel.cc'
--- src/ui_basic/panel.cc	2010-12-03 21:41:49 +0000
+++ src/ui_basic/panel.cc	2011-01-30 15:33:06 +0000
@@ -23,10 +23,12 @@
 #include "graphic/font_handler.h"
 #include "graphic/offscreensurface.h"
 #include "graphic/rendertarget.h"
+#include "graphic/wordwrap.h"
 #include "log.h"
 #include "profile/profile.h"
 #include "sound/sound_handler.h"
 #include "wlapplication.h"
+#include <boost/concept_check.hpp>
 
 namespace UI {
 
@@ -1089,39 +1091,38 @@
 /**
  * Draw the tooltip.
  */
-void Panel::draw_tooltip(RenderTarget & dst, char const * const text)
+void Panel::draw_tooltip(RenderTarget & dst, const std::string & text)
 {
-#define TIP_WIDTH_MAX 360
-	uint32_t tip_width, tip_height;
-	UI::g_fh->get_size
-		(UI_FONT_TOOLTIP, text, tip_width, tip_height, TIP_WIDTH_MAX);
-	tip_width += 4;
-	tip_height += 4;
+	static const uint32_t TIP_WIDTH_MAX = 360;
+	static TextStyle tooltip_style;
+	if (!tooltip_style.font) {
+		tooltip_style.font = Font::get(UI_FONT_TOOLTIP);
+		tooltip_style.fg = RGBColor(255, 255, 0);
+		tooltip_style.bold = true;
+	}
+
+	WordWrap ww(tooltip_style, TIP_WIDTH_MAX);
+
+	ww.wrap(text);
+
+	uint32_t tip_width = ww.width() + 4;
+	uint32_t tip_height = ww.height() + 4;
+
 	const WLApplication & wlapplication = *WLApplication::get();
 	Rect r
 		(wlapplication.get_mouse_position() + Point(2, 32),
 		 tip_width, tip_height);
-	const Point tooltip_bottom_left = r.bottom_left();
-	const Point screen_bottom_left(g_gr->get_xres(), g_gr->get_yres());
-	if (screen_bottom_left.x < tooltip_bottom_left.x)
+	const Point tooltip_bottom_right = r.bottom_right();
+	const Point screen_bottom_right(g_gr->get_xres(), g_gr->get_yres());
+	if (screen_bottom_right.x < tooltip_bottom_right.x)
 		r.x -=  4 + r.w;
-	if (screen_bottom_left.y < tooltip_bottom_left.y)
+	if (screen_bottom_right.y < tooltip_bottom_right.y)
 		r.y -= 35 + r.h;
 
 	dst.fill_rect(r, RGBColor(230, 200, 50));
 	dst.draw_rect(r, RGBColor(0, 0, 0));
-	UI::g_fh->draw_string
-		(dst,
-		 UI_FONT_TOOLTIP,
-		 UI_FONT_TOOLTIP_CLR,
-		 r + Point(2, 2),
-		 text,
-		 Align_Left,
-		 TIP_WIDTH_MAX,
-		 Widget_Cache_None,
-		 0,
-		 std::numeric_limits<uint32_t>::max(),
-		 false);
+
+	ww.draw(dst, r + Point(2, 2));
 }
 
 std::string Panel::ui_fn() {

=== modified file 'src/ui_basic/panel.h'
--- src/ui_basic/panel.h	2010-12-03 21:41:49 +0000
+++ src/ui_basic/panel.h	2011-01-30 15:33:06 +0000
@@ -282,7 +282,7 @@
 	char * _tooltip;
 
 protected:
-	static void draw_tooltip(RenderTarget &, char const * const text);
+	static void draw_tooltip(RenderTarget &, const std::string & text);
 
 public:
 	void set_tooltip(const char * const);

=== modified file 'src/ui_basic/progressbar.cc'
--- src/ui_basic/progressbar.cc	2010-05-12 10:16:44 +0000
+++ src/ui_basic/progressbar.cc	2011-01-30 15:33:06 +0000
@@ -20,6 +20,7 @@
 #include "progressbar.h"
 
 #include "constants.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/rendertarget.h"
 
@@ -107,9 +108,8 @@
 	snprintf
 		(buffer, sizeof(buffer), "%u%%", static_cast<uint32_t>(fraction * 100));
 
-	UI::g_fh->draw_string
-		(dst,
-		 UI_FONT_SMALL, UI_FONT_SMALL_CLR,
+	UI::g_fh->draw_text
+		(dst, UI::TextStyle::ui_small(),
 		 Point(get_w() / 2, get_h() / 2),
 		 buffer,
 		 Align_Center);

=== modified file 'src/ui_basic/progresswindow.cc'
--- src/ui_basic/progresswindow.cc	2010-11-27 13:51:57 +0000
+++ src/ui_basic/progresswindow.cc	2011-01-30 15:33:06 +0000
@@ -20,6 +20,7 @@
 #include "progresswindow.h"
 
 #include "constants.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/rendertarget.h"
 #include "i18n.h"
@@ -143,9 +144,10 @@
 	draw_background(rt, xres, yres);
 
 	rt.fill_rect(m_label_rectangle, PROGRESS_FONT_COLOR_BG);
-	UI::g_fh->draw_string
-		(rt, UI_FONT_SMALL, PROGRESS_FONT_COLOR,
-		 m_label_center, description, Align_Center);
+
+	UI::TextStyle ts(UI::TextStyle::ui_small());
+	ts.fg = PROGRESS_FONT_COLOR_FG;
+	UI::g_fh->draw_text(rt, ts, m_label_center, description, Align_Center);
 	g_gr->update_rectangle(m_label_rectangle);
 
 	update(true);

=== modified file 'src/ui_basic/spinbox.cc'
--- src/ui_basic/spinbox.cc	2010-11-01 23:54:06 +0000
+++ src/ui_basic/spinbox.cc	2011-01-30 15:33:06 +0000
@@ -57,11 +57,6 @@
 	/// Special names for specific Values
 	std::vector<IntValueTextReplacement> valrep;
 
-	/// Font variables
-	std::string fontname;
-	uint32_t    fontsize;
-	RGBColor    fontcolor;
-
 	/// The UI parts
 	Textarea * text;
 	Callback_Button * butPlus;
@@ -97,9 +92,6 @@
 
 	sbi->background = background;
 	sbi->align      = alignm;
-	sbi->fontname   = UI_FONT_NAME;
-	sbi->fontsize   = UI_FONT_SIZE_SMALL;
-	sbi->fontcolor  = UI_FONT_CLR_FG;
 
 	if (w < 20)
 		throw wexception("Not enough space to draw spinbox");
@@ -115,7 +107,6 @@
 
 	sbi->text = new UI::Textarea
 		(this, butw * 16 / 5, 0, textw, h, buf, Align_Center);
-	sbi->text->set_font(sbi->fontname, sbi->fontsize, sbi->fontcolor);
 	sbi->butPlus =
 		new Callback_Button
 			(this, "+",
@@ -123,7 +114,7 @@
 			 sbi->background,
 			 boost::bind(&SpinBox::changeValue, boost::ref(*this), 1),
 			 "+", _("Increase the value"),
-			 true, false, sbi->fontname, sbi->fontsize);
+			 true, false);
 	sbi->butMinus =
 		new Callback_Button
 			(this, "-",
@@ -131,7 +122,7 @@
 			 sbi->background,
 			 boost::bind(&SpinBox::changeValue, boost::ref(*this), -1),
 			 "-", _("Decrease the value"),
-			 true, false, sbi->fontname, sbi->fontsize);
+			 true, false);
 	sbi->butPlus->set_repeating(true);
 	sbi->butMinus->set_repeating(true);
 	if (m_big) {
@@ -142,7 +133,7 @@
 				 sbi->background,
 				 boost::bind(&SpinBox::changeValue, boost::ref(*this), 10),
 				 "++", _("Increase the value by 10"),
-				 true, false, sbi->fontname, sbi->fontsize);
+				 true, false);
 		sbi->butTenMinus =
 			new Callback_Button
 				(this, "--",
@@ -150,10 +141,12 @@
 				 sbi->background,
 				 boost::bind(&SpinBox::changeValue, boost::ref(*this), -10),
 				 "--", _("Decrease the value by 10"),
-				 true, false, sbi->fontname, sbi->fontsize);
+				 true, false);
 		sbi->butTenPlus->set_repeating(true);
 		sbi->butTenMinus->set_repeating(true);
 	}
+
+	set_font(UI_FONT_NAME, UI_FONT_SIZE_SMALL, UI_FONT_CLR_FG);
 }
 
 
@@ -269,19 +262,25 @@
 
 /**
  * Sets the font of all UI elements
+ *
+ * @deprecated, see set_textstyle
  */
 void SpinBox::set_font(std::string const & name, int32_t size, RGBColor color)
 {
-	sbi->fontname = name;
-	sbi->fontsize = size;
-	sbi->fontcolor = color;
+	set_textstyle(TextStyle::makebold(Font::get(name, size), color));
+}
 
-	sbi->text->set_font(name, size, color);
-	sbi->butPlus->set_font(name, size);
-	sbi->butMinus->set_font(name, size);
+/**
+ * Sets the font and textstyle of all UI elements
+ */
+void SpinBox::set_textstyle(const TextStyle & textstyle)
+{
+	sbi->text->set_textstyle(textstyle);
+	sbi->butPlus->set_font(textstyle.font);
+	sbi->butMinus->set_font(textstyle.font);
 	if (m_big) {
-		sbi->butTenPlus->set_font(name, size);
-		sbi->butTenMinus->set_font(name, size);
+		sbi->butTenPlus->set_font(textstyle.font);
+		sbi->butTenMinus->set_font(textstyle.font);
 	}
 	update();
 }

=== modified file 'src/ui_basic/spinbox.h'
--- src/ui_basic/spinbox.h	2009-11-17 09:32:58 +0000
+++ src/ui_basic/spinbox.h	2011-01-30 15:33:06 +0000
@@ -29,6 +29,7 @@
 
 struct SpinBoxImpl;
 struct IntValueTextReplacement;
+struct TextStyle;
 
 /// A spinbox is an UI element for setting the integer value of a variable.
 struct SpinBox : public Panel {
@@ -50,6 +51,7 @@
 	Align align() const;
 	void setAlign(Align);
 	void set_font(std::string const &, int32_t, RGBColor);
+	void set_textstyle(const TextStyle & style);
 	void add_replacement(int32_t, std::string);
 	void remove_replacement(int32_t);
 	bool has_replacement(int32_t);

=== modified file 'src/ui_basic/table.cc'
--- src/ui_basic/table.cc	2010-11-01 23:54:06 +0000
+++ src/ui_basic/table.cc	2011-01-30 15:33:06 +0000
@@ -19,6 +19,7 @@
 
 #include "table.h"
 
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/rendertarget.h"
 #include "graphic/surface.h"
@@ -97,7 +98,8 @@
 					 complete_width, 0, width, m_headerheight,
 					 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 					 boost::bind(&Table::header_button_clicked, boost::ref(*this), m_columns.size()),
-					 title, "", true, false, m_fontname, m_fontsize);
+					 title, "", true, false);
+			c.btn->set_font(Font::get(m_fontname, m_fontsize));
 		}
 		c.width = width;
 		c.alignment = alignment;
@@ -145,7 +147,8 @@
 				 complete_width, 0, column.width, m_headerheight,
 				 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 				 boost::bind(&Table::header_button_clicked, boost::ref(*this), col),
-				 title, "", true, false, m_fontname, m_fontsize);
+				 title, "", true, false);
+		column.btn->set_font(Font::get(m_fontname, m_fontsize));
 	} else if (column.btn and title.empty()) { //  had title before, not now
 		delete column.btn;
 		column.btn = 0;
@@ -291,18 +294,17 @@
 					 	 / 2),
 					 entry_picture);
 
-			UI::g_fh->draw_string
+			UI::g_fh->draw_text
 				(dst,
-				 m_fontname, m_fontsize,
-				 col,
-				 RGBColor(107, 87, 55),
+				 TextStyle::makebold(Font::get(m_fontname, m_fontsize), col),
 				 point +
 				 Point
 				 	(picw,
 				 	 (static_cast<int32_t>(lineheight) -
 				 	  static_cast<int32_t>(stringh))
 				 	 / 2),
-				 entry_string, alignment);
+				 entry_string,
+				 alignment);
 
 			curx += curw;
 		}

=== modified file 'src/ui_basic/textarea.cc'
--- src/ui_basic/textarea.cc	2010-06-16 18:43:40 +0000
+++ src/ui_basic/textarea.cc	2011-01-30 15:33:06 +0000
@@ -26,71 +26,62 @@
 Textarea::Textarea
 	(Panel * const parent,
 	 const int32_t x, const int32_t y,
-	 const std::string & text, const Align align, const bool multiline)
+	 const std::string & text, const Align align)
 	:
 		Panel      (parent, x, y, 0, 0),
 		m_layoutmode(AutoMove),
-		m_align    (align),
-		m_multiline(multiline)
+		m_align    (align)
 {
-	set_handle_mouse(false);
-	set_think       (false);
-	set_font        (UI_FONT_SMALL, UI_FONT_CLR_FG);
-	set_text        (text);
+	init();
+	set_text(text);
 }
 
 Textarea::Textarea
 	(Panel *  const parent,
 	 const int32_t x, const int32_t y, const uint32_t w, const uint32_t h,
-	 const Align align, const bool multiline)
+	 const Align align)
 	:
 		Panel      (parent, x, y, w, h),
 		m_layoutmode(AutoMove),
-		m_align    (align),
-		m_multiline(multiline),
-		m_fontname (UI_FONT_NAME),
-		m_fontsize (UI_FONT_SIZE_SMALL),
-		m_fcolor   (UI_FONT_CLR_FG)
+		m_align    (align)
 {
-	set_handle_mouse(false);
-	set_think(false);
+	init();
 }
 
 Textarea:: Textarea
 	(Panel * const parent,
 	 const int32_t x, const int32_t y, const uint32_t w, const uint32_t h,
-	 const std::string & text, const Align align,
-	 const bool multiline)
+	 const std::string & text, const Align align)
 	:
 		Panel      (parent, x, y, w, h),
 		m_layoutmode(AutoMove),
-		m_align    (align),
-		m_multiline(multiline),
-		m_fontname (UI_FONT_NAME),
-		m_fontsize (UI_FONT_SIZE_SMALL),
-		m_fcolor   (UI_FONT_CLR_FG)
+		m_align    (align)
 {
-	set_handle_mouse(false);
-	set_think(false);
+	init();
 	set_text(text);
 }
 
 Textarea::Textarea
 	(Panel * parent,
 	 const std::string & text,
-	 Align align, bool multiline, uint32_t width)
+	 Align align, uint32_t width)
 :
 Panel(parent, 0, 0, width, 0),
 m_layoutmode(Layouted),
-m_align(align),
-m_multiline(multiline),
-m_fontname(UI_FONT_NAME),
-m_fontsize(UI_FONT_SIZE_SMALL),
-m_fcolor(UI_FONT_CLR_FG)
+m_align(align)
+{
+	init();
+	set_text(text);
+}
+
+/**
+ * Initialization tasks that are common to all constructors.
+ */
+void Textarea::init()
 {
 	set_handle_mouse(false);
 	set_think(false);
-	set_text(text);
+	set_textstyle(TextStyle::ui_small());
 }
 
 /**
@@ -107,14 +98,14 @@
 /**
  * Set the font of the textarea.
  */
-void Textarea::set_font(const std::string & name, int32_t size, RGBColor fg)
+void Textarea::set_textstyle(const TextStyle & style)
 {
+	if (m_textstyle == style)
+		return;
+
 	if (m_layoutmode == AutoMove)
 		collapse();
-	m_fontname = name;
-	m_fontsize = size;
-	m_fcolor   = fg;
-	set_text(m_text);
+	m_textstyle = style;
 	if (m_layoutmode == AutoMove)
 		expand();
 	else if (m_layoutmode == Layouted)
@@ -122,10 +113,19 @@
 }
 
 /**
+ * @deprecated
+ */
+void Textarea::set_font(const std::string & name, int size, RGBColor clr)
+{
+	set_textstyle(TextStyle::makebold(Font::get(name, size), clr));
+}
+
+/**
  * Set the text of the Textarea. Size (or desired size) is automatically
  * adjusted depending on the Textarea mode.
  */
-void Textarea::set_text(const std::string & text) {
+void Textarea::set_text(const std::string & text)
+{
 	if (m_text == text)
 		return;
 
@@ -139,7 +139,8 @@
 		update_desired_size();
 }
 
-std::string Textarea::get_text() {
+std::string Textarea::get_text()
+{
 	return m_text;
 }
 
@@ -162,18 +163,15 @@
  */
 void Textarea::draw(RenderTarget & dst)
 {
-	if (m_text.length())
-		UI::g_fh->draw_string
-			(dst,
-			 m_fontname, m_fontsize, m_fcolor, UI_FONT_CLR_BG,
-			 Point
-			 	(m_align & Align_HCenter ?
-			 	 get_w() / 2 : m_align & Align_Right  ? get_w() : 0,
-			 	 m_align & Align_VCenter ?
-			 	 get_h() / 2 : m_align & Align_Bottom ? get_h() : 0),
-			 m_text,
-			 m_align,
-			 m_multiline ? get_w() : std::numeric_limits<uint32_t>::max());
+	if (m_text.length()) {
+		Point anchor
+		 	(m_align & Align_HCenter ?
+		 	 get_w() / 2 : m_align & Align_Right  ? get_w() : 0,
+		 	 m_align & Align_VCenter ?
+		 	 get_h() / 2 : m_align & Align_Bottom ? get_h() : 0);
+
+		g_fh->draw_text(dst, m_textstyle, anchor, m_text, m_align);
+	}
 }
 
 
@@ -187,12 +185,10 @@
 	int32_t w = get_w();
 	int32_t h = get_h();
 
-	if (not m_multiline) {
-		if      (m_align & Align_HCenter)
-			x += w >> 1;
-		else if (m_align & Align_Right)
-			x += w;
-	}
+	if      (m_align & Align_HCenter)
+		x += w >> 1;
+	else if (m_align & Align_Right)
+		x += w;
 
 	if      (m_align & Align_VCenter)
 		y += h >> 1;
@@ -200,7 +196,7 @@
 		y += h;
 
 	set_pos(Point(x, y));
-	set_size(m_multiline ? get_w() : 0, 0);
+	set_size(0, 0);
 }
 
 
@@ -214,21 +210,13 @@
 
 	int32_t x = get_x();
 	int32_t y = get_y();
-	uint32_t w, h;
-
-	UI::g_fh->get_size
-		(m_fontname,
-		 m_fontsize,
-		 m_text,
-		 w, h,
-		 m_multiline ? get_w() : -1);
-
-	if (not m_multiline) {
-		if      (m_align & Align_HCenter)
-			x -= w >> 1;
-		else if (m_align & Align_Right)
-			x -= w;
-	}
+	uint32_t w = m_textstyle.calc_bare_width(m_text);
+	uint32_t h = m_textstyle.font->height();
+
+	if      (m_align & Align_HCenter)
+		x -= w >> 1;
+	else if (m_align & Align_Right)
+		x -= w;
 
 	if      (m_align & Align_VCenter)
 		y -= h >> 1;
@@ -236,7 +224,7 @@
 		y -= h;
 
 	set_pos(Point(x, y));
-	set_size(m_multiline ? get_w() : w, h);
+	set_size(w, h);
 }
 
 /**
@@ -244,19 +232,10 @@
  */
 void Textarea::update_desired_size()
 {
-	uint32_t olddesiredw, tmp;
-
-	get_desired_size(olddesiredw, tmp);
-
-	uint32_t w, h;
-	UI::g_fh->get_size
-		(m_fontname,
-		 m_fontsize,
-		 m_text,
-		 w, h,
-		 m_multiline ? olddesiredw : -1);
-
-	set_desired_size(m_multiline ? olddesiredw : w, h);
+	uint32_t w = m_textstyle.calc_bare_width(m_text);
+	uint32_t h = m_textstyle.font->height();
+
+	set_desired_size(w, h);
 }
 
 /**
@@ -265,8 +244,8 @@
  */
 void Textarea::set_fixed_size(const std::string & text)
 {
-	uint32_t w, h;
-	UI::g_fh->get_size(m_fontname, m_fontsize, text, w, h);
+	uint32_t w = m_textstyle.calc_bare_width(m_text);
+	uint32_t h = m_textstyle.font->height();
 	set_size(w, h);
 	set_desired_size(w, h);
 }

=== modified file 'src/ui_basic/textarea.h'
--- src/ui_basic/textarea.h	2010-05-25 18:40:43 +0000
+++ src/ui_basic/textarea.h	2011-01-30 15:33:06 +0000
@@ -22,6 +22,7 @@
 
 #include "align.h"
 #include "constants.h"
+#include "graphic/font.h"
 #include "panel.h"
 
 namespace UI {
@@ -59,20 +60,20 @@
 		(Panel * parent,
 		 int32_t x, int32_t y,
 		 std::string const & text = std::string(),
-		 Align align = Align_Left, bool multiline = false);
+		 Align align = Align_Left);
 	Textarea
 		(Panel * parent,
 		 int32_t x, int32_t y, uint32_t w, uint32_t h,
-		 Align align = Align_Left, bool multiline = false);
+		 Align align = Align_Left);
 	Textarea
 		(Panel *  const parent,
 		 int32_t x, int32_t y, uint32_t w, uint32_t h,
 		 const std::string & text,
-		 Align align = Align_Left, bool multiline = false);
+		 Align align = Align_Left);
 	Textarea
 		(Panel * parent,
 		 const std::string & text = std::string(),
-		 Align align = Align_Left, bool multiline = false, uint32_t width = 0);
+		 Align align = Align_Left, uint32_t width = 0);
 
 	void set_layout_mode(LayoutMode lm);
 	void set_fixed_size(const std::string & text);
@@ -83,22 +84,23 @@
 	// Drawing and event handlers
 	void draw(RenderTarget &);
 
-	void set_font(std::string const & name, int32_t size, RGBColor fg);
+	void set_textstyle(const TextStyle & style);
+	const TextStyle & get_textstyle() const {return m_textstyle;}
+
+	void set_font(const std::string & name, int size, RGBColor clr);
 
 protected:
 	virtual void update_desired_size();
 
 private:
+	void init();
 	void collapse();
 	void expand();
 
 	LayoutMode m_layoutmode;
 	std::string m_text;
-	Align       m_align;
-	bool        m_multiline;
-	std::string m_fontname;
-	int32_t     m_fontsize;
-	RGBColor    m_fcolor;
+	Align m_align;
+	TextStyle m_textstyle;
 };
 
 }

=== modified file 'src/ui_basic/window.cc'
--- src/ui_basic/window.cc	2010-12-04 15:22:29 +0000
+++ src/ui_basic/window.cc	2011-01-30 15:33:06 +0000
@@ -20,6 +20,7 @@
 #include "window.h"
 
 #include "constants.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/rendertarget.h"
 #include "wlapplication.h"
@@ -308,11 +309,10 @@
 
 	// draw the title if we have one
 	if (m_title.length())
-		UI::g_fh->draw_string
-			(dst,
-			 UI_FONT_SMALL, UI_FONT_SMALL_CLR,
+		UI::g_fh->draw_text
+			(dst, UI::TextStyle::ui_small(),
 			 Point(get_lborder() + get_inner_w() / 2, TP_B_PIXMAP_THICKNESS / 2),
-			 m_title.c_str(), Align_Center);
+			 m_title, Align_Center);
 
 	if (not _is_minimal) {
 		const int32_t vt_bar_end = get_h() -

=== modified file 'src/ui_fsmenu/base.cc'
--- src/ui_fsmenu/base.cc	2010-11-27 13:51:57 +0000
+++ src/ui_fsmenu/base.cc	2011-01-30 15:33:06 +0000
@@ -21,6 +21,7 @@
 
 #include "constants.h"
 #include "io/filesystem/filesystem.h"
+#include "graphic/font.h"
 #include "graphic/graphic.h"
 #include "log.h"
 #include "profile/profile.h"
@@ -38,6 +39,12 @@
 ==============================================================================
 */
 
+struct Fullscreen_Menu_Base::Data {
+	PictureID res_background;
+	UI::TextStyle textstyle_small;
+	UI::TextStyle textstyle_big;
+};
+
 /**
  * Initialize a pre-game menu
  *
@@ -45,10 +52,8 @@
  */
 Fullscreen_Menu_Base::Fullscreen_Menu_Base(char const * const bgpic)
 	: UI::Panel(0, 0, 0, gr_x(), gr_y()),
-	// Switch graphics mode if necessary
-	m_xres(gr_x()), m_yres(gr_y())
+	d(new Data)
 {
-
 	Section & s = g_options.pull_section("global");
 
 #if USE_OPENGL
@@ -57,7 +62,7 @@
 #define GET_BOOL_USE_OPENGL false
 #endif
 	WLApplication::get()->init_graphics
-		(m_xres, m_yres,
+		(get_w(), get_h(),
 		 s.get_int("depth", 16),
 		 s.get_bool("fullscreen", false),
 		 GET_BOOL_USE_OPENGL);
@@ -73,8 +78,14 @@
 			("could not open splash screen; make sure that all data files are "
 			 "installed");
 
-	m_res_background = g_gr->get_resized_picture
-			(background, m_xres, m_yres, Graphic::ResizeMode_Loose);
+	d->res_background = g_gr->get_resized_picture
+			(background, get_w(), get_h(), Graphic::ResizeMode_Loose);
+
+	d->textstyle_small = UI::TextStyle::ui_small();
+	d->textstyle_small.font = UI::Font::get(ui_fn(), fs_small());
+
+	d->textstyle_big = UI::TextStyle::ui_big();
+	d->textstyle_big.font = UI::Font::get(ui_fn(), fs_big());
 }
 
 Fullscreen_Menu_Base::~Fullscreen_Menu_Base()
@@ -86,7 +97,7 @@
  * Draw the background / splash screen
 */
 void Fullscreen_Menu_Base::draw(RenderTarget & dst) {
-	dst.blit(Point(0, 0), m_res_background);
+	dst.blit(Point(0, 0), d->res_background);
 }
 
 
@@ -100,9 +111,29 @@
 
 
 uint32_t Fullscreen_Menu_Base::fs_small() {
-	return UI_FONT_SIZE_SMALL * gr_y() / 600;
+	return UI_FONT_SIZE_SMALL * get_h() / 600;
 }
 
 uint32_t Fullscreen_Menu_Base::fs_big() {
-	return UI_FONT_SIZE_BIG * gr_y() / 600;
+	return UI_FONT_SIZE_BIG * get_h() / 600;
+}
+
+UI::TextStyle & Fullscreen_Menu_Base::ts_small()
+{
+	return d->textstyle_small;
+}
+
+UI::TextStyle & Fullscreen_Menu_Base::ts_big()
+{
+	return d->textstyle_big;
+}
+
+UI::Font * Fullscreen_Menu_Base::font_small()
+{
+	return d->textstyle_small.font;
+}
+
+UI::Font * Fullscreen_Menu_Base::font_big()
+{
+	return d->textstyle_big.font;
 }

=== modified file 'src/ui_fsmenu/base.h'
--- src/ui_fsmenu/base.h	2010-11-27 13:51:57 +0000
+++ src/ui_fsmenu/base.h	2011-01-30 15:33:06 +0000
@@ -20,9 +20,16 @@
 #ifndef FULLSCREEN_MENU_BASE_H
 #define FULLSCREEN_MENU_BASE_H
 
+#include <boost/scoped_ptr.hpp>
+
 #include "ui_basic/panel.h"
 #include <string>
 
+namespace UI {
+struct Font;
+struct TextStyle;
+}
+
 /**
  * This class is the base class for a fullscreen menu.
  * A fullscreen menu is a menu which takes the full screen; it has the size
@@ -35,19 +42,25 @@
 	virtual void draw(RenderTarget &);
 
 public:
-///\return the x/y value of current set resolution
-uint32_t gr_x();
-uint32_t gr_y();
-
-///\return the size for texts fitting to current resolution
-uint32_t fs_small();
-uint32_t fs_big();
-
-protected:
-	uint32_t m_xres;
-	uint32_t m_yres;
+	///\return the size for texts fitting to current resolution
+	uint32_t fs_small();
+	uint32_t fs_big();
+
+	UI::TextStyle & ts_small();
+	UI::TextStyle & ts_big();
+
+	UI::Font * font_small();
+	UI::Font * font_big();
+
 private:
-	PictureID m_res_background;
+	/**
+	 * Query the configured screen resolution.
+	 */
+	uint32_t gr_x();
+	uint32_t gr_y();
+
+	struct Data;
+	boost::scoped_ptr<Data> d;
 };
 
 

=== modified file 'src/ui_fsmenu/campaign_select.cc'
--- src/ui_fsmenu/campaign_select.cc	2010-11-18 10:28:25 +0000
+++ src/ui_fsmenu/campaign_select.cc	2011-01-30 15:33:06 +0000
@@ -40,55 +40,56 @@
 	Fullscreen_Menu_Base("choosemapmenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 9 / 200),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 9 / 200),
 	m_fs   (fs_small()),
 	m_fn   (ui_fn()),
 
 // Text labels
 	title
 		(this,
-		 m_xres / 2, m_yres * 9 / 50,
+		 get_w() / 2, get_h() * 9 / 50,
 		 _("Select a campaign"), UI::Align_HCenter),
 	label_campname
-		(this, m_xres *  3 /   5, m_yres * 17 / 50, _("Campaign:")),
+		(this, get_w() *  3 /   5, get_h() * 17 / 50, _("Campaign:")),
 	tacampname
-		(this, m_xres * 61 / 100, m_yres *  3 /  8, ""),
+		(this, get_w() * 61 / 100, get_h() *  3 /  8, ""),
 	label_difficulty
-		(this, m_xres *  3 /   5, m_yres * 17 / 40, _("Difficulty:")),
+		(this, get_w() *  3 /   5, get_h() * 17 / 40, _("Difficulty:")),
 	tadifficulty
-		(this, m_xres * 61 / 100, m_yres * 23 / 50, ""),
+		(this, get_w() * 61 / 100, get_h() * 23 / 50, ""),
 	label_campdescr
-		(this, m_xres *  3 /   5, m_yres * 51 / 100, _("Description:")),
+		(this, get_w() *  3 /   5, get_h() * 51 / 100, _("Description:")),
 	tacampdescr
 		(this,
-		 m_xres * 61 / 100, m_yres * 11 / 20, m_xres * 9 / 25, m_yres * 7 / 25,
+		 get_w() * 61 / 100, get_h() * 11 / 20, get_w() * 9 / 25, get_h() * 7 / 25,
 		 ""),
 
 // Buttons
 	b_ok
 		(this, "ok",
-		 m_xres * 71 / 100, m_yres * 9 / 10, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 9 / 10, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_CampaignSelect::clicked_ok, boost::ref(*this)),
-		 _("OK"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("OK"), std::string(), false, false),
 	back
 		(this, "back",
-		 m_xres * 71 / 100, m_yres * 17 / 20, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 17 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_CampaignSelect::end_modal, boost::ref(*this), 0),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 
 // Campaign list
 	m_list
 		(this,
-		 m_xres *  47 / 2500, m_yres * 3417 / 10000,
-		 m_xres * 711 / 1250, m_yres * 6083 / 10000)
+		 get_w() *  47 / 2500, get_h() * 3417 / 10000,
+		 get_w() * 711 / 1250, get_h() * 6083 / 10000)
 {
+	back.set_font(font_small());
+	b_ok.set_font(font_small());
+
 	title           .set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
 	label_campname  .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
 	tacampname      .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
@@ -251,51 +252,50 @@
 	Fullscreen_Menu_Base("choosemapmenu.jpg"),
 
 // Values for alignment and size
-	m_xres (gr_x()),
-	m_yres (gr_y()),
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 9 / 200),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 9 / 200),
 	m_fs   (fs_small()),
 	m_fn   (ui_fn()),
 
 // Text labels
 	title
 		(this,
-		 m_xres / 2, m_yres * 9 / 50, _("Choose your map!"),
+		 get_w() / 2, get_h() * 9 / 50, _("Choose your map!"),
 		 UI::Align_HCenter),
-	label_mapname (this, m_xres * 3 / 5,  m_yres * 17 / 50, _("Name:")),
-	tamapname     (this, m_xres * 61 / 100, m_yres * 3 / 8, ""),
-	label_author  (this, m_xres * 3 / 5,  m_yres * 17 / 40, _("Author:")),
-	taauthor      (this, m_xres * 61 / 100, m_yres * 23 / 50, ""),
-	label_mapdescr(this, m_xres * 3 / 5,  m_yres * 51 / 100, _("Description:")),
+	label_mapname (this, get_w() * 3 / 5,  get_h() * 17 / 50, _("Name:")),
+	tamapname     (this, get_w() * 61 / 100, get_h() * 3 / 8, ""),
+	label_author  (this, get_w() * 3 / 5,  get_h() * 17 / 40, _("Author:")),
+	taauthor      (this, get_w() * 61 / 100, get_h() * 23 / 50, ""),
+	label_mapdescr(this, get_w() * 3 / 5,  get_h() * 51 / 100, _("Description:")),
 	tamapdescr
 		(this,
-		 m_xres * 61 / 100, m_yres * 11 / 20, m_xres * 9 / 25, m_yres * 7 / 25),
+		 get_w() * 61 / 100, get_h() * 11 / 20, get_w() * 9 / 25, get_h() * 7 / 25),
 
 // Buttons
 	b_ok
 		(this, "ok",
-		 m_xres * 71 / 100, m_yres * 9 / 10, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 9 / 10, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_CampaignMapSelect::clicked_ok, boost::ref(*this)),
-		 _("OK"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("OK"), std::string(), false, false),
 	back
 		(this, "back",
-		 m_xres * 71 / 100, m_yres * 17 / 20, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 17 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_CampaignMapSelect::end_modal, boost::ref(*this), 0),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 
 // Campaign map list
 	m_list
 		(this,
-		 m_xres *  47 / 2500, m_yres * 3417 / 10000,
-		 m_xres * 711 / 1250, m_yres * 6083 / 10000)
+		 get_w() *  47 / 2500, get_h() * 3417 / 10000,
+		 get_w() * 711 / 1250, get_h() * 6083 / 10000)
 {
+	b_ok.set_font(font_small());
+	back.set_font(font_small());
+
 	title         .set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
 	label_mapname .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
 	tamapname     .set_font(m_fn, m_fs, UI_FONT_CLR_FG);

=== modified file 'src/ui_fsmenu/campaign_select.h'
--- src/ui_fsmenu/campaign_select.h	2010-11-08 20:15:10 +0000
+++ src/ui_fsmenu/campaign_select.h	2011-01-30 15:33:06 +0000
@@ -79,8 +79,6 @@
 	void set_campaign(uint32_t);
 
 private:
-	uint32_t    m_xres;
-	uint32_t    m_yres;
 	uint32_t    m_butw;
 	uint32_t    m_buth;
 	uint32_t    m_fs;

=== modified file 'src/ui_fsmenu/editor.cc'
--- src/ui_fsmenu/editor.cc	2010-10-18 21:05:42 +0000
+++ src/ui_fsmenu/editor.cc	2011-01-30 15:33:06 +0000
@@ -26,36 +26,36 @@
 	Fullscreen_Menu_Base("singleplmenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres * 7 / 20),
-	m_buth (m_yres * 19 / 400),
-	m_butx ((m_xres - m_butw) / 2),
+	m_butw (get_w() * 7 / 20),
+	m_buth (get_h() * 19 / 400),
+	m_butx ((get_w() - m_butw) / 2),
 
 // Title
 	title
-		(this, m_xres / 2, m_yres * 3 / 40, _("Editor Menu"), UI::Align_HCenter),
+		(this, get_w() / 2, get_h() * 3 / 40, _("Editor Menu"), UI::Align_HCenter),
 
 // Buttons
 	new_map
 		(this, "new_map",
-		 m_butx, m_yres * 6 / 25, m_butw, m_buth,
+		 m_butx, get_h() * 6 / 25, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind(&Fullscreen_Menu_Editor::end_modal, boost::ref(*this), static_cast<int32_t>(New_Map)),
-		 _("New Map"), std::string(), true, false,
-		 ui_fn(), fs_small()),
+		 _("New Map"), std::string(), true, false),
 	load_map
 		(this, "load_map",
-		 m_butx, m_yres * 61 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 61 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind(&Fullscreen_Menu_Editor::end_modal, boost::ref(*this), static_cast<int32_t>(Load_Map)),
-		 _("Load Map"), std::string(), true, false,
-		 ui_fn(), fs_small()),
+		 _("Load Map"), std::string(), true, false),
 	back
 		(this, "back",
-		 m_butx, m_yres * 3 / 4, m_butw, m_buth,
+		 m_butx, get_h() * 3 / 4, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&Fullscreen_Menu_Editor::end_modal, boost::ref(*this), static_cast<int32_t>(Back)),
-		 _("Back"), std::string(), true, false,
-		 ui_fn(), fs_small())
+		 _("Back"), std::string(), true, false)
 {
+	new_map.set_font(font_small());
+	load_map.set_font(font_small());
+	back.set_font(font_small());
 	title.set_font(ui_fn(), fs_big(), UI_FONT_CLR_FG);
 }

=== modified file 'src/ui_fsmenu/editor_mapselect.cc'
--- src/ui_fsmenu/editor_mapselect.cc	2010-11-03 01:04:47 +0000
+++ src/ui_fsmenu/editor_mapselect.cc	2011-01-30 15:33:06 +0000
@@ -39,74 +39,75 @@
 	Fullscreen_Menu_Base("choosemapmenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 9 / 200),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 9 / 200),
 	m_fs   (fs_small()),
 	m_fn   (ui_fn()),
 
 // Text labels
 	m_title
 		(this,
-		 m_xres / 2, m_yres * 9 / 50,
+		 get_w() / 2, get_h() * 9 / 50,
 		 _("Choose your map!"), UI::Align_HCenter),
 	m_label_name
 		(this,
-		 m_xres * 7 / 10, m_yres * 17 / 50,
+		 get_w() * 7 / 10, get_h() * 17 / 50,
 		 _("Name:"), UI::Align_Right),
-	m_name (this, m_xres * 71 / 100, m_yres * 17 / 50, std::string()),
+	m_name (this, get_w() * 71 / 100, get_h() * 17 / 50, std::string()),
 	m_label_author
 		(this,
-		 m_xres * 7 / 10, m_yres * 3 / 8,
+		 get_w() * 7 / 10, get_h() * 3 / 8,
 		 _("Author:"), UI::Align_Right),
-	m_author (this, m_xres * 71 / 100, m_yres * 3 / 8, std::string()),
+	m_author (this, get_w() * 71 / 100, get_h() * 3 / 8, std::string()),
 	m_label_size
 		(this,
-		 m_xres * 7 / 10, m_yres * 41 / 100,
+		 get_w() * 7 / 10, get_h() * 41 / 100,
 		 _("Size:"), UI::Align_Right),
-	m_size (this, m_xres * 71 / 100, m_yres * 41 / 100, std::string()),
+	m_size (this, get_w() * 71 / 100, get_h() * 41 / 100, std::string()),
 	m_label_world
 		(this,
-		 m_xres * 7 / 10, m_yres * 89 / 200,
+		 get_w() * 7 / 10, get_h() * 89 / 200,
 		 _("World:"), UI::Align_Right),
-	m_world (this, m_xres * 71 / 100, m_yres * 89 / 200, std::string()),
+	m_world (this, get_w() * 71 / 100, get_h() * 89 / 200, std::string()),
 	m_label_nr_players
 		(this,
-		 m_xres * 7 / 10, m_yres * 12 / 25,
+		 get_w() * 7 / 10, get_h() * 12 / 25,
 		 _("Players:"), UI::Align_Right),
-	m_nr_players (this, m_xres * 71 / 100, m_yres * 12 / 25, std::string()),
+	m_nr_players (this, get_w() * 71 / 100, get_h() * 12 / 25, std::string()),
 	m_label_descr
 		(this,
-		 m_xres * 7 / 10, m_yres * 103 / 200,
+		 get_w() * 7 / 10, get_h() * 103 / 200,
 		 _("Descr:"), UI::Align_Right),
 	m_descr
 		(this,
-		 m_xres * 71 / 100, m_yres * 13 / 25, m_xres / 4, m_yres * 63 / 200),
+		 get_w() * 71 / 100, get_h() * 13 / 25, get_w() / 4, get_h() * 63 / 200),
 
 // Buttons
 	m_back
 		(this, "back",
-		 m_xres * 71 / 100, m_yres * 17 / 20, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 17 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&Fullscreen_Menu_Editor_MapSelect::end_modal, boost::ref(*this), 0),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 	m_ok
 		(this, "ok",
-		 m_xres * 71 / 100, m_yres * 9 / 10, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 9 / 10, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind(&Fullscreen_Menu_Editor_MapSelect::ok, boost::ref(*this)),
-		 _("OK"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("OK"), std::string(), false, false),
 
 // Map list
 	m_list
 		(this,
-		 m_xres *  47 / 2500, m_yres * 3417 / 10000,
-		 m_xres * 711 / 1250, m_yres * 6083 / 10000),
+		 get_w() *  47 / 2500, get_h() * 3417 / 10000,
+		 get_w() * 711 / 1250, get_h() * 6083 / 10000),
 
 // Runtime variables
 	m_curdir("maps"), m_basedir("maps")
 {
+	m_back.set_font(font_small());
+	m_ok.set_font(font_small());
+
 	m_title           .set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
 	m_label_name      .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
 	m_name            .set_font(m_fn, m_fs, UI_FONT_CLR_FG);

=== modified file 'src/ui_fsmenu/fileview.cc'
--- src/ui_fsmenu/fileview.cc	2010-11-01 23:29:48 +0000
+++ src/ui_fsmenu/fileview.cc	2011-01-30 15:33:06 +0000
@@ -30,21 +30,22 @@
 	:
 	Fullscreen_Menu_Base("fileviewmenu.jpg"),
 
-	title (this, m_xres * 3 / 50, m_yres / 10),
+	title (this, get_w() * 3 / 50, get_h() / 10),
 
 	textview
 		(this,
-		 m_xres *   3 /   80, m_yres * 283 / 1000,
-		 m_xres * 919 / 1000, m_yres *  11 /   20),
+		 get_w() *   3 /   80, get_h() * 283 / 1000,
+		 get_w() * 919 / 1000, get_h() *  11 /   20),
 
 	close_button
 		(this, "close",
-		 m_xres * 3 / 8, m_yres * 9 / 10, m_xres / 4, m_yres * 9 / 200,
+		 get_w() * 3 / 8, get_h() * 9 / 10, get_w() / 4, get_h() * 9 / 200,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&Fullscreen_Menu_TextView::end_modal, boost::ref(*this), 0),
-		 _("Close"), std::string(), true, false,
-		 ui_fn(), fs_small())
+		 _("Close"), std::string(), true, false)
 {
+	close_button.set_font(font_small());
+
 	Profile prof(filename.c_str(), "global", "texts"); //  section-less file
 	Section & section = prof.get_safe_section("global");
 
@@ -53,7 +54,7 @@
 
 	title.set_font(ui_fn(), fs_big(), UI_FONT_CLR_FG);
 	title.set_pos
-		(Point((get_inner_w() - title.get_w()) / 2, m_yres * 167 / 1000));
+		(Point((get_inner_w() - title.get_w()) / 2, get_h() * 167 / 1000));
 
 	textview.set_font(PROSA_FONT, PROSA_FONT_CLR_FG);
 }

=== modified file 'src/ui_fsmenu/intro.cc'
--- src/ui_fsmenu/intro.cc	2009-07-11 21:34:13 +0000
+++ src/ui_fsmenu/intro.cc	2011-01-30 15:33:06 +0000
@@ -28,7 +28,7 @@
 // Text area
 m_message
 	(this,
-	 gr_x() / 2, gr_y() * 19 / 20,
+	 get_w() / 2, get_h() * 19 / 20,
 	 _("Press ESC or click to continue ..."), UI::Align_HCenter)
 {
 	m_message.set_font(ui_fn(), fs_small() * 6 / 5, RGBColor(192, 192, 128));

=== modified file 'src/ui_fsmenu/launchMPG.cc'
--- src/ui_fsmenu/launchMPG.cc	2010-12-30 13:28:59 +0000
+++ src/ui_fsmenu/launchMPG.cc	2011-01-30 15:33:06 +0000
@@ -47,7 +47,7 @@
 struct MapOrSaveSelectionWindow : public UI::Window {
 	MapOrSaveSelectionWindow
 		(UI::Panel * parent, uint32_t w, uint32_t h,
-		 uint32_t fontsize, std::string fontname)
+		 UI::Font * font)
 	:
 	Window(parent, "selection_window", 0, 0, w, h, _("Please select"))
 	{
@@ -57,30 +57,32 @@
 		uint32_t space = get_inner_w() / 40;
 		uint32_t butw  = get_inner_w() * 3 / 10;
 		uint32_t buth  = get_inner_h() * 8 / 10;
-		new UI::Callback_Button
+		UI::Button * btn = new UI::Callback_Button
 			(this, "map",
 			 space, y, butw, buth,
 			 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 			 boost::bind
 				 (&MapOrSaveSelectionWindow::pressedButton, boost::ref(*this), 1),
-			 _("Map"), _("Select a map"), true, false,
-			 fontname, fontsize);
-		new UI::Callback_Button
+			 _("Map"), _("Select a map"), true, false);
+		btn->set_font(font);
+
+		btn = new UI::Callback_Button
 			(this, "saved_game",
 			 2 * space + butw, y, butw, buth,
 			 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 			 boost::bind
 				 (&MapOrSaveSelectionWindow::pressedButton, boost::ref(*this), 2),
-			 _("Saved game"), _("Select a saved game"), true, false,
-			 fontname, fontsize);
-		new UI::Callback_Button
+			 _("Saved game"), _("Select a saved game"), true, false);
+		btn->set_font(font);
+
+		btn = new UI::Callback_Button
 			(this, "cancel",
 			 3 * space + 2 * butw, y, butw, buth,
 			 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 			 boost::bind
 				 (&MapOrSaveSelectionWindow::pressedButton, boost::ref(*this), 0),
-			 _("Cancel"), _("Cancel selection"), true, false,
-			 fontname, fontsize);
+			 _("Cancel"), _("Cancel selection"), true, false);
+		btn->set_font(font);
 	}
 
 	void pressedButton(uint8_t i) {
@@ -95,80 +97,75 @@
 	Fullscreen_Menu_Base("launchMPGmenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 9 / 200),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 9 / 200),
 	m_fs   (fs_small()),
 	m_fn   (ui_fn()),
 
 // Buttons
 	m_change_map_or_save
 		(this, "change_map_or_save",
-		 m_xres * 37 / 50 + m_butw - m_buth, m_yres * 3 / 20, m_buth, m_buth,
+		 get_w() * 37 / 50 + m_butw - m_buth, get_h() * 3 / 20, m_buth, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 g_gr->get_picture(PicMod_UI, "pics/menu_toggle_minimap.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_LaunchMPG::change_map_or_save, boost::ref(*this)),
-		 _("Change map or saved game"), false, false,
-		 m_fn, m_fs),
+		 _("Change map or saved game"), false, false),
 	m_ok
 		(this, "ok",
-		 m_xres * 37 / 50, m_yres * 12 / 20, m_butw, m_buth,
+		 get_w() * 37 / 50, get_h() * 12 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_LaunchMPG::start_clicked, boost::ref(*this)),
-		 _("Start game"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("Start game"), std::string(), false, false),
 	m_back
 		(this, "back",
-		 m_xres * 37 / 50, m_yres * 218 / 240, m_butw, m_buth,
+		 get_w() * 37 / 50, get_h() * 218 / 240, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&Fullscreen_Menu_LaunchMPG::back_clicked, boost::ref(*this)),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 	m_wincondition
 		(this, "win_condition",
-		 m_xres * 37 / 50, m_yres * 11 / 20, m_butw, m_buth,
+		 get_w() * 37 / 50, get_h() * 11 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_LaunchMPG::win_condition_clicked,
 			  boost::ref(*this)),
-		 "", std::string(), false, false,
-		 m_fn, m_fs),
+		 "", std::string(), false, false),
 	m_help_button
 		(this, "help",
-		 m_xres * 37 / 50 + m_butw - m_buth, m_yres / 100, m_buth, m_buth,
+		 get_w() * 37 / 50 + m_butw - m_buth, get_h() / 100, m_buth, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 g_gr->get_picture(PicMod_UI, "pics/menu_help.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_LaunchMPG::help_clicked,
 			  boost::ref(*this)),
-		 _("Show the help window"), true, false,
-		 m_fn, m_fs),
+		 _("Show the help window"), true, false),
 
 // Text labels
 	m_title
 		(this,
-		 m_xres / 2, m_yres / 25,
+		 get_w() / 2, get_h() / 25,
 		 _("Multiplayer Game Setup"), UI::Align_HCenter),
 	m_mapname
 		(this,
-		 m_xres * 37 / 50, m_yres * 3 / 20,
+		 get_w() * 37 / 50, get_h() * 3 / 20,
 		 std::string()),
 	m_clients
 		(this,
-		 m_xres / 10, m_yres / 10,
+		 get_w() / 10, get_h() / 10,
 		 _("Clients")),
 	m_players
 		(this,
-		 m_xres / 2, m_yres / 10,
+		 get_w() / 2, get_h() / 10,
 		 _("Players")),
 	m_map
 		(this,
-		 m_xres * 8 / 10, m_yres / 10,
+		 get_w() * 8 / 10, get_h() / 10,
 		 _("Map")),
 
-	m_map_info(this, m_xres * 37 / 50, m_yres * 2 / 10, m_butw, m_yres * 27 / 80),
-	m_client_info(this, m_xres * 37 / 50, m_yres * 13 / 20, m_butw, m_yres * 5 / 20),
+	m_map_info(this, get_w() * 37 / 50, get_h() * 2 / 10, m_butw, get_h() * 27 / 80),
+	m_client_info(this, get_w() * 37 / 50, get_h() * 13 / 20, m_butw, get_h() * 5 / 20),
 	m_help(0),
 
 // Variables and objects used in the menu
@@ -176,6 +173,12 @@
 	m_ctrl         (ctrl),
 	m_chat         (0)
 {
+	m_back.set_font(font_small());
+	m_ok.set_font(font_small());
+	m_wincondition.set_font(font_small());
+	m_help_button.set_font(font_small());
+	m_change_map_or_save.set_font(font_small());
+
 	// Register win condition scripts
 	m_lua = create_LuaInterface();
 	m_lua->register_scripts(*g_fs, "win_conditions", "scripting/win_conditions");
@@ -200,7 +203,7 @@
 	m_mpsg =
 		new MultiPlayerSetupGroup
 			(this,
-			 m_xres / 50, m_yres / 8, m_xres * 57 / 80, m_yres / 2,
+			 get_w() / 50, get_h() / 8, get_w() * 57 / 80, get_h() / 2,
 			 settings, m_butw, m_buth, m_fn, m_fs);
 
 	// If we are the host, open the map or save selection menu at startup
@@ -238,7 +241,8 @@
 void Fullscreen_Menu_LaunchMPG::setChatProvider(ChatProvider & chat)
 {
 	delete m_chat;
-	m_chat = new GameChatPanel(this, m_xres / 50, m_yres * 13 / 20, m_xres * 57 / 80, m_yres * 3 / 10, chat);
+	m_chat = new GameChatPanel
+		(this, get_w() / 50, get_h() * 13 / 20, get_w() * 57 / 80, get_h() * 3 / 10, chat);
 	// For better readability
 	m_chat->set_bg_color(RGBColor(50, 50, 50));
 }
@@ -299,7 +303,7 @@
 /// Opens a popup window to select a map or saved game
 void Fullscreen_Menu_LaunchMPG::change_map_or_save() {
 	MapOrSaveSelectionWindow selection_window
-		(this, m_xres / 2, m_yres / 20, m_fs, m_fn);
+		(this, get_w() / 2, get_h() / 20, font_small());
 	switch (selection_window.run()) {
 		case 1:
 			select_map();

=== modified file 'src/ui_fsmenu/launchSPG.cc'
--- src/ui_fsmenu/launchSPG.cc	2010-11-02 11:13:59 +0000
+++ src/ui_fsmenu/launchSPG.cc	2011-01-30 15:33:06 +0000
@@ -44,72 +44,66 @@
 	Fullscreen_Menu_Base("launchgamemenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 9 / 200),
-	m_fs   (fs_small()),
-	m_fn   (ui_fn()),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 9 / 200),
 
 // Buttons
 	m_select_map
 		(this, "select_map",
-		 m_xres * 7 / 10, m_yres * 3 / 10, m_butw, m_buth,
+		 get_w() * 7 / 10, get_h() * 3 / 10, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind(&Fullscreen_Menu_LaunchSPG::select_map, boost::ref(*this)),
-		 _("Select map"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("Select map"), std::string(), false, false),
 	m_wincondition
 		(this, "win_condition",
-		 m_xres * 7 / 10, m_yres * 4 / 10, m_butw, m_buth,
+		 get_w() * 7 / 10, get_h() * 4 / 10, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_LaunchSPG::win_condition_clicked,
 			  boost::ref(*this)),
-		 "", std::string(), false, false,
-		 m_fn, m_fs),
+		 "", std::string(), false, false),
 	m_back
 		(this, "back",
-		 m_xres * 7 / 10, m_yres * 9 / 20, m_butw, m_buth,
+		 get_w() * 7 / 10, get_h() * 9 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&Fullscreen_Menu_LaunchSPG::back_clicked, boost::ref(*this)),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 	m_ok
 		(this, "ok",
-		 m_xres * 7 / 10, m_yres * 1 / 2, m_butw, m_buth,
+		 get_w() * 7 / 10, get_h() * 1 / 2, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_LaunchSPG::start_clicked, boost::ref(*this)),
-		 _("Start game"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("Start game"), std::string(), false, false),
 
 // Text labels
 	m_title
 		(this,
-		 m_xres / 2, m_yres / 10,
+		 get_w() / 2, get_h() / 10,
 		 _("Launch Game"), UI::Align_HCenter),
 	m_mapname
 		(this,
-		 m_xres * 7 / 10 + m_butw / 2, m_yres * 5 / 20,
+		 get_w() * 7 / 10 + m_butw / 2, get_h() * 5 / 20,
 		 std::string(), UI::Align_HCenter),
 	m_name
 		(this,
-		 m_xres * 1 / 25, m_yres * 53 / 200,
+		 get_w() * 1 / 25, get_h() * 53 / 200,
 		 _("Player's name"), UI::Align_Left),
 	m_type
 		(this,
-		 m_xres * 19 / 100, m_yres * 53 / 200,
+		 get_w() * 19 / 100, get_h() * 53 / 200,
 		 _("Player's type"), UI::Align_Left),
 	m_team
 		(this,
-		 m_xres * 31 / 100, m_yres * 53 / 200,
+		 get_w() * 31 / 100, get_h() * 53 / 200,
 		 _("Team"), UI::Align_Left),
 	m_tribe
 		(this,
-		 m_xres * 36 / 100, m_yres * 53 / 200,
+		 get_w() * 36 / 100, get_h() * 53 / 200,
 		 _("Player's tribe"), UI::Align_Left),
 	m_init
 		(this,
-		 m_xres * 51 / 100, m_yres * 53 / 200,
+		 get_w() * 51 / 100, get_h() * 53 / 200,
 		 _("Start type"), UI::Align_Left),
 
 // Variables and objects used in the menu
@@ -128,22 +122,31 @@
 	m_cur_wincondition = -1;
 	win_condition_clicked();
 
-	m_title  .set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
-	m_mapname.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_name   .set_font(m_fn, m_fs * 4 / 5, UI_FONT_CLR_FG);
-	m_type   .set_font(m_fn, m_fs * 4 / 5, UI_FONT_CLR_FG);
-	m_team   .set_font(m_fn, m_fs * 4 / 5, UI_FONT_CLR_FG);
-	m_tribe  .set_font(m_fn, m_fs * 4 / 5, UI_FONT_CLR_FG);
-	m_init   .set_font(m_fn, m_fs * 4 / 5, UI_FONT_CLR_FG);
-
-	uint32_t y = m_yres / 4;
+	m_title  .set_textstyle(ts_big());
+	m_mapname.set_textstyle(ts_small());
+
+	UI::TextStyle tsmaller
+		(UI::TextStyle::makebold
+		 (UI::Font::get(ui_fn(), fs_small() * 4 / 5), UI_FONT_CLR_FG));
+	m_name.set_textstyle(tsmaller);
+	m_type.set_textstyle(tsmaller);
+	m_team.set_textstyle(tsmaller);
+	m_tribe.set_textstyle(tsmaller);
+	m_init.set_textstyle(tsmaller);
+
+	m_select_map.set_font(font_small());
+	m_wincondition.set_font(font_small());
+	m_back.set_font(font_small());
+	m_ok.set_font(font_small());
+
+	uint32_t y = get_h() / 4;
 	char posIco[42];
 	for (uint32_t i = 0; i < MAX_PLAYERS; ++i) {
 		sprintf(posIco, "pics/fsel_editor_set_player_0%i_pos.png", i + 1);
 		m_pos[i] =
 			new UI::Callback_Button
 				(this, "switch_to_position",
-				 m_xres / 100, y += m_buth, m_yres * 17 / 500, m_yres * 17 / 500,
+				 get_w() / 100, y += m_buth, get_h() * 17 / 500, get_h() * 17 / 500,
 				 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 				 g_gr->get_picture(PicMod_Game, posIco),
 				 boost::bind
@@ -153,9 +156,8 @@
 		m_players[i] =
 			new PlayerDescriptionGroup
 				(this,
-				 m_xres / 25, y, m_xres * 16 / 25, m_yres * 17 / 500,
-				 settings, i,
-				 m_fn, m_fs);
+				 get_w() / 25, y, get_w() * 16 / 25, get_h() * 17 / 500,
+				 settings, i, font_small());
 	}
 }
 

=== modified file 'src/ui_fsmenu/launchSPG.h'
--- src/ui_fsmenu/launchSPG.h	2010-10-29 19:21:59 +0000
+++ src/ui_fsmenu/launchSPG.h	2011-01-30 15:33:06 +0000
@@ -74,8 +74,6 @@
 
 	uint32_t    m_butw;
 	uint32_t    m_buth;
-	uint32_t    m_fs;
-	std::string m_fn;
 
 	UI::Callback_Button       m_select_map, m_wincondition, m_back, m_ok;
 	UI::Callback_Button     * m_pos[MAX_PLAYERS];

=== modified file 'src/ui_fsmenu/loadgame.cc'
--- src/ui_fsmenu/loadgame.cc	2010-11-02 11:13:59 +0000
+++ src/ui_fsmenu/loadgame.cc	2011-01-30 15:33:06 +0000
@@ -33,8 +33,8 @@
 	Fullscreen_Menu_Base("choosemapmenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 9 / 200),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 9 / 200),
 	m_fs   (fs_small()),
 	m_fn   (ui_fn()),
 
@@ -44,48 +44,49 @@
 // Buttons
 	m_back
 		(this, "back",
-		 m_xres * 71 / 100, m_yres * 9 / 10, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 9 / 10, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&Fullscreen_Menu_LoadGame::end_modal, boost::ref(*this), 0),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 	m_ok
 		(this, "ok",
-		 m_xres * 71 / 100, m_yres * 15 / 20, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 15 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind(&Fullscreen_Menu_LoadGame::clicked_ok, boost::ref(*this)),
-		 _("OK"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("OK"), std::string(), false, false),
 	m_delete
 		(this, "delete",
-		 m_xres * 71 / 100, m_yres * 17 / 20, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 17 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_LoadGame::clicked_delete, boost::ref(*this)),
-		 _("Delete"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("Delete"), std::string(), false, false),
 
 // Replay list
 	m_list
-		(this, m_xres * 47 / 2500, m_yres * 3417 / 10000,
-		 m_xres * 711 / 1250, m_yres * 6083 / 10000),
+		(this, get_w() * 47 / 2500, get_h() * 3417 / 10000,
+		 get_w() * 711 / 1250, get_h() * 6083 / 10000),
 
 // Text areas
 	m_title
 		(this,
-		 m_xres / 2, m_yres * 3 / 20,
+		 get_w() / 2, get_h() * 3 / 20,
 		 _("Choose saved game!"), UI::Align_HCenter),
 	m_label_mapname
 		(this,
-		 m_xres * 7 / 10,  m_yres * 17 / 50,
+		 get_w() * 7 / 10,  get_h() * 17 / 50,
 		 _("Map Name:"), UI::Align_Right),
-	m_tamapname(this, m_xres * 71 / 100, m_yres * 17 / 50),
+	m_tamapname(this, get_w() * 71 / 100, get_h() * 17 / 50),
 	m_label_gametime
 		(this,
-		 m_xres * 7 / 10,  m_yres * 3 / 8,
+		 get_w() * 7 / 10,  get_h() * 3 / 8,
 		 _("Gametime:"), UI::Align_Right),
-	m_tagametime(this, m_xres * 71 / 100, m_yres * 3 / 8)
+	m_tagametime(this, get_w() * 71 / 100, get_h() * 3 / 8)
 {
+	m_back.set_font(font_small());
+	m_ok.set_font(font_small());
+	m_delete.set_font(font_small());
+
 	m_title         .set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
 	m_label_mapname .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
 	m_tamapname     .set_font(m_fn, m_fs, UI_FONT_CLR_FG);

=== modified file 'src/ui_fsmenu/loadreplay.cc'
--- src/ui_fsmenu/loadreplay.cc	2010-11-02 11:13:59 +0000
+++ src/ui_fsmenu/loadreplay.cc	2011-01-30 15:33:06 +0000
@@ -30,45 +30,43 @@
 	Fullscreen_Menu_Base("choosemapmenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 19 / 400),
-	m_fs   (fs_small()),
-	m_fn   (ui_fn()),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 19 / 400),
 
 // Buttons
 	m_back
 		(this, "back",
-		 m_xres * 71 / 100, m_yres * 17 / 20, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 17 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_LoadReplay::end_modal, boost::ref(*this), 0),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 	m_ok
 		(this, "ok",
-		 m_xres * 71 / 100, m_yres * 9 / 10, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 9 / 10, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind(&Fullscreen_Menu_LoadReplay::clicked_ok, boost::ref(*this)),
-		 _("OK"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("OK"), std::string(), false, false),
 
 // Replay list
 	m_list
 		(this,
-		 m_xres *  47 / 2500, m_yres * 3417 / 10000,
-		 m_xres * 711 / 1250, m_yres * 6083 / 10000),
+		 get_w() *  47 / 2500, get_h() * 3417 / 10000,
+		 get_w() * 711 / 1250, get_h() * 6083 / 10000),
 
 // Text area
 	m_title
 		(this,
-		 m_xres / 2, m_yres * 3 / 20, _("Choose a replay!"),
+		 get_w() / 2, get_h() * 3 / 20, _("Choose a replay!"),
 		 UI::Align_HCenter)
 {
-	m_title.set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
-	m_list .set_font(m_fn, m_fs);
+	m_title.set_textstyle(ts_big());
+	m_list .set_font(ui_fn(), fs_small());
 	m_list .selected.set(this, &Fullscreen_Menu_LoadReplay::replay_selected);
 	m_list .double_clicked.set
 		(this, &Fullscreen_Menu_LoadReplay::double_clicked);
+	m_back.set_font(font_small());
+	m_ok.set_font(font_small());
 	fill_list();
 }
 

=== modified file 'src/ui_fsmenu/loadreplay.h'
--- src/ui_fsmenu/loadreplay.h	2010-10-17 19:42:01 +0000
+++ src/ui_fsmenu/loadreplay.h	2011-01-30 15:33:06 +0000
@@ -41,10 +41,8 @@
 	void fill_list();
 
 private:
-	uint32_t    m_butw;
-	uint32_t    m_buth;
-	uint32_t    m_fs;
-	std::string m_fn;
+	uint32_t m_butw;
+	uint32_t m_buth;
 
 	UI::Callback_Button m_back, m_ok;
 	UI::Listselect<std::string> m_list;

=== modified file 'src/ui_fsmenu/main.cc'
--- src/ui_fsmenu/main.cc	2010-11-02 11:13:59 +0000
+++ src/ui_fsmenu/main.cc	2011-01-30 15:33:06 +0000
@@ -26,108 +26,107 @@
 	Fullscreen_Menu_Base("mainmenu.jpg"),
 
 // Values for alignment and size
-	m_butx (m_xres * 13 / 40),
-	m_butw (m_xres * 7 / 20),
-	m_buth (m_yres * 19 / 400),
-	m_fs   (fs_small()),
-	m_fn   (ui_fn()),
+	m_butx (get_w() * 13 / 40),
+	m_butw (get_w() * 7 / 20),
+	m_buth (get_h() * 19 / 400),
 	wlcr   (WLCR),
 
 // Buttons
 	playtutorial
 		(this, "play_tutorial",
-		 m_butx, m_yres * 42 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 42 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_Main::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(mm_playtutorial)),
-		 _("Play Tutorial"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Play Tutorial"), std::string(), true, false),
 	singleplayer
 		(this, "single_player",
-		 m_butx, m_yres * 61 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 61 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_Main::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(mm_singleplayer)),
-		 _("Single Player"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Single Player"), std::string(), true, false),
 	multiplayer
 		(this, "multi_player",
-		 m_butx, m_yres * 37 / 100, m_butw, m_buth,
+		 m_butx, get_h() * 37 / 100, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_Main::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(mm_multiplayer)),
-		 _("Multi Player"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Multi Player"), std::string(), true, false),
 	replay
 		(this, "replay",
-		 m_butx, m_yres * 87 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 87 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_Main::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(mm_replay)),
-		 _("Watch Replay"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Watch Replay"), std::string(), true, false),
 	editor
 		(this, "editor",
-		 m_butx, m_yres * 100 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 100 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_Main::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(mm_editor)),
-		 _("Editor"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Editor"), std::string(), true, false),
 	options
 		(this, "options",
-		 m_butx, m_yres * 119 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 119 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_Main::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(mm_options)),
-		 _("Options"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Options"), std::string(), true, false),
 	readme
 		(this, "readme",
-		 m_butx, m_yres * 138 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 138 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_Main::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(mm_readme)),
-		 _("View Readme"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("View Readme"), std::string(), true, false),
 	license
 		(this, "license",
-		 m_butx, m_yres * 151 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 151 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_Main::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(mm_license)),
-		 _("License"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("License"), std::string(), true, false),
 	exit
 		(this, "exit",
-		 m_butx, m_yres * 178 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 178 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but3.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_Main::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(mm_exit)),
-		 _("Exit Game"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Exit Game"), std::string(), true, false),
 
 // Textlabels
 	version
 		(this,
-		 m_xres, m_yres,
+		 get_w(), get_h(),
 		 _("Version ") + build_id() + '(' + build_type() + ')',
 		 UI::Align_BottomRight),
 	copyright
 		(this,
-		 0, m_yres,
+		 0, get_h(),
 		 (wlcr + _("by the Widelands Development Team")).c_str(),
 		 UI::Align_BottomLeft)
 {
-	version.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	copyright.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	playtutorial.set_font(font_small());
+	singleplayer.set_font(font_small());
+	multiplayer.set_font(font_small());
+	replay.set_font(font_small());
+	editor.set_font(font_small());
+	options.set_font(font_small());
+	readme.set_font(font_small());
+	license.set_font(font_small());
+	exit.set_font(font_small());
+
+	version.set_textstyle(ts_small());
+	copyright.set_textstyle(ts_small());
 }

=== modified file 'src/ui_fsmenu/main.h'
--- src/ui_fsmenu/main.h	2010-10-17 19:42:01 +0000
+++ src/ui_fsmenu/main.h	2011-01-30 15:33:06 +0000
@@ -46,8 +46,6 @@
 	uint32_t                                    m_butx;
 	uint32_t                                    m_butw;
 	uint32_t                                    m_buth;
-	uint32_t                                    m_fs;
-	std::string                                 m_fn;
 	std::string                                 wlcr;
 	UI::Callback_Button                     playtutorial;
 	UI::Callback_Button                     singleplayer;

=== modified file 'src/ui_fsmenu/mapselect.cc'
--- src/ui_fsmenu/mapselect.cc	2010-11-05 21:46:43 +0000
+++ src/ui_fsmenu/mapselect.cc	2011-01-30 15:33:06 +0000
@@ -38,102 +38,101 @@
 	Fullscreen_Menu_Base("choosemapmenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 9 / 200),
-	m_fs   (fs_small()),
-	m_fn   (ui_fn()),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 9 / 200),
 
 // Text labels
 	m_title
 		(this,
-		 m_xres / 2, m_yres * 9 / 50,
+		 get_w() / 2, get_h() * 9 / 50,
 		 _("Choose your map!"),
 		 UI::Align_HCenter),
 	m_label_load_map_as_scenario
 		(this,
-		 m_xres * 23 / 25, m_yres * 11 / 40,
+		 get_w() * 23 / 25, get_h() * 11 / 40,
 		 _("Load Map as scenario: "),
 		 UI::Align_Right),
 	m_label_name
 		(this,
-		 m_xres * 7 / 10, m_yres * 17 / 50,
+		 get_w() * 7 / 10, get_h() * 17 / 50,
 		 _("Name:"),
 		 UI::Align_Right),
-	m_name (this, m_xres * 71 / 100, m_yres * 17 / 50),
+	m_name (this, get_w() * 71 / 100, get_h() * 17 / 50),
 	m_label_author
 		(this,
-		 m_xres * 7 / 10, m_yres * 3 / 8,
+		 get_w() * 7 / 10, get_h() * 3 / 8,
 		 _("Author:"),
 		 UI::Align_Right),
-	m_author (this, m_xres * 71 / 100, m_yres * 3 / 8),
+	m_author (this, get_w() * 71 / 100, get_h() * 3 / 8),
 	m_label_size
 		(this,
-		 m_xres * 7 / 10, m_yres * 41 / 100,
+		 get_w() * 7 / 10, get_h() * 41 / 100,
 		 _("Size:"),
 		 UI::Align_Right),
-	m_size (this, m_xres * 71 / 100, m_yres * 41 / 100),
+	m_size (this, get_w() * 71 / 100, get_h() * 41 / 100),
 	m_label_world
 		(this,
-		 m_xres * 7 / 10, m_yres * 89 / 200,
+		 get_w() * 7 / 10, get_h() * 89 / 200,
 		 _("World:"),
 		 UI::Align_Right),
-	m_world (this, m_xres * 71 / 100, m_yres * 89 / 200),
+	m_world (this, get_w() * 71 / 100, get_h() * 89 / 200),
 	m_label_nr_players
 		(this,
-		 m_xres * 7 / 10, m_yres * 12 / 25,
+		 get_w() * 7 / 10, get_h() * 12 / 25,
 		 _("Players:"),
 		 UI::Align_Right),
-	m_nr_players (this, m_xres * 71 / 100, m_yres * 12 / 25),
+	m_nr_players (this, get_w() * 71 / 100, get_h() * 12 / 25),
 	m_label_descr
 		(this,
-		 m_xres * 7 / 10, m_yres * 103 / 200,
+		 get_w() * 7 / 10, get_h() * 103 / 200,
 		 _("Descr:"),
 		 UI::Align_Right),
 	m_descr
 		(this,
-		 m_xres * 71 / 100, m_yres * 13 / 25, m_xres / 4, m_yres * 63 / 200),
+		 get_w() * 71 / 100, get_h() * 13 / 25, get_w() / 4, get_h() * 63 / 200),
 
 // Buttons
 	m_back
 		(this, "back",
-		 m_xres * 71 / 100, m_yres * 17 / 20, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 17 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&Fullscreen_Menu_MapSelect::end_modal, boost::ref(*this), 0),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 	m_ok
 		(this, "ok",
-		 m_xres * 71 / 100, m_yres * 9 / 10, m_butw, m_buth,
+		 get_w() * 71 / 100, get_h() * 9 / 10, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind(&Fullscreen_Menu_MapSelect::ok, boost::ref(*this)),
-		 _("OK"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("OK"), std::string(), false, false),
 
 // Checkbox
-	m_load_map_as_scenario (this, Point (m_xres * 187 / 200, m_yres * 7 / 25)),
+	m_load_map_as_scenario (this, Point (get_w() * 187 / 200, get_h() * 7 / 25)),
 
 // Map table
 	m_table
 		(this,
-		 m_xres *  47 / 2500, m_yres * 3417 / 10000,
-		 m_xres * 711 / 1250, m_yres * 6083 / 10000),
+		 get_w() *  47 / 2500, get_h() * 3417 / 10000,
+		 get_w() * 711 / 1250, get_h() * 6083 / 10000),
 	m_curdir("maps"), m_basedir("maps")
 {
-	m_title.set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
-	m_label_load_map_as_scenario.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_name                .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_name                      .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_author              .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_author                    .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_size                .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_size                      .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_world               .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_world                     .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_nr_players          .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_nr_players                .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_descr               .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_descr                     .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_table                     .set_font(m_fn, m_fs);
+	m_title.set_textstyle(ts_big());
+	m_label_load_map_as_scenario.set_textstyle(ts_small());
+	m_label_name                .set_textstyle(ts_small());
+	m_name                      .set_textstyle(ts_small());
+	m_label_author              .set_textstyle(ts_small());
+	m_author                    .set_textstyle(ts_small());
+	m_label_size                .set_textstyle(ts_small());
+	m_size                      .set_textstyle(ts_small());
+	m_label_world               .set_textstyle(ts_small());
+	m_world                     .set_textstyle(ts_small());
+	m_label_nr_players          .set_textstyle(ts_small());
+	m_nr_players                .set_textstyle(ts_small());
+	m_label_descr               .set_textstyle(ts_small());
+	m_descr                     .set_font(ui_fn(), fs_small(), UI_FONT_CLR_FG);
+	m_table                     .set_font(ui_fn(), fs_small());
+
+	m_back.set_font(font_small());
+	m_ok.set_font(font_small());
 
 #define NR_PLAYERS_WIDTH 35
 	m_table.add_column(NR_PLAYERS_WIDTH, _("#"), UI::Align_HCenter);

=== modified file 'src/ui_fsmenu/mapselect.h'
--- src/ui_fsmenu/mapselect.h	2010-11-05 19:36:57 +0000
+++ src/ui_fsmenu/mapselect.h	2011-01-30 15:33:06 +0000
@@ -72,8 +72,6 @@
 
 	uint32_t     m_butw;
 	uint32_t     m_buth;
-	uint32_t     m_fs;
-	std::string  m_fn;
 	UI::Textarea m_title;
 	UI::Textarea m_label_load_map_as_scenario;
 	UI::Textarea m_label_name,       m_name;

=== modified file 'src/ui_fsmenu/multiplayer.cc'
--- src/ui_fsmenu/multiplayer.cc	2010-11-02 11:13:59 +0000
+++ src/ui_fsmenu/multiplayer.cc	2011-01-30 15:33:06 +0000
@@ -30,60 +30,62 @@
 	Fullscreen_Menu_Base("singleplmenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres * 7 / 20),
-	m_buth (m_yres * 19 / 400),
-	m_butx ((m_xres - m_butw) / 2),
+	m_butw (get_w() * 7 / 20),
+	m_buth (get_h() * 19 / 400),
+	m_butx ((get_w() - m_butw) / 2),
 	m_fs   (fs_small()),
 	m_fn   (ui_fn()),
 
 // Title
 	title
 		(this,
-		 m_xres / 2, m_yres * 3 / 40,
+		 get_w() / 2, get_h() * 3 / 40,
 		 _("Choose game type"), UI::Align_HCenter),
 
 // Buttons
 	metaserver
 		(this, "metaserver",
-		 m_butx, m_yres * 6 / 25, m_butw, m_buth,
+		 m_butx, get_h() * 6 / 25, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind(&Fullscreen_Menu_MultiPlayer::ggzLogin, boost::ref(*this)),
-		 _("Internet game"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Internet game"), std::string(), true, false),
 	lan
 		(this, "lan",
-		 m_butx, m_yres * 61 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 61 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_MultiPlayer::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(Lan)),
-		 _("LAN / Direct IP"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("LAN / Direct IP"), std::string(), true, false),
 	back
 		(this, "back",
-		 m_butx, m_yres * 3 / 4, m_butw, m_buth,
+		 m_butx, get_h() * 3 / 4, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_MultiPlayer::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(Back)),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs)
+		 _("Back"), std::string(), true, false)
 {
+	metaserver.set_font(font_small());
+	lan.set_font(font_small());
+	back.set_font(font_small());
+
 	title.set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
 
 	Section & s = g_options.pull_section("global");
 	m_auto_log = s.get_bool("auto_log", false);
-	if (m_auto_log)
+	if (m_auto_log) {
 		showloginbox =
 			new UI::Callback_Button
 				(this, "login_dialog",
-				 m_butx + m_butw + m_buth / 4, m_yres * 6 / 25, m_buth, m_buth,
+				 m_butx + m_butw + m_buth / 4, get_h() * 6 / 25, m_buth, m_buth,
 				 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 				 g_gr->get_picture(PicMod_UI, "pics/continue.png"),
 				 boost::bind
 					 (&Fullscreen_Menu_MultiPlayer::showGGZLogin, boost::ref(*this)),
-				 _("Show login dialog"), true, false,
-				 m_fn, m_fs);
+				 _("Show login dialog"), true, false);
+		showloginbox->set_font(font_small());
+	}
 }
 
 

=== modified file 'src/ui_fsmenu/netsetup_ggz.cc'
--- src/ui_fsmenu/netsetup_ggz.cc	2010-11-01 23:29:48 +0000
+++ src/ui_fsmenu/netsetup_ggz.cc	2011-01-30 15:33:06 +0000
@@ -36,10 +36,10 @@
 	Fullscreen_Menu_Base("internetmenu.jpg"),
 
 // Values for alignment and size
-	m_butx (m_xres * 13 / 40),
-	m_butw (m_xres * 36 / 125),
-	m_buth (m_yres * 19 / 400),
-	m_lisw (m_xres * 623 / 1000),
+	m_butx (get_w() * 13 / 40),
+	m_butw (get_w() * 36 / 125),
+	m_buth (get_h() * 19 / 400),
+	m_lisw (get_w() * 623 / 1000),
 	m_namechange(0),
 	m_fs   (fs_small()),
 	m_fn   (ui_fn()),
@@ -47,80 +47,77 @@
 // Text labels
 	title
 		(this,
-		 m_xres / 2, m_yres / 20,
+		 get_w() / 2, get_h() / 20,
 		 _("Metaserver Lobby"), UI::Align_HCenter),
 	m_users
 		(this,
-		 m_xres * 4 / 125, m_yres * 15 / 100,
+		 get_w() * 4 / 125, get_h() * 15 / 100,
 		 _("Users online:")),
 	m_opengames
 		(this,
-		 m_xres * 17 / 25, m_yres * 15 / 100,
+		 get_w() * 17 / 25, get_h() * 15 / 100,
 		 _("List of games:")),
 	m_servername
 		(this,
-		 m_xres * 17 / 25, m_yres * 63 / 100,
+		 get_w() * 17 / 25, get_h() * 63 / 100,
 		 _("Name of your server:")),
 	m_maxplayers
 		(this,
-		 m_xres * 17 / 25, m_yres * 73 / 100,
+		 get_w() * 17 / 25, get_h() * 73 / 100,
 		 _("Maximum of players:")),
 
 // Spinboxes
 	maxplayers
 		(this,
-		 m_xres * 17 / 25, m_yres * 77 / 100, m_butw, m_buth * 7 / 10,
+		 get_w() * 17 / 25, get_h() * 77 / 100, m_butw, m_buth * 7 / 10,
 		 7, 1, 7), //  start/min./max. value dummy initializations
 
 // Buttons
 	joingame
 		(this, "join_game",
-		 m_xres * 17 / 25, m_yres * 55 / 100, m_butw, m_buth,
+		 get_w() * 17 / 25, get_h() * 55 / 100, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_NetSetupGGZ::clicked_joingame,
 			  boost::ref(*this)),
-		 _("Join this game"), std::string(), false, false,
-		 m_fn, m_fs),
+		 _("Join this game"), std::string(), false, false),
 	hostgame
 		(this, "host_game",
-		 m_xres * 17 / 25, m_yres * 81 / 100, m_butw, m_buth,
+		 get_w() * 17 / 25, get_h() * 81 / 100, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_NetSetupGGZ::clicked_hostgame,
 			  boost::ref(*this)),
-		 _("Open a new game"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Open a new game"), std::string(), true, false),
 	back
 		(this, "back",
-		 m_xres * 17 / 25, m_yres * 90 / 100, m_butw, m_buth,
+		 get_w() * 17 / 25, get_h() * 90 / 100, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_NetSetupGGZ::end_modal,
 			  boost::ref(*this), static_cast<int32_t>(CANCEL)),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 
 // Edit boxes
 	servername
-		(this, m_xres * 17 / 25, m_yres * 68 / 100, m_butw, m_buth,
+		(this, get_w() * 17 / 25, get_h() * 68 / 100, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"), 0),
 
 // List
 	usersonline
 		(this,
-		 m_xres * 4 / 125, m_yres     / 5,
-		 m_lisw,          m_yres * 3 / 10),
+		 get_w() * 4 / 125, get_h()     / 5,
+		 m_lisw,          get_h() * 3 / 10),
 	opengames
 		(this,
-		 m_xres * 17 / 25, m_yres    / 5,
-		 m_butw,  m_yres * 7 / 20),
+		 get_w() * 17 / 25, get_h()    / 5,
+		 m_butw,  get_h() * 7 / 20),
 
 // The chat UI
 	chat
 		(this,
-		 m_xres * 4 / 125,    m_yres * 51 / 100,
-		 m_lisw, m_yres * 44 / 100,
+		 get_w() * 4 / 125,    get_h() * 51 / 100,
+		 m_lisw, get_h() * 44 / 100,
 		 NetGGZ::ref()),
 
 // Login information
@@ -128,6 +125,10 @@
 	password(pwd),
 	reg(registered)
 {
+	back.set_font(font_small());
+	joingame.set_font(font_small());
+	hostgame.set_font(font_small());
+
 	// Set the texts and style of UI elements
 	Section & s = g_options.pull_section("global"); //  for playername
 

=== modified file 'src/ui_fsmenu/netsetup_lan.cc'
--- src/ui_fsmenu/netsetup_lan.cc	2010-11-02 11:13:59 +0000
+++ src/ui_fsmenu/netsetup_lan.cc	2011-01-30 15:33:06 +0000
@@ -28,94 +28,93 @@
 	Fullscreen_Menu_Base("singleplmenu.jpg"), //  FIXME change this
 
 // Values for alignment and size
-	m_butx (m_xres * 13 / 40),
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 19 / 400),
-	m_lisw (m_xres * 9 / 16),
-	m_fs   (fs_small()),
-	m_fn   (ui_fn()),
+	m_butx (get_w() * 13 / 40),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 19 / 400),
+	m_lisw (get_w() * 9 / 16),
 
 // Text labels
 	title
 		(this,
-		 m_xres / 2, m_yres / 10,
+		 get_w() / 2, get_h() / 10,
 		 _("Begin Network Game"), UI::Align_HCenter),
 	m_opengames
 		(this,
-		 m_xres * 3 / 50, m_yres * 27 / 100,
+		 get_w() * 3 / 50, get_h() * 27 / 100,
 		 _("List of games in your local network:")),
 	m_playername
 		(this,
-		 m_xres * 16 / 25, m_yres * 27 / 100,
+		 get_w() * 16 / 25, get_h() * 27 / 100,
 		 _("Your nickname:")),
 	m_hostname
 		(this,
-		 m_xres * 16 / 25, m_yres * 17 / 40,
+		 get_w() * 16 / 25, get_h() * 17 / 40,
 		 _("Host to connect:")),
 
 // Buttons
 	joingame
 		(this, "join_game",
-		 m_xres * 16 / 25, m_yres * 5333 / 10000, m_butw, m_buth,
+		 get_w() * 16 / 25, get_h() * 5333 / 10000, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_NetSetupLAN::clicked_joingame, boost::ref(*this)),
-		 _("Join this game"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Join this game"), std::string(), true, false),
 	hostgame
 		(this, "host_game",
-		 m_xres * 16 / 25, m_yres * 6083 / 10000, m_butw, m_buth,
+		 get_w() * 16 / 25, get_h() * 6083 / 10000, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_NetSetupLAN::clicked_hostgame, boost::ref(*this)),
-		 _("Host a new game"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Host a new game"), std::string(), true, false),
 	back
 		(this, "back",
-		 m_xres * 16 / 25, m_yres * 8333 / 10000, m_butw, m_buth,
+		 get_w() * 16 / 25, get_h() * 8333 / 10000, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_NetSetupLAN::end_modal, boost::ref(*this),
 			  static_cast<int32_t>(CANCEL)),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Back"), std::string(), true, false),
 	loadlasthost
 		(this, "load_previous_host",
-		 m_xres * 171 / 200, m_yres * 19 / 40, m_buth, m_buth,
+		 get_w() * 171 / 200, get_h() * 19 / 40, m_buth, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 g_gr->get_picture(PicMod_UI, "pics/menu_load_game.png"),
 		 boost::bind
 			 (&Fullscreen_Menu_NetSetupLAN::clicked_lasthost, boost::ref(*this)),
-		 _("Load previous host"), true, false,
-		 m_fn, m_fs),
+		 _("Load previous host"), true, false),
 
 // Edit boxes
 	playername
-		(this, m_xres * 16 / 25, m_yres * 3333 / 10000, m_butw,       m_buth,
+		(this, get_w() * 16 / 25, get_h() * 3333 / 10000, m_butw,       m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"), 0),
 	hostname
-		(this, m_xres * 16 / 25, m_yres * 19 / 40,  m_xres * 17 / 80, m_buth,
+		(this, get_w() * 16 / 25, get_h() * 19 / 40,  get_w() * 17 / 80, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"), 0),
 
 // List
 	opengames
 		(this,
-		 m_xres * 3 / 50, m_yres * 3333 / 10000, m_lisw, m_yres * 5433 / 10000)
+		 get_w() * 3 / 50, get_h() * 3333 / 10000, m_lisw, get_h() * 5433 / 10000)
 {
 	Section & s = g_options.pull_section("global"); //  for playername
 
-	title       .set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
-	m_opengames .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_playername.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_hostname  .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	joingame.set_font(font_small());
+	hostgame.set_font(font_small());
+	back.set_font(font_small());
+	loadlasthost.set_font(font_small());
+
+	title       .set_textstyle(ts_big());
+	m_opengames .set_textstyle(ts_small());
+	m_playername.set_textstyle(ts_small());
+	m_hostname  .set_textstyle(ts_small());
 	hostname    .changed.set
 		(this, &Fullscreen_Menu_NetSetupLAN::change_hostname);
-	hostname    .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	hostname    .set_font(ui_fn(), fs_small(), UI_FONT_CLR_FG);
 	playername  .setText  (s.get_string("nickname", (_("nobody"))));
 	playername  .changed.set
 		(this, &Fullscreen_Menu_NetSetupLAN::change_playername);
-	playername  .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	opengames   .set_font(m_fn, m_fs);
+	playername  .set_font(ui_fn(), fs_small(), UI_FONT_CLR_FG);
+	opengames   .set_font(ui_fn(), fs_small());
 	opengames   .add_column(m_lisw * 2 / 5, _("Host"));
 	opengames   .add_column(m_lisw * 2 / 5, _("Map"));
 	opengames   .add_column(m_lisw     / 5, _("State"));

=== modified file 'src/ui_fsmenu/netsetup_lan.h'
--- src/ui_fsmenu/netsetup_lan.h	2010-10-17 19:42:01 +0000
+++ src/ui_fsmenu/netsetup_lan.h	2011-01-30 15:33:06 +0000
@@ -65,8 +65,6 @@
 	uint32_t                                    m_butw;
 	uint32_t                                    m_buth;
 	uint32_t                                    m_lisw;
-	uint32_t                                    m_fs;
-	std::string                                 m_fn;
 	UI::Textarea                                title, m_opengames;
 	UI::Textarea                                m_playername, m_hostname;
 	UI::Callback_Button                     joingame, hostgame, back, loadlasthost;

=== modified file 'src/ui_fsmenu/options.cc'
--- src/ui_fsmenu/options.cc	2010-11-06 16:31:40 +0000
+++ src/ui_fsmenu/options.cc	2011-01-30 15:33:06 +0000
@@ -39,196 +39,194 @@
 	Fullscreen_Menu_Base("optionsmenu.jpg"),
 
 // Values for alignment and size
-	m_vbutw(m_yres * 333 / 10000),
-	m_butw (m_xres / 4),
-	m_buth (m_yres * 9 / 200),
-	m_fs   (fs_small()),
-	m_fn   (ui_fn()),
+	m_vbutw(get_h() * 333 / 10000),
+	m_butw (get_w() / 4),
+	m_buth (get_h() * 9 / 200),
 
 // Buttons
 	m_advanced_options
 		(this, "advanced_options",
-		 m_xres * 9 / 80, m_yres * 19 / 20, m_butw, m_buth,
+		 get_w() * 9 / 80, get_h() * 19 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind(&Fullscreen_Menu_Options::advanced_options, boost::ref(*this)),
-		 _("Advanced Options"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Advanced Options"), std::string(), true, false),
 	m_cancel
 		(this, "cancel",
-		 m_xres * 51 / 80, m_yres * 19 / 20, m_butw, m_buth,
+		 get_w() * 51 / 80, get_h() * 19 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&Fullscreen_Menu_Options::end_modal, boost::ref(*this), static_cast<int32_t>(om_cancel)),
-		 _("Cancel"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Cancel"), std::string(), true, false),
 	m_apply
 		(this, "apply",
-		 m_xres * 3 / 8, m_yres * 19 / 20, m_butw, m_buth,
+		 get_w() * 3 / 8, get_h() * 19 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind(&Fullscreen_Menu_Options::end_modal, boost::ref(*this), static_cast<int32_t>(om_ok)),
-		 _("Apply"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Apply"), std::string(), true, false),
 
 // Spinboxes
 	m_sb_maxfps
 		(this,
-		 m_xres / 2, m_yres * 3833 / 10000, m_xres / 5, m_vbutw,
+		 get_w() / 2, get_h() * 3833 / 10000, get_w() / 5, m_vbutw,
 		 opt.maxfps, 0, 100, "",
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png")),
 	m_sb_autosave
 		(this,
-		 m_xres * 6767 / 10000, m_yres * 8167 / 10000, m_xres / 4, m_vbutw,
+		 get_w() * 6767 / 10000, get_h() * 8167 / 10000, get_w() / 4, m_vbutw,
 		 opt.autosave / 60, 0, 100, _("min."),
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"), true),
 
 	m_sb_remove_replays
 		(this,
-		 m_xres * 6767 / 10000, m_yres * 8631 / 10000, m_xres / 4, m_vbutw,
+		 get_w() * 6767 / 10000, get_h() * 8631 / 10000, get_w() / 4, m_vbutw,
 		 opt.remove_replays, 0, 365, _("days"),
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"), true),
 
 // Title
 	m_title
 		(this,
-		 m_xres / 2, m_yres / 40,
+		 get_w() / 2, get_h() / 40,
 		 _("General Options"), UI::Align_HCenter),
 
 // First options block 'general options'
-	m_fullscreen (this, Point(m_xres * 3563 / 10000, m_yres * 1667 / 10000)),
+	m_fullscreen (this, Point(get_w() * 3563 / 10000, get_h() * 1667 / 10000)),
 	m_label_fullscreen
 		(this,
-		 m_xres * 1969 / 5000, m_yres * 1833 / 10000,
+		 get_w() * 1969 / 5000, get_h() * 1833 / 10000,
 		 _("Fullscreen"), UI::Align_VCenter),
 
-	m_inputgrab (this, Point(m_xres * 3563 / 10000, m_yres * 2167 / 10000)),
+	m_inputgrab (this, Point(get_w() * 3563 / 10000, get_h() * 2167 / 10000)),
 	m_label_inputgrab
 		(this,
-		 m_xres * 1969 / 5000, m_yres * 2333 / 10000,
+		 get_w() * 1969 / 5000, get_h() * 2333 / 10000,
 		 _("Grab Input"), UI::Align_VCenter),
 
-	m_music (this, Point(m_xres * 3563 / 10000, m_yres * 2667 / 10000)),
+	m_music (this, Point(get_w() * 3563 / 10000, get_h() * 2667 / 10000)),
 	m_label_music
 		(this,
-		 m_xres * 1969 / 5000, m_yres * 2833 / 10000,
+		 get_w() * 1969 / 5000, get_h() * 2833 / 10000,
 		 _("Enable Music"), UI::Align_VCenter),
 
-	m_fx (this, Point(m_xres * 3563 / 10000, m_yres * 3167 / 10000)),
+	m_fx (this, Point(get_w() * 3563 / 10000, get_h() * 3167 / 10000)),
 	m_label_fx
 		(this,
-		 m_xres * 1969 / 5000, m_yres * 3333 / 10000,
+		 get_w() * 1969 / 5000, get_h() * 3333 / 10000,
 		 _("Enable Sound"), UI::Align_VCenter),
 
 	m_label_maxfps
 		(this,
-		 m_xres * 3563 / 10000, m_yres * 2 / 5,
+		 get_w() * 3563 / 10000, get_h() * 2 / 5,
 		 _("Maximum FPS:"), UI::Align_VCenter),
 
 	m_reslist
 		(this,
-		 m_xres      / 10, m_yres * 1667 / 10000,
-		 m_xres * 19 / 80, m_yres * 2833 / 10000,
+		 get_w()      / 10, get_h() * 1667 / 10000,
+		 get_w() * 19 / 80, get_h() * 2833 / 10000,
 		 UI::Align_Left, true),
 	m_label_resolution
 		(this,
-		 m_xres * 1063 / 10000, m_yres * 1417 / 10000,
+		 get_w() * 1063 / 10000, get_h() * 1417 / 10000,
 		 _("In-game resolution"), UI::Align_VCenter),
 
 	m_label_language
 		(this,
-		 m_xres * 133 / 200, m_yres * 1417 / 10000,
+		 get_w() * 133 / 200, get_h() * 1417 / 10000,
 		 _("Language"), UI::Align_VCenter),
 	m_language_list
 		(this,
-		 m_xres * 6563 / 10000, m_yres * 1667 / 10000,
-		 m_xres *   21 /    80, m_yres * 2833 / 10000,
+		 get_w() * 6563 / 10000, get_h() * 1667 / 10000,
+		 get_w() *   21 /    80, get_h() * 2833 / 10000,
 		 UI::Align_Left, true),
 
 // Title 2
 	m_label_game_options
 		(this,
-		 m_xres / 2, m_yres / 2,
+		 get_w() / 2, get_h() / 2,
 		 _("In-game Options"), UI::Align_HCenter),
 
 // Second options block 'In-game options'
-	m_single_watchwin (this, Point(m_xres * 19 / 200, m_yres * 5833 / 10000)),
+	m_single_watchwin (this, Point(get_w() * 19 / 200, get_h() * 5833 / 10000)),
 	m_label_single_watchwin
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 3 / 5,
+		 get_w() * 1313 / 10000, get_h() * 3 / 5,
 		 _("Use single Watchwindow Mode"), UI::Align_VCenter),
 
-	m_auto_roadbuild_mode (this, Point(m_xres * 19 / 200, m_yres * 63 / 100)),
+	m_auto_roadbuild_mode (this, Point(get_w() * 19 / 200, get_h() * 63 / 100)),
 	m_label_auto_roadbuild_mode
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 6467 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 6467 / 10000,
 		 _("Start roadbuilding after placing flag"), UI::Align_VCenter),
 
 	m_show_workarea_preview
-		(this, Point(m_xres * 19 / 200, m_yres * 6767 / 10000)),
+		(this, Point(get_w() * 19 / 200, get_h() * 6767 / 10000)),
 	m_label_show_workarea_preview
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 6933 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 6933 / 10000,
 		 _("Show buildings area preview"), UI::Align_VCenter),
 
 	m_snap_windows_only_when_overlapping
-		(this, Point(m_xres * 19 / 200, m_yres * 7233 / 10000)),
+		(this, Point(get_w() * 19 / 200, get_h() * 7233 / 10000)),
 	m_label_snap_windows_only_when_overlapping
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 37 / 50,
+		 get_w() * 1313 / 10000, get_h() * 37 / 50,
 		 _("Snap windows only when overlapping"), UI::Align_VCenter),
 
-	m_dock_windows_to_edges (this, Point(m_xres * 19 / 200, m_yres * 77 / 100)),
+	m_dock_windows_to_edges (this, Point(get_w() * 19 / 200, get_h() * 77 / 100)),
 	m_label_dock_windows_to_edges
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 7867 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 7867 / 10000,
 		 _("Dock windows to edges"), UI::Align_VCenter),
 
 	m_label_autosave
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 8333 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 8333 / 10000,
 		 _("Save game automatically every"), UI::Align_VCenter),
 	m_label_remove_replays
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 8799 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 8799 / 10000,
 		 _("Remove Replays older than:"), UI::Align_VCenter),
 
 	os(opt)
 {
+	m_advanced_options.set_font(font_small());
+	m_apply.set_font(font_small());
+	m_cancel.set_font(font_small());
+
 	m_sb_autosave     .add_replacement(0, _("Off"));
 
-	m_sb_maxfps       .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_sb_autosave     .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_sb_remove_replays.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_title           .set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
-	m_label_fullscreen.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_sb_maxfps       .set_font(ui_fn(), fs_small(), UI_FONT_CLR_FG);
+	m_sb_autosave     .set_font(ui_fn(), fs_small(), UI_FONT_CLR_FG);
+	m_sb_remove_replays.set_font(ui_fn(), fs_small(), UI_FONT_CLR_FG);
+	m_title           .set_textstyle(ts_big());
+	m_label_fullscreen.set_textstyle(ts_small());
 	m_fullscreen      .set_state(opt.fullscreen);
-	m_label_inputgrab .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_inputgrab .set_textstyle(ts_small());
 	m_inputgrab       .set_state(opt.inputgrab);
-	m_label_music     .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_music     .set_textstyle(ts_small());
 	m_music           .set_state(opt.music);
 	m_music           .set_enabled(not g_sound_handler.m_lock_audio_disabling);
-	m_label_fx        .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_fx        .set_textstyle(ts_small());
 	m_fx              .set_state(opt.fx);
 	m_fx              .set_enabled(not g_sound_handler.m_lock_audio_disabling);
-	m_label_maxfps    .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_resolution.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_reslist         .set_font(m_fn, m_fs);
-	m_label_language  .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_language_list   .set_font(m_fn, m_fs);
+	m_label_maxfps    .set_textstyle(ts_small());
+	m_label_resolution.set_textstyle(ts_small());
+	m_reslist         .set_font(ui_fn(), fs_small());
+	m_label_language  .set_textstyle(ts_small());
+	m_language_list   .set_font(ui_fn(), fs_small());
 
-	m_label_game_options             .set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
-	m_label_single_watchwin          .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_game_options             .set_textstyle(ts_big());
+	m_label_single_watchwin          .set_textstyle(ts_small());
 	m_single_watchwin                .set_state(opt.single_watchwin);
-	m_label_auto_roadbuild_mode      .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_auto_roadbuild_mode      .set_textstyle(ts_small());
 	m_auto_roadbuild_mode            .set_state(opt.auto_roadbuild_mode);
-	m_label_show_workarea_preview    .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_show_workarea_preview    .set_textstyle(ts_small());
 	m_show_workarea_preview          .set_state(opt.show_warea);
-	m_label_snap_windows_only_when_overlapping.set_font
-		(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_snap_windows_only_when_overlapping.set_textstyle(ts_small());
 	m_snap_windows_only_when_overlapping.set_state
 		(opt.snap_windows_only_when_overlapping);
-	m_label_dock_windows_to_edges    .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_dock_windows_to_edges    .set_textstyle(ts_small());
 	m_dock_windows_to_edges          .set_state(opt.dock_windows_to_edges);
-	m_label_autosave                 .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_remove_replays           .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_autosave                 .set_textstyle(ts_small());
+	m_label_remove_replays           .set_textstyle(ts_small());
 
 	//  GRAPHIC_TODO: this shouldn't be here List all resolutions
 	// take a copy to not change real video info structure
@@ -376,48 +374,44 @@
 	Fullscreen_Menu_Base("optionsmenu.jpg"),
 
 // Values for alignment and size
-	m_vbutw (m_yres * 333 / 10000),
-	m_butw  (m_xres / 4),
-	m_buth  (m_yres * 9 / 200),
-	m_fs    (fs_small()),
-	m_fn    (ui_fn()),
+	m_vbutw (get_h() * 333 / 10000),
+	m_butw  (get_w() / 4),
+	m_buth  (get_h() * 9 / 200),
 
 // Buttons
 	m_cancel
 		(this, "cancel",
-		 m_xres * 41 / 80, m_yres * 19 / 20, m_butw, m_buth,
+		 get_w() * 41 / 80, get_h() * 19 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind
 			(&Fullscreen_Menu_Advanced_Options::end_modal,
 			 boost::ref(*this),
 			 static_cast<int32_t>(om_cancel)),
-		 _("Cancel"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Cancel"), std::string(), true, false),
 	m_apply
 		(this, "apply",
-		 m_xres / 4,   m_yres * 19 / 20, m_butw, m_buth,
+		 get_w() / 4,   get_h() * 19 / 20, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but2.png"),
 		 boost::bind
 			(&Fullscreen_Menu_Advanced_Options::end_modal,
 			 boost::ref(*this),
 			 static_cast<int32_t>(om_ok)),
-		 _("Apply"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Apply"), std::string(), true, false),
 
 // Spinboxes
 	m_sb_speed
 		(this,
-		 m_xres * 18 / 25, m_yres * 63 / 100, m_xres / 4, m_vbutw,
+		 get_w() * 18 / 25, get_h() * 63 / 100, get_w() / 4, m_vbutw,
 		 opt.speed_of_new_game / 1000, 0, 100, _("x"),
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png")),
 	m_sb_dis_panel
 		(this,
-		 m_xres * 18 / 25, m_yres * 6768 / 10000, m_xres / 4, m_vbutw,
+		 get_w() * 18 / 25, get_h() * 6768 / 10000, get_w() / 4, m_vbutw,
 		 opt.panel_snap_distance, 0, 100, _("px."),
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png")),
 	m_sb_dis_border
 		(this,
-		 m_xres * 18 / 25, m_yres * 7235 / 10000, m_xres / 4, m_vbutw,
+		 get_w() * 18 / 25, get_h() * 7235 / 10000, get_w() / 4, m_vbutw,
 		 opt.border_snap_distance, 0, 100, _("px."),
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png")),
 
@@ -425,91 +419,94 @@
 // Title
 	m_title
 		(this,
-		 m_xres / 2, m_yres / 40,
+		 get_w() / 2, get_h() / 40,
 		 _("Advanced Options"), UI::Align_HCenter),
 
 // First options block
 	m_ui_font_list
 		(this,
-		 m_xres / 10, m_yres * 1667 / 10000,
-		 m_xres /  4, m_yres * 2833 / 10000,
+		 get_w() / 10, get_h() * 1667 / 10000,
+		 get_w() /  4, get_h() * 2833 / 10000,
 		 UI::Align_Left, true),
 	m_label_ui_font
 		(this,
-		 m_xres * 1063 / 10000, m_yres * 1417 / 10000,
+		 get_w() * 1063 / 10000, get_h() * 1417 / 10000,
 		 _("Main menu font:"), UI::Align_VCenter),
 	m_message_sound
-		(this, Point(m_xres * 29 / 80, m_yres * 171 / 1000)),
+		(this, Point(get_w() * 29 / 80, get_h() * 171 / 1000)),
 	m_label_message_sound
 		(this,
-		 m_xres * 4 / 10, m_yres * 1883 / 10000,
+		 get_w() * 4 / 10, get_h() * 1883 / 10000,
 		 _("Play a sound at message arrival."),
 		 UI::Align_VCenter),
 
 // Second options block
-	m_nozip (this, Point(m_xres * 19 / 200, m_yres * 5833 / 10000)),
+	m_nozip (this, Point(get_w() * 19 / 200, get_h() * 5833 / 10000)),
 	m_label_nozip
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 3 / 5,
+		 get_w() * 1313 / 10000, get_h() * 3 / 5,
 		 _("Do not zip widelands data files (maps, replays and savegames)."),
 		 UI::Align_VCenter),
 	m_label_speed
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 6467 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 6467 / 10000,
 		 _("Speed of a new game:"), UI::Align_VCenter),
 	m_label_snap_dis_panel
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 6933 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 6933 / 10000,
 		 _("Distance for windows to snap to other panels:"), UI::Align_VCenter),
 	m_label_snap_dis_border
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 37 / 50,
+		 get_w() * 1313 / 10000, get_h() * 37 / 50,
 		 _("Distance for windows to snap to borders:"), UI::Align_VCenter),
 
-	m_remove_syncstreams (this, Point(m_xres * 19 / 200, m_yres * 7715 / 10000)),
+	m_remove_syncstreams (this, Point(get_w() * 19 / 200, get_h() * 7715 / 10000)),
 	m_label_remove_syncstreams
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 7865 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 7865 / 10000,
 		 _("Remove Syncstream dumps on startup"), UI::Align_VCenter),
 
-	m_opengl (this, Point(m_xres * 19 / 200, m_yres * 8180 / 10000)),
+	m_opengl (this, Point(get_w() * 19 / 200, get_h() * 8180 / 10000)),
 	m_label_opengl
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 8330 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 8330 / 10000,
 		 _("OpenGL rendering *Highly experimental!*"), UI::Align_VCenter),
-	m_transparent_chat (this, Point(m_xres * 19 / 200, m_yres * 8645 / 10000)),
+	m_transparent_chat (this, Point(get_w() * 19 / 200, get_h() * 8645 / 10000)),
 	m_label_transparent_chat
 		(this,
-		 m_xres * 1313 / 10000, m_yres * 8795 / 10000,
+		 get_w() * 1313 / 10000, get_h() * 8795 / 10000,
 		 _("Show in game chat with transparent background"), UI::Align_VCenter),
 
 	os(opt)
 {
-	m_title                .set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
-	m_label_message_sound  .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_cancel.set_font(font_small());
+	m_apply.set_font(font_small());
+
+	m_title                .set_textstyle(ts_big());
+	m_label_message_sound  .set_textstyle(ts_small());
 	m_message_sound        .set_state(opt.message_sound);
-	m_label_nozip          .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_nozip          .set_textstyle(ts_small());
 	m_nozip                .set_state(opt.nozip);
-	m_label_speed          .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_snap_dis_border.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_snap_dis_panel .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_label_remove_syncstreams.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_speed          .set_textstyle(ts_small());
+	m_label_snap_dis_border.set_textstyle(ts_small());
+	m_label_snap_dis_panel .set_textstyle(ts_small());
+	m_label_remove_syncstreams.set_textstyle(ts_small());
 	m_remove_syncstreams   .set_state(opt.remove_syncstreams);
-	m_label_opengl         .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_opengl         .set_textstyle(ts_small());
 	m_opengl               .set_state(opt.opengl);
 #ifndef USE_OPENGL
 	m_opengl               .set_enabled(false);
 #endif
-	m_label_transparent_chat.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_label_transparent_chat.set_textstyle(ts_small());
 	m_transparent_chat     .set_state(opt.transparent_chat);
-	m_sb_speed             .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_sb_dis_border        .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_sb_dis_panel         .set_font(m_fn, m_fs, UI_FONT_CLR_FG);
+	m_sb_speed             .set_textstyle(ts_small());
+	m_sb_dis_border        .set_textstyle(ts_small());
+	m_sb_dis_panel         .set_textstyle(ts_small());
 
 	m_sb_speed.add_replacement(0, _("Pause"));
 
-	m_label_ui_font.set_font(m_fn, m_fs, UI_FONT_CLR_FG);
-	m_ui_font_list .set_font(m_fn, m_fs);
+	m_label_ui_font.set_textstyle(ts_small());
+	m_ui_font_list .set_font(ui_fn(), fs_small());
 
 	// Fill the font list.
 	{ // For use of string ui_font take a look at fullscreen_menu_base.cc

=== modified file 'src/ui_fsmenu/options.h'
--- src/ui_fsmenu/options.h	2010-10-17 19:42:01 +0000
+++ src/ui_fsmenu/options.h	2011-01-30 15:33:06 +0000
@@ -93,8 +93,6 @@
 	uint32_t                          m_vbutw;
 	uint32_t                          m_butw;
 	uint32_t                          m_buth;
-	uint32_t                          m_fs;
-	std::string                       m_fn;
 	UI::Callback_Button           m_advanced_options, m_cancel, m_apply;
 	UI::SpinBox                       m_sb_maxfps, m_sb_autosave;
 	UI::SpinBox                       m_sb_remove_replays;
@@ -153,8 +151,6 @@
 	uint32_t                    m_vbutw;
 	uint32_t                    m_butw;
 	uint32_t                    m_buth;
-	uint32_t                    m_fs;
-	std::string                 m_fn;
 
 	UI::Callback_Button     m_cancel, m_apply;
 	UI::SpinBox                 m_sb_speed, m_sb_dis_panel, m_sb_dis_border;

=== modified file 'src/ui_fsmenu/singleplayer.cc'
--- src/ui_fsmenu/singleplayer.cc	2010-11-06 16:31:40 +0000
+++ src/ui_fsmenu/singleplayer.cc	2011-01-30 15:33:06 +0000
@@ -26,56 +26,57 @@
 Fullscreen_Menu_Base("singleplmenu.jpg"),
 
 // Values for alignment and size
-	m_butw (m_xres * 7 / 20),
-	m_buth (m_yres * 19 / 400),
-	m_butx ((m_xres - m_butw) / 2),
+	m_butw (get_w() * 7 / 20),
+	m_buth (get_h() * 19 / 400),
+	m_butx ((get_w() - m_butw) / 2),
 	m_fs   (fs_small()),
 	m_fn   (ui_fn()),
 
 // Title
 	title
 		(this,
-		 m_xres / 2, m_yres * 3 / 40,
+		 get_w() / 2, get_h() * 3 / 40,
 		 _("Single Player Menu"), UI::Align_HCenter),
 
 // Buttons
 	new_game
 		(this, "new_game",
-		 m_butx, m_yres * 6 / 25, m_butw, m_buth,
+		 m_butx, get_h() * 6 / 25, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			(&Fullscreen_Menu_SinglePlayer::end_modal,
 			 boost::ref(*this),
 			 static_cast<int32_t>(New_Game)),
-		 _("New Game"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("New Game"), std::string(), true, false),
 	campaign
 		(this, "campaigns",
-		 m_butx, m_yres * 61 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 61 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			(&Fullscreen_Menu_SinglePlayer::end_modal,
 			 boost::ref(*this),
 			 static_cast<int32_t>(Campaign)),
-		 _("Campaigns"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Campaigns"), std::string(), true, false),
 	load_game
 		(this, "load_game",
-		 m_butx, m_yres * 87 / 200, m_butw, m_buth,
+		 m_butx, get_h() * 87 / 200, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 		 boost::bind
 			(&Fullscreen_Menu_SinglePlayer::end_modal,
 			 boost::ref(*this),
 			 static_cast<int32_t>(Load_Game)),
-		 _("Load Game"), std::string(), true, false,
-		 m_fn, m_fs),
+		 _("Load Game"), std::string(), true, false),
 	back
 		(this, "back",
-		 m_butx, m_yres * 3 / 4, m_butw, m_buth,
+		 m_butx, get_h() * 3 / 4, m_butw, m_buth,
 		 g_gr->get_picture(PicMod_UI, "pics/but0.png"),
 		 boost::bind(&Fullscreen_Menu_SinglePlayer::end_modal, boost::ref(*this), static_cast<int32_t>(Back)),
-		 _("Back"), std::string(), true, false,
-		 m_fn, m_fs)
+		 _("Back"), std::string(), true, false)
 {
+	back.set_font(font_small());
+	new_game.set_font(font_small());
+	campaign.set_font(font_small());
+	load_game.set_font(font_small());
+
 	title.set_font(m_fn, fs_big(), UI_FONT_CLR_FG);
 }

=== modified file 'src/wui/attack_box.cc'
--- src/wui/attack_box.cc	2010-10-17 19:42:01 +0000
+++ src/wui/attack_box.cc	2011-01-30 15:33:06 +0000
@@ -96,7 +96,11 @@
 	 uint32_t      fontsize)
 {
 	UI::Textarea & result = *new UI::Textarea(&parent, str.c_str());
-	result.set_font(fontname, fontsize, UI_FONT_CLR_FG);
+	UI::TextStyle textstyle;
+	textstyle.font = UI::Font::get(fontname, fontsize);
+	textstyle.bold = true;
+	textstyle.fg = UI_FONT_CLR_FG;
+	result.set_textstyle(textstyle);
 	parent.add(&result, alignment);
 	return result;
 }

=== modified file 'src/wui/bulldozeconfirm.cc'
--- src/wui/bulldozeconfirm.cc	2010-05-16 15:56:35 +0000
+++ src/wui/bulldozeconfirm.cc	2011-01-30 15:33:06 +0000
@@ -22,7 +22,7 @@
 #include "interactive_player.h"
 #include "logic/building.h"
 #include "logic/player.h"
-#include "ui_basic/textarea.h"
+#include "ui_basic/multilinetextarea.h"
 #include "ui_basic/window.h"
 #include "upcast.h"
 
@@ -50,16 +50,15 @@
 	Widelands::Object_Ptr m_building;
 	Widelands::Object_Ptr m_todestroy;
 
-	struct Message : public UI::Textarea {
+	struct Message : public UI::Multiline_Textarea {
 		Message(BulldozeConfirm & parent, Widelands::Building const & building) :
-			UI::Textarea
+			UI::Multiline_Textarea
 				(&parent,
 				 0, 0, 200, 74,
 				 (format(_("Do you really want to destroy this %s?"))
 				  % building.descname())
 				 	.str(),
-				 UI::Align_Center,
-				 true)
+				 UI::Align_Center)
 		{}
 	} m_message;
 

=== modified file 'src/wui/game_tips.cc'
--- src/wui/game_tips.cc	2010-05-12 10:16:44 +0000
+++ src/wui/game_tips.cc	2011-01-30 15:33:06 +0000
@@ -21,6 +21,7 @@
 
 #include "constants.h"
 #include "io/fileread.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/rendertarget.h"
 #include "i18n.h"
@@ -241,10 +242,12 @@
 	text_area.h -= m_pading_t + m_pading_b;
 	Point center(text_area.x + text_area.w / 2, text_area.y + text_area.h / 2);
 
-	UI::g_fh->draw_string
-		(rt, UI_FONT_NAME, m_font_size,
-		 m_color, m_bgcolor, //RGBColor(107, 87, 55),
-		 center, m_tips[index].text,
-		 UI::Align_Center, text_area.w);
+	UI::TextStyle ts;
+	ts.font = UI::Font::get(UI_FONT_NAME, m_font_size);
+	ts.fg = m_color;
+	ts.bold = true;
+
+	UI::g_fh->draw_multiline
+		(rt, ts, center, m_tips[index].text, UI::Align_Center, text_area.w);
 	g_gr->update_rectangle(tips_area);
 }

=== modified file 'src/wui/interactive_base.cc'
--- src/wui/interactive_base.cc	2010-11-21 11:44:22 +0000
+++ src/wui/interactive_base.cc	2011-01-30 15:33:06 +0000
@@ -23,6 +23,7 @@
 #include "constants.h"
 #include "economy/flag.h"
 #include "economy/road.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "game_chat_menu.h"
 #include "game_debug_ui.h"
@@ -362,8 +363,8 @@
 		char buf[100];
 
 		snprintf(buf, sizeof(buf), "%3i %3i", m_sel.pos.node.x, m_sel.pos.node.y);
-		UI::g_fh->draw_string
-			(dst, UI_FONT_BIG, UI_FONT_BIG_CLR, Point(5, 5), buf, UI::Align_Left);
+		UI::g_fh->draw_text
+			(dst, UI::TextStyle::ui_big(), Point(5, 5), buf, UI::Align_Left);
 		assert(m_sel.pos.triangle.t < 2);
 		const char * const triangle_string[] = {"down", "right"};
 		snprintf
@@ -371,9 +372,8 @@
 			 "%3i %3i %s",
 			 m_sel.pos.triangle.x, m_sel.pos.triangle.y,
 			 triangle_string[m_sel.pos.triangle.t]);
-		UI::g_fh->draw_string
-			(dst,
-			 UI_FONT_BIG, UI_FONT_BIG_CLR,
+		UI::g_fh->draw_text
+			(dst, UI::TextStyle::ui_big(),
 			 Point(5, 25),
 			 buf, UI::Align_Left);
 	}
@@ -385,9 +385,8 @@
 			(buffer, sizeof(buffer),
 			 "%5.1f fps (avg: %5.1f fps)",
 			 1000.0 / m_frametime, 1000.0 / (m_avg_usframetime / 1000));
-		UI::g_fh->draw_string
-			(dst,
-			 UI_FONT_BIG, UI_FONT_BIG_CLR,
+		UI::g_fh->draw_text
+			(dst, UI::TextStyle::ui_big(),
 			 Point(85, 5),
 			 buffer, UI::Align_Left);
 	}

=== modified file 'src/wui/military_box.cc'
--- src/wui/military_box.cc	2010-11-05 19:36:57 +0000
+++ src/wui/military_box.cc	2011-01-30 15:33:06 +0000
@@ -78,7 +78,7 @@
 	 uint32_t      fontsize)
 {
 	UI::Textarea & result = *new UI::Textarea(&parent, 0, 0, str.c_str());
-	result.set_font(fontname, fontsize, UI_FONT_CLR_FG);
+	result.set_textstyle(UI::TextStyle::makebold(UI::Font::get(fontname, fontsize), UI_FONT_CLR_FG));
 	parent.add(&result, alignment);
 	return result;
 }

=== modified file 'src/wui/multiplayersetupgroup.cc'
--- src/wui/multiplayersetupgroup.cc	2010-12-30 17:01:47 +0000
+++ src/wui/multiplayersetupgroup.cc	2011-01-30 15:33:06 +0000
@@ -40,7 +40,7 @@
 		(UI::Panel            * const parent, uint8_t id,
 		 int32_t const x, int32_t const y, int32_t const w, int32_t const h,
 		 GameSettingsProvider * const settings,
-		 std::string const & fname, uint32_t const fsize)
+		 UI::Font * font)
 		 :
 		 UI::Box(parent, 0, 0, UI::Box::Horizontal, w, h),
 		 type_icon(0),
@@ -52,7 +52,7 @@
 		set_size(w, h);
 		name = new UI::Textarea
 			(this, 0, 0, w - h - UI::Scrollbar::Size * 11 / 5, h);
-		name->set_font(fname, fsize, UI_FONT_CLR_FG);
+		name->set_textstyle(UI::TextStyle::makebold(font, UI_FONT_CLR_FG));
 		add(name, UI::Box::AlignCenter);
 		// Either Button if changeable OR text if not
 		if (id == settings->settings().usernum) { // Our Client
@@ -62,7 +62,8 @@
 				 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 				 boost::bind
 					 (&MultiPlayerClientGroup::toggle_type, boost::ref(*this)),
-				 std::string(), std::string(), true, false, fname, fsize);
+				 std::string(), std::string(), true, false);
+			type->set_font(font);
 			add(type, UI::Box::AlignCenter);
 		} else { // just a shown client
 			type_icon = new UI::Icon
@@ -143,7 +144,7 @@
 		(UI::Panel            * const parent, uint8_t id,
 		 int32_t const x, int32_t const y, int32_t const w, int32_t const h,
 		 GameSettingsProvider * const settings,
-		 std::string const & fname, uint32_t const fsize,
+		 UI::Font * font,
 		 std::map<std::string, PictureID> & tp,
 		 std::map<std::string, std::string> & tn)
 		 :
@@ -170,7 +171,8 @@
 			 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 			 boost::bind
 				 (&MultiPlayerPlayerGroup::toggle_type, boost::ref(*this)),
-			 std::string(), std::string(), true, false, fname, fsize);
+			 std::string(), std::string(), true, false);
+		type->set_font(font);
 		add(type, UI::Box::AlignCenter);
 		tribe = new UI::Callback_Button
 			(this, "player_tribe",
@@ -178,7 +180,8 @@
 			 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 			 boost::bind
 				 (&MultiPlayerPlayerGroup::toggle_tribe, boost::ref(*this)),
-			 std::string(), std::string(), true, false, fname, fsize);
+			 std::string(), std::string(), true, false);
+		tribe->set_font(font);
 		add(tribe, UI::Box::AlignCenter);
 		tribe->set_draw_flat_background(true);
 		init = new UI::Callback_Button
@@ -187,7 +190,8 @@
 			 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 			 boost::bind
 				 (&MultiPlayerPlayerGroup::toggle_init, boost::ref(*this)),
-			 std::string(), std::string(), true, false, fname, fsize);
+			 std::string(), std::string(), true, false);
+		init->set_font(font);
 		add(init, UI::Box::AlignCenter);
 		team = new UI::Callback_Button
 			(this, "player_team",
@@ -195,7 +199,8 @@
 			 g_gr->get_picture(PicMod_UI, "pics/but1.png"),
 			 boost::bind
 				 (&MultiPlayerPlayerGroup::toggle_team, boost::ref(*this)),
-			 std::string(), std::string(), true, false, fname, fsize);
+			 std::string(), std::string(), true, false);
+		team->set_font(font);
 		add(team, UI::Box::AlignCenter);
 	}
 
@@ -467,6 +472,8 @@
 m_fsize(fsize),
 m_fname(fname)
 {
+	UI::TextStyle tsmaller(UI::TextStyle::makebold(UI::Font::get(fname, fsize * 3 / 4), UI_FONT_CLR_FG));
+
 	// Clientbox and labels
 	labels.push_back
 		(new UI::Textarea
@@ -474,7 +481,7 @@
 			 UI::Scrollbar::Size * 6 / 5, buth / 3,
 			 w / 3 - buth - UI::Scrollbar::Size * 2, buth));
 	labels.back()->set_text(_("Client name"));
-	labels.back()->set_font(fname, fsize * 3 / 4, UI_FONT_CLR_FG);
+	labels.back()->set_textstyle(tsmaller);
 
 	labels.push_back
 		(new UI::Textarea
@@ -482,7 +489,7 @@
 			 w / 3 - buth - UI::Scrollbar::Size * 6 / 5, buth / 3,
 			 buth * 2, buth));
 	labels.back()->set_text(_("Role"));
-	labels.back()->set_font(fname, fsize * 3 / 4, UI_FONT_CLR_FG);
+	labels.back()->set_textstyle(tsmaller);
 
 	clientbox.set_size(w / 3, h - buth);
 	clientbox.set_scrolling(true);
@@ -498,7 +505,7 @@
 			 w * 6 / 15, buth / 3,
 			 buth, buth));
 	labels.back()->set_text(_("Start"));
-	labels.back()->set_font(fname, fsize * 3 / 4, UI_FONT_CLR_FG);
+	labels.back()->set_textstyle(tsmaller);
 
 	labels.push_back
 		(new UI::Textarea
@@ -506,7 +513,7 @@
 			 w * 6 / 15 + buth, buth / 3,
 			 buth, buth));
 	labels.back()->set_text(_("Type"));
-	labels.back()->set_font(fname, fsize * 3 / 4, UI_FONT_CLR_FG);
+	labels.back()->set_textstyle(tsmaller);
 
 	labels.push_back
 		(new UI::Textarea
@@ -514,7 +521,7 @@
 			 w * 6 / 15 + buth * 2, buth / 3,
 			 buth, buth));
 	labels.back()->set_text(_("Tribe"));
-	labels.back()->set_font(fname, fsize * 3 / 4, UI_FONT_CLR_FG);
+	labels.back()->set_textstyle(tsmaller);
 
 	labels.push_back
 		(new UI::Textarea
@@ -522,11 +529,11 @@
 			 w * 6 / 15 + buth * 3, buth / 3,
 			 w * 9 / 15 - 4 * buth, buth));
 	labels.back()->set_text(_("Initialization"));
-	labels.back()->set_font(fname, fsize * 3 / 4, UI_FONT_CLR_FG);
+	labels.back()->set_textstyle(tsmaller);
 
 	labels.push_back(new UI::Textarea(this, w - buth, buth / 3, buth, buth));
 	labels.back()->set_text(_("Team"));
-	labels.back()->set_font(fname, fsize * 3 / 4, UI_FONT_CLR_FG);
+	labels.back()->set_textstyle(tsmaller);
 
 	playerbox.set_size(w * 9 / 15, h - buth);
 	p.resize(MAX_PLAYERS);
@@ -534,7 +541,7 @@
 		p.at(i) = new MultiPlayerPlayerGroup
 			(&playerbox, i,
 			 0, 0, playerbox.get_w(), buth,
-			 s, fname, fsize,
+			 s, UI::Font::get(fname, fsize),
 			 m_tribepics, m_tribenames);
 		playerbox.add(&*p.at(i), 1);
 	}
@@ -563,7 +570,7 @@
 			c.at(i) = new MultiPlayerClientGroup
 				(&clientbox, i,
 				 0, 0, clientbox.get_w(), m_buth,
-				 s, m_fname, m_fsize);
+				 s, UI::Font::get(m_fname, m_fsize));
 			clientbox.add(&*c.at(i), 1);
 		}
 		c.at(i)->refresh();

=== modified file 'src/wui/playerdescrgroup.cc'
--- src/wui/playerdescrgroup.cc	2010-10-31 02:05:52 +0000
+++ src/wui/playerdescrgroup.cc	2011-01-30 15:33:06 +0000
@@ -49,7 +49,7 @@
 	 int32_t const x, int32_t const y, int32_t const w, int32_t const h,
 	 GameSettingsProvider * const settings,
 	 uint32_t               const plnum,
-	 std::string const & fname, uint32_t const fsize)
+	 UI::Font * font)
 :
 UI::Panel(parent, x, y, w, h),
 d(new PlayerDescriptionGroupImpl)
@@ -63,7 +63,7 @@
 	int32_t xplayertribe = w * 60 / 125;
 	int32_t xplayerinit = w * 85 / 125;
 	d->plr_name = new UI::Textarea(this, xplrname, 0, xplayertype - xplrname, h);
-	d->plr_name->set_font(fname, fsize, UI_FONT_CLR_FG);
+	d->plr_name->set_textstyle(UI::TextStyle::makebold(font, UI_FONT_CLR_FG));
 	d->btnEnablePlayer = new UI::Checkbox(this, Point(xplayertype - 23, 0));
 	d->btnEnablePlayer->changedto.set
 		(this, &PlayerDescriptionGroup::enable_player);
@@ -74,8 +74,8 @@
 		 boost::bind
 			 (&PlayerDescriptionGroup::toggle_playertype, boost::ref(*this)),
 		 std::string(), std::string(),
-		 true, false,
-		 fname, fsize);
+		 true, false);
+	d->btnPlayerType->set_font(font);
 	d->btnPlayerTeam = new UI::Callback_Button
 		(this, "player_team",
 		 xplayerteam, 0, xplayertribe - xplayerteam - 2, h,
@@ -83,8 +83,8 @@
 		 boost::bind
 			 (&PlayerDescriptionGroup::toggle_playerteam, boost::ref(*this)),
 		 std::string(), std::string(),
-		 true, false,
-		 fname, fsize);
+		 true, false);
+	d->btnPlayerTeam->set_font(font);
 	d->btnPlayerTribe = new UI::Callback_Button
 		(this, "player_tribe",
 		 xplayertribe, 0, xplayerinit - xplayertribe - 2, h,
@@ -92,8 +92,8 @@
 		 boost::bind
 			 (&PlayerDescriptionGroup::toggle_playertribe, boost::ref(*this)),
 		 std::string(), std::string(),
-		 true, false,
-		 fname, fsize);
+		 true, false);
+	d->btnPlayerTribe->set_font(font);
 	d->btnPlayerInit = new UI::Callback_Button
 		(this, "player_initialization",
 		 xplayerinit, 0, w - xplayerinit, h,
@@ -101,8 +101,8 @@
 		 boost::bind
 			 (&PlayerDescriptionGroup::toggle_playerinit, boost::ref(*this)),
 		 std::string(), _("Initialization"),
-		 true, false,
-		 fname, fsize);
+		 true, false);
+	d->btnPlayerInit->set_font(font);
 
 	refresh();
 }

=== modified file 'src/wui/playerdescrgroup.h'
--- src/wui/playerdescrgroup.h	2010-11-05 19:36:57 +0000
+++ src/wui/playerdescrgroup.h	2011-01-30 15:33:06 +0000
@@ -25,8 +25,11 @@
 
 #include <string>
 
+namespace UI {
+struct Font;
+}
+
 struct GameSettingsProvider;
-
 struct PlayerDescriptionGroupImpl;
 
 /** class PlayerDescriptionGroup
@@ -40,8 +43,7 @@
 		 int32_t x, int32_t y, int32_t w, int32_t h,
 		 GameSettingsProvider * settings,
 		 uint32_t plnum,
-		 std::string const & fname = UI_FONT_NAME,
-		 uint32_t fsize = UI_FONT_SIZE_SMALL);
+		 UI::Font * font);
 	~PlayerDescriptionGroup();
 
 	void refresh();

=== modified file 'src/wui/plot_area.cc'
--- src/wui/plot_area.cc	2010-11-27 13:30:37 +0000
+++ src/wui/plot_area.cc	2011-01-30 15:33:06 +0000
@@ -20,6 +20,7 @@
 #include "plot_area.h"
 
 #include "constants.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "graphic/graphic.h"
 #include "graphic/rendertarget.h"
@@ -119,6 +120,9 @@
 	//  No Arrow here, since this doesn't continue.
 
 	//  draw xticks
+	UI::TextStyle xtickstyle(UI::TextStyle::ui_small());
+	xtickstyle.fg = RGBColor(255, 0, 0);
+
 	float sub = xline_length / how_many_ticks[m_time];
 	float posx = get_inner_w() - space_at_right;
 	char buffer[200];
@@ -132,20 +136,13 @@
 			(buffer, sizeof(buffer),
 			 "%u", max_x[m_time] / how_many_ticks[m_time] * i);
 
-		UI::g_fh->draw_string
-			(dst,
-			 UI_FONT_SMALL,
-			 RGBColor(255, 0, 0), RGBColor(255, 255, 255),
+		UI::g_fh->draw_text
+			(dst, xtickstyle,
 			 Point
 			 	(static_cast<int32_t>(posx),
 			 	 get_inner_h() - space_at_bottom + 4),
 			 buffer,
-			 UI::Align_Center,
-			 std::numeric_limits<uint32_t>::max(),
-			 UI::Widget_Cache_None,
-			 0,
-			 std::numeric_limits<uint32_t>::max(),
-			 false);
+			 UI::Align_Center);
 		posx -= sub;
 	}
 
@@ -200,18 +197,13 @@
 
 	//  print the maximal value
 	sprintf(buffer, "%u", max);
-	UI::g_fh->draw_string
-		(dst,
-		 UI_FONT_SMALL,
-		 RGBColor(120, 255, 0), RGBColor(255, 255, 255),
+	UI::TextStyle ymarkstyle(UI::TextStyle::ui_small());
+	ymarkstyle.fg = RGBColor(120, 255, 0);
+
+	UI::g_fh->draw_text
+		(dst, ymarkstyle,
 		 Point(get_inner_w() - space_at_right - 2, spacing),
-		 buffer,
-		 UI::Align_CenterRight,
-		 std::numeric_limits<uint32_t>::max(),
-		 UI::Widget_Cache_None,
-		 0,
-		 std::numeric_limits<uint32_t>::max(),
-		 false);
+		 buffer, UI::Align_CenterRight);
 
 	//  plot the pixels
 	sub =

=== modified file 'src/wui/waresdisplay.cc'
--- src/wui/waresdisplay.cc	2010-12-11 15:49:49 +0000
+++ src/wui/waresdisplay.cc	2011-01-30 15:33:06 +0000
@@ -20,9 +20,11 @@
 #include "waresdisplay.h"
 
 #include "logic/editor_game_base.h"
+#include "graphic/font.h"
 #include "graphic/font_handler.h"
 #include "i18n.h"
 #include "logic/player.h"
+#include "graphic/font.h"
 #include "graphic/rendertarget.h"
 #include "logic/tribe.h"
 #include "logic/worker.h"
@@ -225,10 +227,8 @@
 		(Rect(pos + Point(0, WARE_MENU_PIC_HEIGHT), WARE_MENU_PIC_WIDTH, 8),
 		 RGBColor(0, 0, 0));
 
-	UI::g_fh->draw_string
-		(dst,
-		 UI_FONT_ULTRASMALL,
-		 UI_FONT_SMALL_CLR,
+	UI::g_fh->draw_text
+		(dst, UI::TextStyle::ui_ultrasmall(),
 		 p + Point(WARE_MENU_PIC_WIDTH, WARE_MENU_PIC_HEIGHT - 4),
 		 info_for_ware(id),
 		 UI::Align_Right);


Follow ups