continued with localization

This commit is contained in:
Magnus Auvinen 2009-06-15 06:45:44 +00:00
parent bc20e9c433
commit 6309d7ad56
13 changed files with 1075 additions and 58 deletions

View file

@ -7,6 +7,9 @@ Fullscreen
Loading
== Laddar
Ping
== Ping
Next Weapon:
== Nästa vapen:
@ -19,6 +22,9 @@ Use sounds
Body
== Kropp
Ping:
== Ping:
Show name plates
== Visa namnskyltar
@ -37,14 +43,20 @@ Ok
Call Vote
== Starta omröstning
LAN
== LAN
Favorite
== Favorit
Try again
== Försök igen
Refresh
== Uppdatera
FSAA samples
== FSAA samplingar
Hammer:
== Hammare:
No servers match your filter criteria
== Inga servrar matchar dina filter kriterer
Welcome to Teeworlds
== Välkommen till Teeworlds
@ -55,24 +67,42 @@ Voting
Sat.
== Mättnad
Try again
== Försök igen
LAN
== LAN
Prev. Weapon:
== Föregående vapen:
Standard gametype
== Standard speltyp
Skins
== Utseende
Quit
== Avsluta
Controls
== Kontroller
Has people playing
== Har folk som spelar
Version:
== Version:
Dynamic Camera
== Dynamisk kamera
Remote Console:
== Serverkonsol:
Type
== Typ
Disconnected
== Frånkopplad
Feet
== Fötter
Show only supported
== Visa endast upplösningar som stöds
@ -88,12 +118,27 @@ Game
Screenshot:
== Skärmdump
Teeworlds %s is out! Download it at www.teeworlds.com!
== Teeworld %s är släppt! Ladda ner det på www.teeworlds.com!
Grenade:
== Granater:
Connect
== Anslut
Info
== Info
No password
== Inget lösenord
Team Chat:
== Lagchatt:
Refreshing master servers
== Uppdaterar huvudservrar
Settings
== Inställningar
@ -103,6 +148,9 @@ Custom colors
Emoticon:
== Känsloikon
Server details:
== Server detaljer:
Shotgun:
== Hagelgevär:
@ -133,6 +181,9 @@ High Detail
No
== Nej
Reset filter
== Återställ filter
Mute when not active
== Stäng av ljudet när spelet inte är aktivt
@ -160,29 +211,47 @@ Rifle:
Switch weapon on pickup
== Byt vapen vid upplock
Compatible version
== Kompatibel version
Standard map
== Standard karta
Fire:
== Skjuta:
Host address:
== Serveraddress
Weapon
== Vapen
Display Modes
== Skärmlägen
Filter
== Filter
Move Right:
== Gå höger
Controls
== Kontroller
Lht.
== Ljusstyrka
Server not full
== Inte full server
Chat:
== Chatt:
Remote Console:
== Serverkonsol:
Quick search:
== Snabbsök:
Feet
== Fötter
%d of %d servers, %d players
== %d av %d servrar, %d spelare
Demos
== Demon
@ -211,6 +280,9 @@ Current
Hook:
== Haken:
Map
== Karta
Texture Compression
== Texturkompression
@ -229,12 +301,21 @@ Alpha
Name:
== Namn:
Disconnected
== Frånkopplad
Game types:
== Speltyper:
Name
== Namn
You must restart the game for all settings to take effect.
== Du måste starta om spelet för att ändringarna skall gälla.
Maximum ping
== Högsta ping
Players
== Spelare
Downloading map
== Laddar ner karta
@ -244,12 +325,18 @@ Enter
Jump:
== Hoppa:
Game Type:
== Speltyp:
Password:
== Lösenord:
Player
== Spelare
Hammer:
== Hammare:
Vote Yes:
== Rösta ja:
@ -261,8 +348,20 @@ Pistol:
##### needs translation ####
Progression:
==
The server is running a non-standard tuning on a pure game mode.
==
N/A
==
Current version: %s
==
No servers found
==
##### old translations ####

135
src/base/tl/algorithms.hpp Normal file
View file

@ -0,0 +1,135 @@
#ifndef TL_FILE_ALGORITHMS_HPP
#define TL_FILE_ALGORITHMS_HPP
#include "range.hpp"
/*
insert 4
v
1 2 3 4 5 6
*/
template<class R, class T>
R partition_linear(R range, T value)
{
concept_empty::check(range);
concept_forwarditeration::check(range);
concept_sorted::check(range);
for(; !range.empty(); range.pop_front())
{
if(!(range.front() < value))
return range;
}
return range;
}
template<class R, class T>
R partition_binary(R range, T value)
{
concept_empty::check(range);
concept_index::check(range);
concept_size::check(range);
concept_slice::check(range);
concept_sorted::check(range);
if(range.empty())
return range;
if(range.back() < value)
return R();
while(range.size() > 1)
{
unsigned pivot = (range.size()-1)/2;
if(range.index(pivot) < value)
range = range.slice(pivot+1, range.size()-1);
else
range = range.slice(0, pivot+1);
}
return range;
}
template<class R, class T>
R find_linear(R range, T value)
{
concept_empty::check(range);
concept_forwarditeration::check(range);
for(; !range.empty(); range.pop_front())
if(value < range.front())
break;
return range;
}
template<class R, class T>
R find_binary(R range, T value)
{
range = partition_linear(range, value);
if(range.empty()) return range;
if(range.front() == value) return range;
return R();
}
template<class R>
void sort_bubble(R range)
{
concept_empty::check(range);
concept_forwarditeration::check(range);
concept_backwarditeration::check(range);
// slow bubblesort :/
for(; !range.empty(); range.pop_back())
{
R section = range;
typename R::type *prev = &section.front();
section.pop_front();
for(; !section.empty(); section.pop_front())
{
typename R::type *cur = &section.front();
if(*cur < *prev)
swap(*cur, *prev);
prev = cur;
}
}
}
/*
template<class R>
void sort_quick(R range)
{
concept_index::check(range);
}*/
template<class R>
void sort(R range)
{
sort_bubble(range);
}
template<class R>
bool sort_verify(R range)
{
concept_empty::check(range);
concept_forwarditeration::check(range);
typename R::type *prev = &range.front();
range.pop_front();
for(; !range.empty(); range.pop_front())
{
typename R::type *cur = &range.front();
if(*cur < *prev)
return false;
prev = cur;
}
return true;
}
#endif // TL_FILE_ALGORITHMS_HPP

15
src/base/tl/allocator.hpp Normal file
View file

@ -0,0 +1,15 @@
#ifndef TL_FILE_ALLOCATOR_HPP
#define TL_FILE_ALLOCATOR_HPP
template <class T>
class allocator_default
{
public:
static T *alloc() { return new T; }
static void free(T *p) { delete p; }
static T *alloc_array(int size) { return new T [size]; }
static void free_array(T *p) { delete [] p; }
};
#endif // TL_FILE_ALLOCATOR_HPP

341
src/base/tl/array.hpp Normal file
View file

@ -0,0 +1,341 @@
#ifndef TL_FILE_ARRAY_HPP
#define TL_FILE_ARRAY_HPP
#include "range.hpp"
#include "allocator.hpp"
/*
Class: array
Normal dynamic array class
Remarks:
- Grows 50% each time it needs to fit new items
- Use set_size() if you know how many elements
- Use optimize() to reduce the needed space.
*/
template <class T, class ALLOCATOR = allocator_default<T> >
class array : private ALLOCATOR
{
void init()
{
list = 0x0;
clear();
}
public:
typedef plain_range<T> range;
/*
Function: array constructor
*/
array()
{
init();
}
/*
Function: array copy constructor
*/
array(const array &other)
{
init();
set_size(other.size());
for(int i = 0; i < size(); i++)
(*this)[i] = other[i];
}
/*
Function: array destructor
*/
~array()
{
ALLOCATOR::free_array(list);
list = 0x0;
}
/*
Function: delete_all
Remarks:
- Invalidates ranges
*/
void delete_all()
{
for(int i = 0; i < size(); i++)
delete list[i];
clear();
}
/*
Function: clear
Remarks:
- Invalidates ranges
*/
void clear()
{
ALLOCATOR::free_array(list);
list_size = 1;
list = ALLOCATOR::alloc_array(list_size);
num_elements = 0;
}
/*
Function: size
*/
int size() const
{
return num_elements;
}
/*
Function: remove_index_fast
Remarks:
- Invalidates ranges
*/
void remove_index_fast(int index)
{
list[index] = list[num_elements-1];
set_size(size()-1);
}
/*
Function: remove_fast
Remarks:
- Invalidates ranges
*/
void remove_fast(const T& item)
{
for(int i = 0; i < size(); i++)
if(list[i] == item)
{
remove_index_fast(i);
return;
}
}
/*
Function: remove_index
Remarks:
- Invalidates ranges
*/
void remove_index(int index)
{
for(int i = index+1; i < num_elements; i++)
list[i-1] = list[i];
set_size(size()-1);
}
/*
Function: remove
Remarks:
- Invalidates ranges
*/
bool remove(const T& item)
{
for(int i = 0; i < size(); i++)
if(list[i] == item)
{
remove_index(i);
return true;
}
return false;
}
/*
Function: add
Adds an item to the array.
Arguments:
item - Item to add.
Remarks:
- Invalidates ranges
- See remarks about <array> how the array grows.
*/
int add(const T& item)
{
incsize();
set_size(size()+1);
list[num_elements-1] = item;
return num_elements-1;
}
/*
Function: insert
Inserts an item into the array at a specified location.
Arguments:
item - Item to insert.
r - Range where to insert the item
Remarks:
- Invalidates ranges
- See remarks about <array> how the array grows.
*/
int insert(const T& item, range r)
{
if(r.empty())
return add(item);
int index = (int)(&r.front()-list);
incsize();
set_size(size()+1);
for(int i = num_elements-1; i > index; i--)
list[i] = list[i-1];
list[index] = item;
return num_elements-1;
}
/*
Function: operator[]
*/
T& operator[] (int index)
{
return list[index];
}
/*
Function: const operator[]
*/
const T& operator[] (int index) const
{
return list[index];
}
/*
Function: base_ptr
*/
T *base_ptr()
{
return list;
}
/*
Function: base_ptr
*/
const T *base_ptr() const
{
return list;
}
/*
Function: set_size
Resizes the array to the specified size.
Arguments:
new_size - The new size for the array.
*/
void set_size(int new_size)
{
alloc(new_size);
num_elements = new_size;
}
/*
Function: hint_size
Allocates the number of elements wanted but
does not increase the list size.
Arguments:
hint - Size to allocate.
Remarks:
- If the hint is smaller then the number of elements, nothing will be done.
- Invalidates ranges
*/
void hint_size(int hint)
{
if(num_elements < hint)
alloc(hint);
}
/*
Function: optimize
Removes unnessasary data, returns how many bytes was earned.
Remarks:
- Invalidates ranges
*/
int optimize()
{
int before = memusage();
alloc(num_elements);
return before - memusage();
}
/*
Function: memusage
Returns how much memory this dynamic array is using
*/
int memusage()
{
return sizeof(array) + sizeof(T)*size;
}
/*
Function: operator=(array)
Remarks:
- Invalidates ranges
*/
array &operator = (const array &other)
{
set_size(other.size());
for(int i = 0; i < size(); i++)
(*this)[i] = other[i];
return *this;
}
/*
Function: all
Returns a range that contains the whole array.
*/
range all() { return range(list, list+num_elements); }
protected:
void incsize()
{
if(num_elements == list_size)
{
if(list_size < 2)
alloc(list_size+1);
else
alloc(list_size+list_size/2);
}
}
void alloc(int new_len)
{
list_size = new_len;
T *new_list = ALLOCATOR::alloc_array(list_size);
int end = num_elements < list_size ? num_elements : list_size;
for(int i = 0; i < end; i++)
new_list[i] = list[i];
ALLOCATOR::free_array(list);
num_elements = num_elements < list_size ? num_elements : list_size;
list = new_list;
}
T *list;
int list_size;
int num_elements;
};
#endif // TL_FILE_ARRAY_HPP

15
src/base/tl/base.hpp Normal file
View file

@ -0,0 +1,15 @@
#include <base/system.h>
inline void assert(bool statement)
{
dbg_assert(statement, "assert!");
}
template<class T>
inline void swap(T &a, T &b)
{
T c = b;
b = a;
a = c;
}

230
src/base/tl/range.hpp Normal file
View file

@ -0,0 +1,230 @@
#ifndef __RANGE_H
#define __RANGE_H
/*
Group: Range concepts
*/
/*
Concept: concept_empty
template<class T>
struct range
{
bool empty() const;
};
*/
struct concept_empty
{
template<typename T> static void check(T &t) { if(0) t.empty(); };
};
/*
Concept: concept_index
template<class T>
struct range
{
T &index(size_t);
};
*/
struct concept_index
{
template<typename T> static void check(T &t) { if(0) t.index(0); };
};
/*
Concept: concept_size
template<class T>
struct range
{
size_t size();
};
*/
struct concept_size
{
template<typename T> static void check(T &t) { if(0) t.size(); };
};
/*
Concept: concept_slice
template<class T>
struct range
{
range slice(size_t start, size_t count);
};
*/
struct concept_slice
{
template<typename T> static void check(T &t) { if(0) t.slice(0, 0); };
};
/*
Concept: concept_sorted
template<class T>
struct range
{
void sorted();
};
*/
struct concept_sorted
{
template<typename T> static void check(T &t) { if(0) t.sorted(); };
};
/*
Concept: concept_forwarditeration
Checks for the front and pop_front methods
template<class T>
struct range
{
void pop_front();
T &front() const;
};
*/
struct concept_forwarditeration
{
template<typename T> static void check(T &t) { if(0) { t.front(); t.pop_front(); } };
};
/*
Concept: concept_backwarditeration
Checks for the back and pop_back methods
template<class T>
struct range
{
void pop_back();
T &back() const;
};
*/
struct concept_backwarditeration
{
template<typename T> static void check(T &t) { if(0) { t.back(); t.pop_back(); } };
};
/*
Group: Range classes
*/
/*
Class: plain_range
Concepts:
<concept_empty>
<concept_index>
<concept_slice>
<concept_forwardinteration>
<concept_backwardinteration>
*/
template<class T>
class plain_range
{
public:
typedef T type;
plain_range()
{
begin = 0x0;
end = 0x0;
}
plain_range(const plain_range &r)
{
*this = r;
}
plain_range(T *b, T *e)
{
begin = b;
end = e;
}
bool empty() const { return begin >= end; }
void pop_front() { assert(!empty()); begin++; }
void pop_back() { assert(!empty()); end--; }
T& front() { assert(!empty()); return *begin; }
T& back() { assert(!empty()); return *(end-1); }
T& index(unsigned i) { assert(i >= 0 && i < (unsigned)(end-begin)); return begin[i]; }
unsigned size() const { return (unsigned)(end-begin); }
plain_range slice(unsigned startindex, unsigned endindex)
{
return plain_range(begin+startindex, begin+endindex);
}
protected:
T *begin;
T *end;
};
/*
Class: plain_range_sorted
Concepts:
Same as <plain_range> but with these additions:
<concept_sorted>
*/
template<class T>
class plain_range_sorted : public plain_range<T>
{
typedef plain_range<T> parent;
public:
/* sorted concept */
void sorted() const { }
plain_range_sorted()
{}
plain_range_sorted(const plain_range_sorted &r)
{
*this = r;
}
plain_range_sorted(T *b, T *e)
: parent(b, e)
{}
plain_range_sorted slice(unsigned start, unsigned count)
{
return plain_range_sorted(parent::begin+start, parent::begin+start+count);
}
};
template<class R>
class reverse_range
{
private:
reverse_range() {}
public:
typedef typename R::type type;
reverse_range(R r)
{
range = r;
}
reverse_range(const reverse_range &other) { range = other.range; }
bool empty() const { return range.empty(); }
void pop_front() { range.pop_back(); }
void pop_back() { range.pop_front(); }
type& front() { return range.back(); }
type& back() { return range.front(); }
R range;
};
template<class R> reverse_range<R> reverse(R range) {
return reverse_range<R>(range);
}
template<class R> R reverse(reverse_range<R> range) {
return range.range;
}
#endif

View file

@ -0,0 +1,31 @@
#ifndef TL_FILE_SORTED_ARRAY_HPP
#define TL_FILE_SORTED_ARRAY_HPP
#include "algorithms.hpp"
#include "array.hpp"
template <class T, class ALLOCATOR = allocator_default<T> >
class sorted_array : public array<T, ALLOCATOR>
{
typedef array<T, ALLOCATOR> parent;
// insert and size is not allowed
int insert(const T& item, typename parent::range r) { dbg_break(); return 0; }
int set_size(int new_size) { dbg_break(); return 0; }
public:
typedef plain_range_sorted<T> range;
int add(const T& item)
{
return parent::insert(item, partition_binary(all(), item));
}
/*
Function: all
Returns a sorted range that contains the whole array.
*/
range all() { return range(parent::list, parent::list+parent::num_elements); }
};
#endif // TL_FILE_SORTED_ARRAY_HPP

68
src/base/tl/string.hpp Normal file
View file

@ -0,0 +1,68 @@
#ifndef TL_FILE_STRING_HPP
#define TL_FILE_STRING_HPP
#include "base.hpp"
#include "allocator.hpp"
template<class ALLOCATOR >
class string_base : private ALLOCATOR
{
char *str;
int length;
void reset()
{
str = 0; length = 0;
}
void free()
{
ALLOCATOR::free_array(str);
reset();
}
void copy(const char *other_str, int other_length)
{
length = other_length;
str = ALLOCATOR::alloc_array(length+1);
mem_copy(str, other_str, length+1);
}
void copy(const string_base &other)
{
if(!other.str)
return;
copy(other.str, other.length);
}
public:
string_base() { reset(); }
string_base(const char *other_str) { copy(other_str, str_length(other_str)); }
string_base(const string_base &other) { reset(); copy(other); }
~string_base() { free(); }
string_base &operator = (const char *other)
{
free();
if(other)
copy(other, str_length(other));
return *this;
}
string_base &operator = (const string_base &other)
{
free();
copy(other);
return *this;
}
bool operator < (const char *other_str) const { return str_comp(str, other_str) < 0; }
operator const char *() const { return str; }
const char *cstr() const { return str; }
};
/* normal allocated string */
typedef string_base<allocator_default<char> > string;
#endif // TL_FILE_STRING_HPP

View file

@ -58,12 +58,12 @@ void MENUS::render_serverbrowser_serverlist(RECT view)
{COL_FLAG_LOCK, -1, " ", -1, 14.0f, 0, {0}, {0}},
{COL_FLAG_PURE, -1, " ", -1, 14.0f, 0, {0}, {0}},
{COL_FLAG_FAV, -1, " ", -1, 14.0f, 0, {0}, {0}},
{COL_NAME, BROWSESORT_NAME, "Name", 0, 300.0f, 0, {0}, {0}},
{COL_GAMETYPE, BROWSESORT_GAMETYPE, "Type", 1, 50.0f, 0, {0}, {0}},
{COL_MAP, BROWSESORT_MAP, "Map", 1, 100.0f, 0, {0}, {0}},
{COL_PLAYERS, BROWSESORT_NUMPLAYERS, "Players", 1, 60.0f, 0, {0}, {0}},
{COL_NAME, BROWSESORT_NAME, localize("Name"), 0, 300.0f, 0, {0}, {0}},
{COL_GAMETYPE, BROWSESORT_GAMETYPE, localize("Type"), 1, 50.0f, 0, {0}, {0}},
{COL_MAP, BROWSESORT_MAP, localize("Map"), 1, 100.0f, 0, {0}, {0}},
{COL_PLAYERS, BROWSESORT_NUMPLAYERS, localize("Players"), 1, 60.0f, 0, {0}, {0}},
{-1, -1, " ", 1, 10.0f, 0, {0}, {0}},
{COL_PING, BROWSESORT_PING, "Ping", 1, 40.0f, FIXED, {0}, {0}},
{COL_PING, BROWSESORT_PING, localize("Ping"), 1, 40.0f, FIXED, {0}, {0}},
};
int num_cols = sizeof(cols)/sizeof(column);
@ -128,11 +128,11 @@ void MENUS::render_serverbrowser_serverlist(RECT view)
msgbox.y += view.h/3;
if(active_page == PAGE_INTERNET && client_serverbrowse_refreshingmasters())
ui_do_label(&msgbox, "Refreshing master servers", 16.0f, 0);
ui_do_label(&msgbox, localize("Refreshing master servers"), 16.0f, 0);
else if(!client_serverbrowse_num())
ui_do_label(&msgbox, "No servers found", 16.0f, 0);
ui_do_label(&msgbox, localize("No servers found"), 16.0f, 0);
else if(client_serverbrowse_num() && !num_servers)
ui_do_label(&msgbox, "No servers match your filter criteria", 16.0f, 0);
ui_do_label(&msgbox, localize("No servers match your filter criteria"), 16.0f, 0);
}
int num = (int)(view.h/cols[0].rect.h);
@ -330,13 +330,13 @@ void MENUS::render_serverbrowser_serverlist(RECT view)
// render quick search
RECT quicksearch;
ui_vsplit_l(&status, 250.0f, &quicksearch, &status);
ui_do_label(&quicksearch, "Quick search: ", 14.0f, -1);
ui_vsplit_l(&quicksearch, gfx_text_width(0, 14.0f, "Quick search: ", -1), 0, &quicksearch);
ui_do_label(&quicksearch, localize("Quick search:"), 14.0f, -1);
ui_vsplit_l(&quicksearch, gfx_text_width(0, 14.0f, localize("Quick search:"), -1), 0, &quicksearch);
ui_do_edit_box(&config.b_filter_string, &quicksearch, config.b_filter_string, sizeof(config.b_filter_string), 14.0f);
// render status
char buf[128];
str_format(buf, sizeof(buf), "%d of %d servers, %d players", client_serverbrowse_sorted_num(), client_serverbrowse_num(), num_players);
str_format(buf, sizeof(buf), localize("%d of %d servers, %d players"), client_serverbrowse_sorted_num(), client_serverbrowse_num(), num_players);
ui_vsplit_r(&status, gfx_text_width(0, 14.0f, buf, -1), 0, &status);
ui_do_label(&status, buf, 14.0f, -1);
}
@ -353,32 +353,32 @@ void MENUS::render_serverbrowser_filters(RECT view)
// render filters
ui_hsplit_t(&view, 20.0f, &button, &view);
if (ui_do_button(&config.b_filter_empty, "Has people playing", config.b_filter_empty, &button, ui_draw_checkbox, 0))
if (ui_do_button(&config.b_filter_empty, localize("Has people playing"), config.b_filter_empty, &button, ui_draw_checkbox, 0))
config.b_filter_empty ^= 1;
ui_hsplit_t(&view, 20.0f, &button, &view);
if (ui_do_button(&config.b_filter_full, "Server not full", config.b_filter_full, &button, ui_draw_checkbox, 0))
if (ui_do_button(&config.b_filter_full, localize("Server not full"), config.b_filter_full, &button, ui_draw_checkbox, 0))
config.b_filter_full ^= 1;
ui_hsplit_t(&view, 20.0f, &button, &view);
if (ui_do_button(&config.b_filter_pw, "No password", config.b_filter_pw, &button, ui_draw_checkbox, 0))
if (ui_do_button(&config.b_filter_pw, localize("No password"), config.b_filter_pw, &button, ui_draw_checkbox, 0))
config.b_filter_pw ^= 1;
ui_hsplit_t(&view, 20.0f, &button, &view);
if (ui_do_button((char *)&config.b_filter_compatversion, "Compatible Version", config.b_filter_compatversion, &button, ui_draw_checkbox, 0))
if (ui_do_button((char *)&config.b_filter_compatversion, localize("Compatible version"), config.b_filter_compatversion, &button, ui_draw_checkbox, 0))
config.b_filter_compatversion ^= 1;
ui_hsplit_t(&view, 20.0f, &button, &view);
if (ui_do_button((char *)&config.b_filter_pure, "Standard gametype", config.b_filter_pure, &button, ui_draw_checkbox, 0))
if (ui_do_button((char *)&config.b_filter_pure, localize("Standard gametype"), config.b_filter_pure, &button, ui_draw_checkbox, 0))
config.b_filter_pure ^= 1;
ui_hsplit_t(&view, 20.0f, &button, &view);
/*ui_vsplit_l(&button, 20.0f, 0, &button);*/
if (ui_do_button((char *)&config.b_filter_pure_map, "Standard map", config.b_filter_pure_map, &button, ui_draw_checkbox, 0))
if (ui_do_button((char *)&config.b_filter_pure_map, localize("Standard map"), config.b_filter_pure_map, &button, ui_draw_checkbox, 0))
config.b_filter_pure_map ^= 1;
ui_hsplit_t(&view, 20.0f, &button, &view);
ui_do_label(&button, "Game types: ", 14.0f, -1);
ui_do_label(&button, localize("Game types:"), 14.0f, -1);
ui_vsplit_l(&button, 95.0f, 0, &button);
ui_margin(&button, 1.0f, &button);
ui_do_edit_box(&config.b_filter_gametype, &button, config.b_filter_gametype, sizeof(config.b_filter_gametype), 14.0f);
@ -394,12 +394,12 @@ void MENUS::render_serverbrowser_filters(RECT view)
ui_do_edit_box(&config.b_filter_ping, &editbox, buf, sizeof(buf), 14.0f);
config.b_filter_ping = atoi(buf);
ui_do_label(&button, "Maximum ping", 14.0f, -1);
ui_do_label(&button, localize("Maximum ping"), 14.0f, -1);
}
ui_hsplit_b(&view, button_height, &view, &button);
static int clear_button = 0;
if(ui_do_button(&clear_button, "Reset Filter", 0, &button, ui_draw_menu_button, 0))
if(ui_do_button(&clear_button, localize("Reset filter"), 0, &button, ui_draw_menu_button, 0))
{
config.b_filter_full = 0;
config.b_filter_empty = 0;
@ -431,7 +431,7 @@ void MENUS::render_serverbrowser_serverdetail(RECT view)
ui_draw_rect(&server_header, vec4(1,1,1,0.25f), CORNER_T, 4.0f);
ui_draw_rect(&server_details, vec4(0,0,0,0.15f), CORNER_B, 4.0f);
ui_vsplit_l(&server_header, 8.0f, 0x0, &server_header);
ui_do_label(&server_header, "Server Details: ", font_size+2.0f, -1);
ui_do_label(&server_header, localize("Server details:"), font_size+2.0f, -1);
ui_vsplit_l(&server_details, 5.0f, 0x0, &server_details);
@ -440,7 +440,11 @@ void MENUS::render_serverbrowser_serverdetail(RECT view)
if (selected_server)
{
RECT row;
static const char *labels[] = { "Version:", "Game Type:", "Progression:", "Ping:" };
static LOC_CONSTSTRING labels[] = {
localize("Version:"),
localize("Game Type:"),
localize("Progression:"),
localize("Ping:")};
RECT left_column;
RECT right_column;
@ -450,7 +454,7 @@ void MENUS::render_serverbrowser_serverdetail(RECT view)
RECT button;
ui_hsplit_b(&server_details, 20.0f, &server_details, &button);
static int add_fav_button = 0;
if (ui_do_button(&add_fav_button, "Favorite", selected_server->favorite, &button, ui_draw_checkbox, 0))
if (ui_do_button(&add_fav_button, localize("Favorite"), selected_server->favorite, &button, ui_draw_checkbox, 0))
{
if(selected_server->favorite)
client_serverbrowse_removefavorite(selected_server->netaddr);
@ -478,7 +482,7 @@ void MENUS::render_serverbrowser_serverdetail(RECT view)
char temp[16];
if(selected_server->progression < 0)
str_format(temp, sizeof(temp), "N/A");
str_format(temp, sizeof(temp), localize("N/A"));
else
str_format(temp, sizeof(temp), "%d%%", selected_server->progression);
ui_hsplit_t(&right_column, 15.0f, &row, &right_column);
@ -497,7 +501,7 @@ void MENUS::render_serverbrowser_serverdetail(RECT view)
ui_draw_rect(&server_header, vec4(1,1,1,0.25f), CORNER_T, 4.0f);
ui_draw_rect(&server_scoreboard, vec4(0,0,0,0.15f), CORNER_B, 4.0f);
ui_vsplit_l(&server_header, 8.0f, 0x0, &server_header);
ui_do_label(&server_header, "Scoreboard: ", font_size+2.0f, -1);
ui_do_label(&server_header, localize("Scoreboard:"), font_size+2.0f, -1);
ui_vsplit_l(&server_scoreboard, 5.0f, 0x0, &server_scoreboard);
@ -588,11 +592,11 @@ void MENUS::render_serverbrowser(RECT main_view)
ui_vsplit_l(&tabbutton1, 5.0f, 0, &tabbutton1);
static int filters_tab = 0;
if (ui_do_button(&filters_tab, "Filter", toolbox_page==0, &tabbutton0, ui_draw_menu_tab_button, 0))
if (ui_do_button(&filters_tab, localize("Filter"), toolbox_page==0, &tabbutton0, ui_draw_menu_tab_button, 0))
toolbox_page = 0;
static int info_tab = 0;
if (ui_do_button(&info_tab, "Info", toolbox_page==1, &tabbutton1, ui_draw_menu_tab_button, 0))
if (ui_do_button(&info_tab, localize("Info"), toolbox_page==1, &tabbutton1, ui_draw_menu_tab_button, 0))
toolbox_page = 1;
}
@ -613,7 +617,7 @@ void MENUS::render_serverbrowser(RECT main_view)
ui_vsplit_r(&status_toolbar, 100.0f, &status_toolbar, &button);
ui_vmargin(&button, 2.0f, &button);
static int refresh_button = 0;
if(ui_do_button(&refresh_button, "Refresh", 0, &button, ui_draw_menu_button, 0))
if(ui_do_button(&refresh_button, localize("Refresh"), 0, &button, ui_draw_menu_button, 0))
{
if(config.ui_page == PAGE_INTERNET)
client_serverbrowse_refresh(BROWSETYPE_INTERNET);
@ -625,9 +629,9 @@ void MENUS::render_serverbrowser(RECT main_view)
char buf[512];
if(strcmp(client_latestversion(), "0") != 0)
str_format(buf, sizeof(buf), "Teeworlds %s is out! Download it at www.teeworlds.com!\nCurrent version: %s", client_latestversion(), GAME_VERSION);
str_format(buf, sizeof(buf), localize("Teeworlds %s is out! Download it at www.teeworlds.com!"), client_latestversion());
else
str_format(buf, sizeof(buf), "Current version: %s", GAME_VERSION);
str_format(buf, sizeof(buf), localize("Current version: %s"), GAME_VERSION);
ui_do_label(&status_toolbar, buf, 14.0f, -1);
}
@ -643,7 +647,7 @@ void MENUS::render_serverbrowser(RECT main_view)
ui_vmargin(&button, 2.0f, &button);
//ui_vmargin(&button, 2.0f, &button);
static int join_button = 0;
if(ui_do_button(&join_button, "Connect", 0, &button, ui_draw_menu_button, 0) || enter_pressed)
if(ui_do_button(&join_button, localize("Connect"), 0, &button, ui_draw_menu_button, 0) || enter_pressed)
{
client_connect(config.ui_server_address);
enter_pressed = false;
@ -653,6 +657,6 @@ void MENUS::render_serverbrowser(RECT main_view)
ui_hsplit_b(&button_box, 20.0f, &button_box, &button);
ui_do_edit_box(&config.ui_server_address, &button, config.ui_server_address, sizeof(config.ui_server_address), 14.0f);
ui_hsplit_b(&button_box, 20.0f, &button_box, &button);
ui_do_label(&button, "Host address:", 14.0f, -1);
ui_do_label(&button, localize("Host address:"), 14.0f, -1);
}
}

View file

@ -254,7 +254,7 @@ typedef struct
int keyid;
} KEYINFO;
KEYINFO keys[] =
static KEYINFO keys[] =
{
// we need to do localize so the scripts can pickup the string
{ localize("Move Left:"), "+left", 0},
@ -286,7 +286,7 @@ void MENUS::ui_do_getbuttons(int start, int stop, RECT view)
{
for (int i = start; i < stop; i++)
{
KEYINFO key = keys[i];
KEYINFO &key = keys[i];
RECT button, label;
ui_hsplit_t(&view, 20.0f, &button, &view);
ui_vsplit_l(&button, 130.0f, &label, &button);

View file

@ -98,8 +98,77 @@ static void con_serverdummy(void *result, void *user_data)
dbg_msg("client", "this command is not available on the client");
}
#include <base/tl/sorted_array.hpp>
void GAMECLIENT::on_console_init()
{
if(0)
{
int ints[4] = {0,1,2,3};
for(int s = 1; s < 4; s++)
{
//s = 2;
plain_range_sorted<int> test_sorted_range(ints, ints+s);
plain_range_sorted<int> res1, res2;
//res2 = partition_binary(test_sorted_range, 1);
//for(int i = 0; i < 4; i++)
// dbg_assert(partition_linear(test_sorted_range, i).front() == i, "partition linear failed");
dbg_msg("", "size %d", s);
for(int i = -1; i < 5; i++)
{
res1 = partition_linear(test_sorted_range, i);
dbg_msg("", "\tlin %d == %d", i, res1.empty()?-1:res1.front());
res2 = partition_binary(test_sorted_range, i);
dbg_msg("", "\tbin %d == %d", i, res2.empty()?-1:res2.front());
//dbg_assert(partition_binary(plain_range_sorted<int>(ints, ints+6), i).front() == i+1, "partition binary failed");
}
} //*/
sorted_array<int> test;
test.add(4);
test.add(1);
for(int i = 0; i < 100; i++)
{
int this_add = rand();
test.add(this_add);
if(!sort_verify(test.all()))
{
dbg_msg("", "error inserting %d", this_add);
for(sorted_array<int>::range r = test.all(); !r.empty(); r.pop_front())
dbg_msg("", "%d", r.front());
exit(-1);
}
}/*
test.add(1);
test.add(4);
test.add(3);
test.add(4);
test.add(3);
test.add(2);
//test.insert(1, 1);
for(sorted_array<int>::range r = test.all(); !r.empty(); r.pop_front())
dbg_msg("", "%d", r.front());
*/
sort_verify(test.all());
/*
for(int i = 0; i < 15; i++)
{
dbg_msg("", "found %d == %d", i, !find_binary(test.all(), i).empty());
}*/
exit(-1);
}
// setup pointers
binds = &::binds;
console = &::console;

View file

@ -1,5 +1,6 @@
#include "localization.hpp"
#include <base/tl/algorithms.hpp>
extern "C" {
#include <engine/e_linereader.h>
@ -16,7 +17,6 @@ static unsigned str_hash(const char *str)
const char *localize(const char *str)
{
const char *new_str = localization.find_string(str_hash(str));
//dbg_msg("", "no localization for '%s'", str);
return new_str ? new_str : str;
}
@ -86,15 +86,19 @@ bool LOCALIZATIONDATABASE::load(const char *filename)
replacement += 3;
localization.add_string(line, replacement);
}
current_version++;
return true;
}
const char *LOCALIZATIONDATABASE::find_string(unsigned hash)
{
array<STRING>::range r = ::find(strings.all(), hash);
STRING s;
s.hash = hash;
sorted_array<STRING>::range r = ::find_binary(strings.all(), s);
if(r.empty())
return 0;
return r.front().replacement;
}
LOCALIZATIONDATABASE localization;

View file

@ -1,4 +1,5 @@
#include <base/tl/array.hpp>
#include <base/tl/string.hpp>
#include <base/tl/sorted_array.hpp>
class LOCALIZATIONDATABASE
{
@ -6,13 +7,16 @@ class LOCALIZATIONDATABASE
{
public:
unsigned hash;
// TODO: do this as an const char * and put everything on a incremental heap
string replacement;
bool operator ==(unsigned h) const { return hash == h; }
bool operator <(const STRING &other) const { return hash < other.hash; }
bool operator <=(const STRING &other) const { return hash <= other.hash; }
bool operator ==(const STRING &other) const { return hash == other.hash; }
};
array<STRING> strings;
sorted_array<STRING> strings;
int current_version;
public:
@ -26,8 +30,7 @@ public:
const char *find_string(unsigned hash);
};
static LOCALIZATIONDATABASE localization;
extern LOCALIZATIONDATABASE localization;
class LOC_CONSTSTRING
{
@ -46,3 +49,6 @@ public:
return current_str;
}
};
extern const char *localize(const char *str);