diff options
64 files changed, 12268 insertions, 1047 deletions
diff --git a/.gitignore b/.gitignore index ee210c7c0..e282ec130 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,10 @@ src/jthread/cmake_install.cmake src/jthread/libjthread.a src/lua/build/ src/lua/CMakeFiles/ +src/cguittfont/CMakeFiles/ +src/cguittfont/libcguittfont.a +src/cguittfont/cmake_install.cmake +src/cguittfont/Makefile CMakeCache.txt CPackConfig.cmake CPackSourceConfig.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index fdb0347b7..fbf46d059 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,8 @@ if(RUN_IN_PLACE) install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/textures/all/textures_here.txt" DESTINATION "${SHAREDIR}/textures/all") endif() +install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/fonts" DESTINATION "${SHAREDIR}") + install(FILES "README.txt" DESTINATION "${DOCDIR}") install(FILES "doc/lua_api.txt" DESTINATION "${DOCDIR}") install(FILES "doc/mapformat.txt" DESTINATION "${DOCDIR}") diff --git a/README.txt b/README.txt index 8c5a46223..d6344bd2c 100644 --- a/README.txt +++ b/README.txt @@ -372,4 +372,8 @@ DejaVu Sans Mono: Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + Liberation Fonts Copyright: + + Copyright (c) 2007 Red Hat, Inc. All rights reserved. LIBERATION is a trademark of Red Hat, Inc. + diff --git a/builtin/item.lua b/builtin/item.lua index a28798d4d..2233b6c5b 100644 --- a/builtin/item.lua +++ b/builtin/item.lua @@ -141,7 +141,7 @@ function minetest.item_place_node(itemstack, placer, pointed_thing) minetest.log("info", placer:get_player_name() .. " tried to place" .. " node in invalid position " .. minetest.pos_to_string(above) .. ", replacing " .. oldnode_above.name) - return + return itemstack end -- Place above pointed node @@ -186,7 +186,7 @@ function minetest.item_place_node(itemstack, placer, pointed_thing) not check_attached_node(place_to, newnode) then minetest.log("action", "attached node " .. def.name .. " can not be placed at " .. minetest.pos_to_string(place_to)) - return + return itemstack end -- Add node and update @@ -237,8 +237,7 @@ function minetest.item_place(itemstack, placer, pointed_thing) local n = minetest.env:get_node(pointed_thing.under) local nn = n.name if minetest.registered_nodes[nn] and minetest.registered_nodes[nn].on_rightclick then - minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, n, placer) - return + return minetest.registered_nodes[nn].on_rightclick(pointed_thing.under, n, placer, itemstack) end end @@ -263,7 +262,7 @@ function minetest.item_drop(itemstack, dropper, pos) else minetest.env:add_item(pos, itemstack) end - return "" + return ItemStack("") end function minetest.item_eat(hp_change, replace_with_item) diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 7ba2ed001..af70a1047 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1497,8 +1497,10 @@ Node definition (register_node) on_punch = func(pos, node, puncher), ^ default: minetest.node_punch ^ By default: does nothing - on_rightclick = func(pos, node, clicker), + on_rightclick = func(pos, node, clicker, itemstack), ^ default: nil + ^ if defined, itemstack will hold clicker's wielded item + Shall return the leftover itemstack on_dig = func(pos, node, digger), ^ default: minetest.node_dig ^ By default: checks privileges, wears out tool and removes node diff --git a/fonts/liberationmono.ttf b/fonts/liberationmono.ttf Binary files differnew file mode 100644 index 000000000..7260bd65e --- /dev/null +++ b/fonts/liberationmono.ttf diff --git a/fonts/liberationsans.ttf b/fonts/liberationsans.ttf Binary files differnew file mode 100644 index 000000000..59d2e251b --- /dev/null +++ b/fonts/liberationsans.ttf diff --git a/minetest.conf.example b/minetest.conf.example index 6559ac88b..30d0dbd5c 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -163,6 +163,11 @@ # File in client/serverlist/ that contains your favorite servers displayed in the Multiplayer Tab #serverlist_file = favoriteservers.txt +#font_path = fonts/liberationsans.ttf +#font_size = 13 +#mono_font_path = fonts/liberationmono.ttf +#mono_font_size = 13 + # # Server stuff # @@ -239,8 +244,27 @@ #congestion_control_aim_rtt = 0.2 #congestion_control_max_rate = 400 #congestion_control_min_rate = 10 +# Specifies URL from which client fetches media instead of using UDP +# $filename should be accessible from $remote_media$filename via cURL +# (obviously, remote_media should end with a slash) +# Files that are not present would be fetched the usual way #remote_media = +# Physics stuff +#movement_acceleration_default = 3 +#movement_acceleration_air = 2 +#movement_acceleration_fast = 10 +#movement_speed_walk = 4 +#movement_speed_crouch = 1.35 +#movement_speed_fast = 20 +#movement_speed_climb = 2 +#movement_speed_jump = 6.5 +#movement_speed_descend = 6 +#movement_liquid_fluidity = 1 +#movement_liquid_fluidity_smooth = 0.5 +#movement_liquid_sink = 10 +#movement_gravity = 9.81 + # Mapgen stuff #mg_name = v6 #water_level = 1 diff --git a/po/da/minetest.po b/po/da/minetest.po index 9b25cdefe..3981cd1a7 100644 --- a/po/da/minetest.po +++ b/po/da/minetest.po @@ -7,45 +7,47 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.0\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-23 18:24+0200\n" -"PO-Revision-Date: 2011-08-02 00:31+0100\n" -"Last-Translator: Frederik Helth <Guides@live.dk>\n" +"POT-Creation-Date: 2013-01-30 20:25+0100\n" +"PO-Revision-Date: 2013-02-05 20:38+0200\n" +"Last-Translator: Pilz Adam <PilzAdam@gmx.de>\n" "Language-Team: \n" "Language: da\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Weblate 1.4-dev\n" -#: src/guiConfigureWorld.cpp:127 +#: src/guiConfigureWorld.cpp:125 msgid "" "Warning: Some mods are not configured yet.\n" "They will be enabled by default when you save the configuration. " msgstr "" -#: src/guiConfigureWorld.cpp:146 +#: src/guiConfigureWorld.cpp:144 msgid "" "Warning: Some configured mods are missing.\n" "Their setting will be removed when you save the configuration. " msgstr "" -#: src/guiConfigureWorld.cpp:210 +#: src/guiConfigureWorld.cpp:208 msgid "enabled" msgstr "" -#: src/guiConfigureWorld.cpp:217 +#: src/guiConfigureWorld.cpp:215 #, fuzzy msgid "Enable All" msgstr "Tag imod skade" -#: src/guiConfigureWorld.cpp:224 +#: src/guiConfigureWorld.cpp:222 msgid "Disable All" msgstr "" -#: src/guiConfigureWorld.cpp:230 +#: src/guiConfigureWorld.cpp:228 msgid "depends on:" msgstr "" -#: src/guiConfigureWorld.cpp:242 +#: src/guiConfigureWorld.cpp:240 msgid "is required by:" msgstr "" @@ -125,6 +127,75 @@ msgstr "" msgid "press key" msgstr "Tryk knap" +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "Frem" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "Tilbage" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "Venstre" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "Højre" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "Brug" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "Hop" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "Snig" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "Ting" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "Chat" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "Flyvning" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "Hurtig flyvning" + +#: src/guiKeyChangeMenu.cpp:386 +#, fuzzy +msgid "Toggle noclip" +msgstr "Flyvning" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "Afstands load" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "Print stykker" + #: src/guiMainMenu.cpp:55 msgid "Cannot create world: Name contains invalid characters" msgstr "" @@ -205,7 +276,7 @@ msgstr "Logud" #: src/guiMainMenu.cpp:529 msgid "Leave address blank to start a local server." -msgstr "Lad black for at spille localt" +msgstr "Lad black for at spille localt." #: src/guiMainMenu.cpp:538 msgid "Start Game / Connect" @@ -467,18 +538,10 @@ msgid "Execute" msgstr "" #: src/keycode.cpp:228 -msgid "Left" -msgstr "Venstre" - -#: src/keycode.cpp:228 msgid "Print" msgstr "" #: src/keycode.cpp:228 -msgid "Right" -msgstr "Højre" - -#: src/keycode.cpp:228 msgid "Select" msgstr "Vælge" @@ -679,36 +742,3 @@ msgstr "" #~ msgid "Delete map" #~ msgstr "Slet mappen" - -#~ msgid "Print stacks" -#~ msgstr "Print stykker" - -#~ msgid "Range select" -#~ msgstr "Afstands load" - -#~ msgid "Toggle fast" -#~ msgstr "Hurtig flyvning" - -#~ msgid "Toggle fly" -#~ msgstr "Flyvning" - -#~ msgid "Chat" -#~ msgstr "Chat" - -#~ msgid "Inventory" -#~ msgstr "Ting" - -#~ msgid "Jump" -#~ msgstr "Hop" - -#~ msgid "Sneak" -#~ msgstr "Snig" - -#~ msgid "Use" -#~ msgstr "Brug" - -#~ msgid "Backward" -#~ msgstr "Tilbage" - -#~ msgid "Forward" -#~ msgstr "Frem" diff --git a/po/de/minetest.po b/po/de/minetest.po index a3d9684ad..a75456be9 100644 --- a/po/de/minetest.po +++ b/po/de/minetest.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: 0.0.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-01-23 18:24+0200\n" -"PO-Revision-Date: 2013-01-23 20:27+0200\n" -"Last-Translator: Sfan5 . <sfan5@live.de>\n" +"PO-Revision-Date: 2013-02-02 18:51+0200\n" +"Last-Translator: Pilz Adam <PilzAdam@gmx.de>\n" "Language-Team: Deutsch <>\n" "Language: de\n" "MIME-Version: 1.0\n" @@ -18,7 +18,7 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" "X-Generator: Weblate 1.4-dev\n" -#: src/guiConfigureWorld.cpp:127 +#: src/guiConfigureWorld.cpp:125 msgid "" "Warning: Some mods are not configured yet.\n" "They will be enabled by default when you save the configuration. " @@ -26,7 +26,7 @@ msgstr "" "Warnung: Einige Mods sind noch nicht konfiguriert.\n" "Sie werden aktiviert wenn die Konfiguration gespeichert wird. " -#: src/guiConfigureWorld.cpp:146 +#: src/guiConfigureWorld.cpp:144 msgid "" "Warning: Some configured mods are missing.\n" "Their setting will be removed when you save the configuration. " @@ -34,23 +34,23 @@ msgstr "" "Warnung: Einige konfigurierte Mods fehlen.\n" "Mod Einstellungen werden gelöscht wenn die Konfiguration gespeichert wird. " -#: src/guiConfigureWorld.cpp:210 +#: src/guiConfigureWorld.cpp:208 msgid "enabled" msgstr "Aktiviert" -#: src/guiConfigureWorld.cpp:217 +#: src/guiConfigureWorld.cpp:215 msgid "Enable All" -msgstr "Alle einschalten" +msgstr "Alle an" -#: src/guiConfigureWorld.cpp:224 +#: src/guiConfigureWorld.cpp:222 msgid "Disable All" -msgstr "Alle ausschalten" +msgstr "Alle aus" -#: src/guiConfigureWorld.cpp:230 +#: src/guiConfigureWorld.cpp:228 msgid "depends on:" msgstr "abhängig von:" -#: src/guiConfigureWorld.cpp:242 +#: src/guiConfigureWorld.cpp:240 msgid "is required by:" msgstr "wird benötigt von:" @@ -118,7 +118,7 @@ msgstr "\"Benutzen\" = herunterklettern" #: src/guiKeyChangeMenu.cpp:164 msgid "Double tap \"jump\" to toggle fly" -msgstr "Doppelt \"springen\" drücken, um fliegen umzuschalten" +msgstr "Doppelt \"springen\" zum fliegen" #: src/guiKeyChangeMenu.cpp:269 msgid "Key already in use" @@ -128,13 +128,82 @@ msgstr "Taste bereits in Benutzung" msgid "press key" msgstr "Taste drücken" +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "Vorwärts" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "Rückwärts" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "Links" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "Rechts" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "Benutzen" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "Springen" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "Schleichen" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "Wegwerfen" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "Inventar" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "Chat" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "Befehl" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "Konsole" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "Fliegen umsch." + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "Speed umsch." + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "Noclip umsch." + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "Entfernung wählen" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "Stack ausgeben" + #: src/guiMainMenu.cpp:55 msgid "Cannot create world: Name contains invalid characters" msgstr "Kann Welt nicht erstellen: Name enthält ungülige Zeichen" #: src/guiMainMenu.cpp:64 msgid "Cannot create world: A world by this name already exists" -msgstr "Kann Welt nicht erstellen: Eine Welt mit diesem Namen existiert bereits" +msgstr "" +"Kann Welt nicht erstellen: Eine Welt mit diesem Namen existiert bereits" #: src/guiMainMenu.cpp:245 msgid "Singleplayer" @@ -234,7 +303,7 @@ msgstr "3D Wolken" #: src/guiMainMenu.cpp:629 msgid "Opaque water" -msgstr "Undurchsichtiges Wasser" +msgstr "Undurchs. Wasser" #: src/guiMainMenu.cpp:639 msgid "Mip-Mapping" @@ -258,7 +327,7 @@ msgstr "Shader" #: src/guiMainMenu.cpp:675 msgid "Preload item visuals" -msgstr "Lade Miniaturansichten vor" +msgstr "Lade Inventarbilder vor" #: src/guiMainMenu.cpp:682 msgid "Enable Particles" @@ -474,18 +543,10 @@ msgid "Execute" msgstr "Ausführen" #: src/keycode.cpp:228 -msgid "Left" -msgstr "Links" - -#: src/keycode.cpp:228 msgid "Print" msgstr "Druck" #: src/keycode.cpp:228 -msgid "Right" -msgstr "Rechts" - -#: src/keycode.cpp:228 msgid "Select" msgstr "Selektiere" @@ -685,41 +746,8 @@ msgstr "" "\n" "Siehe debug.txt für Details." -#~ msgid "Delete map" -#~ msgstr "Karte löschen" - -#~ msgid "Print stacks" -#~ msgstr "Stack ausgeben" - -#~ msgid "Range select" -#~ msgstr "Entfernung wählen" - -#~ msgid "Toggle fast" -#~ msgstr "Speed umsch." - -#~ msgid "Toggle fly" -#~ msgstr "Fliegen umsch." - -#~ msgid "Chat" -#~ msgstr "Chat" - -#~ msgid "Inventory" -#~ msgstr "Inventar" - -#~ msgid "Jump" -#~ msgstr "Springen" - -#~ msgid "Sneak" -#~ msgstr "Kriechen" - -#~ msgid "Use" -#~ msgstr "Benutzen" - -#~ msgid "Backward" -#~ msgstr "Rückwärts" - -#~ msgid "Forward" -#~ msgstr "Vorwärts" - #~ msgid "KEYBINDINGS" #~ msgstr "TASTEN EINST." + +#~ msgid "Delete map" +#~ msgstr "Karte löschen" diff --git a/po/es/minetest.po b/po/es/minetest.po index 400cb5a4e..70b7daf06 100644 --- a/po/es/minetest.po +++ b/po/es/minetest.po @@ -3,325 +3,401 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-01-23 18:24+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"PO-Revision-Date: 2013-02-07 22:14+0200\n" +"Last-Translator: Francizca Rodriguez <joaoadriano3@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" -"Language: \n" +"Language: es\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Weblate 1.4-dev\n" -#: src/guiConfigureWorld.cpp:127 +#: src/guiConfigureWorld.cpp:125 msgid "" "Warning: Some mods are not configured yet.\n" "They will be enabled by default when you save the configuration. " msgstr "" +"ADVERTENCIA: Algunos mods no están aún configurados.\n" +"Se habilitarán de forma predeterminada al guardar la configuración. " -#: src/guiConfigureWorld.cpp:146 +#: src/guiConfigureWorld.cpp:144 msgid "" "Warning: Some configured mods are missing.\n" "Their setting will be removed when you save the configuration. " msgstr "" +"ADVERTENCIA: Algunos mods configurados faltan.\n" +"Su ajuste se quitará al guardar la configuración. " -#: src/guiConfigureWorld.cpp:210 +#: src/guiConfigureWorld.cpp:208 msgid "enabled" -msgstr "" +msgstr "Activado" -#: src/guiConfigureWorld.cpp:217 +#: src/guiConfigureWorld.cpp:215 msgid "Enable All" -msgstr "" +msgstr "Activar todos" -#: src/guiConfigureWorld.cpp:224 +#: src/guiConfigureWorld.cpp:222 msgid "Disable All" -msgstr "" +msgstr "Desactivar todos" -#: src/guiConfigureWorld.cpp:230 +#: src/guiConfigureWorld.cpp:228 msgid "depends on:" -msgstr "" +msgstr "Dependencia:" -#: src/guiConfigureWorld.cpp:242 +#: src/guiConfigureWorld.cpp:240 msgid "is required by:" -msgstr "" +msgstr "Requiere:" #: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 #: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 msgid "Cancel" -msgstr "" +msgstr "Cancelar" #: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 msgid "Save" -msgstr "" +msgstr "Guardar" #: src/guiConfigureWorld.cpp:394 msgid "Configuration saved. " -msgstr "" +msgstr "Configuración guardada. " #: src/guiConfigureWorld.cpp:402 msgid "Warning: Configuration not consistent. " -msgstr "" +msgstr "ADVERTENCIA: La configuración no corresponde. " #: src/guiConfirmMenu.cpp:120 msgid "Yes" -msgstr "" +msgstr "Sí" #: src/guiConfirmMenu.cpp:126 msgid "No" -msgstr "" +msgstr "No" #: src/guiCreateWorld.cpp:116 msgid "World name" -msgstr "" +msgstr "Nombre del mundo" #: src/guiCreateWorld.cpp:135 msgid "Game" -msgstr "" +msgstr "Juego" #: src/guiCreateWorld.cpp:159 msgid "Create" -msgstr "" +msgstr "Crear" #: src/guiDeathScreen.cpp:96 msgid "You died." -msgstr "" +msgstr "Estas Muerto." #: src/guiDeathScreen.cpp:104 msgid "Respawn" -msgstr "" +msgstr "Respawn" #: src/guiFormSpecMenu.cpp:572 msgid "Left click: Move all items, Right click: Move single item" msgstr "" +"Click izquierdo: Mover todos los objetos. Click derecho: Mover un objeto." #: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109 #: src/guiTextInputMenu.cpp:123 msgid "Proceed" -msgstr "" +msgstr "Continuar" #: src/guiKeyChangeMenu.cpp:114 msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" msgstr "" +"Combinaciones de teclas.(Si este menú da error, cambiar configuración en " +"minetest.conf)" #: src/guiKeyChangeMenu.cpp:151 msgid "\"Use\" = climb down" -msgstr "" +msgstr "\"Usar\" = Descender" #: src/guiKeyChangeMenu.cpp:164 msgid "Double tap \"jump\" to toggle fly" -msgstr "" +msgstr "Pulsar dos veces \"saltar\" para activar volar" #: src/guiKeyChangeMenu.cpp:269 msgid "Key already in use" -msgstr "" +msgstr "La tecla se está utilizando" #: src/guiKeyChangeMenu.cpp:347 msgid "press key" -msgstr "" +msgstr "Pulsa una tecla" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "Adelante" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "Atras" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "Izquierda" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "Derecha" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "Usar" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "Saltar" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "Agacharse" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "Tirar" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "Inventario" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "Chat" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "Comando" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "Consola" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "Activar Volar" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "Activar Modo Rápido" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "Activar noclip" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "Seleccionar rango" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "Imprimir Stacks" #: src/guiMainMenu.cpp:55 msgid "Cannot create world: Name contains invalid characters" -msgstr "" +msgstr "No se puede crear el mundo: El nombre contiene caracteres no válidos" #: src/guiMainMenu.cpp:64 msgid "Cannot create world: A world by this name already exists" -msgstr "" +msgstr "No se puede crear el mundo: Hay un mundo con este nombre" #: src/guiMainMenu.cpp:245 msgid "Singleplayer" -msgstr "" +msgstr "Un jugador" #: src/guiMainMenu.cpp:246 msgid "Multiplayer" -msgstr "" +msgstr "Multijugador" #: src/guiMainMenu.cpp:247 msgid "Advanced" -msgstr "" +msgstr "Server" #: src/guiMainMenu.cpp:248 msgid "Settings" -msgstr "" +msgstr "Configuración" #: src/guiMainMenu.cpp:249 msgid "Credits" -msgstr "" +msgstr "Créditos" #: src/guiMainMenu.cpp:280 msgid "Select World:" -msgstr "" +msgstr "Selecciona un mundo:" #: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229 msgid "Delete" -msgstr "" +msgstr "Borrar" #: src/guiMainMenu.cpp:309 msgid "New" -msgstr "" +msgstr "Nuevo" #: src/guiMainMenu.cpp:317 msgid "Configure" -msgstr "" +msgstr "Configurar" #: src/guiMainMenu.cpp:332 src/keycode.cpp:248 msgid "Play" -msgstr "" +msgstr "Jugar" #: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557 msgid "Creative Mode" -msgstr "" +msgstr "Modo creativo" #: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563 msgid "Enable Damage" -msgstr "" +msgstr "Permitir daños" #: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479 msgid "Name/Password" -msgstr "" +msgstr "Nombre/Clave" #: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506 msgid "Address/Port" -msgstr "" +msgstr "Dirección/Puerto" #: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075 msgid "Show Public" -msgstr "" +msgstr "Servidores Públicos" #: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083 msgid "Show Favorites" -msgstr "" +msgstr "Mostrar Favoritos" #: src/guiMainMenu.cpp:459 msgid "Connect" -msgstr "" +msgstr "Conectar" #: src/guiMainMenu.cpp:529 msgid "Leave address blank to start a local server." -msgstr "" +msgstr "Dejar la dirección en blanco para iniciar un servidor local." #: src/guiMainMenu.cpp:538 msgid "Start Game / Connect" -msgstr "" +msgstr "Iniciar juego/Conectar" #: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006 msgid "Delete world" -msgstr "" +msgstr "Eliminar Mundo" #: src/guiMainMenu.cpp:577 msgid "Create world" -msgstr "" +msgstr "Crear Mundo" #: src/guiMainMenu.cpp:611 msgid "Fancy trees" -msgstr "" +msgstr "Árboles detallados" #: src/guiMainMenu.cpp:617 msgid "Smooth Lighting" -msgstr "" +msgstr "Iluminación Suave" #: src/guiMainMenu.cpp:623 msgid "3D Clouds" -msgstr "" +msgstr "Nubes 3D" #: src/guiMainMenu.cpp:629 msgid "Opaque water" -msgstr "" +msgstr "Agua Opaca" #: src/guiMainMenu.cpp:639 msgid "Mip-Mapping" -msgstr "" +msgstr "Mip-Mapping" #: src/guiMainMenu.cpp:646 msgid "Anisotropic Filtering" -msgstr "" +msgstr "Filtrado Anisotrópico" #: src/guiMainMenu.cpp:653 msgid "Bi-Linear Filtering" -msgstr "" +msgstr "Filtrado Bi-Lineal" #: src/guiMainMenu.cpp:660 msgid "Tri-Linear Filtering" -msgstr "" +msgstr "Filtrado Tri-Lineal" #: src/guiMainMenu.cpp:668 msgid "Shaders" -msgstr "" +msgstr "Habilitar Shaders" #: src/guiMainMenu.cpp:675 msgid "Preload item visuals" -msgstr "" +msgstr "Precarga elementos visuales" #: src/guiMainMenu.cpp:682 msgid "Enable Particles" -msgstr "" +msgstr "Partículas" #: src/guiMainMenu.cpp:692 msgid "Change keys" -msgstr "" +msgstr "Configurar Teclas" #: src/guiMainMenu.cpp:977 msgid "Address required." -msgstr "" +msgstr "Requiere una dirección." #: src/guiMainMenu.cpp:995 msgid "Cannot delete world: Nothing selected" -msgstr "" +msgstr "No se puede eliminar el mundo: ninguno ha sido seleccionado" #: src/guiMainMenu.cpp:1010 msgid "Files to be deleted" -msgstr "" +msgstr "Archivos que se eliminarán" #: src/guiMainMenu.cpp:1026 msgid "Cannot create world: No games found" -msgstr "" +msgstr "No se puede crear el mundo: No se encontraron juegos" #: src/guiMainMenu.cpp:1042 msgid "Cannot configure world: Nothing selected" -msgstr "" +msgstr "No se puede configurar el mundo: Ninguno seleccionado" #: src/guiMainMenu.cpp:1146 msgid "Failed to delete all world files" -msgstr "" +msgstr "No se pudo eliminar todos los archivos del mundo" #: src/guiPasswordChange.cpp:108 msgid "Old Password" -msgstr "" +msgstr "Contraseña anterior" #: src/guiPasswordChange.cpp:125 msgid "New Password" -msgstr "" +msgstr "Nueva contraseña" #: src/guiPasswordChange.cpp:141 msgid "Confirm Password" -msgstr "" +msgstr "Confirmar contraseña" #: src/guiPasswordChange.cpp:158 msgid "Change" -msgstr "" +msgstr "Cambiar" #: src/guiPasswordChange.cpp:167 msgid "Passwords do not match!" -msgstr "" +msgstr "¡Las contraseñas no coinciden!" #: src/guiPauseMenu.cpp:118 msgid "Continue" -msgstr "" +msgstr "Continuar" #: src/guiPauseMenu.cpp:127 msgid "Change Password" -msgstr "" +msgstr "Modificar contraseña" #: src/guiPauseMenu.cpp:135 msgid "Exit to Menu" -msgstr "" +msgstr "Salir al menú" #: src/guiPauseMenu.cpp:142 msgid "Exit to OS" -msgstr "" +msgstr "Salir al S.O." #: src/guiPauseMenu.cpp:149 msgid "" @@ -337,333 +413,340 @@ msgid "" "- ESC: This menu\n" "- T: Chat\n" msgstr "" +"Controles predeterminados:\n" +"- WASD: Caminar \n" +"- Ratón, izquierdo: Cavar/Golpear\n" +"- Ratón, derecho: Poner bloque/Usar\n" +"- Ratón, rueda: seleccionar objecto\n" +"- 0... 9: Seleccionar objecto\n" +"- Mayúscula: caminar despacio\n" +"- R: Ajustar distancia de los chunks cargados\n" +"- I: Inventario \n" +"- ESC: Este Menu\n" +"- T: Chat\n" #: src/keycode.cpp:223 msgid "Left Button" -msgstr "" +msgstr "Click Izquierdo" #: src/keycode.cpp:223 msgid "Middle Button" -msgstr "" +msgstr "Click Centro" #: src/keycode.cpp:223 msgid "Right Button" -msgstr "" +msgstr "Click Derecho" #: src/keycode.cpp:223 msgid "X Button 1" -msgstr "" +msgstr "X Button 1" #: src/keycode.cpp:224 msgid "Back" -msgstr "" +msgstr "Atras" #: src/keycode.cpp:224 msgid "Clear" -msgstr "" +msgstr "Limpiar" #: src/keycode.cpp:224 msgid "Return" -msgstr "" +msgstr "Intro" #: src/keycode.cpp:224 msgid "Tab" -msgstr "" +msgstr "Tabulador" #: src/keycode.cpp:224 msgid "X Button 2" -msgstr "" +msgstr "X Button 2" #: src/keycode.cpp:225 msgid "Capital" -msgstr "" +msgstr "Bloq mayús" #: src/keycode.cpp:225 msgid "Control" -msgstr "" +msgstr "Control" #: src/keycode.cpp:225 msgid "Kana" -msgstr "" +msgstr "Kana" #: src/keycode.cpp:225 msgid "Menu" -msgstr "" +msgstr "Menú" #: src/keycode.cpp:225 msgid "Pause" -msgstr "" +msgstr "Pausa" #: src/keycode.cpp:225 msgid "Shift" -msgstr "" +msgstr "Mayús" #: src/keycode.cpp:226 msgid "Convert" -msgstr "" +msgstr "Convertir" #: src/keycode.cpp:226 msgid "Escape" -msgstr "" +msgstr "Esc" #: src/keycode.cpp:226 msgid "Final" -msgstr "" +msgstr "Final" #: src/keycode.cpp:226 msgid "Junja" -msgstr "" +msgstr "Junja" #: src/keycode.cpp:226 msgid "Kanji" -msgstr "" +msgstr "Kanji" #: src/keycode.cpp:226 msgid "Nonconvert" -msgstr "" +msgstr "Nonconvert" #: src/keycode.cpp:227 msgid "Accept" -msgstr "" +msgstr "Aceptar" #: src/keycode.cpp:227 msgid "End" -msgstr "" +msgstr "Fin" #: src/keycode.cpp:227 msgid "Home" -msgstr "" +msgstr "Inicio" #: src/keycode.cpp:227 msgid "Mode Change" -msgstr "" +msgstr "Cambio de modo" #: src/keycode.cpp:227 msgid "Next" -msgstr "" +msgstr "Siguiente" #: src/keycode.cpp:227 msgid "Prior" -msgstr "" +msgstr "Anterior" #: src/keycode.cpp:227 msgid "Space" -msgstr "" +msgstr "Espacio" #: src/keycode.cpp:228 msgid "Down" -msgstr "" +msgstr "Abajo" #: src/keycode.cpp:228 msgid "Execute" -msgstr "" - -#: src/keycode.cpp:228 -msgid "Left" -msgstr "" +msgstr "Ejecutar" #: src/keycode.cpp:228 msgid "Print" -msgstr "" - -#: src/keycode.cpp:228 -msgid "Right" -msgstr "" +msgstr "Captura" #: src/keycode.cpp:228 msgid "Select" -msgstr "" +msgstr "Seleccionar" #: src/keycode.cpp:228 msgid "Up" -msgstr "" +msgstr "Arriba" #: src/keycode.cpp:229 msgid "Help" -msgstr "" +msgstr "Ayuda" #: src/keycode.cpp:229 msgid "Insert" -msgstr "" +msgstr "Introducir" #: src/keycode.cpp:229 msgid "Snapshot" -msgstr "" +msgstr "Captura de pantalla" #: src/keycode.cpp:232 msgid "Left Windows" -msgstr "" +msgstr "Win Izquierdo" #: src/keycode.cpp:233 msgid "Apps" -msgstr "" +msgstr "Aplicaciones" #: src/keycode.cpp:233 msgid "Numpad 0" -msgstr "" +msgstr "Teclado numérico 0" #: src/keycode.cpp:233 msgid "Numpad 1" -msgstr "" +msgstr "Teclado Numérico 1" #: src/keycode.cpp:233 msgid "Right Windows" -msgstr "" +msgstr "Win Derecho" #: src/keycode.cpp:233 msgid "Sleep" -msgstr "" +msgstr "Suspender" #: src/keycode.cpp:234 msgid "Numpad 2" -msgstr "" +msgstr "Teclado numérico 2" #: src/keycode.cpp:234 msgid "Numpad 3" -msgstr "" +msgstr "Teclado Numérico 3" #: src/keycode.cpp:234 msgid "Numpad 4" -msgstr "" +msgstr "Teclado numérico 4" #: src/keycode.cpp:234 msgid "Numpad 5" -msgstr "" +msgstr "Teclado Numérico 5" #: src/keycode.cpp:234 msgid "Numpad 6" -msgstr "" +msgstr "Teclado Numérico 6" #: src/keycode.cpp:234 msgid "Numpad 7" -msgstr "" +msgstr "Teclado numérico 7" #: src/keycode.cpp:235 msgid "Numpad *" -msgstr "" +msgstr "Teclado numérico *" #: src/keycode.cpp:235 msgid "Numpad +" -msgstr "" +msgstr "Teclado Numérico +" #: src/keycode.cpp:235 msgid "Numpad -" -msgstr "" +msgstr "Teclado Numérico -" #: src/keycode.cpp:235 msgid "Numpad /" -msgstr "" +msgstr "Teclado Numérico /" #: src/keycode.cpp:235 msgid "Numpad 8" -msgstr "" +msgstr "Teclado Numérico 8" #: src/keycode.cpp:235 msgid "Numpad 9" -msgstr "" +msgstr "Teclado Numérico 9" #: src/keycode.cpp:239 msgid "Num Lock" -msgstr "" +msgstr "Bloq Núm" #: src/keycode.cpp:239 msgid "Scroll Lock" -msgstr "" +msgstr "Bloq Despl" #: src/keycode.cpp:240 msgid "Left Shift" -msgstr "" +msgstr "Mayúscula Izquierda" #: src/keycode.cpp:240 msgid "Right Shift" -msgstr "" +msgstr "Mayúscula Derecha" #: src/keycode.cpp:241 msgid "Left Control" -msgstr "" +msgstr "Control Izquierdo" #: src/keycode.cpp:241 msgid "Left Menu" -msgstr "" +msgstr "Menú Izquierda" #: src/keycode.cpp:241 msgid "Right Control" -msgstr "" +msgstr "Control Derecho" #: src/keycode.cpp:241 msgid "Right Menu" -msgstr "" +msgstr "Menú Derecha" #: src/keycode.cpp:243 msgid "Comma" -msgstr "" +msgstr "Coma" #: src/keycode.cpp:243 msgid "Minus" -msgstr "" +msgstr "Menos" #: src/keycode.cpp:243 msgid "Period" -msgstr "" +msgstr "Punto" #: src/keycode.cpp:243 msgid "Plus" -msgstr "" +msgstr "Más" #: src/keycode.cpp:247 msgid "Attn" -msgstr "" +msgstr "Attn" #: src/keycode.cpp:247 msgid "CrSel" -msgstr "" +msgstr "CrSel" #: src/keycode.cpp:248 msgid "Erase OEF" -msgstr "" +msgstr "Borrar OEF" #: src/keycode.cpp:248 msgid "ExSel" -msgstr "" +msgstr "ExSel" #: src/keycode.cpp:248 msgid "OEM Clear" -msgstr "" +msgstr "OEM Limpiar" #: src/keycode.cpp:248 msgid "PA1" -msgstr "" +msgstr "PA1" #: src/keycode.cpp:248 msgid "Zoom" -msgstr "" +msgstr "Zoom" #: src/main.cpp:1384 msgid "Main Menu" -msgstr "" +msgstr "Menú Principal" #: src/main.cpp:1633 msgid "Failed to initialize world" -msgstr "" +msgstr "Fallo al iniciar el mundo" #: src/main.cpp:1645 msgid "No world selected and no address provided. Nothing to do." msgstr "" +"No se seleccionó mundo y no se ha especificado una dirección. Nada que " +"hacer." #: src/main.cpp:1653 msgid "Could not find or load game \"" -msgstr "" +msgstr "No se puede encontrar o cargar el juego \"" #: src/main.cpp:1667 msgid "Invalid gamespec." -msgstr "" +msgstr "Juego especificado no válido." #: src/main.cpp:1707 msgid "Connection error (timed out?)" -msgstr "" +msgstr "Error de conexión (¿tiempo agotado?)" #: src/main.cpp:1718 msgid "" "\n" "Check debug.txt for details." msgstr "" +"\n" +"Consulta debug.txt para obtener más detalles." diff --git a/po/fr/minetest.po b/po/fr/minetest.po index ce0ebff4f..939c53fad 100644 --- a/po/fr/minetest.po +++ b/po/fr/minetest.po @@ -8,97 +8,100 @@ msgstr "" "Project-Id-Version: 0.0.0\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-01-23 18:24+0200\n" -"PO-Revision-Date: 2011-07-21 15:48+0200\n" -"Last-Translator: Cyriaque 'Cisoun' Skrapits <cysoun@gmail.com>\n" +"PO-Revision-Date: 2013-02-05 18:25+0200\n" +"Last-Translator: we prefer instagib metl3 <calinou9999spam@gmail.com>\n" "Language-Team: Français <>\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=2; plural=(n!=1);\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" +"X-Generator: Weblate 1.4-dev\n" -#: src/guiConfigureWorld.cpp:127 +#: src/guiConfigureWorld.cpp:125 msgid "" "Warning: Some mods are not configured yet.\n" "They will be enabled by default when you save the configuration. " msgstr "" +"Attention : certains mods ne sont pas encore configurés.\n" +"Ils seront activés par défaut quand vous enregistrerez la configuration. " -#: src/guiConfigureWorld.cpp:146 +#: src/guiConfigureWorld.cpp:144 msgid "" "Warning: Some configured mods are missing.\n" "Their setting will be removed when you save the configuration. " msgstr "" +"Attention : certains mods configurés sont introuvables.\n" +"Leur réglages seront effacés quand vous enregistrerez la configuration. " -#: src/guiConfigureWorld.cpp:210 +#: src/guiConfigureWorld.cpp:208 msgid "enabled" -msgstr "" +msgstr "activé" -#: src/guiConfigureWorld.cpp:217 -#, fuzzy +#: src/guiConfigureWorld.cpp:215 msgid "Enable All" -msgstr "Activer blessures" +msgstr "Tout activer" -#: src/guiConfigureWorld.cpp:224 +#: src/guiConfigureWorld.cpp:222 msgid "Disable All" -msgstr "" +msgstr "Tout désactiver" -#: src/guiConfigureWorld.cpp:230 +#: src/guiConfigureWorld.cpp:228 msgid "depends on:" -msgstr "" +msgstr "dépend de :" -#: src/guiConfigureWorld.cpp:242 +#: src/guiConfigureWorld.cpp:240 msgid "is required by:" -msgstr "" +msgstr "est requis par :" #: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 #: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 msgid "Cancel" -msgstr "" +msgstr "Annuler" #: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 msgid "Save" -msgstr "" +msgstr "Enregistrer" #: src/guiConfigureWorld.cpp:394 msgid "Configuration saved. " -msgstr "" +msgstr "Configuration enregistrée. " #: src/guiConfigureWorld.cpp:402 msgid "Warning: Configuration not consistent. " -msgstr "" +msgstr "Attention : configuration incorrecte. " #: src/guiConfirmMenu.cpp:120 msgid "Yes" -msgstr "" +msgstr "Oui" #: src/guiConfirmMenu.cpp:126 msgid "No" -msgstr "" +msgstr "Non" #: src/guiCreateWorld.cpp:116 msgid "World name" -msgstr "" +msgstr "Nom du monde" #: src/guiCreateWorld.cpp:135 msgid "Game" -msgstr "" +msgstr "Jeu" #: src/guiCreateWorld.cpp:159 -#, fuzzy msgid "Create" -msgstr "Mode créatif" +msgstr "Créer" #: src/guiDeathScreen.cpp:96 msgid "You died." -msgstr "" +msgstr "Vous êtes mort." #: src/guiDeathScreen.cpp:104 msgid "Respawn" -msgstr "" +msgstr "Réapparaître" #: src/guiFormSpecMenu.cpp:572 msgid "Left click: Move all items, Right click: Move single item" -msgstr "" +msgstr "Clic gauche: déplacer tous les objets -- Clic droit: déplacer un objet" #: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109 #: src/guiTextInputMenu.cpp:123 @@ -107,72 +110,139 @@ msgstr "OK" #: src/guiKeyChangeMenu.cpp:114 msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" -msgstr "" +msgstr "Affectation des touches" #: src/guiKeyChangeMenu.cpp:151 msgid "\"Use\" = climb down" -msgstr "" +msgstr "\"Use\" = descendre (escalade)" #: src/guiKeyChangeMenu.cpp:164 msgid "Double tap \"jump\" to toggle fly" -msgstr "" +msgstr "Double appui sur \"saut\" pour voler" #: src/guiKeyChangeMenu.cpp:269 msgid "Key already in use" -msgstr "" +msgstr "Touche déjà utilisée" #: src/guiKeyChangeMenu.cpp:347 msgid "press key" -msgstr "" +msgstr "appuyez sur la touche" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "Avancer" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "Reculer" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "Gauche" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "Droite" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "Utiliser" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "Sauter" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "Marcher" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "Lâcher" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "Inventaire" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "Parler" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "Commande" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "Console" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "Voler" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "Mode rapide" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "Mode noclip" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "Distance de rendu" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "Imprimer stacks" #: src/guiMainMenu.cpp:55 msgid "Cannot create world: Name contains invalid characters" -msgstr "" +msgstr "Impossible de créer le monde: le nom contient des caractères invalides" #: src/guiMainMenu.cpp:64 msgid "Cannot create world: A world by this name already exists" -msgstr "" +msgstr "Impossible de créer le monde: ce nom est déjà utilisé" #: src/guiMainMenu.cpp:245 msgid "Singleplayer" -msgstr "" +msgstr "Solo" #: src/guiMainMenu.cpp:246 msgid "Multiplayer" -msgstr "" +msgstr "Multijoueur" #: src/guiMainMenu.cpp:247 msgid "Advanced" -msgstr "" +msgstr "Avancé" #: src/guiMainMenu.cpp:248 msgid "Settings" -msgstr "" +msgstr "Réglages" #: src/guiMainMenu.cpp:249 msgid "Credits" -msgstr "" +msgstr "Crédits" #: src/guiMainMenu.cpp:280 msgid "Select World:" -msgstr "" +msgstr "Sélectionner le monde :" #: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229 -#, fuzzy msgid "Delete" -msgstr "Supprimer carte" +msgstr "Supprimer" #: src/guiMainMenu.cpp:309 msgid "New" -msgstr "" +msgstr "Nouveau" #: src/guiMainMenu.cpp:317 msgid "Configure" -msgstr "" +msgstr "Configurer" #: src/guiMainMenu.cpp:332 src/keycode.cpp:248 msgid "Play" -msgstr "" +msgstr "Jouer" #: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557 msgid "Creative Mode" @@ -192,16 +262,15 @@ msgstr "Adresse / Port" #: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075 msgid "Show Public" -msgstr "" +msgstr "Voir serveurs publics" #: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083 msgid "Show Favorites" -msgstr "" +msgstr "Voir serveurs favoris" #: src/guiMainMenu.cpp:459 -#, fuzzy msgid "Connect" -msgstr "Déconnection" +msgstr "Rejoindre" #: src/guiMainMenu.cpp:529 msgid "Leave address blank to start a local server." @@ -212,12 +281,10 @@ msgid "Start Game / Connect" msgstr "Démarrer / Connecter" #: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006 -#, fuzzy msgid "Delete world" -msgstr "Supprimer carte" +msgstr "Supprimer monde" #: src/guiMainMenu.cpp:577 -#, fuzzy msgid "Create world" msgstr "Mode créatif" @@ -231,40 +298,39 @@ msgstr "Lumière douce" #: src/guiMainMenu.cpp:623 msgid "3D Clouds" -msgstr "" +msgstr "Nuages 3D" #: src/guiMainMenu.cpp:629 msgid "Opaque water" -msgstr "" +msgstr "Eau opaque" #: src/guiMainMenu.cpp:639 msgid "Mip-Mapping" -msgstr "" +msgstr "Mip-mapping" #: src/guiMainMenu.cpp:646 msgid "Anisotropic Filtering" -msgstr "" +msgstr "Filtrage anisotropique" #: src/guiMainMenu.cpp:653 msgid "Bi-Linear Filtering" -msgstr "" +msgstr "Filtrage bilinéaire" #: src/guiMainMenu.cpp:660 msgid "Tri-Linear Filtering" -msgstr "" +msgstr "Filtrage trilinéaire" #: src/guiMainMenu.cpp:668 msgid "Shaders" -msgstr "" +msgstr "Shaders" #: src/guiMainMenu.cpp:675 msgid "Preload item visuals" -msgstr "" +msgstr "Précharger les visuels d'objets" #: src/guiMainMenu.cpp:682 -#, fuzzy msgid "Enable Particles" -msgstr "Activer blessures" +msgstr "Activer les particules" #: src/guiMainMenu.cpp:692 msgid "Change keys" @@ -272,27 +338,27 @@ msgstr "Changer touches" #: src/guiMainMenu.cpp:977 msgid "Address required." -msgstr "" +msgstr "Adresse requise." #: src/guiMainMenu.cpp:995 msgid "Cannot delete world: Nothing selected" -msgstr "" +msgstr "Impossible de supprimer le monde : rien n'est sélectionné" #: src/guiMainMenu.cpp:1010 msgid "Files to be deleted" -msgstr "" +msgstr "Fichiers à effacer" #: src/guiMainMenu.cpp:1026 msgid "Cannot create world: No games found" -msgstr "" +msgstr "Impossible de créer le monde : aucun jeu n'est présent" #: src/guiMainMenu.cpp:1042 msgid "Cannot configure world: Nothing selected" -msgstr "" +msgstr "Impossible de configurer ce monde : aucune sélection active" #: src/guiMainMenu.cpp:1146 msgid "Failed to delete all world files" -msgstr "" +msgstr "Tous les fichiers du monde n'ont pu être effacés" #: src/guiPasswordChange.cpp:108 msgid "Old Password" @@ -312,7 +378,7 @@ msgstr "Changer" #: src/guiPasswordChange.cpp:167 msgid "Passwords do not match!" -msgstr "Mauvaise correspondance!" +msgstr "Mot de passe incorrect !" #: src/guiPauseMenu.cpp:118 msgid "Continue" @@ -323,16 +389,14 @@ msgid "Change Password" msgstr "Changer mot de passe" #: src/guiPauseMenu.cpp:135 -#, fuzzy msgid "Exit to Menu" -msgstr "Quitter le jeu" +msgstr "Quitter vers le menu" #: src/guiPauseMenu.cpp:142 msgid "Exit to OS" msgstr "Quitter le jeu" #: src/guiPauseMenu.cpp:149 -#, fuzzy msgid "" "Default Controls:\n" "- WASD: Walk\n" @@ -346,347 +410,340 @@ msgid "" "- ESC: This menu\n" "- T: Chat\n" msgstr "" -"Touches:\n" -"- WASD: Marcher\n" -"- Clic gauche: Creuser bloc\n" -"- Clic droite: Insérer bloc\n" -"- Roulette: Sélection élément\n" -"- 0...9: Sélection élément\n" -"- Shift: S'accroupir\n" -"- R: Active la vue de tous les blocs\n" -"- I: Inventaire\n" -"- T: Chat\n" +"Touches :\n" +"- ZQSD : courir\n" +"- Clic gauche : Creuser bloc\n" +"- Clic droite : Insérer bloc\n" +"- Roulette : Sélection objet\n" +"- 0...9 : Sélection objet\n" +"- Shift : marcher\n" +"- R : active la vue de tous les blocs\n" +"- I : inventaire\n" +"- T : parler\n" #: src/keycode.cpp:223 msgid "Left Button" -msgstr "" +msgstr "Bouton gauche" #: src/keycode.cpp:223 msgid "Middle Button" -msgstr "" +msgstr "Bouton milieu" #: src/keycode.cpp:223 msgid "Right Button" -msgstr "" +msgstr "Bouton droit" #: src/keycode.cpp:223 msgid "X Button 1" -msgstr "" +msgstr "Bouton X 1" #: src/keycode.cpp:224 msgid "Back" -msgstr "" +msgstr "Retour arrière" #: src/keycode.cpp:224 msgid "Clear" -msgstr "" +msgstr "Vider" #: src/keycode.cpp:224 msgid "Return" -msgstr "" +msgstr "Retour" #: src/keycode.cpp:224 msgid "Tab" -msgstr "" +msgstr "Tabulation" #: src/keycode.cpp:224 msgid "X Button 2" -msgstr "" +msgstr "Bouton X 2" #: src/keycode.cpp:225 msgid "Capital" -msgstr "" +msgstr "Verr. maj." #: src/keycode.cpp:225 msgid "Control" -msgstr "" +msgstr "Contrôle" #: src/keycode.cpp:225 msgid "Kana" -msgstr "" +msgstr "Kana" #: src/keycode.cpp:225 msgid "Menu" -msgstr "" +msgstr "Menu" #: src/keycode.cpp:225 msgid "Pause" -msgstr "" +msgstr "Pause" #: src/keycode.cpp:225 msgid "Shift" -msgstr "" +msgstr "Majuscule" #: src/keycode.cpp:226 msgid "Convert" -msgstr "" +msgstr "Convertir" #: src/keycode.cpp:226 msgid "Escape" -msgstr "" +msgstr "Échap" #: src/keycode.cpp:226 msgid "Final" -msgstr "" +msgstr "Final" #: src/keycode.cpp:226 msgid "Junja" -msgstr "" +msgstr "Junja" #: src/keycode.cpp:226 msgid "Kanji" -msgstr "" +msgstr "Kanji" #: src/keycode.cpp:226 msgid "Nonconvert" -msgstr "" +msgstr "Nonconvert" #: src/keycode.cpp:227 msgid "Accept" -msgstr "" +msgstr "Accepter" #: src/keycode.cpp:227 msgid "End" -msgstr "" +msgstr "Fin" #: src/keycode.cpp:227 msgid "Home" -msgstr "" +msgstr "Origine" #: src/keycode.cpp:227 -#, fuzzy msgid "Mode Change" -msgstr "Changer" +msgstr "Changer de mode" #: src/keycode.cpp:227 msgid "Next" -msgstr "" +msgstr "Suivant" #: src/keycode.cpp:227 msgid "Prior" -msgstr "" +msgstr "Précèdent" #: src/keycode.cpp:227 msgid "Space" -msgstr "" +msgstr "Espace" #: src/keycode.cpp:228 msgid "Down" -msgstr "" +msgstr "Bas" #: src/keycode.cpp:228 msgid "Execute" -msgstr "" - -#: src/keycode.cpp:228 -msgid "Left" -msgstr "" +msgstr "Éxécuter" #: src/keycode.cpp:228 msgid "Print" -msgstr "" - -#: src/keycode.cpp:228 -msgid "Right" -msgstr "" +msgstr "Imprimer" #: src/keycode.cpp:228 msgid "Select" -msgstr "" +msgstr "Sélectionner" #: src/keycode.cpp:228 msgid "Up" -msgstr "" +msgstr "Haut" #: src/keycode.cpp:229 msgid "Help" -msgstr "" +msgstr "Aide" #: src/keycode.cpp:229 msgid "Insert" -msgstr "" +msgstr "Insérer" #: src/keycode.cpp:229 msgid "Snapshot" -msgstr "" +msgstr "Capture d'écran" #: src/keycode.cpp:232 msgid "Left Windows" -msgstr "" +msgstr "Windows gauche" #: src/keycode.cpp:233 msgid "Apps" -msgstr "" +msgstr "Applications" #: src/keycode.cpp:233 msgid "Numpad 0" -msgstr "" +msgstr "Pavé num. 0" #: src/keycode.cpp:233 msgid "Numpad 1" -msgstr "" +msgstr "Pavé num. 1" #: src/keycode.cpp:233 msgid "Right Windows" -msgstr "" +msgstr "Windows droite" #: src/keycode.cpp:233 msgid "Sleep" -msgstr "" +msgstr "Mise en veille" #: src/keycode.cpp:234 msgid "Numpad 2" -msgstr "" +msgstr "Pavé num. 2" #: src/keycode.cpp:234 msgid "Numpad 3" -msgstr "" +msgstr "Pavé num. 3" #: src/keycode.cpp:234 msgid "Numpad 4" -msgstr "" +msgstr "Pavé num. 4" #: src/keycode.cpp:234 msgid "Numpad 5" -msgstr "" +msgstr "Pavé num. 5" #: src/keycode.cpp:234 msgid "Numpad 6" -msgstr "" +msgstr "Pavé num. 6" #: src/keycode.cpp:234 msgid "Numpad 7" -msgstr "" +msgstr "Pavé num. 7" #: src/keycode.cpp:235 msgid "Numpad *" -msgstr "" +msgstr "Pavé num. *" #: src/keycode.cpp:235 msgid "Numpad +" -msgstr "" +msgstr "Pavé num. +" #: src/keycode.cpp:235 msgid "Numpad -" -msgstr "" +msgstr "Pavé num. -" #: src/keycode.cpp:235 msgid "Numpad /" -msgstr "" +msgstr "Pavé num. /" #: src/keycode.cpp:235 msgid "Numpad 8" -msgstr "" +msgstr "Pavé num. 8" #: src/keycode.cpp:235 msgid "Numpad 9" -msgstr "" +msgstr "Pavé num. 9" #: src/keycode.cpp:239 msgid "Num Lock" -msgstr "" +msgstr "Verr. pavé num." #: src/keycode.cpp:239 msgid "Scroll Lock" -msgstr "" +msgstr "Verr. défilement" #: src/keycode.cpp:240 msgid "Left Shift" -msgstr "" +msgstr "Majuscule gauche" #: src/keycode.cpp:240 msgid "Right Shift" -msgstr "" +msgstr "Majuscule droite" #: src/keycode.cpp:241 msgid "Left Control" -msgstr "" +msgstr "Contrôle gauche" #: src/keycode.cpp:241 msgid "Left Menu" -msgstr "" +msgstr "Menu gauche" #: src/keycode.cpp:241 msgid "Right Control" -msgstr "" +msgstr "Contrôle droite" #: src/keycode.cpp:241 msgid "Right Menu" -msgstr "" +msgstr "Menu droite" #: src/keycode.cpp:243 msgid "Comma" -msgstr "" +msgstr "Virgule" #: src/keycode.cpp:243 msgid "Minus" -msgstr "" +msgstr "Moins" #: src/keycode.cpp:243 msgid "Period" -msgstr "" +msgstr "Point" #: src/keycode.cpp:243 msgid "Plus" -msgstr "" +msgstr "Plus" #: src/keycode.cpp:247 msgid "Attn" -msgstr "" +msgstr "Attente" #: src/keycode.cpp:247 msgid "CrSel" -msgstr "" +msgstr "Vider sélection" #: src/keycode.cpp:248 msgid "Erase OEF" -msgstr "" +msgstr "Écraser l'OEF" #: src/keycode.cpp:248 msgid "ExSel" -msgstr "" +msgstr "ExSel" #: src/keycode.cpp:248 msgid "OEM Clear" -msgstr "" +msgstr "OEM Clear" #: src/keycode.cpp:248 msgid "PA1" -msgstr "" +msgstr "PA1" #: src/keycode.cpp:248 msgid "Zoom" -msgstr "" +msgstr "Zoomer" #: src/main.cpp:1384 msgid "Main Menu" -msgstr "" +msgstr "Menu principal" #: src/main.cpp:1633 msgid "Failed to initialize world" -msgstr "" +msgstr "Le monde n'a pas pu être initialisé" #: src/main.cpp:1645 msgid "No world selected and no address provided. Nothing to do." -msgstr "" +msgstr "Pas de monde sélectionné et pas d'adresse. Rien à faire." #: src/main.cpp:1653 msgid "Could not find or load game \"" -msgstr "" +msgstr "N'a pas pu trouver ou charger le jeu \"" #: src/main.cpp:1667 msgid "Invalid gamespec." -msgstr "" +msgstr "gamespec invalide." #: src/main.cpp:1707 msgid "Connection error (timed out?)" -msgstr "" +msgstr "Erreur de connexion (perte de connexion ?)" #: src/main.cpp:1718 msgid "" "\n" "Check debug.txt for details." msgstr "" +"\n" +"Voir debug.txt pour plus d'information." #~ msgid "Delete map" #~ msgstr "Supprimer carte" diff --git a/po/it/minetest.po b/po/it/minetest.po index 4a0daf7f9..09c4b4ca2 100644 --- a/po/it/minetest.po +++ b/po/it/minetest.po @@ -8,45 +8,48 @@ msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-01-23 18:24+0200\n" -"PO-Revision-Date: 2011-07-24 18:56+0200\n" -"Last-Translator: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>\n" +"PO-Revision-Date: 2013-02-09 22:18+0200\n" +"Last-Translator: Pilz Adam <PilzAdam@gmx.de>\n" "Language-Team: Italian\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Weblate 1.4-dev\n" -#: src/guiConfigureWorld.cpp:127 +#: src/guiConfigureWorld.cpp:125 msgid "" "Warning: Some mods are not configured yet.\n" "They will be enabled by default when you save the configuration. " msgstr "" +"Attenzione: Alcuni mods non sono ancora configurati.\n" +"Saranno attivati, in modo predefinito, al salvataggio delle impostazioni. " -#: src/guiConfigureWorld.cpp:146 +#: src/guiConfigureWorld.cpp:144 msgid "" "Warning: Some configured mods are missing.\n" "Their setting will be removed when you save the configuration. " msgstr "" -#: src/guiConfigureWorld.cpp:210 +#: src/guiConfigureWorld.cpp:208 msgid "enabled" msgstr "" -#: src/guiConfigureWorld.cpp:217 +#: src/guiConfigureWorld.cpp:215 #, fuzzy msgid "Enable All" msgstr "Attiva Danno" -#: src/guiConfigureWorld.cpp:224 +#: src/guiConfigureWorld.cpp:222 msgid "Disable All" msgstr "" -#: src/guiConfigureWorld.cpp:230 +#: src/guiConfigureWorld.cpp:228 msgid "depends on:" msgstr "" -#: src/guiConfigureWorld.cpp:242 +#: src/guiConfigureWorld.cpp:240 msgid "is required by:" msgstr "" @@ -126,6 +129,74 @@ msgstr "" msgid "press key" msgstr "premi tasto" +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "Avanti" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "Indietro" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "Sinistra" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "Destra" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "Usa" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "Salta" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "Invetario" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "Parla" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "" + #: src/guiMainMenu.cpp:55 msgid "Cannot create world: Name contains invalid characters" msgstr "" @@ -205,7 +276,7 @@ msgstr "Disconnetti" #: src/guiMainMenu.cpp:529 msgid "Leave address blank to start a local server." -msgstr "Lascia vuoto l'indirizzo per avviare un server locale" +msgstr "Lascia vuoto l'indirizzo per avviare un server locale." #: src/guiMainMenu.cpp:538 msgid "Start Game / Connect" @@ -479,18 +550,10 @@ msgid "Execute" msgstr "" #: src/keycode.cpp:228 -msgid "Left" -msgstr "Sinistra" - -#: src/keycode.cpp:228 msgid "Print" msgstr "Stampa" #: src/keycode.cpp:228 -msgid "Right" -msgstr "Destra" - -#: src/keycode.cpp:228 msgid "Select" msgstr "" @@ -691,21 +754,3 @@ msgstr "" #~ msgid "Delete map" #~ msgstr "Cancella mappa" - -#~ msgid "Chat" -#~ msgstr "Parla" - -#~ msgid "Inventory" -#~ msgstr "Invetario" - -#~ msgid "Jump" -#~ msgstr "Salta" - -#~ msgid "Use" -#~ msgstr "Usa" - -#~ msgid "Backward" -#~ msgstr "Indietro" - -#~ msgid "Forward" -#~ msgstr "Avanti" diff --git a/po/ja/minetest.po b/po/ja/minetest.po new file mode 100644 index 000000000..d2ca9cad9 --- /dev/null +++ b/po/ja/minetest.po @@ -0,0 +1,730 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: minetest\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-01-30 20:25+0100\n" +"PO-Revision-Date: 2013-02-07 17:38+0200\n" +"Last-Translator: Mitori Itoshiki <mito551@gmail.com>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 1.4-dev\n" + +#: src/guiConfigureWorld.cpp:125 +msgid "" +"Warning: Some mods are not configured yet.\n" +"They will be enabled by default when you save the configuration. " +msgstr "" + +#: src/guiConfigureWorld.cpp:144 +msgid "" +"Warning: Some configured mods are missing.\n" +"Their setting will be removed when you save the configuration. " +msgstr "" + +#: src/guiConfigureWorld.cpp:208 +msgid "enabled" +msgstr "有効しました" + +#: src/guiConfigureWorld.cpp:215 +msgid "Enable All" +msgstr "全部を有効する" + +#: src/guiConfigureWorld.cpp:222 +msgid "Disable All" +msgstr "全部を無効する" + +#: src/guiConfigureWorld.cpp:228 +msgid "depends on:" +msgstr "" + +#: src/guiConfigureWorld.cpp:240 +msgid "is required by:" +msgstr "" + +#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 +#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 +msgid "Cancel" +msgstr "キャンセル" + +#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 +msgid "Save" +msgstr "保存" + +#: src/guiConfigureWorld.cpp:394 +msgid "Configuration saved. " +msgstr "" + +#: src/guiConfigureWorld.cpp:402 +msgid "Warning: Configuration not consistent. " +msgstr "" + +#: src/guiConfirmMenu.cpp:120 +msgid "Yes" +msgstr "はい" + +#: src/guiConfirmMenu.cpp:126 +msgid "No" +msgstr "いいえ" + +#: src/guiCreateWorld.cpp:116 +msgid "World name" +msgstr "ワールド名" + +#: src/guiCreateWorld.cpp:135 +msgid "Game" +msgstr "ゲーム" + +#: src/guiCreateWorld.cpp:159 +msgid "Create" +msgstr "設ける" + +#: src/guiDeathScreen.cpp:96 +msgid "You died." +msgstr "死んでしまいました。" + +#: src/guiDeathScreen.cpp:104 +msgid "Respawn" +msgstr "生まれて帰る" + +#: src/guiFormSpecMenu.cpp:572 +msgid "Left click: Move all items, Right click: Move single item" +msgstr "" + +#: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109 +#: src/guiTextInputMenu.cpp:123 +msgid "Proceed" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:114 +msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:151 +msgid "\"Use\" = climb down" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:164 +msgid "Double tap \"jump\" to toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:269 +msgid "Key already in use" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:347 +msgid "press key" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "" + +#: src/guiMainMenu.cpp:55 +msgid "Cannot create world: Name contains invalid characters" +msgstr "" + +#: src/guiMainMenu.cpp:64 +msgid "Cannot create world: A world by this name already exists" +msgstr "" + +#: src/guiMainMenu.cpp:245 +msgid "Singleplayer" +msgstr "" + +#: src/guiMainMenu.cpp:246 +msgid "Multiplayer" +msgstr "" + +#: src/guiMainMenu.cpp:247 +msgid "Advanced" +msgstr "" + +#: src/guiMainMenu.cpp:248 +msgid "Settings" +msgstr "" + +#: src/guiMainMenu.cpp:249 +msgid "Credits" +msgstr "" + +#: src/guiMainMenu.cpp:280 +msgid "Select World:" +msgstr "" + +#: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229 +msgid "Delete" +msgstr "" + +#: src/guiMainMenu.cpp:309 +msgid "New" +msgstr "" + +#: src/guiMainMenu.cpp:317 +msgid "Configure" +msgstr "" + +#: src/guiMainMenu.cpp:332 src/keycode.cpp:248 +msgid "Play" +msgstr "" + +#: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557 +msgid "Creative Mode" +msgstr "" + +#: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563 +msgid "Enable Damage" +msgstr "" + +#: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479 +msgid "Name/Password" +msgstr "" + +#: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506 +msgid "Address/Port" +msgstr "" + +#: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075 +msgid "Show Public" +msgstr "" + +#: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083 +msgid "Show Favorites" +msgstr "" + +#: src/guiMainMenu.cpp:459 +msgid "Connect" +msgstr "" + +#: src/guiMainMenu.cpp:529 +msgid "Leave address blank to start a local server." +msgstr "" + +#: src/guiMainMenu.cpp:538 +msgid "Start Game / Connect" +msgstr "" + +#: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006 +msgid "Delete world" +msgstr "" + +#: src/guiMainMenu.cpp:577 +msgid "Create world" +msgstr "" + +#: src/guiMainMenu.cpp:611 +msgid "Fancy trees" +msgstr "" + +#: src/guiMainMenu.cpp:617 +msgid "Smooth Lighting" +msgstr "" + +#: src/guiMainMenu.cpp:623 +msgid "3D Clouds" +msgstr "" + +#: src/guiMainMenu.cpp:629 +msgid "Opaque water" +msgstr "" + +#: src/guiMainMenu.cpp:639 +msgid "Mip-Mapping" +msgstr "" + +#: src/guiMainMenu.cpp:646 +msgid "Anisotropic Filtering" +msgstr "" + +#: src/guiMainMenu.cpp:653 +msgid "Bi-Linear Filtering" +msgstr "" + +#: src/guiMainMenu.cpp:660 +msgid "Tri-Linear Filtering" +msgstr "" + +#: src/guiMainMenu.cpp:668 +msgid "Shaders" +msgstr "" + +#: src/guiMainMenu.cpp:675 +msgid "Preload item visuals" +msgstr "" + +#: src/guiMainMenu.cpp:682 +msgid "Enable Particles" +msgstr "" + +#: src/guiMainMenu.cpp:692 +msgid "Change keys" +msgstr "" + +#: src/guiMainMenu.cpp:977 +msgid "Address required." +msgstr "" + +#: src/guiMainMenu.cpp:995 +msgid "Cannot delete world: Nothing selected" +msgstr "" + +#: src/guiMainMenu.cpp:1010 +msgid "Files to be deleted" +msgstr "" + +#: src/guiMainMenu.cpp:1026 +msgid "Cannot create world: No games found" +msgstr "" + +#: src/guiMainMenu.cpp:1042 +msgid "Cannot configure world: Nothing selected" +msgstr "" + +#: src/guiMainMenu.cpp:1146 +msgid "Failed to delete all world files" +msgstr "" + +#: src/guiPasswordChange.cpp:108 +msgid "Old Password" +msgstr "" + +#: src/guiPasswordChange.cpp:125 +msgid "New Password" +msgstr "" + +#: src/guiPasswordChange.cpp:141 +msgid "Confirm Password" +msgstr "" + +#: src/guiPasswordChange.cpp:158 +msgid "Change" +msgstr "" + +#: src/guiPasswordChange.cpp:167 +msgid "Passwords do not match!" +msgstr "" + +#: src/guiPauseMenu.cpp:118 +msgid "Continue" +msgstr "" + +#: src/guiPauseMenu.cpp:127 +msgid "Change Password" +msgstr "" + +#: src/guiPauseMenu.cpp:135 +msgid "Exit to Menu" +msgstr "" + +#: src/guiPauseMenu.cpp:142 +msgid "Exit to OS" +msgstr "" + +#: src/guiPauseMenu.cpp:149 +msgid "" +"Default Controls:\n" +"- WASD: Walk\n" +"- Mouse left: dig/hit\n" +"- Mouse right: place/use\n" +"- Mouse wheel: select item\n" +"- 0...9: select item\n" +"- Shift: sneak\n" +"- R: Toggle viewing all loaded chunks\n" +"- I: Inventory menu\n" +"- ESC: This menu\n" +"- T: Chat\n" +msgstr "" + +#: src/keycode.cpp:223 +msgid "Left Button" +msgstr "" + +#: src/keycode.cpp:223 +msgid "Middle Button" +msgstr "" + +#: src/keycode.cpp:223 +msgid "Right Button" +msgstr "" + +#: src/keycode.cpp:223 +msgid "X Button 1" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Back" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Clear" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Return" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Tab" +msgstr "" + +#: src/keycode.cpp:224 +msgid "X Button 2" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Capital" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Control" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Kana" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Menu" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Pause" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Shift" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Convert" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Escape" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Final" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Junja" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Kanji" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Nonconvert" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Accept" +msgstr "" + +#: src/keycode.cpp:227 +msgid "End" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Home" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Mode Change" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Next" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Prior" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Space" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Down" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Execute" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Print" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Select" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Up" +msgstr "" + +#: src/keycode.cpp:229 +msgid "Help" +msgstr "" + +#: src/keycode.cpp:229 +msgid "Insert" +msgstr "" + +#: src/keycode.cpp:229 +msgid "Snapshot" +msgstr "" + +#: src/keycode.cpp:232 +msgid "Left Windows" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Apps" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Numpad 0" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Numpad 1" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Right Windows" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Sleep" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 2" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 3" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 4" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 5" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 6" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 7" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad *" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad +" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad -" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad /" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad 8" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad 9" +msgstr "" + +#: src/keycode.cpp:239 +msgid "Num Lock" +msgstr "" + +#: src/keycode.cpp:239 +msgid "Scroll Lock" +msgstr "" + +#: src/keycode.cpp:240 +msgid "Left Shift" +msgstr "" + +#: src/keycode.cpp:240 +msgid "Right Shift" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Left Control" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Left Menu" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Right Control" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Right Menu" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Comma" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Minus" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Period" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Plus" +msgstr "" + +#: src/keycode.cpp:247 +msgid "Attn" +msgstr "" + +#: src/keycode.cpp:247 +msgid "CrSel" +msgstr "" + +#: src/keycode.cpp:248 +msgid "Erase OEF" +msgstr "" + +#: src/keycode.cpp:248 +msgid "ExSel" +msgstr "" + +#: src/keycode.cpp:248 +msgid "OEM Clear" +msgstr "" + +#: src/keycode.cpp:248 +msgid "PA1" +msgstr "" + +#: src/keycode.cpp:248 +msgid "Zoom" +msgstr "" + +#: src/main.cpp:1384 +msgid "Main Menu" +msgstr "" + +#: src/main.cpp:1633 +msgid "Failed to initialize world" +msgstr "" + +#: src/main.cpp:1645 +msgid "No world selected and no address provided. Nothing to do." +msgstr "" + +#: src/main.cpp:1653 +msgid "Could not find or load game \"" +msgstr "" + +#: src/main.cpp:1667 +msgid "Invalid gamespec." +msgstr "" + +#: src/main.cpp:1707 +msgid "Connection error (timed out?)" +msgstr "" + +#: src/main.cpp:1718 +msgid "" +"\n" +"Check debug.txt for details." +msgstr "" diff --git a/po/ko/minetest.po b/po/ko/minetest.po new file mode 100644 index 000000000..f07b816a5 --- /dev/null +++ b/po/ko/minetest.po @@ -0,0 +1,729 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: minetest\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-01-30 20:25+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/guiConfigureWorld.cpp:125 +msgid "" +"Warning: Some mods are not configured yet.\n" +"They will be enabled by default when you save the configuration. " +msgstr "" + +#: src/guiConfigureWorld.cpp:144 +msgid "" +"Warning: Some configured mods are missing.\n" +"Their setting will be removed when you save the configuration. " +msgstr "" + +#: src/guiConfigureWorld.cpp:208 +msgid "enabled" +msgstr "" + +#: src/guiConfigureWorld.cpp:215 +msgid "Enable All" +msgstr "" + +#: src/guiConfigureWorld.cpp:222 +msgid "Disable All" +msgstr "" + +#: src/guiConfigureWorld.cpp:228 +msgid "depends on:" +msgstr "" + +#: src/guiConfigureWorld.cpp:240 +msgid "is required by:" +msgstr "" + +#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 +#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 +msgid "Cancel" +msgstr "" + +#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 +msgid "Save" +msgstr "" + +#: src/guiConfigureWorld.cpp:394 +msgid "Configuration saved. " +msgstr "" + +#: src/guiConfigureWorld.cpp:402 +msgid "Warning: Configuration not consistent. " +msgstr "" + +#: src/guiConfirmMenu.cpp:120 +msgid "Yes" +msgstr "" + +#: src/guiConfirmMenu.cpp:126 +msgid "No" +msgstr "" + +#: src/guiCreateWorld.cpp:116 +msgid "World name" +msgstr "" + +#: src/guiCreateWorld.cpp:135 +msgid "Game" +msgstr "" + +#: src/guiCreateWorld.cpp:159 +msgid "Create" +msgstr "" + +#: src/guiDeathScreen.cpp:96 +msgid "You died." +msgstr "" + +#: src/guiDeathScreen.cpp:104 +msgid "Respawn" +msgstr "" + +#: src/guiFormSpecMenu.cpp:572 +msgid "Left click: Move all items, Right click: Move single item" +msgstr "" + +#: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109 +#: src/guiTextInputMenu.cpp:123 +msgid "Proceed" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:114 +msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:151 +msgid "\"Use\" = climb down" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:164 +msgid "Double tap \"jump\" to toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:269 +msgid "Key already in use" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:347 +msgid "press key" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "" + +#: src/guiMainMenu.cpp:55 +msgid "Cannot create world: Name contains invalid characters" +msgstr "" + +#: src/guiMainMenu.cpp:64 +msgid "Cannot create world: A world by this name already exists" +msgstr "" + +#: src/guiMainMenu.cpp:245 +msgid "Singleplayer" +msgstr "" + +#: src/guiMainMenu.cpp:246 +msgid "Multiplayer" +msgstr "" + +#: src/guiMainMenu.cpp:247 +msgid "Advanced" +msgstr "" + +#: src/guiMainMenu.cpp:248 +msgid "Settings" +msgstr "" + +#: src/guiMainMenu.cpp:249 +msgid "Credits" +msgstr "" + +#: src/guiMainMenu.cpp:280 +msgid "Select World:" +msgstr "" + +#: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229 +msgid "Delete" +msgstr "" + +#: src/guiMainMenu.cpp:309 +msgid "New" +msgstr "" + +#: src/guiMainMenu.cpp:317 +msgid "Configure" +msgstr "" + +#: src/guiMainMenu.cpp:332 src/keycode.cpp:248 +msgid "Play" +msgstr "" + +#: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557 +msgid "Creative Mode" +msgstr "" + +#: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563 +msgid "Enable Damage" +msgstr "" + +#: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479 +msgid "Name/Password" +msgstr "" + +#: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506 +msgid "Address/Port" +msgstr "" + +#: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075 +msgid "Show Public" +msgstr "" + +#: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083 +msgid "Show Favorites" +msgstr "" + +#: src/guiMainMenu.cpp:459 +msgid "Connect" +msgstr "" + +#: src/guiMainMenu.cpp:529 +msgid "Leave address blank to start a local server." +msgstr "" + +#: src/guiMainMenu.cpp:538 +msgid "Start Game / Connect" +msgstr "" + +#: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006 +msgid "Delete world" +msgstr "" + +#: src/guiMainMenu.cpp:577 +msgid "Create world" +msgstr "" + +#: src/guiMainMenu.cpp:611 +msgid "Fancy trees" +msgstr "" + +#: src/guiMainMenu.cpp:617 +msgid "Smooth Lighting" +msgstr "" + +#: src/guiMainMenu.cpp:623 +msgid "3D Clouds" +msgstr "" + +#: src/guiMainMenu.cpp:629 +msgid "Opaque water" +msgstr "" + +#: src/guiMainMenu.cpp:639 +msgid "Mip-Mapping" +msgstr "" + +#: src/guiMainMenu.cpp:646 +msgid "Anisotropic Filtering" +msgstr "" + +#: src/guiMainMenu.cpp:653 +msgid "Bi-Linear Filtering" +msgstr "" + +#: src/guiMainMenu.cpp:660 +msgid "Tri-Linear Filtering" +msgstr "" + +#: src/guiMainMenu.cpp:668 +msgid "Shaders" +msgstr "" + +#: src/guiMainMenu.cpp:675 +msgid "Preload item visuals" +msgstr "" + +#: src/guiMainMenu.cpp:682 +msgid "Enable Particles" +msgstr "" + +#: src/guiMainMenu.cpp:692 +msgid "Change keys" +msgstr "" + +#: src/guiMainMenu.cpp:977 +msgid "Address required." +msgstr "" + +#: src/guiMainMenu.cpp:995 +msgid "Cannot delete world: Nothing selected" +msgstr "" + +#: src/guiMainMenu.cpp:1010 +msgid "Files to be deleted" +msgstr "" + +#: src/guiMainMenu.cpp:1026 +msgid "Cannot create world: No games found" +msgstr "" + +#: src/guiMainMenu.cpp:1042 +msgid "Cannot configure world: Nothing selected" +msgstr "" + +#: src/guiMainMenu.cpp:1146 +msgid "Failed to delete all world files" +msgstr "" + +#: src/guiPasswordChange.cpp:108 +msgid "Old Password" +msgstr "" + +#: src/guiPasswordChange.cpp:125 +msgid "New Password" +msgstr "" + +#: src/guiPasswordChange.cpp:141 +msgid "Confirm Password" +msgstr "" + +#: src/guiPasswordChange.cpp:158 +msgid "Change" +msgstr "" + +#: src/guiPasswordChange.cpp:167 +msgid "Passwords do not match!" +msgstr "" + +#: src/guiPauseMenu.cpp:118 +msgid "Continue" +msgstr "" + +#: src/guiPauseMenu.cpp:127 +msgid "Change Password" +msgstr "" + +#: src/guiPauseMenu.cpp:135 +msgid "Exit to Menu" +msgstr "" + +#: src/guiPauseMenu.cpp:142 +msgid "Exit to OS" +msgstr "" + +#: src/guiPauseMenu.cpp:149 +msgid "" +"Default Controls:\n" +"- WASD: Walk\n" +"- Mouse left: dig/hit\n" +"- Mouse right: place/use\n" +"- Mouse wheel: select item\n" +"- 0...9: select item\n" +"- Shift: sneak\n" +"- R: Toggle viewing all loaded chunks\n" +"- I: Inventory menu\n" +"- ESC: This menu\n" +"- T: Chat\n" +msgstr "" + +#: src/keycode.cpp:223 +msgid "Left Button" +msgstr "" + +#: src/keycode.cpp:223 +msgid "Middle Button" +msgstr "" + +#: src/keycode.cpp:223 +msgid "Right Button" +msgstr "" + +#: src/keycode.cpp:223 +msgid "X Button 1" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Back" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Clear" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Return" +msgstr "" + +#: src/keycode.cpp:224 +msgid "Tab" +msgstr "" + +#: src/keycode.cpp:224 +msgid "X Button 2" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Capital" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Control" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Kana" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Menu" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Pause" +msgstr "" + +#: src/keycode.cpp:225 +msgid "Shift" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Convert" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Escape" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Final" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Junja" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Kanji" +msgstr "" + +#: src/keycode.cpp:226 +msgid "Nonconvert" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Accept" +msgstr "" + +#: src/keycode.cpp:227 +msgid "End" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Home" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Mode Change" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Next" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Prior" +msgstr "" + +#: src/keycode.cpp:227 +msgid "Space" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Down" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Execute" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Print" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Select" +msgstr "" + +#: src/keycode.cpp:228 +msgid "Up" +msgstr "" + +#: src/keycode.cpp:229 +msgid "Help" +msgstr "" + +#: src/keycode.cpp:229 +msgid "Insert" +msgstr "" + +#: src/keycode.cpp:229 +msgid "Snapshot" +msgstr "" + +#: src/keycode.cpp:232 +msgid "Left Windows" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Apps" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Numpad 0" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Numpad 1" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Right Windows" +msgstr "" + +#: src/keycode.cpp:233 +msgid "Sleep" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 2" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 3" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 4" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 5" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 6" +msgstr "" + +#: src/keycode.cpp:234 +msgid "Numpad 7" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad *" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad +" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad -" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad /" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad 8" +msgstr "" + +#: src/keycode.cpp:235 +msgid "Numpad 9" +msgstr "" + +#: src/keycode.cpp:239 +msgid "Num Lock" +msgstr "" + +#: src/keycode.cpp:239 +msgid "Scroll Lock" +msgstr "" + +#: src/keycode.cpp:240 +msgid "Left Shift" +msgstr "" + +#: src/keycode.cpp:240 +msgid "Right Shift" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Left Control" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Left Menu" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Right Control" +msgstr "" + +#: src/keycode.cpp:241 +msgid "Right Menu" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Comma" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Minus" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Period" +msgstr "" + +#: src/keycode.cpp:243 +msgid "Plus" +msgstr "" + +#: src/keycode.cpp:247 +msgid "Attn" +msgstr "" + +#: src/keycode.cpp:247 +msgid "CrSel" +msgstr "" + +#: src/keycode.cpp:248 +msgid "Erase OEF" +msgstr "" + +#: src/keycode.cpp:248 +msgid "ExSel" +msgstr "" + +#: src/keycode.cpp:248 +msgid "OEM Clear" +msgstr "" + +#: src/keycode.cpp:248 +msgid "PA1" +msgstr "" + +#: src/keycode.cpp:248 +msgid "Zoom" +msgstr "" + +#: src/main.cpp:1384 +msgid "Main Menu" +msgstr "" + +#: src/main.cpp:1633 +msgid "Failed to initialize world" +msgstr "" + +#: src/main.cpp:1645 +msgid "No world selected and no address provided. Nothing to do." +msgstr "" + +#: src/main.cpp:1653 +msgid "Could not find or load game \"" +msgstr "" + +#: src/main.cpp:1667 +msgid "Invalid gamespec." +msgstr "" + +#: src/main.cpp:1707 +msgid "Connection error (timed out?)" +msgstr "" + +#: src/main.cpp:1718 +msgid "" +"\n" +"Check debug.txt for details." +msgstr "" diff --git a/po/minetest.pot b/po/minetest.pot index 400cb5a4e..f07b816a5 100644 --- a/po/minetest.pot +++ b/po/minetest.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-23 18:24+0200\n" +"POT-Creation-Date: 2013-01-30 20:25+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,35 +17,35 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: src/guiConfigureWorld.cpp:127 +#: src/guiConfigureWorld.cpp:125 msgid "" "Warning: Some mods are not configured yet.\n" "They will be enabled by default when you save the configuration. " msgstr "" -#: src/guiConfigureWorld.cpp:146 +#: src/guiConfigureWorld.cpp:144 msgid "" "Warning: Some configured mods are missing.\n" "Their setting will be removed when you save the configuration. " msgstr "" -#: src/guiConfigureWorld.cpp:210 +#: src/guiConfigureWorld.cpp:208 msgid "enabled" msgstr "" -#: src/guiConfigureWorld.cpp:217 +#: src/guiConfigureWorld.cpp:215 msgid "Enable All" msgstr "" -#: src/guiConfigureWorld.cpp:224 +#: src/guiConfigureWorld.cpp:222 msgid "Disable All" msgstr "" -#: src/guiConfigureWorld.cpp:230 +#: src/guiConfigureWorld.cpp:228 msgid "depends on:" msgstr "" -#: src/guiConfigureWorld.cpp:242 +#: src/guiConfigureWorld.cpp:240 msgid "is required by:" msgstr "" @@ -123,6 +123,74 @@ msgstr "" msgid "press key" msgstr "" +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "" + #: src/guiMainMenu.cpp:55 msgid "Cannot create world: Name contains invalid characters" msgstr "" @@ -459,18 +527,10 @@ msgid "Execute" msgstr "" #: src/keycode.cpp:228 -msgid "Left" -msgstr "" - -#: src/keycode.cpp:228 msgid "Print" msgstr "" #: src/keycode.cpp:228 -msgid "Right" -msgstr "" - -#: src/keycode.cpp:228 msgid "Select" msgstr "" diff --git a/po/pl/minetest.po b/po/pl/minetest.po index 400cb5a4e..96c6570f1 100644 --- a/po/pl/minetest.po +++ b/po/pl/minetest.po @@ -3,325 +3,403 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-01-23 18:24+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"PO-Revision-Date: 2013-01-30 01:32+0200\n" +"Last-Translator: Maciej Kasatkin <maciej.kasatkin@yahoo.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" -"Language: \n" +"Language: pl\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" +"X-Generator: Weblate 1.4-dev\n" -#: src/guiConfigureWorld.cpp:127 +#: src/guiConfigureWorld.cpp:125 msgid "" "Warning: Some mods are not configured yet.\n" "They will be enabled by default when you save the configuration. " msgstr "" +"Ostrzeżenie: Niektóre z modyfikacji nie zostały jeszcze skonfigurowane.\n" +"Zostaną domyślnie włączone gdy zapiszesz konfigurację. " -#: src/guiConfigureWorld.cpp:146 +#: src/guiConfigureWorld.cpp:144 msgid "" "Warning: Some configured mods are missing.\n" "Their setting will be removed when you save the configuration. " msgstr "" +"Ostrzeżenie: Niektóre z modyfikacji nie zostały znalezione.\n" +"Ich ustawienia zostaną usunięte gdy zapiszesz konfigurację. " -#: src/guiConfigureWorld.cpp:210 +#: src/guiConfigureWorld.cpp:208 msgid "enabled" -msgstr "" +msgstr "włączone" -#: src/guiConfigureWorld.cpp:217 +#: src/guiConfigureWorld.cpp:215 msgid "Enable All" -msgstr "" +msgstr "Włącz wszystkie" -#: src/guiConfigureWorld.cpp:224 +#: src/guiConfigureWorld.cpp:222 msgid "Disable All" -msgstr "" +msgstr "Wyłącz wszystkie" -#: src/guiConfigureWorld.cpp:230 +#: src/guiConfigureWorld.cpp:228 msgid "depends on:" -msgstr "" +msgstr "zależne od:" -#: src/guiConfigureWorld.cpp:242 +#: src/guiConfigureWorld.cpp:240 msgid "is required by:" -msgstr "" +msgstr "wymagane przez:" #: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 #: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 msgid "Cancel" -msgstr "" +msgstr "Anuluj" #: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 msgid "Save" -msgstr "" +msgstr "Zapisz" #: src/guiConfigureWorld.cpp:394 msgid "Configuration saved. " -msgstr "" +msgstr "Konfiguracja zapisana. " #: src/guiConfigureWorld.cpp:402 msgid "Warning: Configuration not consistent. " -msgstr "" +msgstr "Ostrzeżenie: Plik konfiguracyjny niespójny. " #: src/guiConfirmMenu.cpp:120 msgid "Yes" -msgstr "" +msgstr "Tak" #: src/guiConfirmMenu.cpp:126 msgid "No" -msgstr "" +msgstr "Nie" #: src/guiCreateWorld.cpp:116 msgid "World name" -msgstr "" +msgstr "Nazwa świata" #: src/guiCreateWorld.cpp:135 msgid "Game" -msgstr "" +msgstr "Gra" #: src/guiCreateWorld.cpp:159 msgid "Create" -msgstr "" +msgstr "Utwórz" #: src/guiDeathScreen.cpp:96 msgid "You died." -msgstr "" +msgstr "Zginąłeś." #: src/guiDeathScreen.cpp:104 msgid "Respawn" -msgstr "" +msgstr "Wróć do gry" #: src/guiFormSpecMenu.cpp:572 msgid "Left click: Move all items, Right click: Move single item" msgstr "" +"Lewy klik: Przenieś wszystkie przedmioty, Prawy klik: przenieś pojedynczy " +"przedmiot" #: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109 #: src/guiTextInputMenu.cpp:123 msgid "Proceed" -msgstr "" +msgstr "Kontynuuj" #: src/guiKeyChangeMenu.cpp:114 msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" msgstr "" +"Zdefiniowane klawisze. (Jeżeli to menu nie działa, usuń skonfigurowane " +"klawisze z pliku minetest.conf)" #: src/guiKeyChangeMenu.cpp:151 msgid "\"Use\" = climb down" -msgstr "" +msgstr "\"Użyj\" = wspinaj się" #: src/guiKeyChangeMenu.cpp:164 msgid "Double tap \"jump\" to toggle fly" -msgstr "" +msgstr "Wciśnij dwukrotnie \"Skok\" by włączyć tryb latania" #: src/guiKeyChangeMenu.cpp:269 msgid "Key already in use" -msgstr "" +msgstr "Klawisz już zdefiniowany" #: src/guiKeyChangeMenu.cpp:347 msgid "press key" +msgstr "naciśnij klawisz" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" msgstr "" #: src/guiMainMenu.cpp:55 msgid "Cannot create world: Name contains invalid characters" -msgstr "" +msgstr "Nie można stworzyć świata: nazwa zawiera niedozwolone znaki" #: src/guiMainMenu.cpp:64 msgid "Cannot create world: A world by this name already exists" -msgstr "" +msgstr "Nie można stworzyć świata: Istnieje już świat o takiej nazwie" #: src/guiMainMenu.cpp:245 msgid "Singleplayer" -msgstr "" +msgstr "Pojedynczy gracz" #: src/guiMainMenu.cpp:246 msgid "Multiplayer" -msgstr "" +msgstr "Gra wieloosobowa" #: src/guiMainMenu.cpp:247 msgid "Advanced" -msgstr "" +msgstr "Zaawansowane" #: src/guiMainMenu.cpp:248 msgid "Settings" -msgstr "" +msgstr "Ustawienia" #: src/guiMainMenu.cpp:249 msgid "Credits" -msgstr "" +msgstr "Autorzy" #: src/guiMainMenu.cpp:280 msgid "Select World:" -msgstr "" +msgstr "Wybierz świat:" #: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229 msgid "Delete" -msgstr "" +msgstr "Skasuj" #: src/guiMainMenu.cpp:309 msgid "New" -msgstr "" +msgstr "Nowy" #: src/guiMainMenu.cpp:317 msgid "Configure" -msgstr "" +msgstr "Ustaw" #: src/guiMainMenu.cpp:332 src/keycode.cpp:248 msgid "Play" -msgstr "" +msgstr "Graj" #: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557 msgid "Creative Mode" -msgstr "" +msgstr "Tryb kreatywny" #: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563 msgid "Enable Damage" -msgstr "" +msgstr "Włącz obrażenia" #: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479 msgid "Name/Password" -msgstr "" +msgstr "Nazwa gracza/Hasło" #: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506 msgid "Address/Port" -msgstr "" +msgstr "Adres/Port" #: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075 msgid "Show Public" -msgstr "" +msgstr "Pokaż publiczne" #: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083 msgid "Show Favorites" -msgstr "" +msgstr "Pokaż ulubione" #: src/guiMainMenu.cpp:459 msgid "Connect" -msgstr "" +msgstr "Połącz" #: src/guiMainMenu.cpp:529 msgid "Leave address blank to start a local server." -msgstr "" +msgstr "Nie wpisuj adresu by uruchomić lokalny serwer." #: src/guiMainMenu.cpp:538 msgid "Start Game / Connect" -msgstr "" +msgstr "Rozpocznij grę/Połącz" #: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006 msgid "Delete world" -msgstr "" +msgstr "Skasuj świat" #: src/guiMainMenu.cpp:577 msgid "Create world" -msgstr "" +msgstr "Stwórz świat" #: src/guiMainMenu.cpp:611 msgid "Fancy trees" -msgstr "" +msgstr "Ozdobne drzewa" #: src/guiMainMenu.cpp:617 msgid "Smooth Lighting" -msgstr "" +msgstr "Płynne oświetlenie" #: src/guiMainMenu.cpp:623 msgid "3D Clouds" -msgstr "" +msgstr "Chmury 3D" #: src/guiMainMenu.cpp:629 msgid "Opaque water" -msgstr "" +msgstr "Nieprzeźroczysta woda" #: src/guiMainMenu.cpp:639 msgid "Mip-Mapping" -msgstr "" +msgstr "Mip-Mappowanie" #: src/guiMainMenu.cpp:646 msgid "Anisotropic Filtering" -msgstr "" +msgstr "Filtrowanie anizotropowe" #: src/guiMainMenu.cpp:653 msgid "Bi-Linear Filtering" -msgstr "" +msgstr "Dwuliniowe filtrowanie" #: src/guiMainMenu.cpp:660 msgid "Tri-Linear Filtering" -msgstr "" +msgstr "Trójliniowe filtrowanie" #: src/guiMainMenu.cpp:668 msgid "Shaders" -msgstr "" +msgstr "Shadery" #: src/guiMainMenu.cpp:675 msgid "Preload item visuals" -msgstr "" +msgstr "Ładuj obrazy przedmiotów" #: src/guiMainMenu.cpp:682 msgid "Enable Particles" -msgstr "" +msgstr "Włącz cząstki" #: src/guiMainMenu.cpp:692 msgid "Change keys" -msgstr "" +msgstr "Zmień klawisze" #: src/guiMainMenu.cpp:977 msgid "Address required." -msgstr "" +msgstr "Wymagany adres." #: src/guiMainMenu.cpp:995 msgid "Cannot delete world: Nothing selected" -msgstr "" +msgstr "Nie można skasować świata: nic nie zaznaczono" #: src/guiMainMenu.cpp:1010 msgid "Files to be deleted" -msgstr "" +msgstr "Pliki do skasowania" #: src/guiMainMenu.cpp:1026 msgid "Cannot create world: No games found" -msgstr "" +msgstr "Nie można utworzyć świata: Nie znaleziono żadnego trybu gry" #: src/guiMainMenu.cpp:1042 msgid "Cannot configure world: Nothing selected" -msgstr "" +msgstr "Nie można skonfigurować świata: Nic nie zaznaczono" #: src/guiMainMenu.cpp:1146 msgid "Failed to delete all world files" -msgstr "" +msgstr "Nie można skasować wszystkich plików świata" #: src/guiPasswordChange.cpp:108 msgid "Old Password" -msgstr "" +msgstr "Stare hasło" #: src/guiPasswordChange.cpp:125 msgid "New Password" -msgstr "" +msgstr "Nowe hasło" #: src/guiPasswordChange.cpp:141 msgid "Confirm Password" -msgstr "" +msgstr "Potwierdź hasło" #: src/guiPasswordChange.cpp:158 msgid "Change" -msgstr "" +msgstr "Zmień" #: src/guiPasswordChange.cpp:167 msgid "Passwords do not match!" -msgstr "" +msgstr "Hasła nie są jednakowe!" #: src/guiPauseMenu.cpp:118 msgid "Continue" -msgstr "" +msgstr "Dalej" #: src/guiPauseMenu.cpp:127 msgid "Change Password" -msgstr "" +msgstr "Zmień hasło" #: src/guiPauseMenu.cpp:135 msgid "Exit to Menu" -msgstr "" +msgstr "Wyjdź do menu" #: src/guiPauseMenu.cpp:142 msgid "Exit to OS" -msgstr "" +msgstr "Wyjście z gry" #: src/guiPauseMenu.cpp:149 msgid "" @@ -337,333 +415,338 @@ msgid "" "- ESC: This menu\n" "- T: Chat\n" msgstr "" +"Domyślne ustawienia:\n" +"- WASD: poruszanie\n" +"- Lewy przycisk myszki: kop/uderz\n" +"- Prawy przycisk myszki: połóż/użyj\n" +"- Kółko myszki: wybieranie przedmiotu\n" +"- 0...9: wybieranie przedmiotu\n" +"- Shift: skradanie\n" +"- R: przełączanie trybu widoczności\n" +"- I: menu posiadanych przedmiotów\n" +"- ESC: to menu\n" +"- T: Czat\n" #: src/keycode.cpp:223 msgid "Left Button" -msgstr "" +msgstr "Lewy przycisk myszki" #: src/keycode.cpp:223 msgid "Middle Button" -msgstr "" +msgstr "Środkowy przycisk myszki" #: src/keycode.cpp:223 msgid "Right Button" -msgstr "" +msgstr "Prawy przycisk myszki" #: src/keycode.cpp:223 msgid "X Button 1" -msgstr "" +msgstr "X Button 1" #: src/keycode.cpp:224 msgid "Back" -msgstr "" +msgstr "Backspace" #: src/keycode.cpp:224 msgid "Clear" -msgstr "" +msgstr "Delete" #: src/keycode.cpp:224 msgid "Return" -msgstr "" +msgstr "Enter" #: src/keycode.cpp:224 msgid "Tab" -msgstr "" +msgstr "Tab" #: src/keycode.cpp:224 msgid "X Button 2" -msgstr "" +msgstr "X Button 2" #: src/keycode.cpp:225 msgid "Capital" -msgstr "" +msgstr "Caps Lock" #: src/keycode.cpp:225 msgid "Control" -msgstr "" +msgstr "Control" #: src/keycode.cpp:225 msgid "Kana" -msgstr "" +msgstr "Kana" #: src/keycode.cpp:225 msgid "Menu" -msgstr "" +msgstr "Menu" #: src/keycode.cpp:225 msgid "Pause" -msgstr "" +msgstr "Pause" #: src/keycode.cpp:225 msgid "Shift" -msgstr "" +msgstr "Shift" #: src/keycode.cpp:226 msgid "Convert" -msgstr "" +msgstr "Convert" #: src/keycode.cpp:226 msgid "Escape" -msgstr "" +msgstr "Escape" #: src/keycode.cpp:226 msgid "Final" -msgstr "" +msgstr "Final" #: src/keycode.cpp:226 msgid "Junja" -msgstr "" +msgstr "Junja" #: src/keycode.cpp:226 msgid "Kanji" -msgstr "" +msgstr "Kanji" #: src/keycode.cpp:226 msgid "Nonconvert" -msgstr "" +msgstr "Nonconvert" #: src/keycode.cpp:227 msgid "Accept" -msgstr "" +msgstr "Accept" #: src/keycode.cpp:227 msgid "End" -msgstr "" +msgstr "End" #: src/keycode.cpp:227 msgid "Home" -msgstr "" +msgstr "Home" #: src/keycode.cpp:227 msgid "Mode Change" -msgstr "" +msgstr "Mode Change" #: src/keycode.cpp:227 msgid "Next" -msgstr "" +msgstr "Next" #: src/keycode.cpp:227 msgid "Prior" -msgstr "" +msgstr "Prior" #: src/keycode.cpp:227 msgid "Space" -msgstr "" +msgstr "Spacja" #: src/keycode.cpp:228 msgid "Down" -msgstr "" +msgstr "Dół" #: src/keycode.cpp:228 msgid "Execute" -msgstr "" - -#: src/keycode.cpp:228 -msgid "Left" -msgstr "" +msgstr "Execute" #: src/keycode.cpp:228 msgid "Print" -msgstr "" - -#: src/keycode.cpp:228 -msgid "Right" -msgstr "" +msgstr "Print" #: src/keycode.cpp:228 msgid "Select" -msgstr "" +msgstr "Select" #: src/keycode.cpp:228 msgid "Up" -msgstr "" +msgstr "Góra" #: src/keycode.cpp:229 msgid "Help" -msgstr "" +msgstr "Help" #: src/keycode.cpp:229 msgid "Insert" -msgstr "" +msgstr "Insert" #: src/keycode.cpp:229 msgid "Snapshot" -msgstr "" +msgstr "Snapshot" #: src/keycode.cpp:232 msgid "Left Windows" -msgstr "" +msgstr "Lewy Windows" #: src/keycode.cpp:233 msgid "Apps" -msgstr "" +msgstr "Apps" #: src/keycode.cpp:233 msgid "Numpad 0" -msgstr "" +msgstr "Numpad 0" #: src/keycode.cpp:233 msgid "Numpad 1" -msgstr "" +msgstr "Numpad 1" #: src/keycode.cpp:233 msgid "Right Windows" -msgstr "" +msgstr "Prawy Windows" #: src/keycode.cpp:233 msgid "Sleep" -msgstr "" +msgstr "Sleep" #: src/keycode.cpp:234 msgid "Numpad 2" -msgstr "" +msgstr "Numpad 2" #: src/keycode.cpp:234 msgid "Numpad 3" -msgstr "" +msgstr "Numpad 3" #: src/keycode.cpp:234 msgid "Numpad 4" -msgstr "" +msgstr "Numpad 4" #: src/keycode.cpp:234 msgid "Numpad 5" -msgstr "" +msgstr "Numpad 5" #: src/keycode.cpp:234 msgid "Numpad 6" -msgstr "" +msgstr "Numpad 6" #: src/keycode.cpp:234 msgid "Numpad 7" -msgstr "" +msgstr "Numpad 7" #: src/keycode.cpp:235 msgid "Numpad *" -msgstr "" +msgstr "Numpad *" #: src/keycode.cpp:235 msgid "Numpad +" -msgstr "" +msgstr "Numpad +" #: src/keycode.cpp:235 msgid "Numpad -" -msgstr "" +msgstr "Numpad -" #: src/keycode.cpp:235 msgid "Numpad /" -msgstr "" +msgstr "Numpad /" #: src/keycode.cpp:235 msgid "Numpad 8" -msgstr "" +msgstr "Numpad 8" #: src/keycode.cpp:235 msgid "Numpad 9" -msgstr "" +msgstr "Numpad 9" #: src/keycode.cpp:239 msgid "Num Lock" -msgstr "" +msgstr "Num Lock" #: src/keycode.cpp:239 msgid "Scroll Lock" -msgstr "" +msgstr "Scroll Lock" #: src/keycode.cpp:240 msgid "Left Shift" -msgstr "" +msgstr "Lewy Shift" #: src/keycode.cpp:240 msgid "Right Shift" -msgstr "" +msgstr "Prawy Shift" #: src/keycode.cpp:241 msgid "Left Control" -msgstr "" +msgstr "Lewy Control" #: src/keycode.cpp:241 msgid "Left Menu" -msgstr "" +msgstr "Lewy Menu" #: src/keycode.cpp:241 msgid "Right Control" -msgstr "" +msgstr "Prawy Control" #: src/keycode.cpp:241 msgid "Right Menu" -msgstr "" +msgstr "Prawy Menu" #: src/keycode.cpp:243 msgid "Comma" -msgstr "" +msgstr "Przecinek" #: src/keycode.cpp:243 msgid "Minus" -msgstr "" +msgstr "Minus" #: src/keycode.cpp:243 msgid "Period" -msgstr "" +msgstr "Kropka" #: src/keycode.cpp:243 msgid "Plus" -msgstr "" +msgstr "Plus" #: src/keycode.cpp:247 msgid "Attn" -msgstr "" +msgstr "Attn" #: src/keycode.cpp:247 msgid "CrSel" -msgstr "" +msgstr "CrSel" #: src/keycode.cpp:248 msgid "Erase OEF" -msgstr "" +msgstr "Erase OEF" #: src/keycode.cpp:248 msgid "ExSel" -msgstr "" +msgstr "ExSel" #: src/keycode.cpp:248 msgid "OEM Clear" -msgstr "" +msgstr "OEM Clear" #: src/keycode.cpp:248 msgid "PA1" -msgstr "" +msgstr "PA1" #: src/keycode.cpp:248 msgid "Zoom" -msgstr "" +msgstr "Zoom" #: src/main.cpp:1384 msgid "Main Menu" -msgstr "" +msgstr "Menu główne" #: src/main.cpp:1633 msgid "Failed to initialize world" -msgstr "" +msgstr "Inicjalizacja świata nie powiodła się" #: src/main.cpp:1645 msgid "No world selected and no address provided. Nothing to do." -msgstr "" +msgstr "Nie wybrano świata ani adresu." #: src/main.cpp:1653 msgid "Could not find or load game \"" -msgstr "" +msgstr "Nie można znaleźć lub wczytać trybu gry \"" #: src/main.cpp:1667 msgid "Invalid gamespec." -msgstr "" +msgstr "Nieprawidłowa specyfikacja trybu gry." #: src/main.cpp:1707 msgid "Connection error (timed out?)" -msgstr "" +msgstr "Błąd połączenia (brak odpowiedzi?)" #: src/main.cpp:1718 msgid "" "\n" "Check debug.txt for details." msgstr "" +"\n" +"Sprawdź plik debug.txt by uzyskać więcej informacji." diff --git a/po/pt/minetest.po b/po/pt/minetest.po new file mode 100644 index 000000000..d146d63ec --- /dev/null +++ b/po/pt/minetest.po @@ -0,0 +1,748 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: minetest\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-01-30 20:25+0100\n" +"PO-Revision-Date: 2013-02-09 22:01+0200\n" +"Last-Translator: Pilz Adam <PilzAdam@gmx.de>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: pt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Weblate 1.4-dev\n" + +#: src/guiConfigureWorld.cpp:125 +msgid "" +"Warning: Some mods are not configured yet.\n" +"They will be enabled by default when you save the configuration. " +msgstr "" +"Alerta: Alguns mods não estão configurados ainda.\n" +"Eles vão ser ativos por predefinição quando guardar a configuração. " + +#: src/guiConfigureWorld.cpp:144 +msgid "" +"Warning: Some configured mods are missing.\n" +"Their setting will be removed when you save the configuration. " +msgstr "" +"Alerta: Alguns mods configurados estão em falta.\n" +"As definições vão ser removidas quando gravar a configuração. " + +#: src/guiConfigureWorld.cpp:208 +msgid "enabled" +msgstr "ativo" + +#: src/guiConfigureWorld.cpp:215 +msgid "Enable All" +msgstr "Ativar Tudo" + +#: src/guiConfigureWorld.cpp:222 +msgid "Disable All" +msgstr "Desativar Tudo" + +#: src/guiConfigureWorld.cpp:228 +msgid "depends on:" +msgstr "depende de:" + +#: src/guiConfigureWorld.cpp:240 +msgid "is required by:" +msgstr "é necessário pelo:" + +#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 +#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 +msgid "Cancel" +msgstr "Cancelar" + +#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 +msgid "Save" +msgstr "Guardar" + +#: src/guiConfigureWorld.cpp:394 +msgid "Configuration saved. " +msgstr "Configuração gravada. " + +#: src/guiConfigureWorld.cpp:402 +msgid "Warning: Configuration not consistent. " +msgstr "Alerta: Configuração não compativel. " + +#: src/guiConfirmMenu.cpp:120 +msgid "Yes" +msgstr "Sim" + +#: src/guiConfirmMenu.cpp:126 +msgid "No" +msgstr "Não" + +#: src/guiCreateWorld.cpp:116 +msgid "World name" +msgstr "Nome do Mundo" + +#: src/guiCreateWorld.cpp:135 +msgid "Game" +msgstr "Jogo" + +#: src/guiCreateWorld.cpp:159 +msgid "Create" +msgstr "Criar" + +#: src/guiDeathScreen.cpp:96 +msgid "You died." +msgstr "Estás morto." + +#: src/guiDeathScreen.cpp:104 +msgid "Respawn" +msgstr "Renascer" + +#: src/guiFormSpecMenu.cpp:572 +msgid "Left click: Move all items, Right click: Move single item" +msgstr "Botão esq.: Mover todos os items, Botão dir.: Mover um item" + +#: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109 +#: src/guiTextInputMenu.cpp:123 +msgid "Proceed" +msgstr "Continuar" + +#: src/guiKeyChangeMenu.cpp:114 +msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" +msgstr "Teclas. (Se este menu estragar-se, remova as linhas do minetest.conf)" + +#: src/guiKeyChangeMenu.cpp:151 +msgid "\"Use\" = climb down" +msgstr "\"Use\" = ir para baixo" + +#: src/guiKeyChangeMenu.cpp:164 +msgid "Double tap \"jump\" to toggle fly" +msgstr "Duas vezes \"saltar\" para ativar vôo" + +#: src/guiKeyChangeMenu.cpp:269 +msgid "Key already in use" +msgstr "Tecla já em uso" + +#: src/guiKeyChangeMenu.cpp:347 +msgid "press key" +msgstr "pressione tecla" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "Avançar" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "Para trás" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "Esquerda" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "Direita" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "Usar" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "Saltar" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "Agachar" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "Dropar" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "Inventário" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "CHAT" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "Comando" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "Consola" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "Ativar vôo" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "Ativar correr" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "Ativar noclip" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "Seleccionar Distância" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "Imprimir stacks" + +#: src/guiMainMenu.cpp:55 +msgid "Cannot create world: Name contains invalid characters" +msgstr "Não foi possível criar mundo: Nome com carácteres inválidos" + +#: src/guiMainMenu.cpp:64 +msgid "Cannot create world: A world by this name already exists" +msgstr "Não foi possivel criar mundo: Mundo com este nome já existente" + +#: src/guiMainMenu.cpp:245 +msgid "Singleplayer" +msgstr "Um Jogador" + +#: src/guiMainMenu.cpp:246 +msgid "Multiplayer" +msgstr "Multijogador" + +#: src/guiMainMenu.cpp:247 +msgid "Advanced" +msgstr "Avançado" + +#: src/guiMainMenu.cpp:248 +msgid "Settings" +msgstr "Definições" + +#: src/guiMainMenu.cpp:249 +msgid "Credits" +msgstr "Créditos" + +#: src/guiMainMenu.cpp:280 +msgid "Select World:" +msgstr "Seleccionar Mundo:" + +#: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229 +msgid "Delete" +msgstr "Eliminar" + +#: src/guiMainMenu.cpp:309 +msgid "New" +msgstr "Novo" + +#: src/guiMainMenu.cpp:317 +msgid "Configure" +msgstr "Configurar" + +#: src/guiMainMenu.cpp:332 src/keycode.cpp:248 +msgid "Play" +msgstr "Jogar" + +#: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557 +msgid "Creative Mode" +msgstr "Modo Criativo" + +#: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563 +msgid "Enable Damage" +msgstr "Ativar Dano" + +#: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479 +msgid "Name/Password" +msgstr "Nome/Senha" + +#: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506 +msgid "Address/Port" +msgstr "Endereço/Porta" + +#: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075 +msgid "Show Public" +msgstr "Mostrar Públicos" + +#: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083 +msgid "Show Favorites" +msgstr "Mostrar Favoritos" + +#: src/guiMainMenu.cpp:459 +msgid "Connect" +msgstr "Conectar" + +#: src/guiMainMenu.cpp:529 +msgid "Leave address blank to start a local server." +msgstr "Deixe endereço em branco para iniciar servidor local." + +#: src/guiMainMenu.cpp:538 +msgid "Start Game / Connect" +msgstr "Iniciar Jogo / Conectar" + +#: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006 +msgid "Delete world" +msgstr "Eliminar mundo" + +#: src/guiMainMenu.cpp:577 +msgid "Create world" +msgstr "Criar mundo" + +#: src/guiMainMenu.cpp:611 +msgid "Fancy trees" +msgstr "Árvores Melhoradas" + +#: src/guiMainMenu.cpp:617 +msgid "Smooth Lighting" +msgstr "Iluminação Suave" + +#: src/guiMainMenu.cpp:623 +msgid "3D Clouds" +msgstr "Nuvens 3D" + +#: src/guiMainMenu.cpp:629 +msgid "Opaque water" +msgstr "Água Opaca" + +#: src/guiMainMenu.cpp:639 +msgid "Mip-Mapping" +msgstr "Mip-Mapping" + +#: src/guiMainMenu.cpp:646 +msgid "Anisotropic Filtering" +msgstr "Filtro Anisotropico" + +#: src/guiMainMenu.cpp:653 +msgid "Bi-Linear Filtering" +msgstr "Filtro Bi-Linear" + +#: src/guiMainMenu.cpp:660 +msgid "Tri-Linear Filtering" +msgstr "Filtro Tri-Linear" + +#: src/guiMainMenu.cpp:668 +msgid "Shaders" +msgstr "Sombras" + +#: src/guiMainMenu.cpp:675 +msgid "Preload item visuals" +msgstr "Precarregamento dos items" + +#: src/guiMainMenu.cpp:682 +msgid "Enable Particles" +msgstr "Ativar Particulas" + +#: src/guiMainMenu.cpp:692 +msgid "Change keys" +msgstr "Mudar teclas" + +#: src/guiMainMenu.cpp:977 +msgid "Address required." +msgstr "Endereço necessário." + +#: src/guiMainMenu.cpp:995 +msgid "Cannot delete world: Nothing selected" +msgstr "Não foi possível eliminar mundo: Nada seleccionado" + +#: src/guiMainMenu.cpp:1010 +msgid "Files to be deleted" +msgstr "Ficheiros para eliminar" + +#: src/guiMainMenu.cpp:1026 +msgid "Cannot create world: No games found" +msgstr "Não foi possivel criar mundo: Jogos não detectados" + +#: src/guiMainMenu.cpp:1042 +msgid "Cannot configure world: Nothing selected" +msgstr "Não foi possivel configurar mundo: Nada seleccionado" + +#: src/guiMainMenu.cpp:1146 +msgid "Failed to delete all world files" +msgstr "Remoção dos ficheiros dos mundos falhada" + +#: src/guiPasswordChange.cpp:108 +msgid "Old Password" +msgstr "Senha antiga" + +#: src/guiPasswordChange.cpp:125 +msgid "New Password" +msgstr "Senha Nova" + +#: src/guiPasswordChange.cpp:141 +msgid "Confirm Password" +msgstr "Confirmar Senha" + +#: src/guiPasswordChange.cpp:158 +msgid "Change" +msgstr "Mudar" + +#: src/guiPasswordChange.cpp:167 +msgid "Passwords do not match!" +msgstr "Senhas não correspondem!" + +#: src/guiPauseMenu.cpp:118 +msgid "Continue" +msgstr "Continuar" + +#: src/guiPauseMenu.cpp:127 +msgid "Change Password" +msgstr "Mudar Senha" + +#: src/guiPauseMenu.cpp:135 +msgid "Exit to Menu" +msgstr "Sair para Menu" + +#: src/guiPauseMenu.cpp:142 +msgid "Exit to OS" +msgstr "Sair para SO" + +#: src/guiPauseMenu.cpp:149 +msgid "" +"Default Controls:\n" +"- WASD: Walk\n" +"- Mouse left: dig/hit\n" +"- Mouse right: place/use\n" +"- Mouse wheel: select item\n" +"- 0...9: select item\n" +"- Shift: sneak\n" +"- R: Toggle viewing all loaded chunks\n" +"- I: Inventory menu\n" +"- ESC: This menu\n" +"- T: Chat\n" +msgstr "" +"Controlos Normais:\n" +"- WASD: Andar\n" +"- Botão esq.: partir/atacar\n" +"- Botão dir.: colocar/usar\n" +"- Roda do Rato: seleccionar item\n" +"- 0...9: seleccionar item\n" +"- Shift: agachar\n" +"- R: Mudar visualização de todos os chunks\n" +"- I: Inventário\n" +"- ESC: Este menu\n" +"- T: Chat\n" + +#: src/keycode.cpp:223 +msgid "Left Button" +msgstr "Botão Esquerdo" + +#: src/keycode.cpp:223 +msgid "Middle Button" +msgstr "Roda do Rato" + +#: src/keycode.cpp:223 +msgid "Right Button" +msgstr "Botão Direito" + +#: src/keycode.cpp:223 +msgid "X Button 1" +msgstr "Botão X 1" + +#: src/keycode.cpp:224 +msgid "Back" +msgstr "Voltar" + +#: src/keycode.cpp:224 +msgid "Clear" +msgstr "Limpar" + +#: src/keycode.cpp:224 +msgid "Return" +msgstr "Enter" + +#: src/keycode.cpp:224 +msgid "Tab" +msgstr "Tabulação" + +#: src/keycode.cpp:224 +msgid "X Button 2" +msgstr "Botão X 2" + +#: src/keycode.cpp:225 +msgid "Capital" +msgstr "Capital" + +#: src/keycode.cpp:225 +msgid "Control" +msgstr "Control" + +#: src/keycode.cpp:225 +msgid "Kana" +msgstr "Kana" + +#: src/keycode.cpp:225 +msgid "Menu" +msgstr "Menu" + +#: src/keycode.cpp:225 +msgid "Pause" +msgstr "Pausa" + +#: src/keycode.cpp:225 +msgid "Shift" +msgstr "SHIFT" + +#: src/keycode.cpp:226 +msgid "Convert" +msgstr "Converter" + +#: src/keycode.cpp:226 +msgid "Escape" +msgstr "ESC" + +#: src/keycode.cpp:226 +msgid "Final" +msgstr "Final" + +#: src/keycode.cpp:226 +msgid "Junja" +msgstr "Junja" + +#: src/keycode.cpp:226 +msgid "Kanji" +msgstr "Kanji" + +#: src/keycode.cpp:226 +msgid "Nonconvert" +msgstr "Nãoconverter" + +#: src/keycode.cpp:227 +msgid "Accept" +msgstr "Aceitar" + +#: src/keycode.cpp:227 +msgid "End" +msgstr "END" + +#: src/keycode.cpp:227 +msgid "Home" +msgstr "HOME" + +#: src/keycode.cpp:227 +msgid "Mode Change" +msgstr "MODE Change" + +#: src/keycode.cpp:227 +msgid "Next" +msgstr "Próximo" + +#: src/keycode.cpp:227 +msgid "Prior" +msgstr "Prévio" + +#: src/keycode.cpp:227 +msgid "Space" +msgstr "Espaço" + +#: src/keycode.cpp:228 +msgid "Down" +msgstr "Baixo" + +#: src/keycode.cpp:228 +msgid "Execute" +msgstr "Executar" + +#: src/keycode.cpp:228 +msgid "Print" +msgstr "PRINT" + +#: src/keycode.cpp:228 +msgid "Select" +msgstr "Seleccionar" + +#: src/keycode.cpp:228 +msgid "Up" +msgstr "Cima" + +#: src/keycode.cpp:229 +msgid "Help" +msgstr "Ajuda" + +#: src/keycode.cpp:229 +msgid "Insert" +msgstr "INSERT" + +#: src/keycode.cpp:229 +msgid "Snapshot" +msgstr "Screenshot" + +#: src/keycode.cpp:232 +msgid "Left Windows" +msgstr "WINDOWS Esq." + +#: src/keycode.cpp:233 +msgid "Apps" +msgstr "App" + +#: src/keycode.cpp:233 +msgid "Numpad 0" +msgstr "Numpad 0" + +#: src/keycode.cpp:233 +msgid "Numpad 1" +msgstr "Numpad 1" + +#: src/keycode.cpp:233 +msgid "Right Windows" +msgstr "WINDOWS Dir." + +#: src/keycode.cpp:233 +msgid "Sleep" +msgstr "Suspender" + +#: src/keycode.cpp:234 +msgid "Numpad 2" +msgstr "Numpad 2" + +#: src/keycode.cpp:234 +msgid "Numpad 3" +msgstr "Numpad 3" + +#: src/keycode.cpp:234 +msgid "Numpad 4" +msgstr "Numpad 4" + +#: src/keycode.cpp:234 +msgid "Numpad 5" +msgstr "Numpad 5" + +#: src/keycode.cpp:234 +msgid "Numpad 6" +msgstr "Numpad 6" + +#: src/keycode.cpp:234 +msgid "Numpad 7" +msgstr "Numpad 7" + +#: src/keycode.cpp:235 +msgid "Numpad *" +msgstr "Numpad *" + +#: src/keycode.cpp:235 +msgid "Numpad +" +msgstr "Numpad +" + +#: src/keycode.cpp:235 +msgid "Numpad -" +msgstr "Numpad -" + +#: src/keycode.cpp:235 +msgid "Numpad /" +msgstr "Numpad /" + +#: src/keycode.cpp:235 +msgid "Numpad 8" +msgstr "Numpad 8" + +#: src/keycode.cpp:235 +msgid "Numpad 9" +msgstr "Numpad 9" + +#: src/keycode.cpp:239 +msgid "Num Lock" +msgstr "Num Lock" + +#: src/keycode.cpp:239 +msgid "Scroll Lock" +msgstr "Scroll Lock" + +#: src/keycode.cpp:240 +msgid "Left Shift" +msgstr "Shift Esquerdo" + +#: src/keycode.cpp:240 +msgid "Right Shift" +msgstr "Shift Direito" + +#: src/keycode.cpp:241 +msgid "Left Control" +msgstr "Control Esq" + +#: src/keycode.cpp:241 +msgid "Left Menu" +msgstr "Menu Esquerdo" + +#: src/keycode.cpp:241 +msgid "Right Control" +msgstr "Control Direito" + +#: src/keycode.cpp:241 +msgid "Right Menu" +msgstr "Menu Direito" + +#: src/keycode.cpp:243 +msgid "Comma" +msgstr "Virgula" + +#: src/keycode.cpp:243 +msgid "Minus" +msgstr "Menos" + +#: src/keycode.cpp:243 +msgid "Period" +msgstr "Período" + +#: src/keycode.cpp:243 +msgid "Plus" +msgstr "Mais" + +#: src/keycode.cpp:247 +msgid "Attn" +msgstr "Attm" + +#: src/keycode.cpp:247 +msgid "CrSel" +msgstr "CrSel" + +#: src/keycode.cpp:248 +msgid "Erase OEF" +msgstr "Apagar OEF" + +#: src/keycode.cpp:248 +msgid "ExSel" +msgstr "ExSel" + +#: src/keycode.cpp:248 +msgid "OEM Clear" +msgstr "Limpar OEM" + +#: src/keycode.cpp:248 +msgid "PA1" +msgstr "PAL" + +#: src/keycode.cpp:248 +msgid "Zoom" +msgstr "Zoom" + +#: src/main.cpp:1384 +msgid "Main Menu" +msgstr "Menu Principal" + +#: src/main.cpp:1633 +msgid "Failed to initialize world" +msgstr "Falha ao iniciar mundo" + +#: src/main.cpp:1645 +msgid "No world selected and no address provided. Nothing to do." +msgstr "" +"Nenhum mundo seleccionado e nenhum endereço providenciado. Nada para fazer." + +#: src/main.cpp:1653 +msgid "Could not find or load game \"" +msgstr "Não foi possível encontrar ou carregar jogo \"" + +#: src/main.cpp:1667 +msgid "Invalid gamespec." +msgstr "gamespec inválido." + +#: src/main.cpp:1707 +msgid "Connection error (timed out?)" +msgstr "Erro de conexão (excedeu tempo?)" + +#: src/main.cpp:1718 +msgid "" +"\n" +"Check debug.txt for details." +msgstr "" +"\n" +"Verifique debug.txt para mais detalhes." diff --git a/po/ro/minetest.po b/po/ro/minetest.po index 400cb5a4e..f07b816a5 100644 --- a/po/ro/minetest.po +++ b/po/ro/minetest.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-01-23 18:24+0200\n" +"POT-Creation-Date: 2013-01-30 20:25+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,35 +17,35 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: src/guiConfigureWorld.cpp:127 +#: src/guiConfigureWorld.cpp:125 msgid "" "Warning: Some mods are not configured yet.\n" "They will be enabled by default when you save the configuration. " msgstr "" -#: src/guiConfigureWorld.cpp:146 +#: src/guiConfigureWorld.cpp:144 msgid "" "Warning: Some configured mods are missing.\n" "Their setting will be removed when you save the configuration. " msgstr "" -#: src/guiConfigureWorld.cpp:210 +#: src/guiConfigureWorld.cpp:208 msgid "enabled" msgstr "" -#: src/guiConfigureWorld.cpp:217 +#: src/guiConfigureWorld.cpp:215 msgid "Enable All" msgstr "" -#: src/guiConfigureWorld.cpp:224 +#: src/guiConfigureWorld.cpp:222 msgid "Disable All" msgstr "" -#: src/guiConfigureWorld.cpp:230 +#: src/guiConfigureWorld.cpp:228 msgid "depends on:" msgstr "" -#: src/guiConfigureWorld.cpp:242 +#: src/guiConfigureWorld.cpp:240 msgid "is required by:" msgstr "" @@ -123,6 +123,74 @@ msgstr "" msgid "press key" msgstr "" +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" +msgstr "" + #: src/guiMainMenu.cpp:55 msgid "Cannot create world: Name contains invalid characters" msgstr "" @@ -459,18 +527,10 @@ msgid "Execute" msgstr "" #: src/keycode.cpp:228 -msgid "Left" -msgstr "" - -#: src/keycode.cpp:228 msgid "Print" msgstr "" #: src/keycode.cpp:228 -msgid "Right" -msgstr "" - -#: src/keycode.cpp:228 msgid "Select" msgstr "" diff --git a/po/ru/minetest.po b/po/ru/minetest.po index 400cb5a4e..6315e2d05 100644 --- a/po/ru/minetest.po +++ b/po/ru/minetest.po @@ -3,325 +3,401 @@ # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # -#, fuzzy msgid "" msgstr "" "Project-Id-Version: minetest\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2013-01-23 18:24+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" -"Language-Team: LANGUAGE <LL@li.org>\n" -"Language: \n" +"PO-Revision-Date: 2013-02-09 18:46+0200\n" +"Last-Translator: Oleg Matveev <gkotolegokot@gmail.com>\n" +"Language-Team: Russian\n" +"Language: ru\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" +"Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%" +"10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"X-Generator: Weblate 1.4-dev\n" -#: src/guiConfigureWorld.cpp:127 +#: src/guiConfigureWorld.cpp:125 msgid "" "Warning: Some mods are not configured yet.\n" "They will be enabled by default when you save the configuration. " msgstr "" +"Предупреждение: Некоторые моды еще не настроены.\n" +"Они будут включены, когда вы сохраните конфигурацию. " -#: src/guiConfigureWorld.cpp:146 +#: src/guiConfigureWorld.cpp:144 msgid "" "Warning: Some configured mods are missing.\n" "Their setting will be removed when you save the configuration. " msgstr "" +"Предупреждение: Некоторые моды не найдены.\n" +"Их настройки будут удалены, когда вы сохраните конфигурацию. " -#: src/guiConfigureWorld.cpp:210 +#: src/guiConfigureWorld.cpp:208 msgid "enabled" -msgstr "" +msgstr "включено" -#: src/guiConfigureWorld.cpp:217 +#: src/guiConfigureWorld.cpp:215 msgid "Enable All" -msgstr "" +msgstr "Включить все" -#: src/guiConfigureWorld.cpp:224 +#: src/guiConfigureWorld.cpp:222 msgid "Disable All" -msgstr "" +msgstr "Отключить все" -#: src/guiConfigureWorld.cpp:230 +#: src/guiConfigureWorld.cpp:228 msgid "depends on:" -msgstr "" +msgstr "зависит от:" -#: src/guiConfigureWorld.cpp:242 +#: src/guiConfigureWorld.cpp:240 msgid "is required by:" -msgstr "" +msgstr "требуется для:" #: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 #: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 msgid "Cancel" -msgstr "" +msgstr "Отменить" #: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 msgid "Save" -msgstr "" +msgstr "Сохранить" #: src/guiConfigureWorld.cpp:394 msgid "Configuration saved. " -msgstr "" +msgstr "Настройки сохранены. " #: src/guiConfigureWorld.cpp:402 msgid "Warning: Configuration not consistent. " -msgstr "" +msgstr "Предупреждение: Неверная конфигурация. " #: src/guiConfirmMenu.cpp:120 msgid "Yes" -msgstr "" +msgstr "Да" #: src/guiConfirmMenu.cpp:126 msgid "No" -msgstr "" +msgstr "Нет" #: src/guiCreateWorld.cpp:116 msgid "World name" -msgstr "" +msgstr "Название мира" #: src/guiCreateWorld.cpp:135 msgid "Game" -msgstr "" +msgstr "Игра" #: src/guiCreateWorld.cpp:159 msgid "Create" -msgstr "" +msgstr "Создать" #: src/guiDeathScreen.cpp:96 msgid "You died." -msgstr "" +msgstr "Вы умерли." #: src/guiDeathScreen.cpp:104 msgid "Respawn" -msgstr "" +msgstr "Воскреснуть" #: src/guiFormSpecMenu.cpp:572 msgid "Left click: Move all items, Right click: Move single item" -msgstr "" +msgstr "ЛКМ: Переместить все предметы, ПКМ: Переместить один предмет" #: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109 #: src/guiTextInputMenu.cpp:123 msgid "Proceed" -msgstr "" +msgstr "В работе" #: src/guiKeyChangeMenu.cpp:114 msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" msgstr "" +"Сочетания клавиш. (Если это меню сломалось, удалите настройки из " +"minetest.conf)" #: src/guiKeyChangeMenu.cpp:151 msgid "\"Use\" = climb down" -msgstr "" +msgstr "\"Использовать\" = спускаться" #: src/guiKeyChangeMenu.cpp:164 msgid "Double tap \"jump\" to toggle fly" -msgstr "" +msgstr "Дважды нажмите «прыгнуть», чтобы включить полет" #: src/guiKeyChangeMenu.cpp:269 msgid "Key already in use" -msgstr "" +msgstr "Клавиша уже используется" #: src/guiKeyChangeMenu.cpp:347 msgid "press key" +msgstr "нажмите клавишу" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "Вперед" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "Назад" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "Влево" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "Вправо" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "Использовать" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "Прыжок" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "Красться" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "Выбросить" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "Инвентарь" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "Чат" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "Комманда" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "Консоль" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "Полёт" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "Ускорение" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "Включить прохождение сквозь стены" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "Выбор видимой области" + +#: src/guiKeyChangeMenu.cpp:388 +msgid "Print stacks" msgstr "" #: src/guiMainMenu.cpp:55 msgid "Cannot create world: Name contains invalid characters" -msgstr "" +msgstr "Невозможно создать мир: имя содержит недопустимые символы" #: src/guiMainMenu.cpp:64 msgid "Cannot create world: A world by this name already exists" -msgstr "" +msgstr "Невозможно создать мир: Такое имя уже используется" #: src/guiMainMenu.cpp:245 msgid "Singleplayer" -msgstr "" +msgstr "Одиночная игра" #: src/guiMainMenu.cpp:246 msgid "Multiplayer" -msgstr "" +msgstr "Сетевая игра" #: src/guiMainMenu.cpp:247 msgid "Advanced" -msgstr "" +msgstr "Дополнительно" #: src/guiMainMenu.cpp:248 msgid "Settings" -msgstr "" +msgstr "Настройки" #: src/guiMainMenu.cpp:249 msgid "Credits" -msgstr "" +msgstr "Об авторах" #: src/guiMainMenu.cpp:280 msgid "Select World:" -msgstr "" +msgstr "Выбрать мир:" #: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229 msgid "Delete" -msgstr "" +msgstr "Удалить" #: src/guiMainMenu.cpp:309 msgid "New" -msgstr "" +msgstr "Новый" #: src/guiMainMenu.cpp:317 msgid "Configure" -msgstr "" +msgstr "Настройка" #: src/guiMainMenu.cpp:332 src/keycode.cpp:248 msgid "Play" -msgstr "" +msgstr "Играть" #: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557 msgid "Creative Mode" -msgstr "" +msgstr "Творчество" #: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563 msgid "Enable Damage" -msgstr "" +msgstr "Включить повреждения" #: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479 msgid "Name/Password" -msgstr "" +msgstr "Имя/Пароль" #: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506 msgid "Address/Port" -msgstr "" +msgstr "Адрес/Порт" #: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075 msgid "Show Public" -msgstr "" +msgstr "Публичные" #: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083 msgid "Show Favorites" -msgstr "" +msgstr "Сохраненные" #: src/guiMainMenu.cpp:459 msgid "Connect" -msgstr "" +msgstr "Подключиться" #: src/guiMainMenu.cpp:529 msgid "Leave address blank to start a local server." -msgstr "" +msgstr "Оставьте адрес пустым для запуска локального сервера." #: src/guiMainMenu.cpp:538 msgid "Start Game / Connect" -msgstr "" +msgstr "Начать игру / Подключиться" #: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006 msgid "Delete world" -msgstr "" +msgstr "Удалить мир" #: src/guiMainMenu.cpp:577 msgid "Create world" -msgstr "" +msgstr "Создать мир" #: src/guiMainMenu.cpp:611 msgid "Fancy trees" -msgstr "" +msgstr "Красивые деревья" #: src/guiMainMenu.cpp:617 msgid "Smooth Lighting" -msgstr "" +msgstr "Мягкое освещение" #: src/guiMainMenu.cpp:623 msgid "3D Clouds" -msgstr "" +msgstr "3D облака" #: src/guiMainMenu.cpp:629 msgid "Opaque water" -msgstr "" +msgstr "Непрозрачная вода" #: src/guiMainMenu.cpp:639 msgid "Mip-Mapping" -msgstr "" +msgstr "Mip-Mapping" #: src/guiMainMenu.cpp:646 msgid "Anisotropic Filtering" -msgstr "" +msgstr "Анизотропная фильтрация" #: src/guiMainMenu.cpp:653 msgid "Bi-Linear Filtering" -msgstr "" +msgstr "Билинейная фильтрация" #: src/guiMainMenu.cpp:660 msgid "Tri-Linear Filtering" -msgstr "" +msgstr "Трилинейная фильтрация" #: src/guiMainMenu.cpp:668 msgid "Shaders" -msgstr "" +msgstr "Шейдеры" #: src/guiMainMenu.cpp:675 msgid "Preload item visuals" -msgstr "" +msgstr "Кэшировать предметы" #: src/guiMainMenu.cpp:682 msgid "Enable Particles" -msgstr "" +msgstr "Включить частицы" #: src/guiMainMenu.cpp:692 msgid "Change keys" -msgstr "" +msgstr "Настройки управления" #: src/guiMainMenu.cpp:977 msgid "Address required." -msgstr "" +msgstr "Введите адрес." #: src/guiMainMenu.cpp:995 msgid "Cannot delete world: Nothing selected" -msgstr "" +msgstr "Не могу удалить мир: ничего не выбрано" #: src/guiMainMenu.cpp:1010 msgid "Files to be deleted" -msgstr "" +msgstr "Следующие файлы будут удалены" #: src/guiMainMenu.cpp:1026 msgid "Cannot create world: No games found" -msgstr "" +msgstr "Не могу создать мир: Ни одной игры не найдено" #: src/guiMainMenu.cpp:1042 msgid "Cannot configure world: Nothing selected" -msgstr "" +msgstr "Не могу настроить мир: ничего не выбрано" #: src/guiMainMenu.cpp:1146 msgid "Failed to delete all world files" -msgstr "" +msgstr "Ошибка при удалении файлов мира" #: src/guiPasswordChange.cpp:108 msgid "Old Password" -msgstr "" +msgstr "Старый пароль" #: src/guiPasswordChange.cpp:125 msgid "New Password" -msgstr "" +msgstr "Новый пароль" #: src/guiPasswordChange.cpp:141 msgid "Confirm Password" -msgstr "" +msgstr "Подтверждение пароля" #: src/guiPasswordChange.cpp:158 msgid "Change" -msgstr "" +msgstr "Изменить" #: src/guiPasswordChange.cpp:167 msgid "Passwords do not match!" -msgstr "" +msgstr "Пароли не совпадают!" #: src/guiPauseMenu.cpp:118 msgid "Continue" -msgstr "" +msgstr "Продолжить" #: src/guiPauseMenu.cpp:127 msgid "Change Password" -msgstr "" +msgstr "Изменить пароль" #: src/guiPauseMenu.cpp:135 msgid "Exit to Menu" -msgstr "" +msgstr "Выход в меню" #: src/guiPauseMenu.cpp:142 msgid "Exit to OS" -msgstr "" +msgstr "Выход в реальность" #: src/guiPauseMenu.cpp:149 msgid "" @@ -337,18 +413,29 @@ msgid "" "- ESC: This menu\n" "- T: Chat\n" msgstr "" +"Управление по умолчанию:\n" +"- WASD: перемещение\n" +"- ЛКМ: копать/ударить\n" +"- ПКМ: строить/использовать\n" +"- Колесо мыши: выбор предмета\n" +"- 0...9: выбор предмета\n" +"- Shift: красться\n" +"- R: переключить видимость всех загруженных чанков\n" +"- I: инвентарь\n" +"- ESC: это меню\n" +"- T: чат\n" #: src/keycode.cpp:223 msgid "Left Button" -msgstr "" +msgstr "Левая клавиша" #: src/keycode.cpp:223 msgid "Middle Button" -msgstr "" +msgstr "Средняя клавиша" #: src/keycode.cpp:223 msgid "Right Button" -msgstr "" +msgstr "Правая клавиша" #: src/keycode.cpp:223 msgid "X Button 1" @@ -356,11 +443,11 @@ msgstr "" #: src/keycode.cpp:224 msgid "Back" -msgstr "" +msgstr "Назад" #: src/keycode.cpp:224 msgid "Clear" -msgstr "" +msgstr "Очистить" #: src/keycode.cpp:224 msgid "Return" @@ -368,7 +455,7 @@ msgstr "" #: src/keycode.cpp:224 msgid "Tab" -msgstr "" +msgstr "Вкладка" #: src/keycode.cpp:224 msgid "X Button 2" @@ -384,15 +471,15 @@ msgstr "" #: src/keycode.cpp:225 msgid "Kana" -msgstr "" +msgstr "Кана" #: src/keycode.cpp:225 msgid "Menu" -msgstr "" +msgstr "Меню" #: src/keycode.cpp:225 msgid "Pause" -msgstr "" +msgstr "Пауза" #: src/keycode.cpp:225 msgid "Shift" @@ -416,7 +503,7 @@ msgstr "" #: src/keycode.cpp:226 msgid "Kanji" -msgstr "" +msgstr "Иероглифы" #: src/keycode.cpp:226 msgid "Nonconvert" @@ -424,7 +511,7 @@ msgstr "" #: src/keycode.cpp:227 msgid "Accept" -msgstr "" +msgstr "Принять" #: src/keycode.cpp:227 msgid "End" @@ -459,18 +546,10 @@ msgid "Execute" msgstr "" #: src/keycode.cpp:228 -msgid "Left" -msgstr "" - -#: src/keycode.cpp:228 msgid "Print" msgstr "" #: src/keycode.cpp:228 -msgid "Right" -msgstr "" - -#: src/keycode.cpp:228 msgid "Select" msgstr "" @@ -635,24 +714,25 @@ msgid "PA1" msgstr "" #: src/keycode.cpp:248 +#, fuzzy msgid "Zoom" -msgstr "" +msgstr "Масштаб" #: src/main.cpp:1384 msgid "Main Menu" -msgstr "" +msgstr "Главное меню" #: src/main.cpp:1633 msgid "Failed to initialize world" -msgstr "" +msgstr "Ошибка при инициализации мира" #: src/main.cpp:1645 msgid "No world selected and no address provided. Nothing to do." -msgstr "" +msgstr "Не выбран мир и не введен адрес." #: src/main.cpp:1653 msgid "Could not find or load game \"" -msgstr "" +msgstr "Невозможно найти или загрузить игру \"" #: src/main.cpp:1667 msgid "Invalid gamespec." @@ -660,10 +740,12 @@ msgstr "" #: src/main.cpp:1707 msgid "Connection error (timed out?)" -msgstr "" +msgstr "Ошибка соединения (таймаут?)" #: src/main.cpp:1718 msgid "" "\n" "Check debug.txt for details." msgstr "" +"\n" +"Подробная информация в debug.txt." diff --git a/po/zh_CN/minetest.po b/po/zh_CN/minetest.po new file mode 100644 index 000000000..0b87ee6b9 --- /dev/null +++ b/po/zh_CN/minetest.po @@ -0,0 +1,784 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: minetest\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-01-30 20:25+0100\n" +"PO-Revision-Date: 2013-02-06 15:03+0200\n" +"Last-Translator: Shen Zheyu <arsdragonfly@gmail.com>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 1.4-dev\n" + +#: src/guiConfigureWorld.cpp:125 +msgid "" +"Warning: Some mods are not configured yet.\n" +"They will be enabled by default when you save the configuration. " +msgstr "" +"警告:一些MOD仍未设定。\n" +"它们会在你保存配置的时候自动启用。 " + +#: src/guiConfigureWorld.cpp:144 +msgid "" +"Warning: Some configured mods are missing.\n" +"Their setting will be removed when you save the configuration. " +msgstr "" +"警告:缺少一些设定了的MOD。\n" +"它们的设置会在你保存配置的时候被移除。 " + +#: src/guiConfigureWorld.cpp:208 +msgid "enabled" +msgstr "启用" + +#: src/guiConfigureWorld.cpp:215 +msgid "Enable All" +msgstr "全部启用" + +#: src/guiConfigureWorld.cpp:222 +msgid "Disable All" +msgstr "全部禁用" + +#: src/guiConfigureWorld.cpp:228 +msgid "depends on:" +msgstr "依赖于:" + +#: src/guiConfigureWorld.cpp:240 +msgid "is required by:" +msgstr "需要:" + +#: src/guiConfigureWorld.cpp:262 src/guiCreateWorld.cpp:165 +#: src/guiKeyChangeMenu.cpp:179 src/keycode.cpp:223 +msgid "Cancel" +msgstr "取消" + +#: src/guiConfigureWorld.cpp:268 src/guiKeyChangeMenu.cpp:173 +msgid "Save" +msgstr "保存" + +#: src/guiConfigureWorld.cpp:394 +msgid "Configuration saved. " +msgstr "配置已保存。 " + +#: src/guiConfigureWorld.cpp:402 +msgid "Warning: Configuration not consistent. " +msgstr "警告:配置不一致。 " + +#: src/guiConfirmMenu.cpp:120 +msgid "Yes" +msgstr "是" + +#: src/guiConfirmMenu.cpp:126 +msgid "No" +msgstr "否" + +#: src/guiCreateWorld.cpp:116 +msgid "World name" +msgstr "世界名称" + +#: src/guiCreateWorld.cpp:135 +msgid "Game" +msgstr "游戏" + +#: src/guiCreateWorld.cpp:159 +msgid "Create" +msgstr "创建" + +#: src/guiDeathScreen.cpp:96 +msgid "You died." +msgstr "你死了。" + +#: src/guiDeathScreen.cpp:104 +msgid "Respawn" +msgstr "重生" + +#: src/guiFormSpecMenu.cpp:572 +msgid "Left click: Move all items, Right click: Move single item" +msgstr "左键:移动所有物品,右键:移动单个物品" + +#: src/guiFormSpecMenu.cpp:597 src/guiMessageMenu.cpp:109 +#: src/guiTextInputMenu.cpp:123 +msgid "Proceed" +msgstr "继续游戏" + +#: src/guiKeyChangeMenu.cpp:114 +msgid "Keybindings. (If this menu screws up, remove stuff from minetest.conf)" +msgstr "键位配置。(如果这个菜单被弄乱,从minetest.conf中删掉点东西)" + +#: src/guiKeyChangeMenu.cpp:151 +msgid "\"Use\" = climb down" +msgstr "“使用” = 向下爬" + +#: src/guiKeyChangeMenu.cpp:164 +msgid "Double tap \"jump\" to toggle fly" +msgstr "连按两次“跳”切换飞行状态" + +#: src/guiKeyChangeMenu.cpp:269 +msgid "Key already in use" +msgstr "按键已被占用" + +#: src/guiKeyChangeMenu.cpp:347 +msgid "press key" +msgstr "按键" + +#: src/guiKeyChangeMenu.cpp:372 +msgid "Forward" +msgstr "向前" + +#: src/guiKeyChangeMenu.cpp:373 +msgid "Backward" +msgstr "向后" + +#: src/guiKeyChangeMenu.cpp:374 src/keycode.cpp:228 +msgid "Left" +msgstr "向左" + +#: src/guiKeyChangeMenu.cpp:375 src/keycode.cpp:228 +msgid "Right" +msgstr "向右" + +#: src/guiKeyChangeMenu.cpp:376 +msgid "Use" +msgstr "使用" + +#: src/guiKeyChangeMenu.cpp:377 +msgid "Jump" +msgstr "跳" + +#: src/guiKeyChangeMenu.cpp:378 +msgid "Sneak" +msgstr "潜行" + +#: src/guiKeyChangeMenu.cpp:379 +msgid "Drop" +msgstr "丢出" + +#: src/guiKeyChangeMenu.cpp:380 +msgid "Inventory" +msgstr "物品栏" + +#: src/guiKeyChangeMenu.cpp:381 +msgid "Chat" +msgstr "聊天" + +#: src/guiKeyChangeMenu.cpp:382 +msgid "Command" +msgstr "命令" + +#: src/guiKeyChangeMenu.cpp:383 +msgid "Console" +msgstr "控制台" + +#: src/guiKeyChangeMenu.cpp:384 +msgid "Toggle fly" +msgstr "切换飞行状态" + +#: src/guiKeyChangeMenu.cpp:385 +msgid "Toggle fast" +msgstr "切换快速移动状态" + +#: src/guiKeyChangeMenu.cpp:386 +msgid "Toggle noclip" +msgstr "切换穿墙模式" + +#: src/guiKeyChangeMenu.cpp:387 +msgid "Range select" +msgstr "选择范围" + +#: src/guiKeyChangeMenu.cpp:388 +#, fuzzy +msgid "Print stacks" +msgstr "打印堆" + +#: src/guiMainMenu.cpp:55 +msgid "Cannot create world: Name contains invalid characters" +msgstr "无法创建世界:名字包含非法字符" + +#: src/guiMainMenu.cpp:64 +msgid "Cannot create world: A world by this name already exists" +msgstr "无法创建世界:同名世界已经存在" + +#: src/guiMainMenu.cpp:245 +msgid "Singleplayer" +msgstr "单人游戏" + +#: src/guiMainMenu.cpp:246 +msgid "Multiplayer" +msgstr "多人游戏" + +#: src/guiMainMenu.cpp:247 +#, fuzzy +msgid "Advanced" +msgstr "高级" + +#: src/guiMainMenu.cpp:248 +msgid "Settings" +msgstr "设置" + +#: src/guiMainMenu.cpp:249 +#, fuzzy +msgid "Credits" +msgstr "制作人员名单" + +#: src/guiMainMenu.cpp:280 +msgid "Select World:" +msgstr "选择世界:" + +#: src/guiMainMenu.cpp:302 src/guiMainMenu.cpp:449 src/keycode.cpp:229 +msgid "Delete" +msgstr "删除" + +#: src/guiMainMenu.cpp:309 +msgid "New" +msgstr "新建" + +#: src/guiMainMenu.cpp:317 +msgid "Configure" +msgstr "配置" + +#: src/guiMainMenu.cpp:332 src/keycode.cpp:248 +msgid "Play" +msgstr "开始游戏" + +#: src/guiMainMenu.cpp:343 src/guiMainMenu.cpp:557 +msgid "Creative Mode" +msgstr "创造模式" + +#: src/guiMainMenu.cpp:349 src/guiMainMenu.cpp:563 +msgid "Enable Damage" +msgstr "开启伤害" + +#: src/guiMainMenu.cpp:369 src/guiMainMenu.cpp:479 +msgid "Name/Password" +msgstr "名字/密码" + +#: src/guiMainMenu.cpp:408 src/guiMainMenu.cpp:506 +msgid "Address/Port" +msgstr "地址/端口" + +#: src/guiMainMenu.cpp:435 src/guiMainMenu.cpp:1075 +#, fuzzy +msgid "Show Public" +msgstr "显示公共" + +#: src/guiMainMenu.cpp:439 src/guiMainMenu.cpp:1083 +#, fuzzy +msgid "Show Favorites" +msgstr "显示最爱" + +#: src/guiMainMenu.cpp:459 +msgid "Connect" +msgstr "连接" + +#: src/guiMainMenu.cpp:529 +msgid "Leave address blank to start a local server." +msgstr "地址栏留空可启动本地服务器。" + +#: src/guiMainMenu.cpp:538 +msgid "Start Game / Connect" +msgstr "启动游戏/连接" + +#: src/guiMainMenu.cpp:570 src/guiMainMenu.cpp:1006 +msgid "Delete world" +msgstr "删除世界" + +#: src/guiMainMenu.cpp:577 +msgid "Create world" +msgstr "创造世界" + +#: src/guiMainMenu.cpp:611 +#, fuzzy +msgid "Fancy trees" +msgstr "更好看的树" + +#: src/guiMainMenu.cpp:617 +msgid "Smooth Lighting" +msgstr "平滑光照" + +#: src/guiMainMenu.cpp:623 +msgid "3D Clouds" +msgstr "3D云彩" + +#: src/guiMainMenu.cpp:629 +msgid "Opaque water" +msgstr "不反光的水" + +#: src/guiMainMenu.cpp:639 +msgid "Mip-Mapping" +msgstr "贴图处理" + +#: src/guiMainMenu.cpp:646 +msgid "Anisotropic Filtering" +msgstr "各向异性过滤" + +#: src/guiMainMenu.cpp:653 +msgid "Bi-Linear Filtering" +msgstr "双线性过滤" + +#: src/guiMainMenu.cpp:660 +msgid "Tri-Linear Filtering" +msgstr "三线性过滤" + +#: src/guiMainMenu.cpp:668 +msgid "Shaders" +msgstr "着色器" + +#: src/guiMainMenu.cpp:675 +msgid "Preload item visuals" +msgstr "预先加载物品图像" + +#: src/guiMainMenu.cpp:682 +msgid "Enable Particles" +msgstr "启用粒子效果" + +#: src/guiMainMenu.cpp:692 +msgid "Change keys" +msgstr "改变键位设置" + +#: src/guiMainMenu.cpp:977 +msgid "Address required." +msgstr "需要地址。" + +#: src/guiMainMenu.cpp:995 +msgid "Cannot delete world: Nothing selected" +msgstr "无法删除世界:没有选择世界" + +#: src/guiMainMenu.cpp:1010 +msgid "Files to be deleted" +msgstr "将被删除的文件" + +#: src/guiMainMenu.cpp:1026 +msgid "Cannot create world: No games found" +msgstr "无法创造世界:未找到游戏模式" + +#: src/guiMainMenu.cpp:1042 +msgid "Cannot configure world: Nothing selected" +msgstr "无法配置世界:没有选择世界" + +#: src/guiMainMenu.cpp:1146 +msgid "Failed to delete all world files" +msgstr "无法删除所有该世界的文件" + +#: src/guiPasswordChange.cpp:108 +msgid "Old Password" +msgstr "旧密码" + +#: src/guiPasswordChange.cpp:125 +msgid "New Password" +msgstr "新密码" + +#: src/guiPasswordChange.cpp:141 +msgid "Confirm Password" +msgstr "确认密码" + +#: src/guiPasswordChange.cpp:158 +msgid "Change" +msgstr "更改" + +#: src/guiPasswordChange.cpp:167 +msgid "Passwords do not match!" +msgstr "密码不匹配!" + +#: src/guiPauseMenu.cpp:118 +msgid "Continue" +msgstr "继续" + +#: src/guiPauseMenu.cpp:127 +msgid "Change Password" +msgstr "更改密码" + +#: src/guiPauseMenu.cpp:135 +msgid "Exit to Menu" +msgstr "退出至菜单" + +#: src/guiPauseMenu.cpp:142 +msgid "Exit to OS" +msgstr "退出至操作系统" + +#: src/guiPauseMenu.cpp:149 +msgid "" +"Default Controls:\n" +"- WASD: Walk\n" +"- Mouse left: dig/hit\n" +"- Mouse right: place/use\n" +"- Mouse wheel: select item\n" +"- 0...9: select item\n" +"- Shift: sneak\n" +"- R: Toggle viewing all loaded chunks\n" +"- I: Inventory menu\n" +"- ESC: This menu\n" +"- T: Chat\n" +msgstr "" +"默认控制:\n" +"W/A/S/D: 走\n" +"空格: 跳\n" +"鼠标左键: 挖方块/攻击\n" +"鼠标右键: 放置/使用\n" +"鼠标滚轮: 选择物品\n" +"0-9: 选择物品\n" +"Shift: 潜行\n" +"R:切换查看所有已载入区块\n" +"I:物品栏\n" +"ESC:菜单\n" +"T:聊天\n" + +#: src/keycode.cpp:223 +msgid "Left Button" +msgstr "左键" + +#: src/keycode.cpp:223 +msgid "Middle Button" +msgstr "中键" + +#: src/keycode.cpp:223 +msgid "Right Button" +msgstr "右键" + +#: src/keycode.cpp:223 +#, fuzzy +msgid "X Button 1" +msgstr "X键1" + +#: src/keycode.cpp:224 +#, fuzzy +msgid "Back" +msgstr "返回" + +#: src/keycode.cpp:224 +#, fuzzy +msgid "Clear" +msgstr "清除" + +#: src/keycode.cpp:224 +#, fuzzy +msgid "Return" +msgstr "返回" + +#: src/keycode.cpp:224 +#, fuzzy +msgid "Tab" +msgstr "Tab" + +#: src/keycode.cpp:224 +msgid "X Button 2" +msgstr "X键2" + +#: src/keycode.cpp:225 +msgid "Capital" +msgstr "大写" + +#: src/keycode.cpp:225 +msgid "Control" +msgstr "Ctrl" + +#: src/keycode.cpp:225 +#, fuzzy +msgid "Kana" +msgstr "假名" + +#: src/keycode.cpp:225 +msgid "Menu" +msgstr "菜单" + +#: src/keycode.cpp:225 +msgid "Pause" +msgstr "暂停" + +#: src/keycode.cpp:225 +#, fuzzy +msgid "Shift" +msgstr "Shift" + +#: src/keycode.cpp:226 +msgid "Convert" +msgstr "转换" + +#: src/keycode.cpp:226 +#, fuzzy +msgid "Escape" +msgstr "Escape" + +#: src/keycode.cpp:226 +#, fuzzy +msgid "Final" +msgstr "最终" + +#: src/keycode.cpp:226 +#, fuzzy +msgid "Junja" +msgstr "Junja" + +#: src/keycode.cpp:226 +#, fuzzy +msgid "Kanji" +msgstr "汉字" + +#: src/keycode.cpp:226 +#, fuzzy +msgid "Nonconvert" +msgstr "无变换" + +#: src/keycode.cpp:227 +msgid "Accept" +msgstr "接受" + +#: src/keycode.cpp:227 +#, fuzzy +msgid "End" +msgstr "End" + +#: src/keycode.cpp:227 +#, fuzzy +msgid "Home" +msgstr "Home" + +#: src/keycode.cpp:227 +msgid "Mode Change" +msgstr "改变模式" + +#: src/keycode.cpp:227 +msgid "Next" +msgstr "下一个" + +#: src/keycode.cpp:227 +#, fuzzy +msgid "Prior" +msgstr "前一个" + +#: src/keycode.cpp:227 +msgid "Space" +msgstr "空格" + +#: src/keycode.cpp:228 +msgid "Down" +msgstr "向下" + +#: src/keycode.cpp:228 +msgid "Execute" +msgstr "执行" + +#: src/keycode.cpp:228 +msgid "Print" +msgstr "打印" + +#: src/keycode.cpp:228 +msgid "Select" +msgstr "选择" + +#: src/keycode.cpp:228 +msgid "Up" +msgstr "向上" + +#: src/keycode.cpp:229 +msgid "Help" +msgstr "帮助" + +#: src/keycode.cpp:229 +msgid "Insert" +msgstr "插入" + +#: src/keycode.cpp:229 +msgid "Snapshot" +msgstr "快照" + +#: src/keycode.cpp:232 +msgid "Left Windows" +msgstr "左窗口" + +#: src/keycode.cpp:233 +msgid "Apps" +msgstr "应用" + +#: src/keycode.cpp:233 +msgid "Numpad 0" +msgstr "小键盘0" + +#: src/keycode.cpp:233 +msgid "Numpad 1" +msgstr "小键盘1" + +#: src/keycode.cpp:233 +msgid "Right Windows" +msgstr "右窗口" + +#: src/keycode.cpp:233 +msgid "Sleep" +msgstr "睡眠" + +#: src/keycode.cpp:234 +msgid "Numpad 2" +msgstr "小键盘2" + +#: src/keycode.cpp:234 +msgid "Numpad 3" +msgstr "小键盘3" + +#: src/keycode.cpp:234 +msgid "Numpad 4" +msgstr "小键盘4" + +#: src/keycode.cpp:234 +msgid "Numpad 5" +msgstr "小键盘5" + +#: src/keycode.cpp:234 +msgid "Numpad 6" +msgstr "小键盘6" + +#: src/keycode.cpp:234 +msgid "Numpad 7" +msgstr "小键盘7" + +#: src/keycode.cpp:235 +msgid "Numpad *" +msgstr "小键盘*" + +#: src/keycode.cpp:235 +msgid "Numpad +" +msgstr "小键盘+" + +#: src/keycode.cpp:235 +msgid "Numpad -" +msgstr "小键盘-" + +#: src/keycode.cpp:235 +msgid "Numpad /" +msgstr "小键盘/" + +#: src/keycode.cpp:235 +msgid "Numpad 8" +msgstr "小键盘8" + +#: src/keycode.cpp:235 +msgid "Numpad 9" +msgstr "小键盘9" + +#: src/keycode.cpp:239 +msgid "Num Lock" +msgstr "小键盘锁" + +#: src/keycode.cpp:239 +#, fuzzy +msgid "Scroll Lock" +msgstr "滚动锁" + +#: src/keycode.cpp:240 +#, fuzzy +msgid "Left Shift" +msgstr "左上档" + +#: src/keycode.cpp:240 +#, fuzzy +msgid "Right Shift" +msgstr "右上档" + +#: src/keycode.cpp:241 +#, fuzzy +msgid "Left Control" +msgstr "左控制" + +#: src/keycode.cpp:241 +#, fuzzy +msgid "Left Menu" +msgstr "左菜单" + +#: src/keycode.cpp:241 +#, fuzzy +msgid "Right Control" +msgstr "右控制" + +#: src/keycode.cpp:241 +#, fuzzy +msgid "Right Menu" +msgstr "右菜单" + +#: src/keycode.cpp:243 +msgid "Comma" +msgstr "逗号" + +#: src/keycode.cpp:243 +msgid "Minus" +msgstr "减号" + +#: src/keycode.cpp:243 +msgid "Period" +msgstr "句号" + +#: src/keycode.cpp:243 +msgid "Plus" +msgstr "加号" + +#: src/keycode.cpp:247 +#, fuzzy +msgid "Attn" +msgstr "注意" + +#: src/keycode.cpp:247 +#, fuzzy +msgid "CrSel" +msgstr "CrSel" + +#: src/keycode.cpp:248 +#, fuzzy +msgid "Erase OEF" +msgstr "Erase OEF" + +#: src/keycode.cpp:248 +#, fuzzy +msgid "ExSel" +msgstr "不选" + +#: src/keycode.cpp:248 +#, fuzzy +msgid "OEM Clear" +msgstr "默认设置" + +#: src/keycode.cpp:248 +#, fuzzy +msgid "PA1" +msgstr "PA1" + +#: src/keycode.cpp:248 +msgid "Zoom" +msgstr "缩放" + +#: src/main.cpp:1384 +msgid "Main Menu" +msgstr "主菜单" + +#: src/main.cpp:1633 +msgid "Failed to initialize world" +msgstr "无法初始化世界" + +#: src/main.cpp:1645 +msgid "No world selected and no address provided. Nothing to do." +msgstr "没有选择世界或提供地址。未执行操作。" + +#: src/main.cpp:1653 +#, fuzzy +msgid "Could not find or load game \"" +msgstr "无法找到或载入游戏模式“" + +#: src/main.cpp:1667 +#, fuzzy +msgid "Invalid gamespec." +msgstr "非法游戏模式规格。" + +#: src/main.cpp:1707 +msgid "Connection error (timed out?)" +msgstr "连接出错(超时?)" + +#: src/main.cpp:1718 +msgid "" +"\n" +"Check debug.txt for details." +msgstr "" +"\n" +"查看 debug.txt 以获得详细信息。" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8d0363548..6b96f53fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -93,6 +93,12 @@ if(USE_SOUND) ) endif() +option(ENABLE_FREETYPE "Enable freetype2 (truetype fonts and basic unicode support)" OFF) +set(USE_FREETYPE 0) +if(ENABLE_FREETYPE) + set(USE_FREETYPE 1) +endif(ENABLE_FREETYPE) + if(NOT MSVC) set(USE_GPROF 0 CACHE BOOL "Use -pg flag for g++") endif() @@ -117,6 +123,14 @@ if(WIN32) CACHE FILEPATH "Path to zlibwapi.dll (for installation)") set(IRRLICHT_SOURCE_DIR "${PROJECT_SOURCE_DIR}/../../irrlicht-1.7.2" CACHE PATH "irrlicht dir") + if(USE_FREETYPE) + set(FREETYPE_INCLUDE_DIR_ft2build "${PROJECT_SOURCE_DIR}/../../freetype2/include/" + CACHE PATH "freetype include dir") + set(FREETYPE_INCLUDE_DIR_freetype2 "${PROJECT_SOURCE_DIR}/../../freetype2/include/freetype" + CACHE PATH "freetype include dir") + set(FREETYPE_LIBRARY "${PROJECT_SOURCE_DIR}/../../freetype2/objs/win32/vc2005/freetype247.lib" + CACHE FILEPATH "Path to freetype247.lib") + endif(USE_FREETYPE) set(MINGWM10_DLL "" CACHE FILEPATH "Path to mingwm10.dll (for installation)") if(ENABLE_SOUND) @@ -157,6 +171,12 @@ endif() find_package(Jthread REQUIRED) find_package(Sqlite3 REQUIRED) +if(USE_FREETYPE) + find_package(Freetype REQUIRED) + set(CGUITTFONT_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cguittfont") + set(CGUITTFONT_LIBRARY cguittfont) +endif(USE_FREETYPE) + # Do not use system-wide installation of Lua, because it'll likely be a # different version and/or has different build options. set(LUA_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/lua/src") @@ -288,6 +308,13 @@ set(minetest_SRCS main.cpp ) +if(USE_FREETYPE) + set(minetest_SRCS + ${minetest_SRCS} + intlGUIEditBox.cpp + ) +endif(USE_FREETYPE) + # Server sources set(minetestserver_SRCS ${common_SRCS} @@ -307,6 +334,13 @@ include_directories( ${LUA_INCLUDE_DIR} ) +if(USE_FREETYPE) + include_directories( + ${FREETYPE_INCLUDE_DIRS} + ${CGUITTFONT_INCLUDE_DIR} + ) +endif(USE_FREETYPE) + set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/bin") if(BUILD_CLIENT) @@ -338,6 +372,13 @@ if(BUILD_CLIENT) ${CURL_INCLUDE_DIR} ) endif(USE_CURL) + if(USE_FREETYPE) + target_link_libraries( + ${PROJECT_NAME} + ${FREETYPE_LIBRARY} + ${CGUITTFONT_LIBRARY} + ) + endif(USE_FREETYPE) endif(BUILD_CLIENT) if(BUILD_SERVER) @@ -347,6 +388,7 @@ if(BUILD_SERVER) ${ZLIB_LIBRARIES} ${JTHREAD_LIBRARY} ${SQLITE3_LIBRARY} + ${GETTEXT_LIBRARY} ${LUA_LIBRARY} ${PLATFORM_LIBS} ) @@ -518,6 +560,10 @@ else (SQLITE3_FOUND) add_subdirectory(sqlite) endif (SQLITE3_FOUND) +if (BUILD_CLIENT AND USE_FREETYPE) + add_subdirectory(cguittfont) +endif (BUILD_CLIENT AND USE_FREETYPE) + if (LUA_FOUND) else (LUA_FOUND) add_subdirectory(lua) diff --git a/src/biome.cpp b/src/biome.cpp index 180a9c4a5..34d51839f 100644 --- a/src/biome.cpp +++ b/src/biome.cpp @@ -127,7 +127,7 @@ void BiomeDefManager::addBiome(Biome *b) { bgroup->push_back(b); verbosestream << "BiomeDefManager: added biome '" << b->name << - "' to biome group " << b->groupid << std::endl; + "' to biome group " << (int)b->groupid << std::endl; } diff --git a/src/cguittfont/CGUITTFont.cpp b/src/cguittfont/CGUITTFont.cpp new file mode 100644 index 000000000..fb8199e21 --- /dev/null +++ b/src/cguittfont/CGUITTFont.cpp @@ -0,0 +1,1146 @@ +/* + CGUITTFont FreeType class for Irrlicht + Copyright (c) 2009-2010 John Norman + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + The original version of this class can be located at: + http://irrlicht.suckerfreegames.com/ + + John Norman + john@suckerfreegames.com +*/ + +#include <irrlicht.h> +#include "CGUITTFont.h" + +namespace irr +{ +namespace gui +{ + +// Manages the FT_Face cache. +struct SGUITTFace : public virtual irr::IReferenceCounted +{ + SGUITTFace() : face_buffer(0), face_buffer_size(0) + { + memset((void*)&face, 0, sizeof(FT_Face)); + } + + ~SGUITTFace() + { + FT_Done_Face(face); + delete[] face_buffer; + } + + FT_Face face; + FT_Byte* face_buffer; + FT_Long face_buffer_size; +}; + +// Static variables. +FT_Library CGUITTFont::c_library; +core::map<io::path, SGUITTFace*> CGUITTFont::c_faces; +bool CGUITTFont::c_libraryLoaded = false; +scene::IMesh* CGUITTFont::shared_plane_ptr_ = 0; +scene::SMesh CGUITTFont::shared_plane_; + +// + +video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const +{ + // Determine what our texture size should be. + // Add 1 because textures are inclusive-exclusive. + core::dimension2du d(bits.width + 1, bits.rows + 1); + core::dimension2du texture_size; + //core::dimension2du texture_size(bits.width + 1, bits.rows + 1); + + // Create and load our image now. + video::IImage* image = 0; + switch (bits.pixel_mode) + { + case FT_PIXEL_MODE_MONO: + { + // Create a blank image and fill it with transparent pixels. + texture_size = d.getOptimalSize(true, true); + image = driver->createImage(video::ECF_A1R5G5B5, texture_size); + image->fill(video::SColor(0, 255, 255, 255)); + + // Load the monochrome data in. + const u32 image_pitch = image->getPitch() / sizeof(u16); + u16* image_data = (u16*)image->lock(); + u8* glyph_data = bits.buffer; + for (s32 y = 0; y < bits.rows; ++y) + { + u16* row = image_data; + for (s32 x = 0; x < bits.width; ++x) + { + // Monochrome bitmaps store 8 pixels per byte. The left-most pixel is the bit 0x80. + // So, we go through the data each bit at a time. + if ((glyph_data[y * bits.pitch + (x / 8)] & (0x80 >> (x % 8))) != 0) + *row = 0xFFFF; + ++row; + } + image_data += image_pitch; + } + image->unlock(); + break; + } + + case FT_PIXEL_MODE_GRAY: + { + // Create our blank image. + texture_size = d.getOptimalSize(!driver->queryFeature(video::EVDF_TEXTURE_NPOT), !driver->queryFeature(video::EVDF_TEXTURE_NSQUARE), true, 0); + image = driver->createImage(video::ECF_A8R8G8B8, texture_size); + image->fill(video::SColor(0, 255, 255, 255)); + + // Load the grayscale data in. + const float gray_count = static_cast<float>(bits.num_grays); + const u32 image_pitch = image->getPitch() / sizeof(u32); + u32* image_data = (u32*)image->lock(); + u8* glyph_data = bits.buffer; + for (s32 y = 0; y < bits.rows; ++y) + { + u8* row = glyph_data; + for (s32 x = 0; x < bits.width; ++x) + { + image_data[y * image_pitch + x] |= static_cast<u32>(255.0f * (static_cast<float>(*row++) / gray_count)) << 24; + //data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24); + } + glyph_data += bits.pitch; + } + image->unlock(); + break; + } + default: + // TODO: error message? + return 0; + } + return image; +} + +void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver* driver, u32 font_size, const FT_Int32 loadFlags) +{ + if (isLoaded) return; + + // Set the size of the glyph. + FT_Set_Pixel_Sizes(face, 0, font_size); + + // Attempt to load the glyph. + if (FT_Load_Glyph(face, char_index, loadFlags) != FT_Err_Ok) + // TODO: error message? + return; + + FT_GlyphSlot glyph = face->glyph; + FT_Bitmap bits = glyph->bitmap; + + // Setup the glyph information here: + advance = glyph->advance; + offset = core::vector2di(glyph->bitmap_left, glyph->bitmap_top); + + // Try to get the last page with available slots. + CGUITTGlyphPage* page = parent->getLastGlyphPage(); + + // If we need to make a new page, do that now. + if (!page) + { + page = parent->createGlyphPage(bits.pixel_mode); + if (!page) + // TODO: add error message? + return; + } + + glyph_page = parent->getLastGlyphPageIndex(); + u32 texture_side_length = page->texture->getOriginalSize().Width; + core::vector2di page_position( + (page->used_slots % (texture_side_length / font_size)) * font_size, + (page->used_slots / (texture_side_length / font_size)) * font_size + ); + source_rect.UpperLeftCorner = page_position; + source_rect.LowerRightCorner = core::vector2di(page_position.X + bits.width, page_position.Y + bits.rows); + + page->dirty = true; + ++page->used_slots; + --page->available_slots; + + // We grab the glyph bitmap here so the data won't be removed when the next glyph is loaded. + surface = createGlyphImage(bits, driver); + + // Set our glyph as loaded. + isLoaded = true; +} + +void SGUITTGlyph::unload() +{ + if (surface) + { + surface->drop(); + surface = 0; + } + isLoaded = false; +} + +////////////////////// + +CGUITTFont* CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias, const bool transparency) +{ + if (!c_libraryLoaded) + { + if (FT_Init_FreeType(&c_library)) + return 0; + c_libraryLoaded = true; + } + + CGUITTFont* font = new CGUITTFont(env); + bool ret = font->load(filename, size, antialias, transparency); + if (!ret) + { + font->drop(); + return 0; + } + + return font; +} + +CGUITTFont* CGUITTFont::createTTFont(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias, const bool transparency) +{ + if (!c_libraryLoaded) + { + if (FT_Init_FreeType(&c_library)) + return 0; + c_libraryLoaded = true; + } + + CGUITTFont* font = new CGUITTFont(device->getGUIEnvironment()); + font->Device = device; + bool ret = font->load(filename, size, antialias, transparency); + if (!ret) + { + font->drop(); + return 0; + } + + return font; +} + +CGUITTFont* CGUITTFont::create(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias, const bool transparency) +{ + return CGUITTFont::createTTFont(env, filename, size, antialias, transparency); +} + +CGUITTFont* CGUITTFont::create(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias, const bool transparency) +{ + return CGUITTFont::createTTFont(device, filename, size, antialias, transparency); +} + +////////////////////// + +//! Constructor. +CGUITTFont::CGUITTFont(IGUIEnvironment *env) +: use_monochrome(false), use_transparency(true), use_hinting(true), use_auto_hinting(true), +batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0) +{ + #ifdef _DEBUG + setDebugName("CGUITTFont"); + #endif + + if (Environment) + { + // don't grab environment, to avoid circular references + Driver = Environment->getVideoDriver(); + } + + if (Driver) + Driver->grab(); + + setInvisibleCharacters(L" "); + + // Glyphs aren't reference counted, so don't try to delete them when we free the array. + Glyphs.set_free_when_destroyed(false); +} + +bool CGUITTFont::load(const io::path& filename, const u32 size, const bool antialias, const bool transparency) +{ + // Some sanity checks. + if (Environment == 0 || Driver == 0) return false; + if (size == 0) return false; + if (filename.size() == 0) return false; + + io::IFileSystem* filesystem = Environment->getFileSystem(); + irr::ILogger* logger = (Device != 0 ? Device->getLogger() : 0); + this->size = size; + this->filename = filename; + + // Update the font loading flags when the font is first loaded. + this->use_monochrome = !antialias; + this->use_transparency = transparency; + update_load_flags(); + + // Log. + if (logger) + logger->log(L"CGUITTFont", core::stringw(core::stringw(L"Creating new font: ") + core::ustring(filename).toWCHAR_s() + L" " + core::stringc(size) + L"pt " + (antialias ? L"+antialias " : L"-antialias ") + (transparency ? L"+transparency" : L"-transparency")).c_str(), irr::ELL_INFORMATION); + + // Grab the face. + SGUITTFace* face = 0; + core::map<io::path, SGUITTFace*>::Node* node = c_faces.find(filename); + if (node == 0) + { + face = new SGUITTFace(); + c_faces.set(filename, face); + + if (filesystem) + { + // Read in the file data. + io::IReadFile* file = filesystem->createAndOpenFile(filename); + if (file == 0) + { + if (logger) logger->log(L"CGUITTFont", L"Failed to open the file.", irr::ELL_INFORMATION); + + c_faces.remove(filename); + delete face; + face = 0; + return false; + } + face->face_buffer = new FT_Byte[file->getSize()]; + file->read(face->face_buffer, file->getSize()); + face->face_buffer_size = file->getSize(); + file->drop(); + + // Create the face. + if (FT_New_Memory_Face(c_library, face->face_buffer, face->face_buffer_size, 0, &face->face)) + { + if (logger) logger->log(L"CGUITTFont", L"FT_New_Memory_Face failed.", irr::ELL_INFORMATION); + + c_faces.remove(filename); + delete face; + face = 0; + return false; + } + } + else + { + core::ustring converter(filename); + if (FT_New_Face(c_library, reinterpret_cast<const char*>(converter.toUTF8_s().c_str()), 0, &face->face)) + { + if (logger) logger->log(L"CGUITTFont", L"FT_New_Face failed.", irr::ELL_INFORMATION); + + c_faces.remove(filename); + delete face; + face = 0; + return false; + } + } + } + else + { + // Using another instance of this face. + face = node->getValue(); + face->grab(); + } + + // Store our face. + tt_face = face->face; + + // Store font metrics. + FT_Set_Pixel_Sizes(tt_face, size, 0); + font_metrics = tt_face->size->metrics; + + // Allocate our glyphs. + Glyphs.clear(); + Glyphs.reallocate(tt_face->num_glyphs); + Glyphs.set_used(tt_face->num_glyphs); + for (FT_Long i = 0; i < tt_face->num_glyphs; ++i) + { + Glyphs[i].isLoaded = false; + Glyphs[i].glyph_page = 0; + Glyphs[i].source_rect = core::recti(); + Glyphs[i].offset = core::vector2di(); + Glyphs[i].advance = FT_Vector(); + Glyphs[i].surface = 0; + Glyphs[i].parent = this; + } + + // Cache the first 127 ascii characters. + u32 old_size = batch_load_size; + batch_load_size = 127; + getGlyphIndexByChar((uchar32_t)0); + batch_load_size = old_size; + + return true; +} + +CGUITTFont::~CGUITTFont() +{ + // Delete the glyphs and glyph pages. + reset_images(); + CGUITTAssistDelete::Delete(Glyphs); + //Glyphs.clear(); + + // We aren't using this face anymore. + core::map<io::path, SGUITTFace*>::Node* n = c_faces.find(filename); + if (n) + { + SGUITTFace* f = n->getValue(); + + // Drop our face. If this was the last face, the destructor will clean up. + if (f->drop()) + c_faces.remove(filename); + + // If there are no more faces referenced by FreeType, clean up. + if (c_faces.size() == 0) + { + FT_Done_FreeType(c_library); + c_libraryLoaded = false; + } + } + + // Drop our driver now. + if (Driver) + Driver->drop(); +} + +void CGUITTFont::reset_images() +{ + // Delete the glyphs. + for (u32 i = 0; i != Glyphs.size(); ++i) + Glyphs[i].unload(); + + // Unload the glyph pages from video memory. + for (u32 i = 0; i != Glyph_Pages.size(); ++i) + delete Glyph_Pages[i]; + Glyph_Pages.clear(); + + // Always update the internal FreeType loading flags after resetting. + update_load_flags(); +} + +void CGUITTFont::update_glyph_pages() const +{ + for (u32 i = 0; i != Glyph_Pages.size(); ++i) + { + if (Glyph_Pages[i]->dirty) + Glyph_Pages[i]->updateTexture(); + } +} + +CGUITTGlyphPage* CGUITTFont::getLastGlyphPage() const +{ + CGUITTGlyphPage* page = 0; + if (Glyph_Pages.empty()) + return 0; + else + { + page = Glyph_Pages[getLastGlyphPageIndex()]; + if (page->available_slots == 0) + page = 0; + } + return page; +} + +CGUITTGlyphPage* CGUITTFont::createGlyphPage(const u8& pixel_mode) +{ + CGUITTGlyphPage* page = 0; + + // Name of our page. + io::path name("TTFontGlyphPage_"); + name += tt_face->family_name; + name += "."; + name += tt_face->style_name; + name += "."; + name += size; + name += "_"; + name += Glyph_Pages.size(); // The newly created page will be at the end of the collection. + + // Create the new page. + page = new CGUITTGlyphPage(Driver, name); + + // Determine our maximum texture size. + // If we keep getting 0, set it to 1024x1024, as that number is pretty safe. + core::dimension2du max_texture_size = max_page_texture_size; + if (max_texture_size.Width == 0 || max_texture_size.Height == 0) + max_texture_size = Driver->getMaxTextureSize(); + if (max_texture_size.Width == 0 || max_texture_size.Height == 0) + max_texture_size = core::dimension2du(1024, 1024); + + // We want to try to put at least 144 glyphs on a single texture. + core::dimension2du page_texture_size; + if (size <= 21) page_texture_size = core::dimension2du(256, 256); + else if (size <= 42) page_texture_size = core::dimension2du(512, 512); + else if (size <= 84) page_texture_size = core::dimension2du(1024, 1024); + else if (size <= 168) page_texture_size = core::dimension2du(2048, 2048); + else page_texture_size = core::dimension2du(4096, 4096); + + if (page_texture_size.Width > max_texture_size.Width || page_texture_size.Height > max_texture_size.Height) + page_texture_size = max_texture_size; + + if (!page->createPageTexture(pixel_mode, page_texture_size)) + // TODO: add error message? + return 0; + + if (page) + { + // Determine the number of glyph slots on the page and add it to the list of pages. + page->available_slots = (page_texture_size.Width / size) * (page_texture_size.Height / size); + Glyph_Pages.push_back(page); + } + return page; +} + +void CGUITTFont::setTransparency(const bool flag) +{ + use_transparency = flag; + reset_images(); +} + +void CGUITTFont::setMonochrome(const bool flag) +{ + use_monochrome = flag; + reset_images(); +} + +void CGUITTFont::setFontHinting(const bool enable, const bool enable_auto_hinting) +{ + use_hinting = enable; + use_auto_hinting = enable_auto_hinting; + reset_images(); +} + +void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip) +{ + if (!Driver) + return; + + // Clear the glyph pages of their render information. + for (u32 i = 0; i < Glyph_Pages.size(); ++i) + { + Glyph_Pages[i]->render_positions.clear(); + Glyph_Pages[i]->render_source_rects.clear(); + } + + // Set up some variables. + core::dimension2d<s32> textDimension; + core::position2d<s32> offset = position.UpperLeftCorner; + + // Determine offset positions. + if (hcenter || vcenter) + { + textDimension = getDimension(text.c_str()); + + if (hcenter) + offset.X = ((position.getWidth() - textDimension.Width) >> 1) + offset.X; + + if (vcenter) + offset.Y = ((position.getHeight() - textDimension.Height) >> 1) + offset.Y; + } + + // Convert to a unicode string. + core::ustring utext(text); + + // Set up our render map. + core::map<u32, CGUITTGlyphPage*> Render_Map; + + // Start parsing characters. + u32 n; + uchar32_t previousChar = 0; + core::ustring::const_iterator iter(utext); + while (!iter.atEnd()) + { + uchar32_t currentChar = *iter; + n = getGlyphIndexByChar(currentChar); + bool visible = (Invisible.findFirst(currentChar) == -1); + if (n > 0 && visible) + { + bool lineBreak=false; + if (currentChar == L'\r') // Mac or Windows breaks + { + lineBreak = true; + if (*(iter + 1) == (uchar32_t)'\n') // Windows line breaks. + currentChar = *(++iter); + } + else if (currentChar == (uchar32_t)'\n') // Unix breaks + { + lineBreak = true; + } + + if (lineBreak) + { + previousChar = 0; + offset.Y += font_metrics.ascender / 64; + offset.X = position.UpperLeftCorner.X; + + if (hcenter) + offset.X += (position.getWidth() - textDimension.Width) >> 1; + ++iter; + continue; + } + + // Calculate the glyph offset. + s32 offx = Glyphs[n-1].offset.X; + s32 offy = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y; + + // Apply kerning. + core::vector2di k = getKerning(currentChar, previousChar); + offset.X += k.X; + offset.Y += k.Y; + + // Determine rendering information. + SGUITTGlyph& glyph = Glyphs[n-1]; + CGUITTGlyphPage* const page = Glyph_Pages[glyph.glyph_page]; + page->render_positions.push_back(core::position2di(offset.X + offx, offset.Y + offy)); + page->render_source_rects.push_back(glyph.source_rect); + Render_Map.set(glyph.glyph_page, page); + } + offset.X += getWidthFromCharacter(currentChar); + + previousChar = currentChar; + ++iter; + } + + // Draw now. + update_glyph_pages(); + core::map<u32, CGUITTGlyphPage*>::Iterator j = Render_Map.getIterator(); + while (!j.atEnd()) + { + core::map<u32, CGUITTGlyphPage*>::Node* n = j.getNode(); + j++; + if (n == 0) continue; + + CGUITTGlyphPage* page = n->getValue(); + + if (!use_transparency) color.color |= 0xff000000; + Driver->draw2DImageBatch(page->texture, page->render_positions, page->render_source_rects, clip, color, true); + } +} + +core::dimension2d<u32> CGUITTFont::getCharDimension(const wchar_t ch) const +{ + return core::dimension2d<u32>(getWidthFromCharacter(ch), getHeightFromCharacter(ch)); +} + +core::dimension2d<u32> CGUITTFont::getDimension(const wchar_t* text) const +{ + return getDimension(core::ustring(text)); +} + +core::dimension2d<u32> CGUITTFont::getDimension(const core::ustring& text) const +{ + // Get the maximum font height. Unfortunately, we have to do this hack as + // Irrlicht will draw things wrong. In FreeType, the font size is the + // maximum size for a single glyph, but that glyph may hang "under" the + // draw line, increasing the total font height to beyond the set size. + // Irrlicht does not understand this concept when drawing fonts. Also, I + // add +1 to give it a 1 pixel blank border. This makes things like + // tooltips look nicer. + s32 test1 = getHeightFromCharacter((uchar32_t)'g') + 1; + s32 test2 = getHeightFromCharacter((uchar32_t)'j') + 1; + s32 test3 = getHeightFromCharacter((uchar32_t)'_') + 1; + s32 max_font_height = core::max_(test1, core::max_(test2, test3)); + + core::dimension2d<u32> text_dimension(0, max_font_height); + core::dimension2d<u32> line(0, max_font_height); + + uchar32_t previousChar = 0; + core::ustring::const_iterator iter = text.begin(); + for (; !iter.atEnd(); ++iter) + { + uchar32_t p = *iter; + bool lineBreak = false; + if (p == '\r') // Mac or Windows line breaks. + { + lineBreak = true; + if (*(iter + 1) == '\n') + { + ++iter; + p = *iter; + } + } + else if (p == '\n') // Unix line breaks. + { + lineBreak = true; + } + + // Kerning. + core::vector2di k = getKerning(p, previousChar); + line.Width += k.X; + previousChar = p; + + // Check for linebreak. + if (lineBreak) + { + previousChar = 0; + text_dimension.Height += line.Height; + if (text_dimension.Width < line.Width) + text_dimension.Width = line.Width; + line.Width = 0; + line.Height = max_font_height; + continue; + } + line.Width += getWidthFromCharacter(p); + } + if (text_dimension.Width < line.Width) + text_dimension.Width = line.Width; + + return text_dimension; +} + +inline u32 CGUITTFont::getWidthFromCharacter(wchar_t c) const +{ + return getWidthFromCharacter((uchar32_t)c); +} + +inline u32 CGUITTFont::getWidthFromCharacter(uchar32_t c) const +{ + // Set the size of the face. + // This is because we cache faces and the face may have been set to a different size. + //FT_Set_Pixel_Sizes(tt_face, 0, size); + + u32 n = getGlyphIndexByChar(c); + if (n > 0) + { + int w = Glyphs[n-1].advance.x / 64; + return w; + } + if (c >= 0x2000) + return (font_metrics.ascender / 64); + else return (font_metrics.ascender / 64) / 2; +} + +inline u32 CGUITTFont::getHeightFromCharacter(wchar_t c) const +{ + return getHeightFromCharacter((uchar32_t)c); +} + +inline u32 CGUITTFont::getHeightFromCharacter(uchar32_t c) const +{ + // Set the size of the face. + // This is because we cache faces and the face may have been set to a different size. + //FT_Set_Pixel_Sizes(tt_face, 0, size); + + u32 n = getGlyphIndexByChar(c); + if (n > 0) + { + // Grab the true height of the character, taking into account underhanging glyphs. + s32 height = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y + Glyphs[n-1].source_rect.getHeight(); + return height; + } + if (c >= 0x2000) + return (font_metrics.ascender / 64); + else return (font_metrics.ascender / 64) / 2; +} + +u32 CGUITTFont::getGlyphIndexByChar(wchar_t c) const +{ + return getGlyphIndexByChar((uchar32_t)c); +} + +u32 CGUITTFont::getGlyphIndexByChar(uchar32_t c) const +{ + // Get the glyph. + u32 glyph = FT_Get_Char_Index(tt_face, c); + + // Check for a valid glyph. If it is invalid, attempt to use the replacement character. + if (glyph == 0) + glyph = FT_Get_Char_Index(tt_face, core::unicode::UTF_REPLACEMENT_CHARACTER); + + // If our glyph is already loaded, don't bother doing any batch loading code. + if (glyph != 0 && Glyphs[glyph - 1].isLoaded) + return glyph; + + // Determine our batch loading positions. + u32 half_size = (batch_load_size / 2); + u32 start_pos = 0; + if (c > half_size) start_pos = c - half_size; + u32 end_pos = start_pos + batch_load_size; + + // Load all our characters. + do + { + // Get the character we are going to load. + u32 char_index = FT_Get_Char_Index(tt_face, start_pos); + + // If the glyph hasn't been loaded yet, do it now. + if (char_index) + { + SGUITTGlyph& glyph = Glyphs[char_index - 1]; + if (!glyph.isLoaded) + { + glyph.preload(char_index, tt_face, Driver, size, load_flags); + Glyph_Pages[glyph.glyph_page]->pushGlyphToBePaged(&glyph); + } + } + } + while (++start_pos < end_pos); + + // Return our original character. + return glyph; +} + +s32 CGUITTFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const +{ + return getCharacterFromPos(core::ustring(text), pixel_x); +} + +s32 CGUITTFont::getCharacterFromPos(const core::ustring& text, s32 pixel_x) const +{ + s32 x = 0; + //s32 idx = 0; + + u32 character = 0; + uchar32_t previousChar = 0; + core::ustring::const_iterator iter = text.begin(); + while (!iter.atEnd()) + { + uchar32_t c = *iter; + x += getWidthFromCharacter(c); + + // Kerning. + core::vector2di k = getKerning(c, previousChar); + x += k.X; + + if (x >= pixel_x) + return character; + + previousChar = c; + ++iter; + ++character; + } + + return -1; +} + +void CGUITTFont::setKerningWidth(s32 kerning) +{ + GlobalKerningWidth = kerning; +} + +void CGUITTFont::setKerningHeight(s32 kerning) +{ + GlobalKerningHeight = kerning; +} + +s32 CGUITTFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const +{ + if (tt_face == 0) + return GlobalKerningWidth; + if (thisLetter == 0 || previousLetter == 0) + return 0; + + return getKerningWidth((uchar32_t)*thisLetter, (uchar32_t)*previousLetter); +} + +s32 CGUITTFont::getKerningWidth(const uchar32_t thisLetter, const uchar32_t previousLetter) const +{ + // Return only the kerning width. + return getKerning(thisLetter, previousLetter).X; +} + +s32 CGUITTFont::getKerningHeight() const +{ + // FreeType 2 currently doesn't return any height kerning information. + return GlobalKerningHeight; +} + +core::vector2di CGUITTFont::getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const +{ + return getKerning((uchar32_t)thisLetter, (uchar32_t)previousLetter); +} + +core::vector2di CGUITTFont::getKerning(const uchar32_t thisLetter, const uchar32_t previousLetter) const +{ + if (tt_face == 0 || thisLetter == 0 || previousLetter == 0) + return core::vector2di(); + + // Set the size of the face. + // This is because we cache faces and the face may have been set to a different size. + FT_Set_Pixel_Sizes(tt_face, 0, size); + + core::vector2di ret(GlobalKerningWidth, GlobalKerningHeight); + + // If we don't have kerning, no point in continuing. + if (!FT_HAS_KERNING(tt_face)) + return ret; + + // Get the kerning information. + FT_Vector v; + FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), getGlyphIndexByChar(thisLetter), FT_KERNING_DEFAULT, &v); + + // If we have a scalable font, the return value will be in font points. + if (FT_IS_SCALABLE(tt_face)) + { + // Font points, so divide by 64. + ret.X += (v.x / 64); + ret.Y += (v.y / 64); + } + else + { + // Pixel units. + ret.X += v.x; + ret.Y += v.y; + } + return ret; +} + +void CGUITTFont::setInvisibleCharacters(const wchar_t *s) +{ + core::ustring us(s); + Invisible = us; +} + +void CGUITTFont::setInvisibleCharacters(const core::ustring& s) +{ + Invisible = s; +} + +video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch) +{ + u32 n = getGlyphIndexByChar(ch); + const SGUITTGlyph& glyph = Glyphs[n-1]; + CGUITTGlyphPage* page = Glyph_Pages[glyph.glyph_page]; + + if (page->dirty) + page->updateTexture(); + + video::ITexture* tex = page->texture; + + // Acquire a read-only lock of the corresponding page texture. + #if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR>=8 + void* ptr = tex->lock(video::ETLM_READ_ONLY); + #else + void* ptr = tex->lock(true); + #endif + + video::ECOLOR_FORMAT format = tex->getColorFormat(); + core::dimension2du tex_size = tex->getOriginalSize(); + video::IImage* pageholder = Driver->createImageFromData(format, tex_size, ptr, true, false); + + // Copy the image data out of the page texture. + core::dimension2du glyph_size(glyph.source_rect.getSize()); + video::IImage* image = Driver->createImage(format, glyph_size); + pageholder->copyTo(image, core::position2di(0, 0), glyph.source_rect); + + tex->unlock(); + return image; +} + +video::ITexture* CGUITTFont::getPageTextureByIndex(const u32& page_index) const +{ + if (page_index < Glyph_Pages.size()) + return Glyph_Pages[page_index]->texture; + else + return 0; +} + +void CGUITTFont::createSharedPlane() +{ + /* + 2___3 + | /| + | / | <-- plane mesh is like this, point 2 is (0,0), point 0 is (0, -1) + |/ | <-- the texture coords of point 2 is (0,0, point 0 is (0, 1) + 0---1 + */ + + using namespace core; + using namespace video; + using namespace scene; + S3DVertex vertices[4]; + u16 indices[6] = {0,2,3,3,1,0}; + vertices[0] = S3DVertex(vector3df(0,-1,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(0,1)); + vertices[1] = S3DVertex(vector3df(1,-1,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(1,1)); + vertices[2] = S3DVertex(vector3df(0, 0,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(0,0)); + vertices[3] = S3DVertex(vector3df(1, 0,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(1,0)); + + SMeshBuffer* buf = new SMeshBuffer(); + buf->append(vertices, 4, indices, 6); + + shared_plane_.addMeshBuffer( buf ); + + shared_plane_ptr_ = &shared_plane_; + buf->drop(); //the addMeshBuffer method will grab it, so we can drop this ptr. +} + +core::dimension2d<u32> CGUITTFont::getDimensionUntilEndOfLine(const wchar_t* p) const +{ + core::stringw s; + for (const wchar_t* temp = p; temp && *temp != '\0' && *temp != L'\r' && *temp != L'\n'; ++temp ) + s.append(*temp); + + return getDimension(s.c_str()); +} + +core::array<scene::ISceneNode*> CGUITTFont::addTextSceneNode(const wchar_t* text, scene::ISceneManager* smgr, scene::ISceneNode* parent, const video::SColor& color, bool center) +{ + using namespace core; + using namespace video; + using namespace scene; + + array<scene::ISceneNode*> container; + + if (!Driver || !smgr) return container; + if (!parent) + parent = smgr->addEmptySceneNode(smgr->getRootSceneNode(), -1); + // if you don't specify parent, then we add a empty node attached to the root node + // this is generally undesirable. + + if (!shared_plane_ptr_) //this points to a static mesh that contains the plane + createSharedPlane(); //if it's not initialized, we create one. + + dimension2d<s32> text_size(getDimension(text)); //convert from unsigned to signed. + vector3df start_point(0, 0, 0), offset; + + /** NOTICE: + Because we are considering adding texts into 3D world, all Y axis vectors are inverted. + **/ + + // There's currently no "vertical center" concept when you apply text scene node to the 3D world. + if (center) + { + offset.X = start_point.X = -text_size.Width / 2.f; + offset.Y = start_point.Y = +text_size.Height/ 2.f; + offset.X += (text_size.Width - getDimensionUntilEndOfLine(text).Width) >> 1; + } + + // the default font material + SMaterial mat; + mat.setFlag(video::EMF_LIGHTING, true); + mat.setFlag(video::EMF_ZWRITE_ENABLE, false); + mat.setFlag(video::EMF_NORMALIZE_NORMALS, true); + mat.ColorMaterial = video::ECM_NONE; + mat.MaterialType = use_transparency ? video::EMT_TRANSPARENT_ALPHA_CHANNEL : video::EMT_SOLID; + mat.MaterialTypeParam = 0.01f; + mat.DiffuseColor = color; + + wchar_t current_char = 0, previous_char = 0; + u32 n = 0; + + array<u32> glyph_indices; + + while (*text) + { + current_char = *text; + bool line_break=false; + if (current_char == L'\r') // Mac or Windows breaks + { + line_break = true; + if (*(text + 1) == L'\n') // Windows line breaks. + current_char = *(++text); + } + else if (current_char == L'\n') // Unix breaks + { + line_break = true; + } + + if (line_break) + { + previous_char = 0; + offset.Y -= tt_face->size->metrics.ascender / 64; + offset.X = start_point.X; + if (center) + offset.X += (text_size.Width - getDimensionUntilEndOfLine(text+1).Width) >> 1; + ++text; + } + else + { + n = getGlyphIndexByChar(current_char); + if (n > 0) + { + glyph_indices.push_back( n ); + + // Store glyph size and offset informations. + SGUITTGlyph const& glyph = Glyphs[n-1]; + u32 texw = glyph.source_rect.getWidth(); + u32 texh = glyph.source_rect.getHeight(); + s32 offx = glyph.offset.X; + s32 offy = (font_metrics.ascender / 64) - glyph.offset.Y; + + // Apply kerning. + vector2di k = getKerning(current_char, previous_char); + offset.X += k.X; + offset.Y += k.Y; + + vector3df current_pos(offset.X + offx, offset.Y - offy, 0); + dimension2d<u32> letter_size = dimension2d<u32>(texw, texh); + + // Now we copy planes corresponding to the letter size. + IMeshManipulator* mani = smgr->getMeshManipulator(); + IMesh* meshcopy = mani->createMeshCopy(shared_plane_ptr_); + #if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR>=8 + mani->scale(meshcopy, vector3df((f32)letter_size.Width, (f32)letter_size.Height, 1)); + #else + mani->scaleMesh(meshcopy, vector3df((f32)letter_size.Width, (f32)letter_size.Height, 1)); + #endif + + ISceneNode* current_node = smgr->addMeshSceneNode(meshcopy, parent, -1, current_pos); + meshcopy->drop(); + + current_node->getMaterial(0) = mat; + current_node->setAutomaticCulling(EAC_OFF); + current_node->setIsDebugObject(true); //so the picking won't have any effect on individual letter + //current_node->setDebugDataVisible(EDS_BBOX); //de-comment this when debugging + + container.push_back(current_node); + } + offset.X += getWidthFromCharacter(current_char); + previous_char = current_char; + ++text; + } + } + + update_glyph_pages(); + //only after we update the textures can we use the glyph page textures. + + for (u32 i = 0; i < glyph_indices.size(); ++i) + { + u32 n = glyph_indices[i]; + SGUITTGlyph const& glyph = Glyphs[n-1]; + ITexture* current_tex = Glyph_Pages[glyph.glyph_page]->texture; + f32 page_texture_size = (f32)current_tex->getSize().Width; + //Now we calculate the UV position according to the texture size and the source rect. + // + // 2___3 + // | /| + // | / | <-- plane mesh is like this, point 2 is (0,0), point 0 is (0, -1) + // |/ | <-- the texture coords of point 2 is (0,0, point 0 is (0, 1) + // 0---1 + // + f32 u1 = glyph.source_rect.UpperLeftCorner.X / page_texture_size; + f32 u2 = u1 + (glyph.source_rect.getWidth() / page_texture_size); + f32 v1 = glyph.source_rect.UpperLeftCorner.Y / page_texture_size; + f32 v2 = v1 + (glyph.source_rect.getHeight() / page_texture_size); + + //we can be quite sure that this is IMeshSceneNode, because we just added them in the above loop. + IMeshSceneNode* node = static_cast<IMeshSceneNode*>(container[i]); + + S3DVertex* pv = static_cast<S3DVertex*>(node->getMesh()->getMeshBuffer(0)->getVertices()); + //pv[0].TCoords.Y = pv[1].TCoords.Y = (letter_size.Height - 1) / static_cast<f32>(letter_size.Height); + //pv[1].TCoords.X = pv[3].TCoords.X = (letter_size.Width - 1) / static_cast<f32>(letter_size.Width); + pv[0].TCoords = vector2df(u1, v2); + pv[1].TCoords = vector2df(u2, v2); + pv[2].TCoords = vector2df(u1, v1); + pv[3].TCoords = vector2df(u2, v1); + + container[i]->getMaterial(0).setTexture(0, current_tex); + } + + return container; +} + +} // end namespace gui +} // end namespace irr diff --git a/src/cguittfont/CGUITTFont.h b/src/cguittfont/CGUITTFont.h new file mode 100644 index 000000000..12e25e0f3 --- /dev/null +++ b/src/cguittfont/CGUITTFont.h @@ -0,0 +1,377 @@ +/* + CGUITTFont FreeType class for Irrlicht + Copyright (c) 2009-2010 John Norman + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + The original version of this class can be located at: + http://irrlicht.suckerfreegames.com/ + + John Norman + john@suckerfreegames.com +*/ + +#ifndef __C_GUI_TTFONT_H_INCLUDED__ +#define __C_GUI_TTFONT_H_INCLUDED__ + +#include <irrlicht.h> +#include <ft2build.h> +#include FT_FREETYPE_H + +namespace irr +{ +namespace gui +{ + struct SGUITTFace; + class CGUITTFont; + + //! Class to assist in deleting glyphs. + class CGUITTAssistDelete + { + public: + template <class T, typename TAlloc> + static void Delete(core::array<T, TAlloc>& a) + { + TAlloc allocator; + allocator.deallocate(a.pointer()); + } + }; + + //! Structure representing a single TrueType glyph. + struct SGUITTGlyph + { + //! Constructor. + SGUITTGlyph() : isLoaded(false), glyph_page(0), surface(0), parent(0) {} + + //! Destructor. + ~SGUITTGlyph() { unload(); } + + //! Preload the glyph. + //! The preload process occurs when the program tries to cache the glyph from FT_Library. + //! However, it simply defines the SGUITTGlyph's properties and will only create the page + //! textures if necessary. The actual creation of the textures should only occur right + //! before the batch draw call. + void preload(u32 char_index, FT_Face face, video::IVideoDriver* driver, u32 font_size, const FT_Int32 loadFlags); + + //! Unloads the glyph. + void unload(); + + //! Creates the IImage object from the FT_Bitmap. + video::IImage* createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const; + + //! If true, the glyph has been loaded. + bool isLoaded; + + //! The page the glyph is on. + u32 glyph_page; + + //! The source rectangle for the glyph. + core::recti source_rect; + + //! The offset of glyph when drawn. + core::vector2di offset; + + //! Glyph advance information. + FT_Vector advance; + + //! This is just the temporary image holder. After this glyph is paged, + //! it will be dropped. + mutable video::IImage* surface; + + //! The pointer pointing to the parent (CGUITTFont) + CGUITTFont* parent; + }; + + //! Holds a sheet of glyphs. + class CGUITTGlyphPage + { + public: + CGUITTGlyphPage(video::IVideoDriver* Driver, const io::path& texture_name) :texture(0), available_slots(0), used_slots(0), dirty(false), driver(Driver), name(texture_name) {} + ~CGUITTGlyphPage() + { + if (texture) + { + if (driver) + driver->removeTexture(texture); + else texture->drop(); + } + } + + //! Create the actual page texture, + bool createPageTexture(const u8& pixel_mode, const core::dimension2du& texture_size) + { + if( texture ) + return false; + + bool flgmip = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); + + // Set the texture color format. + switch (pixel_mode) + { + case FT_PIXEL_MODE_MONO: + texture = driver->addTexture(texture_size, name, video::ECF_A1R5G5B5); + break; + case FT_PIXEL_MODE_GRAY: + default: + texture = driver->addTexture(texture_size, name, video::ECF_A8R8G8B8); + break; + } + + // Restore our texture creation flags. + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flgmip); + return texture ? true : false; + } + + //! Add the glyph to a list of glyphs to be paged. + //! This collection will be cleared after updateTexture is called. + void pushGlyphToBePaged(const SGUITTGlyph* glyph) + { + glyph_to_be_paged.push_back(glyph); + } + + //! Updates the texture atlas with new glyphs. + void updateTexture() + { + if (!dirty) return; + + void* ptr = texture->lock(); + video::ECOLOR_FORMAT format = texture->getColorFormat(); + core::dimension2du size = texture->getOriginalSize(); + video::IImage* pageholder = driver->createImageFromData(format, size, ptr, true, false); + + for (u32 i = 0; i < glyph_to_be_paged.size(); ++i) + { + const SGUITTGlyph* glyph = glyph_to_be_paged[i]; + if (glyph && glyph->isLoaded) + { + if (glyph->surface) + { + glyph->surface->copyTo(pageholder, glyph->source_rect.UpperLeftCorner); + glyph->surface->drop(); + glyph->surface = 0; + } + else + { + ; // TODO: add error message? + //currently, if we failed to create the image, just ignore this operation. + } + } + } + + pageholder->drop(); + texture->unlock(); + glyph_to_be_paged.clear(); + dirty = false; + } + + video::ITexture* texture; + u32 available_slots; + u32 used_slots; + bool dirty; + + core::array<core::vector2di> render_positions; + core::array<core::recti> render_source_rects; + + private: + core::array<const SGUITTGlyph*> glyph_to_be_paged; + video::IVideoDriver* driver; + io::path name; + }; + + //! Class representing a TrueType font. + class CGUITTFont : public IGUIFont + { + public: + //! Creates a new TrueType font and returns a pointer to it. The pointer must be drop()'ed when finished. + //! \param env The IGUIEnvironment the font loads out of. + //! \param filename The filename of the font. + //! \param size The size of the font glyphs in pixels. Since this is the size of the individual glyphs, the true height of the font may change depending on the characters used. + //! \param antialias set the use_monochrome (opposite to antialias) flag + //! \param transparency set the use_transparency flag + //! \return Returns a pointer to a CGUITTFont. Will return 0 if the font failed to load. + static CGUITTFont* createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true); + static CGUITTFont* createTTFont(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true); + static CGUITTFont* create(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true); + static CGUITTFont* create(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true); + + //! Destructor + virtual ~CGUITTFont(); + + //! Sets the amount of glyphs to batch load. + virtual void setBatchLoadSize(u32 batch_size) { batch_load_size = batch_size; } + + //! Sets the maximum texture size for a page of glyphs. + virtual void setMaxPageTextureSize(const core::dimension2du& texture_size) { max_page_texture_size = texture_size; } + + //! Get the font size. + virtual u32 getFontSize() const { return size; } + + //! Check the font's transparency. + virtual bool isTransparent() const { return use_transparency; } + + //! Check if the font auto-hinting is enabled. + //! Auto-hinting is FreeType's built-in font hinting engine. + virtual bool useAutoHinting() const { return use_auto_hinting; } + + //! Check if the font hinting is enabled. + virtual bool useHinting() const { return use_hinting; } + + //! Check if the font is being loaded as a monochrome font. + //! The font can either be a 256 color grayscale font, or a 2 color monochrome font. + virtual bool useMonochrome() const { return use_monochrome; } + + //! Tells the font to allow transparency when rendering. + //! Default: true. + //! \param flag If true, the font draws using transparency. + virtual void setTransparency(const bool flag); + + //! Tells the font to use monochrome rendering. + //! Default: false. + //! \param flag If true, the font draws using a monochrome image. If false, the font uses a grayscale image. + virtual void setMonochrome(const bool flag); + + //! Enables or disables font hinting. + //! Default: Hinting and auto-hinting true. + //! \param enable If false, font hinting is turned off. If true, font hinting is turned on. + //! \param enable_auto_hinting If true, FreeType uses its own auto-hinting algorithm. If false, it tries to use the algorithm specified by the font. + virtual void setFontHinting(const bool enable, const bool enable_auto_hinting = true); + + //! Draws some text and clips it to the specified rectangle if wanted. + virtual void draw(const core::stringw& text, const core::rect<s32>& position, + video::SColor color, bool hcenter=false, bool vcenter=false, + const core::rect<s32>* clip=0); + + //! Returns the dimension of a character produced by this font. + virtual core::dimension2d<u32> getCharDimension(const wchar_t ch) const; + + //! Returns the dimension of a text string. + virtual core::dimension2d<u32> getDimension(const wchar_t* text) const; + virtual core::dimension2d<u32> getDimension(const core::ustring& text) const; + + //! Calculates the index of the character in the text which is on a specific position. + virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const; + virtual s32 getCharacterFromPos(const core::ustring& text, s32 pixel_x) const; + + //! Sets global kerning width for the font. + virtual void setKerningWidth(s32 kerning); + + //! Sets global kerning height for the font. + virtual void setKerningHeight(s32 kerning); + + //! Gets kerning values (distance between letters) for the font. If no parameters are provided, + virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const; + virtual s32 getKerningWidth(const uchar32_t thisLetter=0, const uchar32_t previousLetter=0) const; + + //! Returns the distance between letters + virtual s32 getKerningHeight() const; + + //! Define which characters should not be drawn by the font. + virtual void setInvisibleCharacters(const wchar_t *s); + virtual void setInvisibleCharacters(const core::ustring& s); + + //! Get the last glyph page if there's still available slots. + //! If not, it will return zero. + CGUITTGlyphPage* getLastGlyphPage() const; + + //! Create a new glyph page texture. + //! \param pixel_mode the pixel mode defined by FT_Pixel_Mode + //should be better typed. fix later. + CGUITTGlyphPage* createGlyphPage(const u8& pixel_mode); + + //! Get the last glyph page's index. + u32 getLastGlyphPageIndex() const { return Glyph_Pages.size() - 1; } + + //! Create corresponding character's software image copy from the font, + //! so you can use this data just like any ordinary video::IImage. + //! \param ch The character you need + virtual video::IImage* createTextureFromChar(const uchar32_t& ch); + + //! This function is for debugging mostly. If the page doesn't exist it returns zero. + //! \param page_index Simply return the texture handle of a given page index. + virtual video::ITexture* getPageTextureByIndex(const u32& page_index) const; + + //! Add a list of scene nodes generated by putting font textures on the 3D planes. + virtual core::array<scene::ISceneNode*> addTextSceneNode + (const wchar_t* text, scene::ISceneManager* smgr, scene::ISceneNode* parent = 0, + const video::SColor& color = video::SColor(255, 0, 0, 0), bool center = false ); + + protected: + bool use_monochrome; + bool use_transparency; + bool use_hinting; + bool use_auto_hinting; + u32 size; + u32 batch_load_size; + core::dimension2du max_page_texture_size; + + private: + // Manages the FreeType library. + static FT_Library c_library; + static core::map<io::path, SGUITTFace*> c_faces; + static bool c_libraryLoaded; + static scene::IMesh* shared_plane_ptr_; + static scene::SMesh shared_plane_; + + CGUITTFont(IGUIEnvironment *env); + bool load(const io::path& filename, const u32 size, const bool antialias, const bool transparency); + void reset_images(); + void update_glyph_pages() const; + void update_load_flags() + { + // Set up our loading flags. + load_flags = FT_LOAD_DEFAULT | FT_LOAD_RENDER; + if (!useHinting()) load_flags |= FT_LOAD_NO_HINTING; + if (!useAutoHinting()) load_flags |= FT_LOAD_NO_AUTOHINT; + if (useMonochrome()) load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO | FT_RENDER_MODE_MONO; + else load_flags |= FT_LOAD_TARGET_NORMAL; + } + u32 getWidthFromCharacter(wchar_t c) const; + u32 getWidthFromCharacter(uchar32_t c) const; + u32 getHeightFromCharacter(wchar_t c) const; + u32 getHeightFromCharacter(uchar32_t c) const; + u32 getGlyphIndexByChar(wchar_t c) const; + u32 getGlyphIndexByChar(uchar32_t c) const; + core::vector2di getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const; + core::vector2di getKerning(const uchar32_t thisLetter, const uchar32_t previousLetter) const; + core::dimension2d<u32> getDimensionUntilEndOfLine(const wchar_t* p) const; + + void createSharedPlane(); + + irr::IrrlichtDevice* Device; + gui::IGUIEnvironment* Environment; + video::IVideoDriver* Driver; + io::path filename; + FT_Face tt_face; + FT_Size_Metrics font_metrics; + FT_Int32 load_flags; + + mutable core::array<CGUITTGlyphPage*> Glyph_Pages; + mutable core::array<SGUITTGlyph> Glyphs; + + s32 GlobalKerningWidth; + s32 GlobalKerningHeight; + core::ustring Invisible; + }; + +} // end namespace gui +} // end namespace irr + +#endif // __C_GUI_TTFONT_H_INCLUDED__ diff --git a/src/cguittfont/CMakeLists.txt b/src/cguittfont/CMakeLists.txt new file mode 100644 index 000000000..94d061462 --- /dev/null +++ b/src/cguittfont/CMakeLists.txt @@ -0,0 +1,17 @@ +include_directories( + ${IRRLICHT_INCLUDE_DIR} + ${FREETYPE_INCLUDE_DIRS} +) + +# CGUITTFont authors, y u no include headers you use? +# Do not add CGUITTFont.cpp to the line below. +# xCGUITTFont.cpp is a wrapper file that includes +# additional required headers. +add_library(cguittfont xCGUITTFont.cpp) + +target_link_libraries( + cguittfont + ${IRRLICHT_LIBRARY} + ${FREETYPE_LIBRARY} + ${ZLIB_LIBRARIES} # needed by freetype, repeated here for safety +) diff --git a/src/cguittfont/irrUString.h b/src/cguittfont/irrUString.h new file mode 100644 index 000000000..f41fa1f7b --- /dev/null +++ b/src/cguittfont/irrUString.h @@ -0,0 +1,3877 @@ +/* + Basic Unicode string class for Irrlicht. + Copyright (c) 2009-2011 John Norman + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any + damages arising from the use of this software. + + Permission is granted to anyone to use this software for any + purpose, including commercial applications, and to alter it and + redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. + + The original version of this class can be located at: + http://irrlicht.suckerfreegames.com/ + + John Norman + john@suckerfreegames.com +*/ + +#ifndef __IRR_USTRING_H_INCLUDED__ +#define __IRR_USTRING_H_INCLUDED__ + +#if (__cplusplus > 199711L) || (_MSC_VER >= 1600) || defined(__GXX_EXPERIMENTAL_CXX0X__) +# define USTRING_CPP0X +# if defined(__GXX_EXPERIMENTAL_CXX0X__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5))) +# define USTRING_CPP0X_NEWLITERALS +# endif +#endif + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#ifdef USTRING_CPP0X +# include <utility> +#endif + +#ifndef USTRING_NO_STL +# include <string> +# include <iterator> +# include <ostream> +#endif + +#include "irrTypes.h" +#include "irrAllocator.h" +#include "irrArray.h" +#include "irrMath.h" +#include "irrString.h" +#include "path.h" + +//! UTF-16 surrogate start values. +static const irr::u16 UTF16_HI_SURROGATE = 0xD800; +static const irr::u16 UTF16_LO_SURROGATE = 0xDC00; + +//! Is a UTF-16 code point a surrogate? +#define UTF16_IS_SURROGATE(c) (((c) & 0xF800) == 0xD800) +#define UTF16_IS_SURROGATE_HI(c) (((c) & 0xFC00) == 0xD800) +#define UTF16_IS_SURROGATE_LO(c) (((c) & 0xFC00) == 0xDC00) + + +namespace irr +{ + + // Define our character types. +#ifdef USTRING_CPP0X_NEWLITERALS // C++0x + typedef char32_t uchar32_t; + typedef char16_t uchar16_t; + typedef char uchar8_t; +#else + typedef u32 uchar32_t; + typedef u16 uchar16_t; + typedef u8 uchar8_t; +#endif + +namespace core +{ + +namespace unicode +{ + +//! The unicode replacement character. Used to replace invalid characters. +const irr::u16 UTF_REPLACEMENT_CHARACTER = 0xFFFD; + +//! Convert a UTF-16 surrogate pair into a UTF-32 character. +//! \param high The high value of the pair. +//! \param low The low value of the pair. +//! \return The UTF-32 character expressed by the surrogate pair. +inline uchar32_t toUTF32(uchar16_t high, uchar16_t low) +{ + // Convert the surrogate pair into a single UTF-32 character. + uchar32_t x = ((high & ((1 << 6) -1)) << 10) | (low & ((1 << 10) -1)); + uchar32_t wu = ((high >> 6) & ((1 << 5) - 1)) + 1; + return (wu << 16) | x; +} + +//! Swaps the endianness of a 16-bit value. +//! \return The new value. +inline uchar16_t swapEndian16(const uchar16_t& c) +{ + return ((c >> 8) & 0x00FF) | ((c << 8) & 0xFF00); +} + +//! Swaps the endianness of a 32-bit value. +//! \return The new value. +inline uchar32_t swapEndian32(const uchar32_t& c) +{ + return ((c >> 24) & 0x000000FF) | + ((c >> 8) & 0x0000FF00) | + ((c << 8) & 0x00FF0000) | + ((c << 24) & 0xFF000000); +} + +//! The Unicode byte order mark. +const u16 BOM = 0xFEFF; + +//! The size of the Unicode byte order mark in terms of the Unicode character size. +const u8 BOM_UTF8_LEN = 3; +const u8 BOM_UTF16_LEN = 1; +const u8 BOM_UTF32_LEN = 1; + +//! Unicode byte order marks for file operations. +const u8 BOM_ENCODE_UTF8[3] = { 0xEF, 0xBB, 0xBF }; +const u8 BOM_ENCODE_UTF16_BE[2] = { 0xFE, 0xFF }; +const u8 BOM_ENCODE_UTF16_LE[2] = { 0xFF, 0xFE }; +const u8 BOM_ENCODE_UTF32_BE[4] = { 0x00, 0x00, 0xFE, 0xFF }; +const u8 BOM_ENCODE_UTF32_LE[4] = { 0xFF, 0xFE, 0x00, 0x00 }; + +//! The size in bytes of the Unicode byte marks for file operations. +const u8 BOM_ENCODE_UTF8_LEN = 3; +const u8 BOM_ENCODE_UTF16_LEN = 2; +const u8 BOM_ENCODE_UTF32_LEN = 4; + +//! Unicode encoding type. +enum EUTF_ENCODE +{ + EUTFE_NONE = 0, + EUTFE_UTF8, + EUTFE_UTF16, + EUTFE_UTF16_LE, + EUTFE_UTF16_BE, + EUTFE_UTF32, + EUTFE_UTF32_LE, + EUTFE_UTF32_BE +}; + +//! Unicode endianness. +enum EUTF_ENDIAN +{ + EUTFEE_NATIVE = 0, + EUTFEE_LITTLE, + EUTFEE_BIG +}; + +//! Returns the specified unicode byte order mark in a byte array. +//! The byte order mark is the first few bytes in a text file that signifies its encoding. +/** \param mode The Unicode encoding method that we want to get the byte order mark for. + If EUTFE_UTF16 or EUTFE_UTF32 is passed, it uses the native system endianness. **/ +//! \return An array that contains a byte order mark. +inline core::array<u8> getUnicodeBOM(EUTF_ENCODE mode) +{ +#define COPY_ARRAY(source, size) \ + memcpy(ret.pointer(), source, size); \ + ret.set_used(size) + + core::array<u8> ret(4); + switch (mode) + { + case EUTFE_UTF8: + COPY_ARRAY(BOM_ENCODE_UTF8, BOM_ENCODE_UTF8_LEN); + break; + case EUTFE_UTF16: + #ifdef __BIG_ENDIAN__ + COPY_ARRAY(BOM_ENCODE_UTF16_BE, BOM_ENCODE_UTF16_LEN); + #else + COPY_ARRAY(BOM_ENCODE_UTF16_LE, BOM_ENCODE_UTF16_LEN); + #endif + break; + case EUTFE_UTF16_BE: + COPY_ARRAY(BOM_ENCODE_UTF16_BE, BOM_ENCODE_UTF16_LEN); + break; + case EUTFE_UTF16_LE: + COPY_ARRAY(BOM_ENCODE_UTF16_LE, BOM_ENCODE_UTF16_LEN); + break; + case EUTFE_UTF32: + #ifdef __BIG_ENDIAN__ + COPY_ARRAY(BOM_ENCODE_UTF32_BE, BOM_ENCODE_UTF32_LEN); + #else + COPY_ARRAY(BOM_ENCODE_UTF32_LE, BOM_ENCODE_UTF32_LEN); + #endif + break; + case EUTFE_UTF32_BE: + COPY_ARRAY(BOM_ENCODE_UTF32_BE, BOM_ENCODE_UTF32_LEN); + break; + case EUTFE_UTF32_LE: + COPY_ARRAY(BOM_ENCODE_UTF32_LE, BOM_ENCODE_UTF32_LEN); + break; + } + return ret; + +#undef COPY_ARRAY +} + +//! Detects if the given data stream starts with a unicode BOM. +//! \param data The data stream to check. +//! \return The unicode BOM associated with the data stream, or EUTFE_NONE if none was found. +inline EUTF_ENCODE determineUnicodeBOM(const char* data) +{ + if (memcmp(data, BOM_ENCODE_UTF8, 3) == 0) return EUTFE_UTF8; + if (memcmp(data, BOM_ENCODE_UTF16_BE, 2) == 0) return EUTFE_UTF16_BE; + if (memcmp(data, BOM_ENCODE_UTF16_LE, 2) == 0) return EUTFE_UTF16_LE; + if (memcmp(data, BOM_ENCODE_UTF32_BE, 4) == 0) return EUTFE_UTF32_BE; + if (memcmp(data, BOM_ENCODE_UTF32_LE, 4) == 0) return EUTFE_UTF32_LE; + return EUTFE_NONE; +} + +} // end namespace unicode + + +//! UTF-16 string class. +template <typename TAlloc = irrAllocator<uchar16_t> > +class ustring16 +{ +public: + + ///------------------/// + /// iterator classes /// + ///------------------/// + + //! Access an element in a unicode string, allowing one to change it. + class _ustring16_iterator_access + { + public: + _ustring16_iterator_access(const ustring16<TAlloc>* s, u32 p) : ref(s), pos(p) {} + + //! Allow the class to be interpreted as a single UTF-32 character. + operator uchar32_t() const + { + return _get(); + } + + //! Allow one to change the character in the unicode string. + //! \param c The new character to use. + //! \return Myself. + _ustring16_iterator_access& operator=(const uchar32_t c) + { + _set(c); + return *this; + } + + //! Increments the value by 1. + //! \return Myself. + _ustring16_iterator_access& operator++() + { + _set(_get() + 1); + return *this; + } + + //! Increments the value by 1, returning the old value. + //! \return A unicode character. + uchar32_t operator++(int) + { + uchar32_t old = _get(); + _set(old + 1); + return old; + } + + //! Decrements the value by 1. + //! \return Myself. + _ustring16_iterator_access& operator--() + { + _set(_get() - 1); + return *this; + } + + //! Decrements the value by 1, returning the old value. + //! \return A unicode character. + uchar32_t operator--(int) + { + uchar32_t old = _get(); + _set(old - 1); + return old; + } + + //! Adds to the value by a specified amount. + //! \param val The amount to add to this character. + //! \return Myself. + _ustring16_iterator_access& operator+=(int val) + { + _set(_get() + val); + return *this; + } + + //! Subtracts from the value by a specified amount. + //! \param val The amount to subtract from this character. + //! \return Myself. + _ustring16_iterator_access& operator-=(int val) + { + _set(_get() - val); + return *this; + } + + //! Multiples the value by a specified amount. + //! \param val The amount to multiply this character by. + //! \return Myself. + _ustring16_iterator_access& operator*=(int val) + { + _set(_get() * val); + return *this; + } + + //! Divides the value by a specified amount. + //! \param val The amount to divide this character by. + //! \return Myself. + _ustring16_iterator_access& operator/=(int val) + { + _set(_get() / val); + return *this; + } + + //! Modulos the value by a specified amount. + //! \param val The amount to modulo this character by. + //! \return Myself. + _ustring16_iterator_access& operator%=(int val) + { + _set(_get() % val); + return *this; + } + + //! Adds to the value by a specified amount. + //! \param val The amount to add to this character. + //! \return A unicode character. + uchar32_t operator+(int val) const + { + return _get() + val; + } + + //! Subtracts from the value by a specified amount. + //! \param val The amount to subtract from this character. + //! \return A unicode character. + uchar32_t operator-(int val) const + { + return _get() - val; + } + + //! Multiplies the value by a specified amount. + //! \param val The amount to multiply this character by. + //! \return A unicode character. + uchar32_t operator*(int val) const + { + return _get() * val; + } + + //! Divides the value by a specified amount. + //! \param val The amount to divide this character by. + //! \return A unicode character. + uchar32_t operator/(int val) const + { + return _get() / val; + } + + //! Modulos the value by a specified amount. + //! \param val The amount to modulo this character by. + //! \return A unicode character. + uchar32_t operator%(int val) const + { + return _get() % val; + } + + private: + //! Gets a uchar32_t from our current position. + uchar32_t _get() const + { + const uchar16_t* a = ref->c_str(); + if (!UTF16_IS_SURROGATE(a[pos])) + return static_cast<uchar32_t>(a[pos]); + else + { + if (pos + 1 >= ref->size_raw()) + return 0; + + return unicode::toUTF32(a[pos], a[pos + 1]); + } + } + + //! Sets a uchar32_t at our current position. + void _set(uchar32_t c) + { + ustring16<TAlloc>* ref2 = const_cast<ustring16<TAlloc>*>(ref); + const uchar16_t* a = ref2->c_str(); + if (c > 0xFFFF) + { + // c will be multibyte, so split it up into the high and low surrogate pairs. + uchar16_t x = static_cast<uchar16_t>(c); + uchar16_t vh = UTF16_HI_SURROGATE | ((((c >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); + uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); + + // If the previous position was a surrogate pair, just replace them. Else, insert the low pair. + if (UTF16_IS_SURROGATE_HI(a[pos]) && pos + 1 != ref2->size_raw()) + ref2->replace_raw(vl, static_cast<u32>(pos) + 1); + else ref2->insert_raw(vl, static_cast<u32>(pos) + 1); + + ref2->replace_raw(vh, static_cast<u32>(pos)); + } + else + { + // c will be a single byte. + uchar16_t vh = static_cast<uchar16_t>(c); + + // If the previous position was a surrogate pair, remove the extra byte. + if (UTF16_IS_SURROGATE_HI(a[pos])) + ref2->erase_raw(static_cast<u32>(pos) + 1); + + ref2->replace_raw(vh, static_cast<u32>(pos)); + } + } + + const ustring16<TAlloc>* ref; + u32 pos; + }; + typedef typename ustring16<TAlloc>::_ustring16_iterator_access access; + + + //! Iterator to iterate through a UTF-16 string. +#ifndef USTRING_NO_STL + class _ustring16_const_iterator : public std::iterator< + std::bidirectional_iterator_tag, // iterator_category + access, // value_type + ptrdiff_t, // difference_type + const access, // pointer + const access // reference + > +#else + class _ustring16_const_iterator +#endif + { + public: + typedef _ustring16_const_iterator _Iter; + typedef std::iterator<std::bidirectional_iterator_tag, access, ptrdiff_t, const access, const access> _Base; + typedef const access const_pointer; + typedef const access const_reference; + +#ifndef USTRING_NO_STL + typedef typename _Base::value_type value_type; + typedef typename _Base::difference_type difference_type; + typedef typename _Base::difference_type distance_type; + typedef typename _Base::pointer pointer; + typedef const_reference reference; +#else + typedef access value_type; + typedef u32 difference_type; + typedef u32 distance_type; + typedef const_pointer pointer; + typedef const_reference reference; +#endif + + //! Constructors. + _ustring16_const_iterator(const _Iter& i) : ref(i.ref), pos(i.pos) {} + _ustring16_const_iterator(const ustring16<TAlloc>& s) : ref(&s), pos(0) {} + _ustring16_const_iterator(const ustring16<TAlloc>& s, const u32 p) : ref(&s), pos(0) + { + if (ref->size_raw() == 0 || p == 0) + return; + + // Go to the appropriate position. + u32 i = p; + u32 sr = ref->size_raw(); + const uchar16_t* a = ref->c_str(); + while (i != 0 && pos < sr) + { + if (UTF16_IS_SURROGATE_HI(a[pos])) + pos += 2; + else ++pos; + --i; + } + } + + //! Test for equalness. + bool operator==(const _Iter& iter) const + { + if (ref == iter.ref && pos == iter.pos) + return true; + return false; + } + + //! Test for unequalness. + bool operator!=(const _Iter& iter) const + { + if (ref != iter.ref || pos != iter.pos) + return true; + return false; + } + + //! Switch to the next full character in the string. + _Iter& operator++() + { // ++iterator + if (pos == ref->size_raw()) return *this; + const uchar16_t* a = ref->c_str(); + if (UTF16_IS_SURROGATE_HI(a[pos])) + pos += 2; // TODO: check for valid low surrogate? + else ++pos; + if (pos > ref->size_raw()) pos = ref->size_raw(); + return *this; + } + + //! Switch to the next full character in the string, returning the previous position. + _Iter operator++(int) + { // iterator++ + _Iter _tmp(*this); + ++*this; + return _tmp; + } + + //! Switch to the previous full character in the string. + _Iter& operator--() + { // --iterator + if (pos == 0) return *this; + const uchar16_t* a = ref->c_str(); + --pos; + if (UTF16_IS_SURROGATE_LO(a[pos]) && pos != 0) // low surrogate, go back one more. + --pos; + return *this; + } + + //! Switch to the previous full character in the string, returning the previous position. + _Iter operator--(int) + { // iterator-- + _Iter _tmp(*this); + --*this; + return _tmp; + } + + //! Advance a specified number of full characters in the string. + //! \return Myself. + _Iter& operator+=(const difference_type v) + { + if (v == 0) return *this; + if (v < 0) return operator-=(v * -1); + + if (pos >= ref->size_raw()) + return *this; + + // Go to the appropriate position. + // TODO: Don't force u32 on an x64 OS. Make it agnostic. + u32 i = (u32)v; + u32 sr = ref->size_raw(); + const uchar16_t* a = ref->c_str(); + while (i != 0 && pos < sr) + { + if (UTF16_IS_SURROGATE_HI(a[pos])) + pos += 2; + else ++pos; + --i; + } + if (pos > sr) + pos = sr; + + return *this; + } + + //! Go back a specified number of full characters in the string. + //! \return Myself. + _Iter& operator-=(const difference_type v) + { + if (v == 0) return *this; + if (v > 0) return operator+=(v * -1); + + if (pos == 0) + return *this; + + // Go to the appropriate position. + // TODO: Don't force u32 on an x64 OS. Make it agnostic. + u32 i = (u32)v; + const uchar16_t* a = ref->c_str(); + while (i != 0 && pos != 0) + { + --pos; + if (UTF16_IS_SURROGATE_LO(a[pos]) != 0 && pos != 0) + --pos; + --i; + } + + return *this; + } + + //! Return a new iterator that is a variable number of full characters forward from the current position. + _Iter operator+(const difference_type v) const + { + _Iter ret(*this); + ret += v; + return ret; + } + + //! Return a new iterator that is a variable number of full characters backward from the current position. + _Iter operator-(const difference_type v) const + { + _Iter ret(*this); + ret -= v; + return ret; + } + + //! Returns the distance between two iterators. + difference_type operator-(const _Iter& iter) const + { + // Make sure we reference the same object! + if (ref != iter.ref) + return difference_type(); + + _Iter i = iter; + difference_type ret; + + // Walk up. + if (pos > i.pos) + { + while (pos > i.pos) + { + ++i; + ++ret; + } + return ret; + } + + // Walk down. + while (pos < i.pos) + { + --i; + --ret; + } + return ret; + } + + //! Accesses the full character at the iterator's position. + const_reference operator*() const + { + if (pos >= ref->size_raw()) + { + const uchar16_t* a = ref->c_str(); + u32 p = ref->size_raw(); + if (UTF16_IS_SURROGATE_LO(a[p])) + --p; + reference ret(ref, p); + return ret; + } + const_reference ret(ref, pos); + return ret; + } + + //! Accesses the full character at the iterator's position. + reference operator*() + { + if (pos >= ref->size_raw()) + { + const uchar16_t* a = ref->c_str(); + u32 p = ref->size_raw(); + if (UTF16_IS_SURROGATE_LO(a[p])) + --p; + reference ret(ref, p); + return ret; + } + reference ret(ref, pos); + return ret; + } + + //! Accesses the full character at the iterator's position. + const_pointer operator->() const + { + return operator*(); + } + + //! Accesses the full character at the iterator's position. + pointer operator->() + { + return operator*(); + } + + //! Is the iterator at the start of the string? + bool atStart() const + { + return pos == 0; + } + + //! Is the iterator at the end of the string? + bool atEnd() const + { + const uchar16_t* a = ref->c_str(); + if (UTF16_IS_SURROGATE(a[pos])) + return (pos + 1) >= ref->size_raw(); + else return pos >= ref->size_raw(); + } + + //! Moves the iterator to the start of the string. + void toStart() + { + pos = 0; + } + + //! Moves the iterator to the end of the string. + void toEnd() + { + const uchar16_t* a = ref->c_str(); + pos = ref->size_raw(); + } + + //! Returns the iterator's position. + //! \return The iterator's position. + u32 getPos() const + { + return pos; + } + + protected: + const ustring16<TAlloc>* ref; + u32 pos; + }; + + //! Iterator to iterate through a UTF-16 string. + class _ustring16_iterator : public _ustring16_const_iterator + { + public: + typedef _ustring16_iterator _Iter; + typedef _ustring16_const_iterator _Base; + typedef typename _Base::const_pointer const_pointer; + typedef typename _Base::const_reference const_reference; + + typedef typename _Base::value_type value_type; + typedef typename _Base::difference_type difference_type; + typedef typename _Base::distance_type distance_type; + typedef access pointer; + typedef access reference; + + using _Base::pos; + using _Base::ref; + + //! Constructors. + _ustring16_iterator(const _Iter& i) : _ustring16_const_iterator(i) {} + _ustring16_iterator(const ustring16<TAlloc>& s) : _ustring16_const_iterator(s) {} + _ustring16_iterator(const ustring16<TAlloc>& s, const u32 p) : _ustring16_const_iterator(s, p) {} + + //! Accesses the full character at the iterator's position. + reference operator*() const + { + if (pos >= ref->size_raw()) + { + const uchar16_t* a = ref->c_str(); + u32 p = ref->size_raw(); + if (UTF16_IS_SURROGATE_LO(a[p])) + --p; + reference ret(ref, p); + return ret; + } + reference ret(ref, pos); + return ret; + } + + //! Accesses the full character at the iterator's position. + reference operator*() + { + if (pos >= ref->size_raw()) + { + const uchar16_t* a = ref->c_str(); + u32 p = ref->size_raw(); + if (UTF16_IS_SURROGATE_LO(a[p])) + --p; + reference ret(ref, p); + return ret; + } + reference ret(ref, pos); + return ret; + } + + //! Accesses the full character at the iterator's position. + pointer operator->() const + { + return operator*(); + } + + //! Accesses the full character at the iterator's position. + pointer operator->() + { + return operator*(); + } + }; + + typedef typename ustring16<TAlloc>::_ustring16_iterator iterator; + typedef typename ustring16<TAlloc>::_ustring16_const_iterator const_iterator; + + ///----------------------/// + /// end iterator classes /// + ///----------------------/// + + //! Default constructor + ustring16() + : array(0), allocated(1), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + array = allocator.allocate(1); // new u16[1]; + array[0] = 0x0; + } + + + //! Constructor + ustring16(const ustring16<TAlloc>& other) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + *this = other; + } + + + //! Constructor from other string types + template <class B, class A> + ustring16(const string<B, A>& other) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + *this = other; + } + + +#ifndef USTRING_NO_STL + //! Constructor from std::string + template <class B, class A, typename Alloc> + ustring16(const std::basic_string<B, A, Alloc>& other) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + *this = other.c_str(); + } + + + //! Constructor from iterator. + template <typename Itr> + ustring16(Itr first, Itr last) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + reserve(std::distance(first, last)); + array[used] = 0; + + for (; first != last; ++first) + append((uchar32_t)*first); + } +#endif + + +#ifndef USTRING_CPP0X_NEWLITERALS + //! Constructor for copying a character string from a pointer. + ustring16(const char* const c) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + loadDataStream(c, strlen(c)); + //append((uchar8_t*)c); + } + + + //! Constructor for copying a character string from a pointer with a given length. + ustring16(const char* const c, u32 length) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + loadDataStream(c, length); + } +#endif + + + //! Constructor for copying a UTF-8 string from a pointer. + ustring16(const uchar8_t* const c) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + append(c); + } + + + //! Constructor for copying a UTF-8 string from a single char. + ustring16(const char c) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + append((uchar32_t)c); + } + + + //! Constructor for copying a UTF-8 string from a pointer with a given length. + ustring16(const uchar8_t* const c, u32 length) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + append(c, length); + } + + + //! Constructor for copying a UTF-16 string from a pointer. + ustring16(const uchar16_t* const c) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + append(c); + } + + + //! Constructor for copying a UTF-16 string from a pointer with a given length + ustring16(const uchar16_t* const c, u32 length) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + append(c, length); + } + + + //! Constructor for copying a UTF-32 string from a pointer. + ustring16(const uchar32_t* const c) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + append(c); + } + + + //! Constructor for copying a UTF-32 from a pointer with a given length. + ustring16(const uchar32_t* const c, u32 length) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + append(c, length); + } + + + //! Constructor for copying a wchar_t string from a pointer. + ustring16(const wchar_t* const c) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + if (sizeof(wchar_t) == 4) + append(reinterpret_cast<const uchar32_t* const>(c)); + else if (sizeof(wchar_t) == 2) + append(reinterpret_cast<const uchar16_t* const>(c)); + else if (sizeof(wchar_t) == 1) + append(reinterpret_cast<const uchar8_t* const>(c)); + } + + + //! Constructor for copying a wchar_t string from a pointer with a given length. + ustring16(const wchar_t* const c, u32 length) + : array(0), allocated(0), used(0) + { +#if __BIG_ENDIAN__ + encoding = unicode::EUTFE_UTF16_BE; +#else + encoding = unicode::EUTFE_UTF16_LE; +#endif + + if (sizeof(wchar_t) == 4) + append(reinterpret_cast<const uchar32_t* const>(c), length); + else if (sizeof(wchar_t) == 2) + append(reinterpret_cast<const uchar16_t* const>(c), length); + else if (sizeof(wchar_t) == 1) + append(reinterpret_cast<const uchar8_t* const>(c), length); + } + + +#ifdef USTRING_CPP0X + //! Constructor for moving a ustring16 + ustring16(ustring16<TAlloc>&& other) + : array(other.array), encoding(other.encoding), allocated(other.allocated), used(other.used) + { + //std::cout << "MOVE constructor" << std::endl; + other.array = 0; + other.allocated = 0; + other.used = 0; + } +#endif + + + //! Destructor + ~ustring16() + { + allocator.deallocate(array); // delete [] array; + } + + + //! Assignment operator + ustring16& operator=(const ustring16<TAlloc>& other) + { + if (this == &other) + return *this; + + used = other.size_raw(); + if (used >= allocated) + { + allocator.deallocate(array); // delete [] array; + allocated = used + 1; + array = allocator.allocate(used + 1); //new u16[used]; + } + + const uchar16_t* p = other.c_str(); + for (u32 i=0; i<=used; ++i, ++p) + array[i] = *p; + + array[used] = 0; + + // Validate our new UTF-16 string. + validate(); + + return *this; + } + + +#ifdef USTRING_CPP0X + //! Move assignment operator + ustring16& operator=(ustring16<TAlloc>&& other) + { + if (this != &other) + { + //std::cout << "MOVE operator=" << std::endl; + allocator.deallocate(array); + + array = other.array; + allocated = other.allocated; + encoding = other.encoding; + used = other.used; + other.array = 0; + other.used = 0; + } + return *this; + } +#endif + + + //! Assignment operator for other string types + template <class B, class A> + ustring16<TAlloc>& operator=(const string<B, A>& other) + { + *this = other.c_str(); + return *this; + } + + + //! Assignment operator for UTF-8 strings + ustring16<TAlloc>& operator=(const uchar8_t* const c) + { + if (!array) + { + array = allocator.allocate(1); //new u16[1]; + allocated = 1; + } + used = 0; + array[used] = 0x0; + if (!c) return *this; + + //! Append our string now. + append(c); + return *this; + } + + + //! Assignment operator for UTF-16 strings + ustring16<TAlloc>& operator=(const uchar16_t* const c) + { + if (!array) + { + array = allocator.allocate(1); //new u16[1]; + allocated = 1; + } + used = 0; + array[used] = 0x0; + if (!c) return *this; + + //! Append our string now. + append(c); + return *this; + } + + + //! Assignment operator for UTF-32 strings + ustring16<TAlloc>& operator=(const uchar32_t* const c) + { + if (!array) + { + array = allocator.allocate(1); //new u16[1]; + allocated = 1; + } + used = 0; + array[used] = 0x0; + if (!c) return *this; + + //! Append our string now. + append(c); + return *this; + } + + + //! Assignment operator for wchar_t strings. + /** Note that this assumes that a correct unicode string is stored in the wchar_t string. + Since wchar_t changes depending on its platform, it could either be a UTF-8, -16, or -32 string. + This function assumes you are storing the correct unicode encoding inside the wchar_t string. **/ + ustring16<TAlloc>& operator=(const wchar_t* const c) + { + if (sizeof(wchar_t) == 4) + *this = reinterpret_cast<const uchar32_t* const>(c); + else if (sizeof(wchar_t) == 2) + *this = reinterpret_cast<const uchar16_t* const>(c); + else if (sizeof(wchar_t) == 1) + *this = reinterpret_cast<const uchar8_t* const>(c); + + return *this; + } + + + //! Assignment operator for other strings. + /** Note that this assumes that a correct unicode string is stored in the string. **/ + template <class B> + ustring16<TAlloc>& operator=(const B* const c) + { + if (sizeof(B) == 4) + *this = reinterpret_cast<const uchar32_t* const>(c); + else if (sizeof(B) == 2) + *this = reinterpret_cast<const uchar16_t* const>(c); + else if (sizeof(B) == 1) + *this = reinterpret_cast<const uchar8_t* const>(c); + + return *this; + } + + + //! Direct access operator + access operator [](const u32 index) + { + _IRR_DEBUG_BREAK_IF(index>=size()) // bad index + iterator iter(*this, index); + return iter.operator*(); + } + + + //! Direct access operator + const access operator [](const u32 index) const + { + _IRR_DEBUG_BREAK_IF(index>=size()) // bad index + const_iterator iter(*this, index); + return iter.operator*(); + } + + + //! Equality operator + bool operator ==(const uchar16_t* const str) const + { + if (!str) + return false; + + u32 i; + for(i=0; array[i] && str[i]; ++i) + if (array[i] != str[i]) + return false; + + return !array[i] && !str[i]; + } + + + //! Equality operator + bool operator ==(const ustring16<TAlloc>& other) const + { + for(u32 i=0; array[i] && other.array[i]; ++i) + if (array[i] != other.array[i]) + return false; + + return used == other.used; + } + + + //! Is smaller comparator + bool operator <(const ustring16<TAlloc>& other) const + { + for(u32 i=0; array[i] && other.array[i]; ++i) + { + s32 diff = array[i] - other.array[i]; + if ( diff ) + return diff < 0; + } + + return used < other.used; + } + + + //! Inequality operator + bool operator !=(const uchar16_t* const str) const + { + return !(*this == str); + } + + + //! Inequality operator + bool operator !=(const ustring16<TAlloc>& other) const + { + return !(*this == other); + } + + + //! Returns the length of a ustring16 in full characters. + //! \return Length of a ustring16 in full characters. + u32 size() const + { + const_iterator i(*this, 0); + u32 pos = 0; + while (!i.atEnd()) + { + ++i; + ++pos; + } + return pos; + } + + + //! Informs if the ustring is empty or not. + //! \return True if the ustring is empty, false if not. + bool empty() const + { + return (size_raw() == 0); + } + + + //! Returns a pointer to the raw UTF-16 string data. + //! \return pointer to C-style NUL terminated array of UTF-16 code points. + const uchar16_t* c_str() const + { + return array; + } + + + //! Compares the first n characters of this string with another. + //! \param other Other string to compare to. + //! \param n Number of characters to compare. + //! \return True if the n first characters of both strings are equal. + bool equalsn(const ustring16<TAlloc>& other, u32 n) const + { + u32 i; + const uchar16_t* oa = other.c_str(); + for(i=0; array[i] && oa[i] && i < n; ++i) + if (array[i] != oa[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same length + return (i == n) || (used == other.used); + } + + + //! Compares the first n characters of this string with another. + //! \param str Other string to compare to. + //! \param n Number of characters to compare. + //! \return True if the n first characters of both strings are equal. + bool equalsn(const uchar16_t* const str, u32 n) const + { + if (!str) + return false; + u32 i; + for(i=0; array[i] && str[i] && i < n; ++i) + if (array[i] != str[i]) + return false; + + // if one (or both) of the strings was smaller then they + // are only equal if they have the same length + return (i == n) || (array[i] == 0 && str[i] == 0); + } + + + //! Appends a character to this ustring16 + //! \param character The character to append. + //! \return A reference to our current string. + ustring16<TAlloc>& append(uchar32_t character) + { + if (used + 2 >= allocated) + reallocate(used + 2); + + if (character > 0xFFFF) + { + used += 2; + + // character will be multibyte, so split it up into a surrogate pair. + uchar16_t x = static_cast<uchar16_t>(character); + uchar16_t vh = UTF16_HI_SURROGATE | ((((character >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); + uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); + array[used-2] = vh; + array[used-1] = vl; + } + else + { + ++used; + array[used-1] = character; + } + array[used] = 0; + + return *this; + } + + + //! Appends a UTF-8 string to this ustring16 + //! \param other The UTF-8 string to append. + //! \param length The length of the string to append. + //! \return A reference to our current string. + ustring16<TAlloc>& append(const uchar8_t* const other, u32 length=0xffffffff) + { + if (!other) + return *this; + + // Determine if the string is long enough for a BOM. + u32 len = 0; + const uchar8_t* p = other; + do + { + ++len; + } while (*p++ && len < unicode::BOM_ENCODE_UTF8_LEN); + + // Check for BOM. + unicode::EUTF_ENCODE c_bom = unicode::EUTFE_NONE; + if (len == unicode::BOM_ENCODE_UTF8_LEN) + { + if (memcmp(other, unicode::BOM_ENCODE_UTF8, unicode::BOM_ENCODE_UTF8_LEN) == 0) + c_bom = unicode::EUTFE_UTF8; + } + + // If a BOM was found, don't include it in the string. + const uchar8_t* c2 = other; + if (c_bom != unicode::EUTFE_NONE) + { + c2 = other + unicode::BOM_UTF8_LEN; + length -= unicode::BOM_UTF8_LEN; + } + + // Calculate the size of the string to read in. + len = 0; + p = c2; + do + { + ++len; + } while(*p++ && len < length); + if (len > length) + len = length; + + // If we need to grow the array, do it now. + if (used + len >= allocated) + reallocate(used + (len * 2)); + u32 start = used; + + // Convert UTF-8 to UTF-16. + u32 pos = start; + for (u32 l = 0; l<len;) + { + ++used; + if (((c2[l] >> 6) & 0x03) == 0x02) + { // Invalid continuation byte. + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + ++l; + } + else if (c2[l] == 0xC0 || c2[l] == 0xC1) + { // Invalid byte - overlong encoding. + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + ++l; + } + else if ((c2[l] & 0xF8) == 0xF0) + { // 4 bytes UTF-8, 2 bytes UTF-16. + // Check for a full string. + if ((l + 3) >= len) + { + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + l += 3; + break; + } + + // Validate. + bool valid = true; + u8 l2 = 0; + if (valid && (((c2[l+1] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (valid && (((c2[l+2] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (valid && (((c2[l+3] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (!valid) + { + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + l += l2; + continue; + } + + // Decode. + uchar8_t b1 = ((c2[l] & 0x7) << 2) | ((c2[l+1] >> 4) & 0x3); + uchar8_t b2 = ((c2[l+1] & 0xF) << 4) | ((c2[l+2] >> 2) & 0xF); + uchar8_t b3 = ((c2[l+2] & 0x3) << 6) | (c2[l+3] & 0x3F); + uchar32_t v = b3 | ((uchar32_t)b2 << 8) | ((uchar32_t)b1 << 16); + + // Split v up into a surrogate pair. + uchar16_t x = static_cast<uchar16_t>(v); + uchar16_t vh = UTF16_HI_SURROGATE | ((((v >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); + uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); + + array[pos++] = vh; + array[pos++] = vl; + l += 4; + ++used; // Using two shorts this time, so increase used by 1. + } + else if ((c2[l] & 0xF0) == 0xE0) + { // 3 bytes UTF-8, 1 byte UTF-16. + // Check for a full string. + if ((l + 2) >= len) + { + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + l += 2; + break; + } + + // Validate. + bool valid = true; + u8 l2 = 0; + if (valid && (((c2[l+1] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (valid && (((c2[l+2] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (!valid) + { + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + l += l2; + continue; + } + + // Decode. + uchar8_t b1 = ((c2[l] & 0xF) << 4) | ((c2[l+1] >> 2) & 0xF); + uchar8_t b2 = ((c2[l+1] & 0x3) << 6) | (c2[l+2] & 0x3F); + uchar16_t ch = b2 | ((uchar16_t)b1 << 8); + array[pos++] = ch; + l += 3; + } + else if ((c2[l] & 0xE0) == 0xC0) + { // 2 bytes UTF-8, 1 byte UTF-16. + // Check for a full string. + if ((l + 1) >= len) + { + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + l += 1; + break; + } + + // Validate. + if (((c2[l+1] >> 6) & 0x03) != 0x02) + { + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + ++l; + continue; + } + + // Decode. + uchar8_t b1 = (c2[l] >> 2) & 0x7; + uchar8_t b2 = ((c2[l] & 0x3) << 6) | (c2[l+1] & 0x3F); + uchar16_t ch = b2 | ((uchar16_t)b1 << 8); + array[pos++] = ch; + l += 2; + } + else + { // 1 byte UTF-8, 1 byte UTF-16. + // Validate. + if (c2[l] > 0x7F) + { // Values above 0xF4 are restricted and aren't used. By now, anything above 0x7F is invalid. + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + } + else array[pos++] = static_cast<uchar16_t>(c2[l]); + ++l; + } + } + array[used] = 0; + + // Validate our new UTF-16 string. + validate(); + + return *this; + } + + + //! Appends a UTF-16 string to this ustring16 + //! \param other The UTF-16 string to append. + //! \param length The length of the string to append. + //! \return A reference to our current string. + ustring16<TAlloc>& append(const uchar16_t* const other, u32 length=0xffffffff) + { + if (!other) + return *this; + + // Determine if the string is long enough for a BOM. + u32 len = 0; + const uchar16_t* p = other; + do + { + ++len; + } while (*p++ && len < unicode::BOM_ENCODE_UTF16_LEN); + + // Check for the BOM to determine the string's endianness. + unicode::EUTF_ENDIAN c_end = unicode::EUTFEE_NATIVE; + if (memcmp(other, unicode::BOM_ENCODE_UTF16_LE, unicode::BOM_ENCODE_UTF16_LEN) == 0) + c_end = unicode::EUTFEE_LITTLE; + else if (memcmp(other, unicode::BOM_ENCODE_UTF16_BE, unicode::BOM_ENCODE_UTF16_LEN) == 0) + c_end = unicode::EUTFEE_BIG; + + // If a BOM was found, don't include it in the string. + const uchar16_t* c2 = other; + if (c_end != unicode::EUTFEE_NATIVE) + { + c2 = other + unicode::BOM_UTF16_LEN; + length -= unicode::BOM_UTF16_LEN; + } + + // Calculate the size of the string to read in. + len = 0; + p = c2; + do + { + ++len; + } while(*p++ && len < length); + if (len > length) + len = length; + + // If we need to grow the size of the array, do it now. + if (used + len >= allocated) + reallocate(used + (len * 2)); + u32 start = used; + used += len; + + // Copy the string now. + unicode::EUTF_ENDIAN m_end = getEndianness(); + for (u32 l = start; l < start + len; ++l) + { + array[l] = (uchar16_t)c2[l]; + if (c_end != unicode::EUTFEE_NATIVE && c_end != m_end) + array[l] = unicode::swapEndian16(array[l]); + } + + array[used] = 0; + + // Validate our new UTF-16 string. + validate(); + return *this; + } + + + //! Appends a UTF-32 string to this ustring16 + //! \param other The UTF-32 string to append. + //! \param length The length of the string to append. + //! \return A reference to our current string. + ustring16<TAlloc>& append(const uchar32_t* const other, u32 length=0xffffffff) + { + if (!other) + return *this; + + // Check for the BOM to determine the string's endianness. + unicode::EUTF_ENDIAN c_end = unicode::EUTFEE_NATIVE; + if (memcmp(other, unicode::BOM_ENCODE_UTF32_LE, unicode::BOM_ENCODE_UTF32_LEN) == 0) + c_end = unicode::EUTFEE_LITTLE; + else if (memcmp(other, unicode::BOM_ENCODE_UTF32_BE, unicode::BOM_ENCODE_UTF32_LEN) == 0) + c_end = unicode::EUTFEE_BIG; + + // If a BOM was found, don't include it in the string. + const uchar32_t* c2 = other; + if (c_end != unicode::EUTFEE_NATIVE) + { + c2 = other + unicode::BOM_UTF32_LEN; + length -= unicode::BOM_UTF32_LEN; + } + + // Calculate the size of the string to read in. + u32 len = 0; + const uchar32_t* p = c2; + do + { + ++len; + } while(*p++ && len < length); + if (len > length) + len = length; + + // If we need to grow the size of the array, do it now. + // In case all of the UTF-32 string is split into surrogate pairs, do len * 2. + if (used + (len * 2) >= allocated) + reallocate(used + ((len * 2) * 2)); + u32 start = used; + + // Convert UTF-32 to UTF-16. + unicode::EUTF_ENDIAN m_end = getEndianness(); + u32 pos = start; + for (u32 l = 0; l<len; ++l) + { + ++used; + + uchar32_t ch = c2[l]; + if (c_end != unicode::EUTFEE_NATIVE && c_end != m_end) + ch = unicode::swapEndian32(ch); + + if (ch > 0xFFFF) + { + // Split ch up into a surrogate pair as it is over 16 bits long. + uchar16_t x = static_cast<uchar16_t>(ch); + uchar16_t vh = UTF16_HI_SURROGATE | ((((ch >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); + uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); + array[pos++] = vh; + array[pos++] = vl; + ++used; // Using two shorts, so increased used again. + } + else if (ch >= 0xD800 && ch <= 0xDFFF) + { + // Between possible UTF-16 surrogates (invalid!) + array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; + } + else array[pos++] = static_cast<uchar16_t>(ch); + } + array[used] = 0; + + // Validate our new UTF-16 string. + validate(); + + return *this; + } + + + //! Appends a ustring16 to this ustring16 + //! \param other The string to append to this one. + //! \return A reference to our current string. + ustring16<TAlloc>& append(const ustring16<TAlloc>& other) + { + const uchar16_t* oa = other.c_str(); + + u32 len = other.size_raw(); + + if (used + len >= allocated) + reallocate(used + len); + + for (u32 l=0; l<len; ++l) + array[used+l] = oa[l]; + + used += len; + array[used] = 0; + + return *this; + } + + + //! Appends a certain amount of characters of a ustring16 to this ustring16. + //! \param other The string to append to this one. + //! \param length How many characters of the other string to add to this one. + //! \return A reference to our current string. + ustring16<TAlloc>& append(const ustring16<TAlloc>& other, u32 length) + { + if (other.size() == 0) + return *this; + + if (other.size() < length) + { + append(other); + return *this; + } + + if (used + length * 2 >= allocated) + reallocate(used + length * 2); + + const_iterator iter(other, 0); + u32 l = length; + while (!iter.atEnd() && l) + { + uchar32_t c = *iter; + append(c); + ++iter; + --l; + } + + return *this; + } + + + //! Reserves some memory. + //! \param count The amount of characters to reserve. + void reserve(u32 count) + { + if (count < allocated) + return; + + reallocate(count); + } + + + //! Finds first occurrence of character. + //! \param c The character to search for. + //! \return Position where the character has been found, or -1 if not found. + s32 findFirst(uchar32_t c) const + { + const_iterator i(*this, 0); + + s32 pos = 0; + while (!i.atEnd()) + { + uchar32_t t = *i; + if (c == t) + return pos; + ++pos; + ++i; + } + + return -1; + } + + //! Finds first occurrence of a character of a list. + //! \param c A list of characters to find. For example if the method should find the first occurrence of 'a' or 'b', this parameter should be "ab". + //! \param count The amount of characters in the list. Usually, this should be strlen(c). + //! \return Position where one of the characters has been found, or -1 if not found. + s32 findFirstChar(const uchar32_t* const c, u32 count=1) const + { + if (!c || !count) + return -1; + + const_iterator i(*this, 0); + + s32 pos = 0; + while (!i.atEnd()) + { + uchar32_t t = *i; + for (u32 j=0; j<count; ++j) + if (t == c[j]) + return pos; + ++pos; + ++i; + } + + return -1; + } + + + //! Finds first position of a character not in a given list. + //! \param c A list of characters to NOT find. For example if the method should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab". + //! \param count The amount of characters in the list. Usually, this should be strlen(c). + //! \return Position where the character has been found, or -1 if not found. + s32 findFirstCharNotInList(const uchar32_t* const c, u32 count=1) const + { + if (!c || !count) + return -1; + + const_iterator i(*this, 0); + + s32 pos = 0; + while (!i.atEnd()) + { + uchar32_t t = *i; + u32 j; + for (j=0; j<count; ++j) + if (t == c[j]) + break; + + if (j==count) + return pos; + ++pos; + ++i; + } + + return -1; + } + + //! Finds last position of a character not in a given list. + //! \param c A list of characters to NOT find. For example if the method should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab". + //! \param count The amount of characters in the list. Usually, this should be strlen(c). + //! \return Position where the character has been found, or -1 if not found. + s32 findLastCharNotInList(const uchar32_t* const c, u32 count=1) const + { + if (!c || !count) + return -1; + + const_iterator i(end()); + --i; + + s32 pos = size() - 1; + while (!i.atStart()) + { + uchar32_t t = *i; + u32 j; + for (j=0; j<count; ++j) + if (t == c[j]) + break; + + if (j==count) + return pos; + --pos; + --i; + } + + return -1; + } + + //! Finds next occurrence of character. + //! \param c The character to search for. + //! \param startPos The position in the string to start searching. + //! \return Position where the character has been found, or -1 if not found. + s32 findNext(uchar32_t c, u32 startPos) const + { + const_iterator i(*this, startPos); + + s32 pos = startPos; + while (!i.atEnd()) + { + uchar32_t t = *i; + if (t == c) + return pos; + ++pos; + ++i; + } + + return -1; + } + + + //! Finds last occurrence of character. + //! \param c The character to search for. + //! \param start The start position of the reverse search ( default = -1, on end ). + //! \return Position where the character has been found, or -1 if not found. + s32 findLast(uchar32_t c, s32 start = -1) const + { + u32 s = size(); + start = core::clamp ( start < 0 ? (s32)s : start, 0, (s32)s ) - 1; + + const_iterator i(*this, start); + u32 pos = start; + while (!i.atStart()) + { + uchar32_t t = *i; + if (t == c) + return pos; + --pos; + --i; + } + + return -1; + } + + //! Finds last occurrence of a character in a list. + //! \param c A list of strings to find. For example if the method should find the last occurrence of 'a' or 'b', this parameter should be "ab". + //! \param count The amount of characters in the list. Usually, this should be strlen(c). + //! \return Position where one of the characters has been found, or -1 if not found. + s32 findLastChar(const uchar32_t* const c, u32 count=1) const + { + if (!c || !count) + return -1; + + const_iterator i(end()); + --i; + + s32 pos = size(); + while (!i.atStart()) + { + uchar32_t t = *i; + for (u32 j=0; j<count; ++j) + if (t == c[j]) + return pos; + --pos; + --i; + } + + return -1; + } + + + //! Finds another ustring16 in this ustring16. + //! \param str The string to find. + //! \param start The start position of the search. + //! \return Positions where the ustring16 has been found, or -1 if not found. + s32 find(const ustring16<TAlloc>& str, const u32 start = 0) const + { + u32 my_size = size(); + u32 their_size = str.size(); + + if (their_size == 0 || my_size - start < their_size) + return -1; + + const_iterator i(*this, start); + + s32 pos = start; + while (!i.atEnd()) + { + const_iterator i2(i); + const_iterator j(str, 0); + uchar32_t t1 = (uchar32_t)*i2; + uchar32_t t2 = (uchar32_t)*j; + while (t1 == t2) + { + ++i2; + ++j; + if (j.atEnd()) + return pos; + t1 = (uchar32_t)*i2; + t2 = (uchar32_t)*j; + } + ++i; + ++pos; + } + + return -1; + } + + + //! Finds another ustring16 in this ustring16. + //! \param str The string to find. + //! \param start The start position of the search. + //! \return Positions where the string has been found, or -1 if not found. + s32 find_raw(const ustring16<TAlloc>& str, const u32 start = 0) const + { + const uchar16_t* data = str.c_str(); + if (data && *data) + { + u32 len = 0; + + while (data[len]) + ++len; + + if (len > used) + return -1; + + for (u32 i=start; i<=used-len; ++i) + { + u32 j=0; + + while(data[j] && array[i+j] == data[j]) + ++j; + + if (!data[j]) + return i; + } + } + + return -1; + } + + + //! Returns a substring. + //! \param begin: Start of substring. + //! \param length: Length of substring. + //! \return A reference to our current string. + ustring16<TAlloc> subString(u32 begin, s32 length) const + { + u32 len = size(); + // if start after ustring16 + // or no proper substring length + if ((length <= 0) || (begin>=len)) + return ustring16<TAlloc>(""); + // clamp length to maximal value + if ((length+begin) > len) + length = len-begin; + + ustring16<TAlloc> o; + o.reserve((length+1) * 2); + + const_iterator i(*this, begin); + while (!i.atEnd() && length) + { + o.append(*i); + ++i; + --length; + } + + return o; + } + + + //! Appends a character to this ustring16. + //! \param c Character to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (char c) + { + append((uchar32_t)c); + return *this; + } + + + //! Appends a character to this ustring16. + //! \param c Character to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (uchar32_t c) + { + append(c); + return *this; + } + + + //! Appends a number to this ustring16. + //! \param c Number to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (short c) + { + append(core::stringc(c)); + return *this; + } + + + //! Appends a number to this ustring16. + //! \param c Number to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (unsigned short c) + { + append(core::stringc(c)); + return *this; + } + + +#ifdef USTRING_CPP0X_NEWLITERALS + //! Appends a number to this ustring16. + //! \param c Number to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (int c) + { + append(core::stringc(c)); + return *this; + } + + + //! Appends a number to this ustring16. + //! \param c Number to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (unsigned int c) + { + append(core::stringc(c)); + return *this; + } +#endif + + + //! Appends a number to this ustring16. + //! \param c Number to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (long c) + { + append(core::stringc(c)); + return *this; + } + + + //! Appends a number to this ustring16. + //! \param c Number to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (unsigned long c) + { + append(core::stringc(c)); + return *this; + } + + + //! Appends a number to this ustring16. + //! \param c Number to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (double c) + { + append(core::stringc(c)); + return *this; + } + + + //! Appends a char ustring16 to this ustring16. + //! \param c Char ustring16 to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (const uchar16_t* const c) + { + append(c); + return *this; + } + + + //! Appends a ustring16 to this ustring16. + //! \param other ustring16 to append. + //! \return A reference to our current string. + ustring16<TAlloc>& operator += (const ustring16<TAlloc>& other) + { + append(other); + return *this; + } + + + //! Replaces all characters of a given type with another one. + //! \param toReplace Character to replace. + //! \param replaceWith Character replacing the old one. + //! \return A reference to our current string. + ustring16<TAlloc>& replace(uchar32_t toReplace, uchar32_t replaceWith) + { + iterator i(*this, 0); + while (!i.atEnd()) + { + typename ustring16<TAlloc>::access a = *i; + if ((uchar32_t)a == toReplace) + a = replaceWith; + ++i; + } + return *this; + } + + + //! Replaces all instances of a string with another one. + //! \param toReplace The string to replace. + //! \param replaceWith The string replacing the old one. + //! \return A reference to our current string. + ustring16<TAlloc>& replace(const ustring16<TAlloc>& toReplace, const ustring16<TAlloc>& replaceWith) + { + if (toReplace.size() == 0) + return *this; + + const uchar16_t* other = toReplace.c_str(); + const uchar16_t* replace = replaceWith.c_str(); + const u32 other_size = toReplace.size_raw(); + const u32 replace_size = replaceWith.size_raw(); + + // Determine the delta. The algorithm will change depending on the delta. + s32 delta = replace_size - other_size; + + // A character for character replace. The string will not shrink or grow. + if (delta == 0) + { + s32 pos = 0; + while ((pos = find_raw(other, pos)) != -1) + { + for (u32 i = 0; i < replace_size; ++i) + array[pos + i] = replace[i]; + ++pos; + } + return *this; + } + + // We are going to be removing some characters. The string will shrink. + if (delta < 0) + { + u32 i = 0; + for (u32 pos = 0; pos <= used; ++i, ++pos) + { + // Is this potentially a match? + if (array[pos] == *other) + { + // Check to see if we have a match. + u32 j; + for (j = 0; j < other_size; ++j) + { + if (array[pos + j] != other[j]) + break; + } + + // If we have a match, replace characters. + if (j == other_size) + { + for (j = 0; j < replace_size; ++j) + array[i + j] = replace[j]; + i += replace_size - 1; + pos += other_size - 1; + continue; + } + } + + // No match found, just copy characters. + array[i - 1] = array[pos]; + } + array[i] = 0; + used = i; + + return *this; + } + + // We are going to be adding characters, so the string size will increase. + // Count the number of times toReplace exists in the string so we can allocate the new size. + u32 find_count = 0; + s32 pos = 0; + while ((pos = find_raw(other, pos)) != -1) + { + ++find_count; + ++pos; + } + + // Re-allocate the string now, if needed. + u32 len = delta * find_count; + if (used + len >= allocated) + reallocate(used + len); + + // Start replacing. + pos = 0; + while ((pos = find_raw(other, pos)) != -1) + { + uchar16_t* start = array + pos + other_size - 1; + uchar16_t* ptr = array + used; + uchar16_t* end = array + used + delta; + + // Shift characters to make room for the string. + while (ptr != start) + { + *end = *ptr; + --ptr; + --end; + } + + // Add the new string now. + for (u32 i = 0; i < replace_size; ++i) + array[pos + i] = replace[i]; + + pos += replace_size; + used += delta; + } + + // Terminate the string and return ourself. + array[used] = 0; + return *this; + } + + + //! Removes characters from a ustring16.. + //! \param c The character to remove. + //! \return A reference to our current string. + ustring16<TAlloc>& remove(uchar32_t c) + { + u32 pos = 0; + u32 found = 0; + u32 len = (c > 0xFFFF ? 2 : 1); // Remove characters equal to the size of c as a UTF-16 character. + for (u32 i=0; i<=used; ++i) + { + uchar32_t uc32 = 0; + if (!UTF16_IS_SURROGATE_HI(array[i])) + uc32 |= array[i]; + else if (i + 1 <= used) + { + // Convert the surrogate pair into a single UTF-32 character. + uc32 = unicode::toUTF32(array[i], array[i + 1]); + } + u32 len2 = (uc32 > 0xFFFF ? 2 : 1); + + if (uc32 == c) + { + found += len; + continue; + } + + array[pos++] = array[i]; + if (len2 == 2) + array[pos++] = array[++i]; + } + used -= found; + array[used] = 0; + return *this; + } + + + //! Removes a ustring16 from the ustring16. + //! \param toRemove The string to remove. + //! \return A reference to our current string. + ustring16<TAlloc>& remove(const ustring16<TAlloc>& toRemove) + { + u32 size = toRemove.size_raw(); + if (size == 0) return *this; + + const uchar16_t* tra = toRemove.c_str(); + u32 pos = 0; + u32 found = 0; + for (u32 i=0; i<=used; ++i) + { + u32 j = 0; + while (j < size) + { + if (array[i + j] != tra[j]) + break; + ++j; + } + if (j == size) + { + found += size; + i += size - 1; + continue; + } + + array[pos++] = array[i]; + } + used -= found; + array[used] = 0; + return *this; + } + + + //! Removes characters from the ustring16. + //! \param characters The characters to remove. + //! \return A reference to our current string. + ustring16<TAlloc>& removeChars(const ustring16<TAlloc>& characters) + { + if (characters.size_raw() == 0) + return *this; + + u32 pos = 0; + u32 found = 0; + const_iterator iter(characters); + for (u32 i=0; i<=used; ++i) + { + uchar32_t uc32 = 0; + if (!UTF16_IS_SURROGATE_HI(array[i])) + uc32 |= array[i]; + else if (i + 1 <= used) + { + // Convert the surrogate pair into a single UTF-32 character. + uc32 = unicode::toUTF32(array[i], array[i+1]); + } + u32 len2 = (uc32 > 0xFFFF ? 2 : 1); + + bool cont = false; + iter.toStart(); + while (!iter.atEnd()) + { + uchar32_t c = *iter; + if (uc32 == c) + { + found += (c > 0xFFFF ? 2 : 1); // Remove characters equal to the size of c as a UTF-16 character. + ++i; + cont = true; + break; + } + ++iter; + } + if (cont) continue; + + array[pos++] = array[i]; + if (len2 == 2) + array[pos++] = array[++i]; + } + used -= found; + array[used] = 0; + return *this; + } + + + //! Trims the ustring16. + //! Removes the specified characters (by default, Latin-1 whitespace) from the begining and the end of the ustring16. + //! \param whitespace The characters that are to be considered as whitespace. + //! \return A reference to our current string. + ustring16<TAlloc>& trim(const ustring16<TAlloc>& whitespace = " \t\n\r") + { + core::array<uchar32_t> utf32white = whitespace.toUTF32(); + + // find start and end of the substring without the specified characters + const s32 begin = findFirstCharNotInList(utf32white.const_pointer(), whitespace.used + 1); + if (begin == -1) + return (*this=""); + + const s32 end = findLastCharNotInList(utf32white.const_pointer(), whitespace.used + 1); + + return (*this = subString(begin, (end +1) - begin)); + } + + + //! Erases a character from the ustring16. + //! May be slow, because all elements following after the erased element have to be copied. + //! \param index Index of element to be erased. + //! \return A reference to our current string. + ustring16<TAlloc>& erase(u32 index) + { + _IRR_DEBUG_BREAK_IF(index>used) // access violation + + iterator i(*this, index); + + uchar32_t t = *i; + u32 len = (t > 0xFFFF ? 2 : 1); + + for (u32 j = static_cast<u32>(i.getPos()) + len; j <= used; ++j) + array[j - len] = array[j]; + + used -= len; + array[used] = 0; + + return *this; + } + + + //! Validate the existing ustring16, checking for valid surrogate pairs and checking for proper termination. + //! \return A reference to our current string. + ustring16<TAlloc>& validate() + { + // Validate all unicode characters. + for (u32 i=0; i<allocated; ++i) + { + // Terminate on existing null. + if (array[i] == 0) + { + used = i; + return *this; + } + if (UTF16_IS_SURROGATE(array[i])) + { + if (((i+1) >= allocated) || UTF16_IS_SURROGATE_LO(array[i])) + array[i] = unicode::UTF_REPLACEMENT_CHARACTER; + else if (UTF16_IS_SURROGATE_HI(array[i]) && !UTF16_IS_SURROGATE_LO(array[i+1])) + array[i] = unicode::UTF_REPLACEMENT_CHARACTER; + ++i; + } + if (array[i] >= 0xFDD0 && array[i] <= 0xFDEF) + array[i] = unicode::UTF_REPLACEMENT_CHARACTER; + } + + // terminate + used = 0; + if (allocated > 0) + { + used = allocated - 1; + array[used] = 0; + } + return *this; + } + + + //! Gets the last char of the ustring16, or 0. + //! \return The last char of the ustring16, or 0. + uchar32_t lastChar() const + { + if (used < 1) + return 0; + + if (UTF16_IS_SURROGATE_LO(array[used-1])) + { + // Make sure we have a paired surrogate. + if (used < 2) + return 0; + + // Check for an invalid surrogate. + if (!UTF16_IS_SURROGATE_HI(array[used-2])) + return 0; + + // Convert the surrogate pair into a single UTF-32 character. + return unicode::toUTF32(array[used-2], array[used-1]); + } + else + { + return array[used-1]; + } + } + + + //! Split the ustring16 into parts. + /** This method will split a ustring16 at certain delimiter characters + into the container passed in as reference. The type of the container + has to be given as template parameter. It must provide a push_back and + a size method. + \param ret The result container + \param c C-style ustring16 of delimiter characters + \param count Number of delimiter characters + \param ignoreEmptyTokens Flag to avoid empty substrings in the result + container. If two delimiters occur without a character in between, an + empty substring would be placed in the result. If this flag is set, + only non-empty strings are stored. + \param keepSeparators Flag which allows to add the separator to the + result ustring16. If this flag is true, the concatenation of the + substrings results in the original ustring16. Otherwise, only the + characters between the delimiters are returned. + \return The number of resulting substrings + */ + template<class container> + u32 split(container& ret, const uchar32_t* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const + { + if (!c) + return 0; + + const_iterator i(*this); + const u32 oldSize=ret.size(); + u32 pos = 0; + u32 lastpos = 0; + u32 lastpospos = 0; + bool lastWasSeparator = false; + while (!i.atEnd()) + { + uchar32_t ch = *i; + bool foundSeparator = false; + for (u32 j=0; j<count; ++j) + { + if (ch == c[j]) + { + if ((!ignoreEmptyTokens || pos - lastpos != 0) && + !lastWasSeparator) + ret.push_back(ustring16<TAlloc>(&array[lastpospos], pos - lastpos)); + foundSeparator = true; + lastpos = (keepSeparators ? pos : pos + 1); + lastpospos = (keepSeparators ? i.getPos() : i.getPos() + 1); + break; + } + } + lastWasSeparator = foundSeparator; + ++pos; + ++i; + } + u32 s = size() + 1; + if (s > lastpos) + ret.push_back(ustring16<TAlloc>(&array[lastpospos], s - lastpos)); + return ret.size()-oldSize; + } + + + //! Split the ustring16 into parts. + /** This method will split a ustring16 at certain delimiter characters + into the container passed in as reference. The type of the container + has to be given as template parameter. It must provide a push_back and + a size method. + \param ret The result container + \param c A unicode string of delimiter characters + \param ignoreEmptyTokens Flag to avoid empty substrings in the result + container. If two delimiters occur without a character in between, an + empty substring would be placed in the result. If this flag is set, + only non-empty strings are stored. + \param keepSeparators Flag which allows to add the separator to the + result ustring16. If this flag is true, the concatenation of the + substrings results in the original ustring16. Otherwise, only the + characters between the delimiters are returned. + \return The number of resulting substrings + */ + template<class container> + u32 split(container& ret, const ustring16<TAlloc>& c, bool ignoreEmptyTokens=true, bool keepSeparators=false) const + { + core::array<uchar32_t> v = c.toUTF32(); + return split(ret, v.pointer(), v.size(), ignoreEmptyTokens, keepSeparators); + } + + + //! Gets the size of the allocated memory buffer for the string. + //! \return The size of the allocated memory buffer. + u32 capacity() const + { + return allocated; + } + + + //! Returns the raw number of UTF-16 code points in the string which includes the individual surrogates. + //! \return The raw number of UTF-16 code points, excluding the trialing NUL. + u32 size_raw() const + { + return used; + } + + + //! Inserts a character into the string. + //! \param c The character to insert. + //! \param pos The position to insert the character. + //! \return A reference to our current string. + ustring16<TAlloc>& insert(uchar32_t c, u32 pos) + { + u8 len = (c > 0xFFFF ? 2 : 1); + + if (used + len >= allocated) + reallocate(used + len); + + used += len; + + iterator iter(*this, pos); + for (u32 i = used - 2; i > iter.getPos(); --i) + array[i] = array[i - len]; + + if (c > 0xFFFF) + { + // c will be multibyte, so split it up into a surrogate pair. + uchar16_t x = static_cast<uchar16_t>(c); + uchar16_t vh = UTF16_HI_SURROGATE | ((((c >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); + uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); + array[iter.getPos()] = vh; + array[iter.getPos()+1] = vl; + } + else + { + array[iter.getPos()] = static_cast<uchar16_t>(c); + } + array[used] = 0; + return *this; + } + + + //! Inserts a string into the string. + //! \param c The string to insert. + //! \param pos The position to insert the string. + //! \return A reference to our current string. + ustring16<TAlloc>& insert(const ustring16<TAlloc>& c, u32 pos) + { + u32 len = c.size_raw(); + if (len == 0) return *this; + + if (used + len >= allocated) + reallocate(used + len); + + used += len; + + iterator iter(*this, pos); + for (u32 i = used - 2; i > iter.getPos() + len; --i) + array[i] = array[i - len]; + + const uchar16_t* s = c.c_str(); + for (u32 i = 0; i < len; ++i) + { + array[pos++] = *s; + ++s; + } + + array[used] = 0; + return *this; + } + + + //! Inserts a character into the string. + //! \param c The character to insert. + //! \param pos The position to insert the character. + //! \return A reference to our current string. + ustring16<TAlloc>& insert_raw(uchar16_t c, u32 pos) + { + if (used + 1 >= allocated) + reallocate(used + 1); + + ++used; + + for (u32 i = used - 1; i > pos; --i) + array[i] = array[i - 1]; + + array[pos] = c; + array[used] = 0; + return *this; + } + + + //! Removes a character from string. + //! \param pos Position of the character to remove. + //! \return A reference to our current string. + ustring16<TAlloc>& erase_raw(u32 pos) + { + for (u32 i=pos; i<=used; ++i) + { + array[i] = array[i + 1]; + } + --used; + array[used] = 0; + return *this; + } + + + //! Replaces a character in the string. + //! \param c The new character. + //! \param pos The position of the character to replace. + //! \return A reference to our current string. + ustring16<TAlloc>& replace_raw(uchar16_t c, u32 pos) + { + array[pos] = c; + return *this; + } + + + //! Returns an iterator to the beginning of the string. + //! \return An iterator to the beginning of the string. + iterator begin() + { + iterator i(*this, 0); + return i; + } + + + //! Returns an iterator to the beginning of the string. + //! \return An iterator to the beginning of the string. + const_iterator begin() const + { + const_iterator i(*this, 0); + return i; + } + + + //! Returns an iterator to the beginning of the string. + //! \return An iterator to the beginning of the string. + const_iterator cbegin() const + { + const_iterator i(*this, 0); + return i; + } + + + //! Returns an iterator to the end of the string. + //! \return An iterator to the end of the string. + iterator end() + { + iterator i(*this, 0); + i.toEnd(); + return i; + } + + + //! Returns an iterator to the end of the string. + //! \return An iterator to the end of the string. + const_iterator end() const + { + const_iterator i(*this, 0); + i.toEnd(); + return i; + } + + + //! Returns an iterator to the end of the string. + //! \return An iterator to the end of the string. + const_iterator cend() const + { + const_iterator i(*this, 0); + i.toEnd(); + return i; + } + + + //! Converts the string to a UTF-8 encoded string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return A string containing the UTF-8 encoded string. + core::string<uchar8_t> toUTF8_s(const bool addBOM = false) const + { + core::string<uchar8_t> ret; + ret.reserve(used * 4 + (addBOM ? unicode::BOM_UTF8_LEN : 0) + 1); + const_iterator iter(*this, 0); + + // Add the byte order mark if the user wants it. + if (addBOM) + { + ret.append(unicode::BOM_ENCODE_UTF8[0]); + ret.append(unicode::BOM_ENCODE_UTF8[1]); + ret.append(unicode::BOM_ENCODE_UTF8[2]); + } + + while (!iter.atEnd()) + { + uchar32_t c = *iter; + if (c > 0xFFFF) + { // 4 bytes + uchar8_t b1 = (0x1E << 3) | ((c >> 18) & 0x7); + uchar8_t b2 = (0x2 << 6) | ((c >> 12) & 0x3F); + uchar8_t b3 = (0x2 << 6) | ((c >> 6) & 0x3F); + uchar8_t b4 = (0x2 << 6) | (c & 0x3F); + ret.append(b1); + ret.append(b2); + ret.append(b3); + ret.append(b4); + } + else if (c > 0x7FF) + { // 3 bytes + uchar8_t b1 = (0xE << 4) | ((c >> 12) & 0xF); + uchar8_t b2 = (0x2 << 6) | ((c >> 6) & 0x3F); + uchar8_t b3 = (0x2 << 6) | (c & 0x3F); + ret.append(b1); + ret.append(b2); + ret.append(b3); + } + else if (c > 0x7F) + { // 2 bytes + uchar8_t b1 = (0x6 << 5) | ((c >> 6) & 0x1F); + uchar8_t b2 = (0x2 << 6) | (c & 0x3F); + ret.append(b1); + ret.append(b2); + } + else + { // 1 byte + ret.append(static_cast<uchar8_t>(c)); + } + ++iter; + } + return ret; + } + + + //! Converts the string to a UTF-8 encoded string array. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An array containing the UTF-8 encoded string. + core::array<uchar8_t> toUTF8(const bool addBOM = false) const + { + core::array<uchar8_t> ret(used * 4 + (addBOM ? unicode::BOM_UTF8_LEN : 0) + 1); + const_iterator iter(*this, 0); + + // Add the byte order mark if the user wants it. + if (addBOM) + { + ret.push_back(unicode::BOM_ENCODE_UTF8[0]); + ret.push_back(unicode::BOM_ENCODE_UTF8[1]); + ret.push_back(unicode::BOM_ENCODE_UTF8[2]); + } + + while (!iter.atEnd()) + { + uchar32_t c = *iter; + if (c > 0xFFFF) + { // 4 bytes + uchar8_t b1 = (0x1E << 3) | ((c >> 18) & 0x7); + uchar8_t b2 = (0x2 << 6) | ((c >> 12) & 0x3F); + uchar8_t b3 = (0x2 << 6) | ((c >> 6) & 0x3F); + uchar8_t b4 = (0x2 << 6) | (c & 0x3F); + ret.push_back(b1); + ret.push_back(b2); + ret.push_back(b3); + ret.push_back(b4); + } + else if (c > 0x7FF) + { // 3 bytes + uchar8_t b1 = (0xE << 4) | ((c >> 12) & 0xF); + uchar8_t b2 = (0x2 << 6) | ((c >> 6) & 0x3F); + uchar8_t b3 = (0x2 << 6) | (c & 0x3F); + ret.push_back(b1); + ret.push_back(b2); + ret.push_back(b3); + } + else if (c > 0x7F) + { // 2 bytes + uchar8_t b1 = (0x6 << 5) | ((c >> 6) & 0x1F); + uchar8_t b2 = (0x2 << 6) | (c & 0x3F); + ret.push_back(b1); + ret.push_back(b2); + } + else + { // 1 byte + ret.push_back(static_cast<uchar8_t>(c)); + } + ++iter; + } + ret.push_back(0); + return ret; + } + + +#ifdef USTRING_CPP0X_NEWLITERALS // C++0x + //! Converts the string to a UTF-16 encoded string. + //! \param endian The desired endianness of the string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return A string containing the UTF-16 encoded string. + core::string<char16_t> toUTF16_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const + { + core::string<char16_t> ret; + ret.reserve(used + (addBOM ? unicode::BOM_UTF16_LEN : 0) + 1); + + // Add the BOM if specified. + if (addBOM) + { + if (endian == unicode::EUTFEE_NATIVE) + ret[0] = unicode::BOM; + else if (endian == unicode::EUTFEE_LITTLE) + { + uchar8_t* ptr8 = reinterpret_cast<uchar8_t*>(ret.c_str()); + *ptr8++ = unicode::BOM_ENCODE_UTF16_LE[0]; + *ptr8 = unicode::BOM_ENCODE_UTF16_LE[1]; + } + else + { + uchar8_t* ptr8 = reinterpret_cast<uchar8_t*>(ret.c_str()); + *ptr8++ = unicode::BOM_ENCODE_UTF16_BE[0]; + *ptr8 = unicode::BOM_ENCODE_UTF16_BE[1]; + } + } + + ret.append(array); + if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) + { + char16_t* ptr = ret.c_str(); + for (u32 i = 0; i < ret.size(); ++i) + *ptr++ = unicode::swapEndian16(*ptr); + } + return ret; + } +#endif + + + //! Converts the string to a UTF-16 encoded string array. + //! Unfortunately, no toUTF16_s() version exists due to limitations with Irrlicht's string class. + //! \param endian The desired endianness of the string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An array containing the UTF-16 encoded string. + core::array<uchar16_t> toUTF16(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const + { + core::array<uchar16_t> ret(used + (addBOM ? unicode::BOM_UTF16_LEN : 0) + 1); + uchar16_t* ptr = ret.pointer(); + + // Add the BOM if specified. + if (addBOM) + { + if (endian == unicode::EUTFEE_NATIVE) + *ptr = unicode::BOM; + else if (endian == unicode::EUTFEE_LITTLE) + { + uchar8_t* ptr8 = reinterpret_cast<uchar8_t*>(ptr); + *ptr8++ = unicode::BOM_ENCODE_UTF16_LE[0]; + *ptr8 = unicode::BOM_ENCODE_UTF16_LE[1]; + } + else + { + uchar8_t* ptr8 = reinterpret_cast<uchar8_t*>(ptr); + *ptr8++ = unicode::BOM_ENCODE_UTF16_BE[0]; + *ptr8 = unicode::BOM_ENCODE_UTF16_BE[1]; + } + ++ptr; + } + + memcpy((void*)ptr, (void*)array, used * sizeof(uchar16_t)); + if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) + { + for (u32 i = 0; i <= used; ++i) + *ptr++ = unicode::swapEndian16(*ptr); + } + ret.set_used(used + (addBOM ? unicode::BOM_UTF16_LEN : 0)); + ret.push_back(0); + return ret; + } + + +#ifdef USTRING_CPP0X_NEWLITERALS // C++0x + //! Converts the string to a UTF-32 encoded string. + //! \param endian The desired endianness of the string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return A string containing the UTF-32 encoded string. + core::string<char32_t> toUTF32_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const + { + core::string<char32_t> ret; + ret.reserve(size() + 1 + (addBOM ? unicode::BOM_UTF32_LEN : 0)); + const_iterator iter(*this, 0); + + // Add the BOM if specified. + if (addBOM) + { + if (endian == unicode::EUTFEE_NATIVE) + ret.append(unicode::BOM); + else + { + union + { + uchar32_t full; + u8 chunk[4]; + } t; + + if (endian == unicode::EUTFEE_LITTLE) + { + t.chunk[0] = unicode::BOM_ENCODE_UTF32_LE[0]; + t.chunk[1] = unicode::BOM_ENCODE_UTF32_LE[1]; + t.chunk[2] = unicode::BOM_ENCODE_UTF32_LE[2]; + t.chunk[3] = unicode::BOM_ENCODE_UTF32_LE[3]; + } + else + { + t.chunk[0] = unicode::BOM_ENCODE_UTF32_BE[0]; + t.chunk[1] = unicode::BOM_ENCODE_UTF32_BE[1]; + t.chunk[2] = unicode::BOM_ENCODE_UTF32_BE[2]; + t.chunk[3] = unicode::BOM_ENCODE_UTF32_BE[3]; + } + ret.append(t.full); + } + } + + while (!iter.atEnd()) + { + uchar32_t c = *iter; + if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) + c = unicode::swapEndian32(c); + ret.append(c); + ++iter; + } + return ret; + } +#endif + + + //! Converts the string to a UTF-32 encoded string array. + //! Unfortunately, no toUTF32_s() version exists due to limitations with Irrlicht's string class. + //! \param endian The desired endianness of the string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An array containing the UTF-32 encoded string. + core::array<uchar32_t> toUTF32(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const + { + core::array<uchar32_t> ret(size() + (addBOM ? unicode::BOM_UTF32_LEN : 0) + 1); + const_iterator iter(*this, 0); + + // Add the BOM if specified. + if (addBOM) + { + if (endian == unicode::EUTFEE_NATIVE) + ret.push_back(unicode::BOM); + else + { + union + { + uchar32_t full; + u8 chunk[4]; + } t; + + if (endian == unicode::EUTFEE_LITTLE) + { + t.chunk[0] = unicode::BOM_ENCODE_UTF32_LE[0]; + t.chunk[1] = unicode::BOM_ENCODE_UTF32_LE[1]; + t.chunk[2] = unicode::BOM_ENCODE_UTF32_LE[2]; + t.chunk[3] = unicode::BOM_ENCODE_UTF32_LE[3]; + } + else + { + t.chunk[0] = unicode::BOM_ENCODE_UTF32_BE[0]; + t.chunk[1] = unicode::BOM_ENCODE_UTF32_BE[1]; + t.chunk[2] = unicode::BOM_ENCODE_UTF32_BE[2]; + t.chunk[3] = unicode::BOM_ENCODE_UTF32_BE[3]; + } + ret.push_back(t.full); + } + } + ret.push_back(0); + + while (!iter.atEnd()) + { + uchar32_t c = *iter; + if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) + c = unicode::swapEndian32(c); + ret.push_back(c); + ++iter; + } + return ret; + } + + + //! Converts the string to a wchar_t encoded string. + /** The size of a wchar_t changes depending on the platform. This function will store a + correct UTF-8, -16, or -32 encoded string depending on the size of a wchar_t. **/ + //! \param endian The desired endianness of the string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return A string containing the wchar_t encoded string. + core::string<wchar_t> toWCHAR_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const + { + if (sizeof(wchar_t) == 4) + { + core::array<uchar32_t> a(toUTF32(endian, addBOM)); + core::stringw ret(a.pointer()); + return ret; + } + else if (sizeof(wchar_t) == 2) + { + if (endian == unicode::EUTFEE_NATIVE && addBOM == false) + { + core::stringw ret(array); + return ret; + } + else + { + core::array<uchar16_t> a(toUTF16(endian, addBOM)); + core::stringw ret(a.pointer()); + return ret; + } + } + else if (sizeof(wchar_t) == 1) + { + core::array<uchar8_t> a(toUTF8(addBOM)); + core::stringw ret(a.pointer()); + return ret; + } + + // Shouldn't happen. + return core::stringw(); + } + + + //! Converts the string to a wchar_t encoded string array. + /** The size of a wchar_t changes depending on the platform. This function will store a + correct UTF-8, -16, or -32 encoded string depending on the size of a wchar_t. **/ + //! \param endian The desired endianness of the string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An array containing the wchar_t encoded string. + core::array<wchar_t> toWCHAR(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const + { + if (sizeof(wchar_t) == 4) + { + core::array<uchar32_t> a(toUTF32(endian, addBOM)); + core::array<wchar_t> ret(a.size()); + ret.set_used(a.size()); + memcpy((void*)ret.pointer(), (void*)a.pointer(), a.size() * sizeof(uchar32_t)); + return ret; + } + if (sizeof(wchar_t) == 2) + { + if (endian == unicode::EUTFEE_NATIVE && addBOM == false) + { + core::array<wchar_t> ret(used); + ret.set_used(used); + memcpy((void*)ret.pointer(), (void*)array, used * sizeof(uchar16_t)); + return ret; + } + else + { + core::array<uchar16_t> a(toUTF16(endian, addBOM)); + core::array<wchar_t> ret(a.size()); + ret.set_used(a.size()); + memcpy((void*)ret.pointer(), (void*)a.pointer(), a.size() * sizeof(uchar16_t)); + return ret; + } + } + if (sizeof(wchar_t) == 1) + { + core::array<uchar8_t> a(toUTF8(addBOM)); + core::array<wchar_t> ret(a.size()); + ret.set_used(a.size()); + memcpy((void*)ret.pointer(), (void*)a.pointer(), a.size() * sizeof(uchar8_t)); + return ret; + } + + // Shouldn't happen. + return core::array<wchar_t>(); + } + + //! Converts the string to a properly encoded io::path string. + //! \param endian The desired endianness of the string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An io::path string containing the properly encoded string. + io::path toPATH_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const + { +#if defined(_IRR_WCHAR_FILESYSTEM) + return toWCHAR_s(endian, addBOM); +#else + return toUTF8_s(addBOM); +#endif + } + + //! Loads an unknown stream of data. + //! Will attempt to determine if the stream is unicode data. Useful for loading from files. + //! \param data The data stream to load from. + //! \param data_size The length of the data string. + //! \return A reference to our current string. + ustring16<TAlloc>& loadDataStream(const char* data, size_t data_size) + { + // Clear our string. + *this = ""; + if (!data) + return *this; + + unicode::EUTF_ENCODE e = unicode::determineUnicodeBOM(data); + switch (e) + { + default: + case unicode::EUTFE_UTF8: + append((uchar8_t*)data, data_size); + break; + + case unicode::EUTFE_UTF16: + case unicode::EUTFE_UTF16_BE: + case unicode::EUTFE_UTF16_LE: + append((uchar16_t*)data, data_size / 2); + break; + + case unicode::EUTFE_UTF32: + case unicode::EUTFE_UTF32_BE: + case unicode::EUTFE_UTF32_LE: + append((uchar32_t*)data, data_size / 4); + break; + } + + return *this; + } + + //! Gets the encoding of the Unicode string this class contains. + //! \return An enum describing the current encoding of this string. + const unicode::EUTF_ENCODE getEncoding() const + { + return encoding; + } + + //! Gets the endianness of the Unicode string this class contains. + //! \return An enum describing the endianness of this string. + const unicode::EUTF_ENDIAN getEndianness() const + { + if (encoding == unicode::EUTFE_UTF16_LE || + encoding == unicode::EUTFE_UTF32_LE) + return unicode::EUTFEE_LITTLE; + else return unicode::EUTFEE_BIG; + } + +private: + + //! Reallocate the string, making it bigger or smaller. + //! \param new_size The new size of the string. + void reallocate(u32 new_size) + { + uchar16_t* old_array = array; + + array = allocator.allocate(new_size + 1); //new u16[new_size]; + allocated = new_size + 1; + if (old_array == 0) return; + + u32 amount = used < new_size ? used : new_size; + for (u32 i=0; i<=amount; ++i) + array[i] = old_array[i]; + + if (allocated <= used) + used = allocated - 1; + + array[used] = 0; + + allocator.deallocate(old_array); // delete [] old_array; + } + + //--- member variables + + uchar16_t* array; + unicode::EUTF_ENCODE encoding; + u32 allocated; + u32 used; + TAlloc allocator; + //irrAllocator<uchar16_t> allocator; +}; + +typedef ustring16<irrAllocator<uchar16_t> > ustring; + + +//! Appends two ustring16s. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a null-terminated unicode string. +template <typename TAlloc, class B> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const B* const right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a null-terminated unicode string. +template <class B, typename TAlloc> +inline ustring16<TAlloc> operator+(const B* const left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +//! Appends a ustring16 and an Irrlicht string. +template <typename TAlloc, typename B, typename BAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const string<B, BAlloc>& right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +//! Appends a ustring16 and an Irrlicht string. +template <typename TAlloc, typename B, typename BAlloc> +inline ustring16<TAlloc> operator+(const string<B, BAlloc>& left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a std::basic_string. +template <typename TAlloc, typename B, typename A, typename BAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const std::basic_string<B, A, BAlloc>& right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a std::basic_string. +template <typename TAlloc, typename B, typename A, typename BAlloc> +inline ustring16<TAlloc> operator+(const std::basic_string<B, A, BAlloc>& left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a char. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const char right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a char. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const char left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +#ifdef USTRING_CPP0X_NEWLITERALS +//! Appends a ustring16 and a uchar32_t. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const uchar32_t right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a uchar32_t. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const uchar32_t left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(left); + ret += right; + return ret; +} +#endif + + +//! Appends a ustring16 and a short. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const short right) +{ + ustring16<TAlloc> ret(left); + ret += core::stringc(right); + return ret; +} + + +//! Appends a ustring16 and a short. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const short left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(core::stringc(left)); + ret += right; + return ret; +} + + +//! Appends a ustring16 and an unsigned short. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned short right) +{ + ustring16<TAlloc> ret(left); + ret += core::stringc(right); + return ret; +} + + +//! Appends a ustring16 and an unsigned short. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const unsigned short left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(core::stringc(left)); + ret += right; + return ret; +} + + +//! Appends a ustring16 and an int. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const int right) +{ + ustring16<TAlloc> ret(left); + ret += core::stringc(right); + return ret; +} + + +//! Appends a ustring16 and an int. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const int left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(core::stringc(left)); + ret += right; + return ret; +} + + +//! Appends a ustring16 and an unsigned int. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned int right) +{ + ustring16<TAlloc> ret(left); + ret += core::stringc(right); + return ret; +} + + +//! Appends a ustring16 and an unsigned int. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const unsigned int left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(core::stringc(left)); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a long. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const long right) +{ + ustring16<TAlloc> ret(left); + ret += core::stringc(right); + return ret; +} + + +//! Appends a ustring16 and a long. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const long left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(core::stringc(left)); + ret += right; + return ret; +} + + +//! Appends a ustring16 and an unsigned long. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned long right) +{ + ustring16<TAlloc> ret(left); + ret += core::stringc(right); + return ret; +} + + +//! Appends a ustring16 and an unsigned long. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const unsigned long left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(core::stringc(left)); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a float. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const float right) +{ + ustring16<TAlloc> ret(left); + ret += core::stringc(right); + return ret; +} + + +//! Appends a ustring16 and a float. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const float left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(core::stringc(left)); + ret += right; + return ret; +} + + +//! Appends a ustring16 and a double. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const double right) +{ + ustring16<TAlloc> ret(left); + ret += core::stringc(right); + return ret; +} + + +//! Appends a ustring16 and a double. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const double left, const ustring16<TAlloc>& right) +{ + ustring16<TAlloc> ret(core::stringc(left)); + ret += right; + return ret; +} + + +#ifdef USTRING_CPP0X +//! Appends two ustring16s. +template <typename TAlloc> +inline ustring16<TAlloc>&& operator+(const ustring16<TAlloc>& left, ustring16<TAlloc>&& right) +{ + //std::cout << "MOVE operator+(&, &&)" << std::endl; + right.insert(left, 0); + return std::move(right); +} + + +//! Appends two ustring16s. +template <typename TAlloc> +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, const ustring16<TAlloc>& right) +{ + //std::cout << "MOVE operator+(&&, &)" << std::endl; + left.append(right); + return std::move(left); +} + + +//! Appends two ustring16s. +template <typename TAlloc> +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, ustring16<TAlloc>&& right) +{ + //std::cout << "MOVE operator+(&&, &&)" << std::endl; + if ((right.size_raw() <= left.capacity() - left.size_raw()) || + (right.capacity() - right.size_raw() < left.size_raw())) + { + left.append(right); + return std::move(left); + } + else + { + right.insert(left, 0); + return std::move(right); + } +} + + +//! Appends a ustring16 and a null-terminated unicode string. +template <typename TAlloc, class B> +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, const B* const right) +{ + //std::cout << "MOVE operator+(&&, B*)" << std::endl; + left.append(right); + return std::move(left); +} + + +//! Appends a ustring16 and a null-terminated unicode string. +template <class B, typename TAlloc> +inline ustring16<TAlloc>&& operator+(const B* const left, ustring16<TAlloc>&& right) +{ + //std::cout << "MOVE operator+(B*, &&)" << std::endl; + right.insert(left, 0); + return std::move(right); +} + + +//! Appends a ustring16 and an Irrlicht string. +template <typename TAlloc, typename B, typename BAlloc> +inline ustring16<TAlloc>&& operator+(const string<B, BAlloc>& left, ustring16<TAlloc>&& right) +{ + //std::cout << "MOVE operator+(&, &&)" << std::endl; + right.insert(left, 0); + return std::move(right); +} + + +//! Appends a ustring16 and an Irrlicht string. +template <typename TAlloc, typename B, typename BAlloc> +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, const string<B, BAlloc>& right) +{ + //std::cout << "MOVE operator+(&&, &)" << std::endl; + left.append(right); + return std::move(left); +} + + +//! Appends a ustring16 and a std::basic_string. +template <typename TAlloc, typename B, typename A, typename BAlloc> +inline ustring16<TAlloc>&& operator+(const std::basic_string<B, A, BAlloc>& left, ustring16<TAlloc>&& right) +{ + //std::cout << "MOVE operator+(&, &&)" << std::endl; + right.insert(core::ustring16<TAlloc>(left), 0); + return std::move(right); +} + + +//! Appends a ustring16 and a std::basic_string. +template <typename TAlloc, typename B, typename A, typename BAlloc> +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, const std::basic_string<B, A, BAlloc>& right) +{ + //std::cout << "MOVE operator+(&&, &)" << std::endl; + left.append(right); + return std::move(left); +} + + +//! Appends a ustring16 and a char. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const char right) +{ + left.append((uchar32_t)right); + return std::move(left); +} + + +//! Appends a ustring16 and a char. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const char left, ustring16<TAlloc>&& right) +{ + right.insert((uchar32_t)left, 0); + return std::move(right); +} + + +#ifdef USTRING_CPP0X_NEWLITERALS +//! Appends a ustring16 and a uchar32_t. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const uchar32_t right) +{ + left.append(right); + return std::move(left); +} + + +//! Appends a ustring16 and a uchar32_t. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const uchar32_t left, ustring16<TAlloc>&& right) +{ + right.insert(left, 0); + return std::move(right); +} +#endif + + +//! Appends a ustring16 and a short. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const short right) +{ + left.append(core::stringc(right)); + return std::move(left); +} + + +//! Appends a ustring16 and a short. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const short left, ustring16<TAlloc>&& right) +{ + right.insert(core::stringc(left), 0); + return std::move(right); +} + + +//! Appends a ustring16 and an unsigned short. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const unsigned short right) +{ + left.append(core::stringc(right)); + return std::move(left); +} + + +//! Appends a ustring16 and an unsigned short. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const unsigned short left, ustring16<TAlloc>&& right) +{ + right.insert(core::stringc(left), 0); + return std::move(right); +} + + +//! Appends a ustring16 and an int. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const int right) +{ + left.append(core::stringc(right)); + return std::move(left); +} + + +//! Appends a ustring16 and an int. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const int left, ustring16<TAlloc>&& right) +{ + right.insert(core::stringc(left), 0); + return std::move(right); +} + + +//! Appends a ustring16 and an unsigned int. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const unsigned int right) +{ + left.append(core::stringc(right)); + return std::move(left); +} + + +//! Appends a ustring16 and an unsigned int. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const unsigned int left, ustring16<TAlloc>&& right) +{ + right.insert(core::stringc(left), 0); + return std::move(right); +} + + +//! Appends a ustring16 and a long. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const long right) +{ + left.append(core::stringc(right)); + return std::move(left); +} + + +//! Appends a ustring16 and a long. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const long left, ustring16<TAlloc>&& right) +{ + right.insert(core::stringc(left), 0); + return std::move(right); +} + + +//! Appends a ustring16 and an unsigned long. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const unsigned long right) +{ + left.append(core::stringc(right)); + return std::move(left); +} + + +//! Appends a ustring16 and an unsigned long. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const unsigned long left, ustring16<TAlloc>&& right) +{ + right.insert(core::stringc(left), 0); + return std::move(right); +} + + +//! Appends a ustring16 and a float. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const float right) +{ + left.append(core::stringc(right)); + return std::move(left); +} + + +//! Appends a ustring16 and a float. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const float left, ustring16<TAlloc>&& right) +{ + right.insert(core::stringc(left), 0); + return std::move(right); +} + + +//! Appends a ustring16 and a double. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const double right) +{ + left.append(core::stringc(right)); + return std::move(left); +} + + +//! Appends a ustring16 and a double. +template <typename TAlloc> +inline ustring16<TAlloc> operator+(const double left, ustring16<TAlloc>&& right) +{ + right.insert(core::stringc(left), 0); + return std::move(right); +} +#endif + + +#ifndef USTRING_NO_STL +//! Writes a ustring16 to an ostream. +template <typename TAlloc> +inline std::ostream& operator<<(std::ostream& out, const ustring16<TAlloc>& in) +{ + out << in.toUTF8_s().c_str(); + return out; +} + +//! Writes a ustring16 to a wostream. +template <typename TAlloc> +inline std::wostream& operator<<(std::wostream& out, const ustring16<TAlloc>& in) +{ + out << in.toWCHAR_s().c_str(); + return out; +} +#endif + + +#ifndef USTRING_NO_STL + +namespace unicode +{ + +//! Hashing algorithm for hashing a ustring. Used for things like unordered_maps. +//! Algorithm taken from std::hash<std::string>. +class hash : public std::unary_function<core::ustring, size_t> +{ + public: + size_t operator()(const core::ustring& s) const + { + size_t ret = 2166136261U; + size_t index = 0; + size_t stride = 1 + s.size_raw() / 10; + + core::ustring::const_iterator i = s.begin(); + while (i != s.end()) + { + // TODO: Don't force u32 on an x64 OS. Make it agnostic. + ret = 16777619U * ret ^ (size_t)s[(u32)index]; + index += stride; + i += stride; + } + return (ret); + } +}; + +} // end namespace unicode + +#endif + +} // end namespace core +} // end namespace irr + +#endif diff --git a/src/cguittfont/xCGUITTFont.cpp b/src/cguittfont/xCGUITTFont.cpp new file mode 100644 index 000000000..c51922e4c --- /dev/null +++ b/src/cguittfont/xCGUITTFont.cpp @@ -0,0 +1,5 @@ +// A wrapper source file to avoid hack with gcc and modifying +// the CGUITTFont files. + +#include "xCGUITTFont.h" +#include "CGUITTFont.cpp" diff --git a/src/cguittfont/xCGUITTFont.h b/src/cguittfont/xCGUITTFont.h new file mode 100644 index 000000000..c3efe7f6f --- /dev/null +++ b/src/cguittfont/xCGUITTFont.h @@ -0,0 +1,7 @@ +// A wrapper header to avoid hack with gcc and modifying +// the CGUITTFont files. + +#include <algorithm> +#include <stddef.h> +#include "irrUString.h" +#include "CGUITTFont.h" diff --git a/src/client.cpp b/src/client.cpp index 9969ef538..415f07311 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1514,6 +1514,26 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) } } } + else if(command == TOCLIENT_MOVEMENT) + { + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + Player *player = m_env.getLocalPlayer(); + assert(player != NULL); + + player->movement_acceleration_default = readF1000(is) * BS; + player->movement_acceleration_air = readF1000(is) * BS; + player->movement_acceleration_fast = readF1000(is) * BS; + player->movement_speed_walk = readF1000(is) * BS; + player->movement_speed_crouch = readF1000(is) * BS; + player->movement_speed_fast = readF1000(is) * BS; + player->movement_speed_climb = readF1000(is) * BS; + player->movement_speed_jump = readF1000(is) * BS; + player->movement_liquid_fluidity = readF1000(is) * BS; + player->movement_liquid_fluidity_smooth = readF1000(is) * BS; + player->movement_liquid_sink = readF1000(is) * BS; + player->movement_gravity = readF1000(is) * BS; + } else if(command == TOCLIENT_HP) { std::string datastring((char*)&data[2], datasize-2); diff --git a/src/clientmap.cpp b/src/clientmap.cpp index 800549a3b..0b30453b8 100644 --- a/src/clientmap.cpp +++ b/src/clientmap.cpp @@ -864,7 +864,7 @@ void ClientMap::renderPostFx() // - If the player is in liquid, draw a semi-transparent overlay. const ContentFeatures& features = nodemgr->get(n); video::SColor post_effect_color = features.post_effect_color; - if(features.solidness == 2 && g_settings->getBool("free_move") == false) + if(features.solidness == 2 && !(g_settings->getBool("noclip") && m_gamedef->checkLocalPrivilege("noclip"))) { post_effect_color = video::SColor(255, 0, 0, 0); } diff --git a/src/clientserver.h b/src/clientserver.h index 52b9dc7b0..7fb3e83d2 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -364,6 +364,23 @@ enum ToClientCommand u16 len u8[len] formname */ + + TOCLIENT_MOVEMENT = 0x45, + /* + u16 command + f1000 movement_acceleration_default + f1000 movement_acceleration_air + f1000 movement_acceleration_fast + f1000 movement_speed_walk + f1000 movement_speed_crouch + f1000 movement_speed_fast + f1000 movement_speed_climb + f1000 movement_speed_jump + f1000 movement_liquid_fluidity + f1000 movement_liquid_fluidity_smooth + f1000 movement_liquid_sink + f1000 movement_gravity + */ }; enum ToServerCommand diff --git a/src/cmake_config.h.in b/src/cmake_config.h.in index 4853d854f..51827cce6 100644 --- a/src/cmake_config.h.in +++ b/src/cmake_config.h.in @@ -9,6 +9,7 @@ #define CMAKE_USE_GETTEXT @USE_GETTEXT@ #define CMAKE_USE_CURL @USE_CURL@ #define CMAKE_USE_SOUND @USE_SOUND@ +#define CMAKE_USE_FREETYPE @USE_FREETYPE@ #define CMAKE_STATIC_SHAREDIR "@SHAREDIR@" #ifdef NDEBUG diff --git a/src/config.h b/src/config.h index f37ec0fed..37dc6e0ef 100644 --- a/src/config.h +++ b/src/config.h @@ -12,6 +12,7 @@ #define USE_GETTEXT 0 #define USE_SOUND 0 #define USE_CURL 0 +#define USE_FREETYPE 0 #define STATIC_SHAREDIR "" #define BUILD_INFO "non-cmake" @@ -29,6 +30,8 @@ #define USE_SOUND CMAKE_USE_SOUND #undef USE_CURL #define USE_CURL CMAKE_USE_CURL + #undef USE_FREETYPE + #define USE_FREETYPE CMAKE_USE_FREETYPE #undef STATIC_SHAREDIR #define STATIC_SHAREDIR CMAKE_STATIC_SHAREDIR #undef BUILD_INFO diff --git a/src/content_abm.cpp b/src/content_abm.cpp index 9e65a7ab0..ce1751117 100644 --- a/src/content_abm.cpp +++ b/src/content_abm.cpp @@ -80,7 +80,8 @@ public: ServerMap *map = &env->getServerMap(); MapNode n_top = map->getNodeNoEx(p+v3s16(0,1,0)); - if(!ndef->get(n_top).light_propagates || + if((!ndef->get(n_top).light_propagates && + n_top.getContent() != CONTENT_IGNORE) || ndef->get(n_top).isLiquid()) { n.setContent(ndef->getId("mapgen_dirt")); diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index aa3c061d6..290890490 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -733,7 +733,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, u16 l = getInteriorLight(n, 1, data); video::SColor c = MapBlock_LightColor(255, l, decode_light(f.light_source)); - for(u32 j=0; j<4; j++) + for(u32 j=0; j<2; j++) { video::S3DVertex vertices[4] = { @@ -759,16 +759,6 @@ void mapblock_mesh_generate_special(MeshMakeData *data, for(u16 i=0; i<4; i++) vertices[i].Pos.rotateXZBy(-45); } - else if(j == 2) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(135); - } - else if(j == 3) - { - for(u16 i=0; i<4; i++) - vertices[i].Pos.rotateXZBy(-135); - } for(u16 i=0; i<4; i++) { diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index e6526d3d7..e3c6b2f7d 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -18,6 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ #include "settings.h" +#include "filesys.h" void set_default_settings(Settings *settings) { @@ -132,6 +133,11 @@ void set_default_settings(Settings *settings) settings->setDefault("serverlist_url", "servers.minetest.ru/server.list"); settings->setDefault("serverlist_file", "favoriteservers.txt"); + settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "liberationsans.ttf")); + settings->setDefault("font_size", "13"); + settings->setDefault("mono_font_path", porting::getDataPath("fonts" DIR_DELIM "liberationmono.ttf")); + settings->setDefault("mono_font_size", "13"); + // Server stuff // "map-dir" doesn't exist by default. settings->setDefault("default_game", "minetest"); @@ -172,12 +178,26 @@ void set_default_settings(Settings *settings) settings->setDefault("congestion_control_max_rate", "400"); settings->setDefault("congestion_control_min_rate", "10"); settings->setDefault("remote_media", ""); + + // physics stuff + settings->setDefault("movement_acceleration_default", "3"); + settings->setDefault("movement_acceleration_air", "2"); + settings->setDefault("movement_acceleration_fast", "10"); + settings->setDefault("movement_speed_walk", "4"); + settings->setDefault("movement_speed_crouch", "1.35"); + settings->setDefault("movement_speed_fast", "20"); + settings->setDefault("movement_speed_climb", "2"); + settings->setDefault("movement_speed_jump", "6.5"); + settings->setDefault("movement_liquid_fluidity", "1"); + settings->setDefault("movement_liquid_fluidity_smooth", "0.5"); + settings->setDefault("movement_liquid_sink", "10"); + settings->setDefault("movement_gravity", "9.81"); //mapgen related things settings->setDefault("mg_name", "v6"); settings->setDefault("water_level", "1"); settings->setDefault("chunksize", "5"); - settings->setDefault("mg_flags", "19"); + settings->setDefault("mg_flags", "trees, caves, v6_biome_blend"); settings->setDefault("mgv6_freq_desert", "0.45"); settings->setDefault("mgv6_freq_beach", "0.15"); diff --git a/src/environment.cpp b/src/environment.cpp index 51255b918..ebf5e9a63 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -2065,20 +2065,37 @@ void ClientEnvironment::step(float dtime) { // Gravity v3f speed = lplayer->getSpeed(); - if(lplayer->swimming_up == false) - speed.Y -= 9.81 * BS * dtime_part * 2; + if(lplayer->in_liquid == false) + speed.Y -= lplayer->movement_gravity * dtime_part * 2; - // Water resistance - if(lplayer->in_water_stable || lplayer->in_water) - { - f32 max_down = 2.0*BS; - if(speed.Y < -max_down) speed.Y = -max_down; + // Liquid floating / sinking + if(lplayer->in_liquid && !lplayer->swimming_vertical) + speed.Y -= lplayer->movement_liquid_sink * dtime_part * 2; - f32 max = 2.5*BS; - if(speed.getLength() > max) - { - speed = speed / speed.getLength() * max; - } + // Liquid resistance + if(lplayer->in_liquid_stable || lplayer->in_liquid) + { + // How much the node's viscosity blocks movement, ranges between 0 and 1 + // Should match the scale at which viscosity increase affects other liquid attributes + const f32 viscosity_factor = 0.3; + + v3f d_wanted = -speed / lplayer->movement_liquid_fluidity; + f32 dl = d_wanted.getLength(); + if(dl > lplayer->movement_liquid_fluidity_smooth) + dl = lplayer->movement_liquid_fluidity_smooth; + dl *= (lplayer->liquid_viscosity * viscosity_factor) + (1 - viscosity_factor); + + v3f d = d_wanted.normalize() * dl; + speed += d; + +#if 0 // old code + if(speed.X > lplayer->movement_liquid_fluidity + lplayer->movement_liquid_fluidity_smooth) speed.X -= lplayer->movement_liquid_fluidity_smooth; + if(speed.X < -lplayer->movement_liquid_fluidity - lplayer->movement_liquid_fluidity_smooth) speed.X += lplayer->movement_liquid_fluidity_smooth; + if(speed.Y > lplayer->movement_liquid_fluidity + lplayer->movement_liquid_fluidity_smooth) speed.Y -= lplayer->movement_liquid_fluidity_smooth; + if(speed.Y < -lplayer->movement_liquid_fluidity - lplayer->movement_liquid_fluidity_smooth) speed.Y += lplayer->movement_liquid_fluidity_smooth; + if(speed.Z > lplayer->movement_liquid_fluidity + lplayer->movement_liquid_fluidity_smooth) speed.Z -= lplayer->movement_liquid_fluidity_smooth; + if(speed.Z < -lplayer->movement_liquid_fluidity - lplayer->movement_liquid_fluidity_smooth) speed.Z += lplayer->movement_liquid_fluidity_smooth; +#endif } lplayer->setSpeed(speed); diff --git a/src/game.cpp b/src/game.cpp index e923cbbb0..5693c5c12 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1262,7 +1262,7 @@ void the_game( gui::IGUIStaticText *guitext_info = guienv->addStaticText( L"", core::rect<s32>(0,0,400,text_height*5+5) + v2s32(100,200), - false, false); + false, true); // Status text (displays info when showing and hiding GUI stuff, etc.) gui::IGUIStaticText *guitext_status = guienv->addStaticText( diff --git a/src/gettext.h b/src/gettext.h index 54470cb0d..452787de4 100644 --- a/src/gettext.h +++ b/src/gettext.h @@ -12,6 +12,11 @@ #define gettext_noop(String) String #define N_(String) gettext_noop (String) +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#endif + inline void init_gettext(const char *path) { #if USE_GETTEXT // don't do this if MSVC compiler is used, it gives an assertion fail @@ -20,14 +25,44 @@ inline void init_gettext(const char *path) { #endif bindtextdomain(PROJECT_NAME, path); textdomain(PROJECT_NAME); +#if defined(_WIN32) + // As linux is successfully switched to UTF-8 completely at about year 2005 + // Windows still uses obsolete codepage based locales because you + // cannot recompile closed-source applications + + // Set character encoding for Win32 + char *tdomain = textdomain( (char *) NULL ); + if( tdomain == NULL ) + { + fprintf( stderr, "warning: domainname parameter is the null pointer, default domain is not set\n" ); + tdomain = (char *) "messages"; + } + /*char *codeset = */bind_textdomain_codeset( tdomain, "UTF-8" ); + //fprintf( stdout, "%s: debug: domainname = %s; codeset = %s\n", argv[0], tdomain, codeset ); +#endif // defined(_WIN32) #endif } inline wchar_t* chartowchar_t(const char *str) { + wchar_t* nstr = 0; +#if defined(_WIN32) + int nResult = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) str, -1, 0, 0 ); + if( nResult == 0 ) + { + fprintf( stderr, "error: MultiByteToWideChar returned null\n" ); + } + else + { + nstr = new wchar_t[nResult]; + MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) str, -1, (WCHAR *) nstr, nResult ); + } +#else size_t l = strlen(str)+1; - wchar_t* nstr = new wchar_t[l]; + nstr = new wchar_t[l]; mbstowcs(nstr, str, l); +#endif + return nstr; } @@ -38,12 +73,12 @@ inline wchar_t* wgettext(const char *str) inline void changeCtype(const char *l) { - char *ret = NULL; + /*char *ret = NULL; ret = setlocale(LC_CTYPE, l); if(ret == NULL) infostream<<"locale could not be set"<<std::endl; else - infostream<<"locale has been set to:"<<ret<<std::endl; + infostream<<"locale has been set to:"<<ret<<std::endl;*/ } #define GETTEXT_HEADER #endif diff --git a/src/guiChatConsole.cpp b/src/guiChatConsole.cpp index 0101b99bb..13883901e 100644 --- a/src/guiChatConsole.cpp +++ b/src/guiChatConsole.cpp @@ -32,6 +32,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gettext.h" +#if USE_FREETYPE +#include "xCGUITTFont.h" +#endif + inline u32 clamp_u8(s32 value) { return (u32) MYMIN(MYMAX(value, 0), 255); @@ -90,8 +94,14 @@ GUIChatConsole::GUIChatConsole( // load the font // FIXME should a custom texture_path be searched too? + #if USE_FREETYPE + std::string font_name = g_settings->get("mono_font_path"); + u16 font_size = g_settings->getU16("mono_font_size"); + m_font = gui::CGUITTFont::createTTFont(env, font_name.c_str(), font_size); + #else std::string font_name = "fontdejavusansmono.png"; m_font = env->getFont(getTexturePath(font_name).c_str()); + #endif if (m_font == NULL) { dstream << "Unable to load font: " << font_name << std::endl; diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp index 6b0412821..3f6d03ebb 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -369,21 +369,21 @@ void GUIKeyChangeMenu::add_key(int id, std::string button_name, std::string sett void GUIKeyChangeMenu::init_keys() { - this->add_key(GUI_ID_KEY_FORWARD_BUTTON, "Forward", "keymap_forward"); - this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, "Backward", "keymap_backward"); - this->add_key(GUI_ID_KEY_LEFT_BUTTON, "Left", "keymap_left"); - this->add_key(GUI_ID_KEY_RIGHT_BUTTON, "Right", "keymap_right"); - this->add_key(GUI_ID_KEY_USE_BUTTON, "Use", "keymap_special1"); - this->add_key(GUI_ID_KEY_JUMP_BUTTON, "Jump", "keymap_jump"); - this->add_key(GUI_ID_KEY_SNEAK_BUTTON, "Sneak", "keymap_sneak"); - this->add_key(GUI_ID_KEY_DROP_BUTTON, "Drop", "keymap_drop"); - this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, "Inventory", "keymap_inventory"); - this->add_key(GUI_ID_KEY_CHAT_BUTTON, "Chat", "keymap_chat"); - this->add_key(GUI_ID_KEY_CMD_BUTTON, "Command", "keymap_cmd"); - this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, "Console", "keymap_console"); - this->add_key(GUI_ID_KEY_FLY_BUTTON, "Toggle fly", "keymap_freemove"); - this->add_key(GUI_ID_KEY_FAST_BUTTON, "Toggle fast", "keymap_fastmove"); - this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, "Toggle noclip", "keymap_noclip"); - this->add_key(GUI_ID_KEY_RANGE_BUTTON, "Range select", "keymap_rangeselect"); - this->add_key(GUI_ID_KEY_DUMP_BUTTON, "Print stacks", "keymap_print_debug_stacks"); + this->add_key(GUI_ID_KEY_FORWARD_BUTTON, gettext("Forward"), "keymap_forward"); + this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, gettext("Backward"), "keymap_backward"); + this->add_key(GUI_ID_KEY_LEFT_BUTTON, gettext("Left"), "keymap_left"); + this->add_key(GUI_ID_KEY_RIGHT_BUTTON, gettext("Right"), "keymap_right"); + this->add_key(GUI_ID_KEY_USE_BUTTON, gettext("Use"), "keymap_special1"); + this->add_key(GUI_ID_KEY_JUMP_BUTTON, gettext("Jump"), "keymap_jump"); + this->add_key(GUI_ID_KEY_SNEAK_BUTTON, gettext("Sneak"), "keymap_sneak"); + this->add_key(GUI_ID_KEY_DROP_BUTTON, gettext("Drop"), "keymap_drop"); + this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, gettext("Inventory"), "keymap_inventory"); + this->add_key(GUI_ID_KEY_CHAT_BUTTON, gettext("Chat"), "keymap_chat"); + this->add_key(GUI_ID_KEY_CMD_BUTTON, gettext("Command"), "keymap_cmd"); + this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, gettext("Console"), "keymap_console"); + this->add_key(GUI_ID_KEY_FLY_BUTTON, gettext("Toggle fly"), "keymap_freemove"); + this->add_key(GUI_ID_KEY_FAST_BUTTON, gettext("Toggle fast"), "keymap_fastmove"); + this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, gettext("Toggle noclip"), "keymap_noclip"); + this->add_key(GUI_ID_KEY_RANGE_BUTTON, gettext("Range select"), "keymap_rangeselect"); + this->add_key(GUI_ID_KEY_DUMP_BUTTON, gettext("Print stacks"), "keymap_print_debug_stacks"); } diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 9291bb4ec..343369643 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -260,7 +260,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) //const wchar_t *text = L"H\nY\nB\nR\nI\nD"; const wchar_t *text = L"T\nA\nP\nE\n\nA\nN\nD\n\nG\nL\nU\nE"; gui::IGUIStaticText *t = - Environment->addStaticText(text, rect, false, false, this, -1); + Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } u32 bs = 5; @@ -359,7 +359,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"C\nL\nI\nE\nN\nT"; gui::IGUIStaticText *t = - Environment->addStaticText(text, rect, false, false, this, -1); + Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } // Nickname + password @@ -469,7 +469,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"C\nL\nI\nE\nN\nT"; gui::IGUIStaticText *t = - Environment->addStaticText(text, rect, false, false, this, -1); + Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } // Nickname + password @@ -546,7 +546,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) rect += m_topleft_server + v2s32(15, 0); const wchar_t *text = L"S\nE\nR\nV\nE\nR"; gui::IGUIStaticText *t = - Environment->addStaticText(text, rect, false, false, this, -1); + Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } // Server parameters @@ -598,7 +598,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"S\nE\nT\nT\nI\nN\nG\nS"; gui::IGUIStaticText *t = - Environment->addStaticText(text, rect, false, false, this, -1); + Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } s32 option_x = 70; @@ -701,7 +701,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) rect += m_topleft_client + v2s32(15, 0); const wchar_t *text = L"C\nR\nE\nD\nI\nT\nS"; gui::IGUIStaticText *t = - Environment->addStaticText(text, rect, false, false, this, -1); + Environment->addStaticText(text, rect, false, true, this, -1); t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); } { diff --git a/src/guiTextInputMenu.cpp b/src/guiTextInputMenu.cpp index 094532a62..857c26a45 100644 --- a/src/guiTextInputMenu.cpp +++ b/src/guiTextInputMenu.cpp @@ -29,6 +29,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "gettext.h" +#if USE_FREETYPE +#include "intlGUIEditBox.h" +#endif + GUITextInputMenu::GUITextInputMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, @@ -105,8 +109,12 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize) { core::rect<s32> rect(0, 0, 300, 30); rect = rect + v2s32(size.X/2-300/2, size.Y/2-30/2-25); - gui::IGUIElement *e = - Environment->addEditBox(text.c_str(), rect, true, this, 256); + #if USE_FREETYPE + gui::IGUIElement *e = (gui::IGUIElement *) new gui::intlGUIEditBox(text.c_str(), true, Environment, this, 256, rect); + e->drop(); + #else + gui::IGUIElement *e = Environment->addEditBox(text.c_str(), rect, true, this, 256); + #endif Environment->setFocus(e); irr::SEvent evt; diff --git a/src/intlGUIEditBox.cpp b/src/intlGUIEditBox.cpp new file mode 100644 index 000000000..4add61e20 --- /dev/null +++ b/src/intlGUIEditBox.cpp @@ -0,0 +1,1508 @@ +// 11.11.2011 11:11 ValkaTR +// +// This is a copy of intlGUIEditBox from the irrlicht, but with a +// fix in the OnEvent function, which doesn't allowed input of +// other keyboard layouts than latin-1 +// +// Characters like: ä ö ü õ ы й ю я ъ № € ° ... +// +// This fix is only needed for linux, because of a bug +// in the CIrrDeviceLinux.cpp:1014-1015 of the irrlicht +// +// Also locale in the programm should not be changed to +// a "C", "POSIX" or whatever, it should be set to "", +// or XLookupString will return nothing for the international +// characters. +// +// From the "man setlocale": +// +// On startup of the main program, the portable "C" locale +// is selected as default. A program may be made +// portable to all locales by calling: +// +// setlocale(LC_ALL, ""); +// +// after program initialization.... +// + +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#include "intlGUIEditBox.h" + +#ifdef _IRR_COMPILE_WITH_GUI_ + +#include "IGUISkin.h" +#include "IGUIEnvironment.h" +#include "IGUIFont.h" +#include "IVideoDriver.h" +//#include "rect.h" +//#include "irrlicht/os.cpp" +#include "porting.h" +//#include "Keycodes.h" + +/* + todo: + optional scrollbars + ctrl+left/right to select word + double click/ctrl click: word select + drag to select whole words, triple click to select line + optional? dragging selected text + numerical +*/ + +namespace irr +{ +namespace gui +{ + +//! constructor +intlGUIEditBox::intlGUIEditBox(const wchar_t* text, bool border, + IGUIEnvironment* environment, IGUIElement* parent, s32 id, + const core::rect<s32>& rectangle) + : IGUIEditBox(environment, parent, id, rectangle), MouseMarking(false), + Border(border), OverrideColorEnabled(false), MarkBegin(0), MarkEnd(0), + OverrideColor(video::SColor(101,255,255,255)), OverrideFont(0), LastBreakFont(0), + Operator(0), BlinkStartTime(0), CursorPos(0), HScrollPos(0), VScrollPos(0), Max(0), + WordWrap(false), MultiLine(false), AutoScroll(true), PasswordBox(false), + PasswordChar(L'*'), HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_CENTER), + CurrentTextRect(0,0,1,1), FrameRect(rectangle) +{ + #ifdef _DEBUG + setDebugName("intlintlGUIEditBox"); + #endif + + Text = text; + + if (Environment) + Operator = Environment->getOSOperator(); + + if (Operator) + Operator->grab(); + + // this element can be tabbed to + setTabStop(true); + setTabOrder(-1); + + IGUISkin *skin = 0; + if (Environment) + skin = Environment->getSkin(); + if (Border && skin) + { + FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1; + FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; + FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1; + FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; + } + + breakText(); + + calculateScrollPos(); +} + + +//! destructor +intlGUIEditBox::~intlGUIEditBox() +{ + if (OverrideFont) + OverrideFont->drop(); + + if (Operator) + Operator->drop(); +} + + +//! Sets another skin independent font. +void intlGUIEditBox::setOverrideFont(IGUIFont* font) +{ + if (OverrideFont == font) + return; + + if (OverrideFont) + OverrideFont->drop(); + + OverrideFont = font; + + if (OverrideFont) + OverrideFont->grab(); + + breakText(); +} + +IGUIFont * intlGUIEditBox::getOverrideFont() const +{ + return OverrideFont; +} + +//! Get the font which is used right now for drawing +IGUIFont* intlGUIEditBox::getActiveFont() const +{ + if ( OverrideFont ) + return OverrideFont; + IGUISkin* skin = Environment->getSkin(); + if (skin) + return skin->getFont(); + return 0; +} + +//! Sets another color for the text. +void intlGUIEditBox::setOverrideColor(video::SColor color) +{ + OverrideColor = color; + OverrideColorEnabled = true; +} + +video::SColor intlGUIEditBox::getOverrideColor() const +{ + return OverrideColor; +} + +//! Turns the border on or off +void intlGUIEditBox::setDrawBorder(bool border) +{ + Border = border; +} + +//! Sets whether to draw the background +void intlGUIEditBox::setDrawBackground(bool draw) +{ +} + +//! Sets if the text should use the overide color or the color in the gui skin. +void intlGUIEditBox::enableOverrideColor(bool enable) +{ + OverrideColorEnabled = enable; +} + +bool intlGUIEditBox::isOverrideColorEnabled() const +{ + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return OverrideColorEnabled; +} + +//! Enables or disables word wrap +void intlGUIEditBox::setWordWrap(bool enable) +{ + WordWrap = enable; + breakText(); +} + + +void intlGUIEditBox::updateAbsolutePosition() +{ + core::rect<s32> oldAbsoluteRect(AbsoluteRect); + IGUIElement::updateAbsolutePosition(); + if ( oldAbsoluteRect != AbsoluteRect ) + { + breakText(); + } +} + + +//! Checks if word wrap is enabled +bool intlGUIEditBox::isWordWrapEnabled() const +{ + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return WordWrap; +} + + +//! Enables or disables newlines. +void intlGUIEditBox::setMultiLine(bool enable) +{ + MultiLine = enable; +} + + +//! Checks if multi line editing is enabled +bool intlGUIEditBox::isMultiLineEnabled() const +{ + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return MultiLine; +} + + +void intlGUIEditBox::setPasswordBox(bool passwordBox, wchar_t passwordChar) +{ + PasswordBox = passwordBox; + if (PasswordBox) + { + PasswordChar = passwordChar; + setMultiLine(false); + setWordWrap(false); + BrokenText.clear(); + } +} + + +bool intlGUIEditBox::isPasswordBox() const +{ + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return PasswordBox; +} + + +//! Sets text justification +void intlGUIEditBox::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) +{ + HAlign = horizontal; + VAlign = vertical; +} + + +//! called if an event happened. +bool intlGUIEditBox::OnEvent(const SEvent& event) +{ + if (IsEnabled) + { + + switch(event.EventType) + { + case EET_GUI_EVENT: + if (event.GUIEvent.EventType == EGET_ELEMENT_FOCUS_LOST) + { + if (event.GUIEvent.Caller == this) + { + MouseMarking = false; + setTextMarkers(0,0); + } + } + break; + case EET_KEY_INPUT_EVENT: + { +#if defined(linux) + // ################################################################ + // ValkaTR: + // This part is the difference from the original intlGUIEditBox + // It converts UTF-8 character into a UCS-2 (wchar_t) + wchar_t wc = L'_'; + mbtowc( &wc, (char *) &event.KeyInput.Char, sizeof(event.KeyInput.Char) ); + + //printf( "char: %lc (%u) \r\n", wc, wc ); + + SEvent irrevent(event); + irrevent.KeyInput.Char = wc; + // ################################################################ + + if (processKey(irrevent)) + return true; +#else + if (processKey(event)) + return true; +#endif // defined(linux) + + break; + } + case EET_MOUSE_INPUT_EVENT: + if (processMouse(event)) + return true; + break; + default: + break; + } + } + + return IGUIElement::OnEvent(event); +} + + +bool intlGUIEditBox::processKey(const SEvent& event) +{ + if (!event.KeyInput.PressedDown) + return false; + + bool textChanged = false; + s32 newMarkBegin = MarkBegin; + s32 newMarkEnd = MarkEnd; + + // control shortcut handling + + if (event.KeyInput.Control) + { + // german backlash '\' entered with control + '?' + if ( event.KeyInput.Char == '\\' ) + { + inputChar(event.KeyInput.Char); + return true; + } + + switch(event.KeyInput.Key) + { + case KEY_KEY_A: + // select all + newMarkBegin = 0; + newMarkEnd = Text.size(); + break; + case KEY_KEY_C: + // copy to clipboard + if (!PasswordBox && Operator && MarkBegin != MarkEnd) + { + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + + core::stringc s; + s = Text.subString(realmbgn, realmend - realmbgn).c_str(); + Operator->copyToClipboard(s.c_str()); + } + break; + case KEY_KEY_X: + // cut to the clipboard + if (!PasswordBox && Operator && MarkBegin != MarkEnd) + { + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + + // copy + core::stringc sc; + sc = Text.subString(realmbgn, realmend - realmbgn).c_str(); + Operator->copyToClipboard(sc.c_str()); + + if (IsEnabled) + { + // delete + core::stringw s; + s = Text.subString(0, realmbgn); + s.append( Text.subString(realmend, Text.size()-realmend) ); + Text = s; + + CursorPos = realmbgn; + newMarkBegin = 0; + newMarkEnd = 0; + textChanged = true; + } + } + break; + case KEY_KEY_V: + if ( !IsEnabled ) + break; + + // paste from the clipboard + if (Operator) + { + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + + // add new character + const c8* p = Operator->getTextFromClipboard(); + if (p) + { + if (MarkBegin == MarkEnd) + { + // insert text + core::stringw s = Text.subString(0, CursorPos); + s.append(p); + s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); + + if (!Max || s.size()<=Max) // thx to Fish FH for fix + { + Text = s; + s = p; + CursorPos += s.size(); + } + } + else + { + // replace text + + core::stringw s = Text.subString(0, realmbgn); + s.append(p); + s.append( Text.subString(realmend, Text.size()-realmend) ); + + if (!Max || s.size()<=Max) // thx to Fish FH for fix + { + Text = s; + s = p; + CursorPos = realmbgn + s.size(); + } + } + } + + newMarkBegin = 0; + newMarkEnd = 0; + textChanged = true; + } + break; + case KEY_HOME: + // move/highlight to start of text + if (event.KeyInput.Shift) + { + newMarkEnd = CursorPos; + newMarkBegin = 0; + CursorPos = 0; + } + else + { + CursorPos = 0; + newMarkBegin = 0; + newMarkEnd = 0; + } + break; + case KEY_END: + // move/highlight to end of text + if (event.KeyInput.Shift) + { + newMarkBegin = CursorPos; + newMarkEnd = Text.size(); + CursorPos = 0; + } + else + { + CursorPos = Text.size(); + newMarkBegin = 0; + newMarkEnd = 0; + } + break; + default: + return false; + } + } + // default keyboard handling + else + switch(event.KeyInput.Key) + { + case KEY_END: + { + s32 p = Text.size(); + if (WordWrap || MultiLine) + { + p = getLineFromPos(CursorPos); + p = BrokenTextPositions[p] + (s32)BrokenText[p].size(); + if (p > 0 && (Text[p-1] == L'\r' || Text[p-1] == L'\n' )) + p-=1; + } + + if (event.KeyInput.Shift) + { + if (MarkBegin == MarkEnd) + newMarkBegin = CursorPos; + + newMarkEnd = p; + } + else + { + newMarkBegin = 0; + newMarkEnd = 0; + } + CursorPos = p; + BlinkStartTime = porting::getTimeMs(); + } + break; + case KEY_HOME: + { + + s32 p = 0; + if (WordWrap || MultiLine) + { + p = getLineFromPos(CursorPos); + p = BrokenTextPositions[p]; + } + + if (event.KeyInput.Shift) + { + if (MarkBegin == MarkEnd) + newMarkBegin = CursorPos; + newMarkEnd = p; + } + else + { + newMarkBegin = 0; + newMarkEnd = 0; + } + CursorPos = p; + BlinkStartTime = porting::getTimeMs(); + } + break; + case KEY_RETURN: + if (MultiLine) + { + inputChar(L'\n'); + return true; + } + else + { + sendGuiEvent( EGET_EDITBOX_ENTER ); + } + break; + case KEY_LEFT: + + if (event.KeyInput.Shift) + { + if (CursorPos > 0) + { + if (MarkBegin == MarkEnd) + newMarkBegin = CursorPos; + + newMarkEnd = CursorPos-1; + } + } + else + { + newMarkBegin = 0; + newMarkEnd = 0; + } + + if (CursorPos > 0) CursorPos--; + BlinkStartTime = porting::getTimeMs(); + break; + + case KEY_RIGHT: + if (event.KeyInput.Shift) + { + if (Text.size() > (u32)CursorPos) + { + if (MarkBegin == MarkEnd) + newMarkBegin = CursorPos; + + newMarkEnd = CursorPos+1; + } + } + else + { + newMarkBegin = 0; + newMarkEnd = 0; + } + + if (Text.size() > (u32)CursorPos) CursorPos++; + BlinkStartTime = porting::getTimeMs(); + break; + case KEY_UP: + if (MultiLine || (WordWrap && BrokenText.size() > 1) ) + { + s32 lineNo = getLineFromPos(CursorPos); + s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin > MarkEnd ? MarkBegin : MarkEnd); + if (lineNo > 0) + { + s32 cp = CursorPos - BrokenTextPositions[lineNo]; + if ((s32)BrokenText[lineNo-1].size() < cp) + CursorPos = BrokenTextPositions[lineNo-1] + (s32)BrokenText[lineNo-1].size()-1; + else + CursorPos = BrokenTextPositions[lineNo-1] + cp; + } + + if (event.KeyInput.Shift) + { + newMarkBegin = mb; + newMarkEnd = CursorPos; + } + else + { + newMarkBegin = 0; + newMarkEnd = 0; + } + + } + else + { + return false; + } + break; + case KEY_DOWN: + if (MultiLine || (WordWrap && BrokenText.size() > 1) ) + { + s32 lineNo = getLineFromPos(CursorPos); + s32 mb = (MarkBegin == MarkEnd) ? CursorPos : (MarkBegin < MarkEnd ? MarkBegin : MarkEnd); + if (lineNo < (s32)BrokenText.size()-1) + { + s32 cp = CursorPos - BrokenTextPositions[lineNo]; + if ((s32)BrokenText[lineNo+1].size() < cp) + CursorPos = BrokenTextPositions[lineNo+1] + BrokenText[lineNo+1].size()-1; + else + CursorPos = BrokenTextPositions[lineNo+1] + cp; + } + + if (event.KeyInput.Shift) + { + newMarkBegin = mb; + newMarkEnd = CursorPos; + } + else + { + newMarkBegin = 0; + newMarkEnd = 0; + } + + } + else + { + return false; + } + break; + + case KEY_BACK: + if ( !this->IsEnabled ) + break; + + if (Text.size()) + { + core::stringw s; + + if (MarkBegin != MarkEnd) + { + // delete marked text + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + + s = Text.subString(0, realmbgn); + s.append( Text.subString(realmend, Text.size()-realmend) ); + Text = s; + + CursorPos = realmbgn; + } + else + { + // delete text behind cursor + if (CursorPos>0) + s = Text.subString(0, CursorPos-1); + else + s = L""; + s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); + Text = s; + --CursorPos; + } + + if (CursorPos < 0) + CursorPos = 0; + BlinkStartTime = porting::getTimeMs(); + newMarkBegin = 0; + newMarkEnd = 0; + textChanged = true; + } + break; + case KEY_DELETE: + if ( !this->IsEnabled ) + break; + + if (Text.size() != 0) + { + core::stringw s; + + if (MarkBegin != MarkEnd) + { + // delete marked text + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + + s = Text.subString(0, realmbgn); + s.append( Text.subString(realmend, Text.size()-realmend) ); + Text = s; + + CursorPos = realmbgn; + } + else + { + // delete text before cursor + s = Text.subString(0, CursorPos); + s.append( Text.subString(CursorPos+1, Text.size()-CursorPos-1) ); + Text = s; + } + + if (CursorPos > (s32)Text.size()) + CursorPos = (s32)Text.size(); + + BlinkStartTime = porting::getTimeMs(); + newMarkBegin = 0; + newMarkEnd = 0; + textChanged = true; + } + break; + + case KEY_ESCAPE: + case KEY_TAB: + case KEY_SHIFT: + case KEY_F1: + case KEY_F2: + case KEY_F3: + case KEY_F4: + case KEY_F5: + case KEY_F6: + case KEY_F7: + case KEY_F8: + case KEY_F9: + case KEY_F10: + case KEY_F11: + case KEY_F12: + case KEY_F13: + case KEY_F14: + case KEY_F15: + case KEY_F16: + case KEY_F17: + case KEY_F18: + case KEY_F19: + case KEY_F20: + case KEY_F21: + case KEY_F22: + case KEY_F23: + case KEY_F24: + // ignore these keys + return false; + + default: + inputChar(event.KeyInput.Char); + return true; + } + + // Set new text markers + setTextMarkers( newMarkBegin, newMarkEnd ); + + // break the text if it has changed + if (textChanged) + { + breakText(); + sendGuiEvent(EGET_EDITBOX_CHANGED); + } + + calculateScrollPos(); + + return true; +} + + +//! draws the element and its children +void intlGUIEditBox::draw() +{ + if (!IsVisible) + return; + + const bool focus = Environment->hasFocus(this); + + IGUISkin* skin = Environment->getSkin(); + if (!skin) + return; + + FrameRect = AbsoluteRect; + + // draw the border + + if (Border) + { + skin->draw3DSunkenPane(this, skin->getColor(EGDC_WINDOW), + false, true, FrameRect, &AbsoluteClippingRect); + + FrameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X)+1; + FrameRect.UpperLeftCorner.Y += skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; + FrameRect.LowerRightCorner.X -= skin->getSize(EGDS_TEXT_DISTANCE_X)+1; + FrameRect.LowerRightCorner.Y -= skin->getSize(EGDS_TEXT_DISTANCE_Y)+1; + } + core::rect<s32> localClipRect = FrameRect; + localClipRect.clipAgainst(AbsoluteClippingRect); + + // draw the text + + IGUIFont* font = OverrideFont; + if (!OverrideFont) + font = skin->getFont(); + + s32 cursorLine = 0; + s32 charcursorpos = 0; + + if (font) + { + if (LastBreakFont != font) + { + breakText(); + } + + // calculate cursor pos + + core::stringw *txtLine = &Text; + s32 startPos = 0; + + core::stringw s, s2; + + // get mark position + const bool ml = (!PasswordBox && (WordWrap || MultiLine)); + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + const s32 hlineStart = ml ? getLineFromPos(realmbgn) : 0; + const s32 hlineCount = ml ? getLineFromPos(realmend) - hlineStart + 1 : 1; + const s32 lineCount = ml ? BrokenText.size() : 1; + + // Save the override color information. + // Then, alter it if the edit box is disabled. + const bool prevOver = OverrideColorEnabled; + const video::SColor prevColor = OverrideColor; + + if (Text.size()) + { + if (!IsEnabled && !OverrideColorEnabled) + { + OverrideColorEnabled = true; + OverrideColor = skin->getColor(EGDC_GRAY_TEXT); + } + + for (s32 i=0; i < lineCount; ++i) + { + setTextRect(i); + + // clipping test - don't draw anything outside the visible area + core::rect<s32> c = localClipRect; + c.clipAgainst(CurrentTextRect); + if (!c.isValid()) + continue; + + // get current line + if (PasswordBox) + { + if (BrokenText.size() != 1) + { + BrokenText.clear(); + BrokenText.push_back(core::stringw()); + } + if (BrokenText[0].size() != Text.size()) + { + BrokenText[0] = Text; + for (u32 q = 0; q < Text.size(); ++q) + { + BrokenText[0] [q] = PasswordChar; + } + } + txtLine = &BrokenText[0]; + startPos = 0; + } + else + { + txtLine = ml ? &BrokenText[i] : &Text; + startPos = ml ? BrokenTextPositions[i] : 0; + } + + + // draw normal text + font->draw(txtLine->c_str(), CurrentTextRect, + OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), + false, true, &localClipRect); + + // draw mark and marked text + if (focus && MarkBegin != MarkEnd && i >= hlineStart && i < hlineStart + hlineCount) + { + + s32 mbegin = 0, mend = 0; + s32 lineStartPos = 0, lineEndPos = txtLine->size(); + + if (i == hlineStart) + { + // highlight start is on this line + s = txtLine->subString(0, realmbgn - startPos); + mbegin = font->getDimension(s.c_str()).Width; + + // deal with kerning + mbegin += font->getKerningWidth( + &((*txtLine)[realmbgn - startPos]), + realmbgn - startPos > 0 ? &((*txtLine)[realmbgn - startPos - 1]) : 0); + + lineStartPos = realmbgn - startPos; + } + if (i == hlineStart + hlineCount - 1) + { + // highlight end is on this line + s2 = txtLine->subString(0, realmend - startPos); + mend = font->getDimension(s2.c_str()).Width; + lineEndPos = (s32)s2.size(); + } + else + mend = font->getDimension(txtLine->c_str()).Width; + + CurrentTextRect.UpperLeftCorner.X += mbegin; + CurrentTextRect.LowerRightCorner.X = CurrentTextRect.UpperLeftCorner.X + mend - mbegin; + + // draw mark + skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), CurrentTextRect, &localClipRect); + + // draw marked text + s = txtLine->subString(lineStartPos, lineEndPos - lineStartPos); + + if (s.size()) + font->draw(s.c_str(), CurrentTextRect, + OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_HIGH_LIGHT_TEXT), + false, true, &localClipRect); + + } + } + + // Return the override color information to its previous settings. + OverrideColorEnabled = prevOver; + OverrideColor = prevColor; + } + + // draw cursor + + if (WordWrap || MultiLine) + { + cursorLine = getLineFromPos(CursorPos); + txtLine = &BrokenText[cursorLine]; + startPos = BrokenTextPositions[cursorLine]; + } + s = txtLine->subString(0,CursorPos-startPos); + charcursorpos = font->getDimension(s.c_str()).Width + + font->getKerningWidth(L"_", CursorPos-startPos > 0 ? &((*txtLine)[CursorPos-startPos-1]) : 0); + + if (focus && (porting::getTimeMs() - BlinkStartTime) % 700 < 350) + { + setTextRect(cursorLine); + CurrentTextRect.UpperLeftCorner.X += charcursorpos; + + font->draw(L"_", CurrentTextRect, + OverrideColorEnabled ? OverrideColor : skin->getColor(EGDC_BUTTON_TEXT), + false, true, &localClipRect); + } + } + + // draw children + IGUIElement::draw(); +} + + +//! Sets the new caption of this element. +void intlGUIEditBox::setText(const wchar_t* text) +{ + Text = text; + if (u32(CursorPos) > Text.size()) + CursorPos = Text.size(); + HScrollPos = 0; + breakText(); +} + + +//! Enables or disables automatic scrolling with cursor position +//! \param enable: If set to true, the text will move around with the cursor position +void intlGUIEditBox::setAutoScroll(bool enable) +{ + AutoScroll = enable; +} + + +//! Checks to see if automatic scrolling is enabled +//! \return true if automatic scrolling is enabled, false if not +bool intlGUIEditBox::isAutoScrollEnabled() const +{ + _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX; + return AutoScroll; +} + + +//! Gets the area of the text in the edit box +//! \return Returns the size in pixels of the text +core::dimension2du intlGUIEditBox::getTextDimension() +{ + core::rect<s32> ret; + + setTextRect(0); + ret = CurrentTextRect; + + for (u32 i=1; i < BrokenText.size(); ++i) + { + setTextRect(i); + ret.addInternalPoint(CurrentTextRect.UpperLeftCorner); + ret.addInternalPoint(CurrentTextRect.LowerRightCorner); + } + + return core::dimension2du(ret.getSize()); +} + + +//! Sets the maximum amount of characters which may be entered in the box. +//! \param max: Maximum amount of characters. If 0, the character amount is +//! infinity. +void intlGUIEditBox::setMax(u32 max) +{ + Max = max; + + if (Text.size() > Max && Max != 0) + Text = Text.subString(0, Max); +} + + +//! Returns maximum amount of characters, previously set by setMax(); +u32 intlGUIEditBox::getMax() const +{ + return Max; +} + + +bool intlGUIEditBox::processMouse(const SEvent& event) +{ + switch(event.MouseInput.Event) + { + case irr::EMIE_LMOUSE_LEFT_UP: + if (Environment->hasFocus(this)) + { + CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); + if (MouseMarking) + { + setTextMarkers( MarkBegin, CursorPos ); + } + MouseMarking = false; + calculateScrollPos(); + return true; + } + break; + case irr::EMIE_MOUSE_MOVED: + { + if (MouseMarking) + { + CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); + setTextMarkers( MarkBegin, CursorPos ); + calculateScrollPos(); + return true; + } + } + break; + case EMIE_LMOUSE_PRESSED_DOWN: + if (!Environment->hasFocus(this)) + { + BlinkStartTime = porting::getTimeMs(); + MouseMarking = true; + CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); + setTextMarkers(CursorPos, CursorPos ); + calculateScrollPos(); + return true; + } + else + { + if (!AbsoluteClippingRect.isPointInside( + core::position2d<s32>(event.MouseInput.X, event.MouseInput.Y))) + { + return false; + } + else + { + // move cursor + CursorPos = getCursorPos(event.MouseInput.X, event.MouseInput.Y); + + s32 newMarkBegin = MarkBegin; + if (!MouseMarking) + newMarkBegin = CursorPos; + + MouseMarking = true; + setTextMarkers( newMarkBegin, CursorPos); + calculateScrollPos(); + return true; + } + } + default: + break; + } + + return false; +} + + +s32 intlGUIEditBox::getCursorPos(s32 x, s32 y) +{ + IGUIFont* font = OverrideFont; + IGUISkin* skin = Environment->getSkin(); + if (!OverrideFont) + font = skin->getFont(); + + const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; + + core::stringw *txtLine=0; + s32 startPos=0; + x+=3; + + for (u32 i=0; i < lineCount; ++i) + { + setTextRect(i); + if (i == 0 && y < CurrentTextRect.UpperLeftCorner.Y) + y = CurrentTextRect.UpperLeftCorner.Y; + if (i == lineCount - 1 && y > CurrentTextRect.LowerRightCorner.Y ) + y = CurrentTextRect.LowerRightCorner.Y; + + // is it inside this region? + if (y >= CurrentTextRect.UpperLeftCorner.Y && y <= CurrentTextRect.LowerRightCorner.Y) + { + // we've found the clicked line + txtLine = (WordWrap || MultiLine) ? &BrokenText[i] : &Text; + startPos = (WordWrap || MultiLine) ? BrokenTextPositions[i] : 0; + break; + } + } + + if (x < CurrentTextRect.UpperLeftCorner.X) + x = CurrentTextRect.UpperLeftCorner.X; + + s32 idx = font->getCharacterFromPos(Text.c_str(), x - CurrentTextRect.UpperLeftCorner.X); + + // click was on or left of the line + if (idx != -1) + return idx + startPos; + + // click was off the right edge of the line, go to end. + return txtLine->size() + startPos; +} + + +//! Breaks the single text line. +void intlGUIEditBox::breakText() +{ + IGUISkin* skin = Environment->getSkin(); + + if ((!WordWrap && !MultiLine) || !skin) + return; + + BrokenText.clear(); // need to reallocate :/ + BrokenTextPositions.set_used(0); + + IGUIFont* font = OverrideFont; + if (!OverrideFont) + font = skin->getFont(); + + if (!font) + return; + + LastBreakFont = font; + + core::stringw line; + core::stringw word; + core::stringw whitespace; + s32 lastLineStart = 0; + s32 size = Text.size(); + s32 length = 0; + s32 elWidth = RelativeRect.getWidth() - 6; + wchar_t c; + + for (s32 i=0; i<size; ++i) + { + c = Text[i]; + bool lineBreak = false; + + if (c == L'\r') // Mac or Windows breaks + { + lineBreak = true; + c = ' '; + if (Text[i+1] == L'\n') // Windows breaks + { + Text.erase(i+1); + --size; + } + } + else if (c == L'\n') // Unix breaks + { + lineBreak = true; + c = ' '; + } + + // don't break if we're not a multi-line edit box + if (!MultiLine) + lineBreak = false; + + if (c == L' ' || c == 0 || i == (size-1)) + { + if (word.size()) + { + // here comes the next whitespace, look if + // we can break the last word to the next line. + s32 whitelgth = font->getDimension(whitespace.c_str()).Width; + s32 worldlgth = font->getDimension(word.c_str()).Width; + + if (WordWrap && length + worldlgth + whitelgth > elWidth) + { + // break to next line + length = worldlgth; + BrokenText.push_back(line); + BrokenTextPositions.push_back(lastLineStart); + lastLineStart = i - (s32)word.size(); + line = word; + } + else + { + // add word to line + line += whitespace; + line += word; + length += whitelgth + worldlgth; + } + + word = L""; + whitespace = L""; + } + + whitespace += c; + + // compute line break + if (lineBreak) + { + line += whitespace; + line += word; + BrokenText.push_back(line); + BrokenTextPositions.push_back(lastLineStart); + lastLineStart = i+1; + line = L""; + word = L""; + whitespace = L""; + length = 0; + } + } + else + { + // yippee this is a word.. + word += c; + } + } + + line += whitespace; + line += word; + BrokenText.push_back(line); + BrokenTextPositions.push_back(lastLineStart); +} + + +void intlGUIEditBox::setTextRect(s32 line) +{ + core::dimension2du d; + + IGUISkin* skin = Environment->getSkin(); + if (!skin) + return; + + IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont(); + + if (!font) + return; + + // get text dimension + const u32 lineCount = (WordWrap || MultiLine) ? BrokenText.size() : 1; + if (WordWrap || MultiLine) + { + d = font->getDimension(BrokenText[line].c_str()); + } + else + { + d = font->getDimension(Text.c_str()); + d.Height = AbsoluteRect.getHeight(); + } + d.Height += font->getKerningHeight(); + + // justification + switch (HAlign) + { + case EGUIA_CENTER: + // align to h centre + CurrentTextRect.UpperLeftCorner.X = (FrameRect.getWidth()/2) - (d.Width/2); + CurrentTextRect.LowerRightCorner.X = (FrameRect.getWidth()/2) + (d.Width/2); + break; + case EGUIA_LOWERRIGHT: + // align to right edge + CurrentTextRect.UpperLeftCorner.X = FrameRect.getWidth() - d.Width; + CurrentTextRect.LowerRightCorner.X = FrameRect.getWidth(); + break; + default: + // align to left edge + CurrentTextRect.UpperLeftCorner.X = 0; + CurrentTextRect.LowerRightCorner.X = d.Width; + + } + + switch (VAlign) + { + case EGUIA_CENTER: + // align to v centre + CurrentTextRect.UpperLeftCorner.Y = + (FrameRect.getHeight()/2) - (lineCount*d.Height)/2 + d.Height*line; + break; + case EGUIA_LOWERRIGHT: + // align to bottom edge + CurrentTextRect.UpperLeftCorner.Y = + FrameRect.getHeight() - lineCount*d.Height + d.Height*line; + break; + default: + // align to top edge + CurrentTextRect.UpperLeftCorner.Y = d.Height*line; + break; + } + + CurrentTextRect.UpperLeftCorner.X -= HScrollPos; + CurrentTextRect.LowerRightCorner.X -= HScrollPos; + CurrentTextRect.UpperLeftCorner.Y -= VScrollPos; + CurrentTextRect.LowerRightCorner.Y = CurrentTextRect.UpperLeftCorner.Y + d.Height; + + CurrentTextRect += FrameRect.UpperLeftCorner; + +} + + +s32 intlGUIEditBox::getLineFromPos(s32 pos) +{ + if (!WordWrap && !MultiLine) + return 0; + + s32 i=0; + while (i < (s32)BrokenTextPositions.size()) + { + if (BrokenTextPositions[i] > pos) + return i-1; + ++i; + } + return (s32)BrokenTextPositions.size() - 1; +} + + +void intlGUIEditBox::inputChar(wchar_t c) +{ + if (!IsEnabled) + return; + + if (c != 0) + { + if (Text.size() < Max || Max == 0) + { + core::stringw s; + + if (MarkBegin != MarkEnd) + { + // replace marked text + const s32 realmbgn = MarkBegin < MarkEnd ? MarkBegin : MarkEnd; + const s32 realmend = MarkBegin < MarkEnd ? MarkEnd : MarkBegin; + + s = Text.subString(0, realmbgn); + s.append(c); + s.append( Text.subString(realmend, Text.size()-realmend) ); + Text = s; + CursorPos = realmbgn+1; + } + else + { + // add new character + s = Text.subString(0, CursorPos); + s.append(c); + s.append( Text.subString(CursorPos, Text.size()-CursorPos) ); + Text = s; + ++CursorPos; + } + + BlinkStartTime = porting::getTimeMs(); + setTextMarkers(0, 0); + } + } + breakText(); + sendGuiEvent(EGET_EDITBOX_CHANGED); + calculateScrollPos(); +} + + +void intlGUIEditBox::calculateScrollPos() +{ + if (!AutoScroll) + return; + + // calculate horizontal scroll position + s32 cursLine = getLineFromPos(CursorPos); + setTextRect(cursLine); + + // don't do horizontal scrolling when wordwrap is enabled. + if (!WordWrap) + { + // get cursor position + IGUISkin* skin = Environment->getSkin(); + if (!skin) + return; + IGUIFont* font = OverrideFont ? OverrideFont : skin->getFont(); + if (!font) + return; + + core::stringw *txtLine = MultiLine ? &BrokenText[cursLine] : &Text; + s32 cPos = MultiLine ? CursorPos - BrokenTextPositions[cursLine] : CursorPos; + + s32 cStart = CurrentTextRect.UpperLeftCorner.X + HScrollPos + + font->getDimension(txtLine->subString(0, cPos).c_str()).Width; + + s32 cEnd = cStart + font->getDimension(L"_ ").Width; + + if (FrameRect.LowerRightCorner.X < cEnd) + HScrollPos = cEnd - FrameRect.LowerRightCorner.X; + else if (FrameRect.UpperLeftCorner.X > cStart) + HScrollPos = cStart - FrameRect.UpperLeftCorner.X; + else + HScrollPos = 0; + + // todo: adjust scrollbar + } + + // vertical scroll position + if (FrameRect.LowerRightCorner.Y < CurrentTextRect.LowerRightCorner.Y + VScrollPos) + VScrollPos = CurrentTextRect.LowerRightCorner.Y - FrameRect.LowerRightCorner.Y + VScrollPos; + + else if (FrameRect.UpperLeftCorner.Y > CurrentTextRect.UpperLeftCorner.Y + VScrollPos) + VScrollPos = CurrentTextRect.UpperLeftCorner.Y - FrameRect.UpperLeftCorner.Y + VScrollPos; + else + VScrollPos = 0; + + // todo: adjust scrollbar +} + +//! set text markers +void intlGUIEditBox::setTextMarkers(s32 begin, s32 end) +{ + if ( begin != MarkBegin || end != MarkEnd ) + { + MarkBegin = begin; + MarkEnd = end; + sendGuiEvent(EGET_EDITBOX_MARKING_CHANGED); + } +} + +//! send some gui event to parent +void intlGUIEditBox::sendGuiEvent(EGUI_EVENT_TYPE type) +{ + if ( Parent ) + { + SEvent e; + e.EventType = EET_GUI_EVENT; + e.GUIEvent.Caller = this; + e.GUIEvent.Element = 0; + e.GUIEvent.EventType = type; + + Parent->OnEvent(e); + } +} + +//! Writes attributes of the element. +void intlGUIEditBox::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const +{ + // IGUIEditBox::serializeAttributes(out,options); + + out->addBool ("OverrideColorEnabled",OverrideColorEnabled ); + out->addColor ("OverrideColor", OverrideColor); + // out->addFont("OverrideFont",OverrideFont); + out->addInt ("MaxChars", Max); + out->addBool ("WordWrap", WordWrap); + out->addBool ("MultiLine", MultiLine); + out->addBool ("AutoScroll", AutoScroll); + out->addBool ("PasswordBox", PasswordBox); + core::stringw ch = L" "; + ch[0] = PasswordChar; + out->addString("PasswordChar", ch.c_str()); + out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); + out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); + + IGUIEditBox::serializeAttributes(out,options); +} + + +//! Reads attributes of the element +void intlGUIEditBox::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) +{ + IGUIEditBox::deserializeAttributes(in,options); + + setOverrideColor(in->getAttributeAsColor("OverrideColor")); + enableOverrideColor(in->getAttributeAsBool("OverrideColorEnabled")); + setMax(in->getAttributeAsInt("MaxChars")); + setWordWrap(in->getAttributeAsBool("WordWrap")); + setMultiLine(in->getAttributeAsBool("MultiLine")); + setAutoScroll(in->getAttributeAsBool("AutoScroll")); + core::stringw ch = in->getAttributeAsStringW("PasswordChar"); + + if (!ch.size()) + setPasswordBox(in->getAttributeAsBool("PasswordBox")); + else + setPasswordBox(in->getAttributeAsBool("PasswordBox"), ch[0]); + + setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), + (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); + + // setOverrideFont(in->getAttributeAsFont("OverrideFont")); +} + + +} // end namespace gui +} // end namespace irr + +#endif // _IRR_COMPILE_WITH_GUI_ diff --git a/src/intlGUIEditBox.h b/src/intlGUIEditBox.h new file mode 100644 index 000000000..f888fb620 --- /dev/null +++ b/src/intlGUIEditBox.h @@ -0,0 +1,178 @@ +// Copyright (C) 2002-2010 Nikolaus Gebhardt +// This file is part of the "Irrlicht Engine". +// For conditions of distribution and use, see copyright notice in irrlicht.h + +#ifndef __C_INTL_GUI_EDIT_BOX_H_INCLUDED__ +#define __C_INTL_GUI_EDIT_BOX_H_INCLUDED__ + +#include "IrrCompileConfig.h" +//#ifdef _IRR_COMPILE_WITH_GUI_ + +#include "IGUIEditBox.h" +#include "irrArray.h" +#include "IOSOperator.h" + +namespace irr +{ +namespace gui +{ + class intlGUIEditBox : public IGUIEditBox + { + public: + + //! constructor + intlGUIEditBox(const wchar_t* text, bool border, IGUIEnvironment* environment, + IGUIElement* parent, s32 id, const core::rect<s32>& rectangle); + + //! destructor + virtual ~intlGUIEditBox(); + + //! Sets another skin independent font. + virtual void setOverrideFont(IGUIFont* font=0); + + //! Gets the override font (if any) + /** \return The override font (may be 0) */ + virtual IGUIFont* getOverrideFont() const; + + //! Get the font which is used right now for drawing + /** Currently this is the override font when one is set and the + font of the active skin otherwise */ + virtual IGUIFont* getActiveFont() const; + + //! Sets another color for the text. + virtual void setOverrideColor(video::SColor color); + + //! Gets the override color + virtual video::SColor getOverrideColor() const; + + //! Sets if the text should use the overide color or the + //! color in the gui skin. + virtual void enableOverrideColor(bool enable); + + //! Checks if an override color is enabled + /** \return true if the override color is enabled, false otherwise */ + virtual bool isOverrideColorEnabled(void) const; + + //! Sets whether to draw the background + virtual void setDrawBackground(bool draw); + + //! Turns the border on or off + virtual void setDrawBorder(bool border); + + //! Enables or disables word wrap for using the edit box as multiline text editor. + virtual void setWordWrap(bool enable); + + //! Checks if word wrap is enabled + //! \return true if word wrap is enabled, false otherwise + virtual bool isWordWrapEnabled() const; + + //! Enables or disables newlines. + /** \param enable: If set to true, the EGET_EDITBOX_ENTER event will not be fired, + instead a newline character will be inserted. */ + virtual void setMultiLine(bool enable); + + //! Checks if multi line editing is enabled + //! \return true if mult-line is enabled, false otherwise + virtual bool isMultiLineEnabled() const; + + //! Enables or disables automatic scrolling with cursor position + //! \param enable: If set to true, the text will move around with the cursor position + virtual void setAutoScroll(bool enable); + + //! Checks to see if automatic scrolling is enabled + //! \return true if automatic scrolling is enabled, false if not + virtual bool isAutoScrollEnabled() const; + + //! Gets the size area of the text in the edit box + //! \return Returns the size in pixels of the text + virtual core::dimension2du getTextDimension(); + + //! Sets text justification + virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); + + //! called if an event happened. + virtual bool OnEvent(const SEvent& event); + + //! draws the element and its children + virtual void draw(); + + //! Sets the new caption of this element. + virtual void setText(const wchar_t* text); + + //! Sets the maximum amount of characters which may be entered in the box. + //! \param max: Maximum amount of characters. If 0, the character amount is + //! infinity. + virtual void setMax(u32 max); + + //! Returns maximum amount of characters, previously set by setMax(); + virtual u32 getMax() const; + + //! Sets whether the edit box is a password box. Setting this to true will + /** disable MultiLine, WordWrap and the ability to copy with ctrl+c or ctrl+x + \param passwordBox: true to enable password, false to disable + \param passwordChar: the character that is displayed instead of letters */ + virtual void setPasswordBox(bool passwordBox, wchar_t passwordChar = L'*'); + + //! Returns true if the edit box is currently a password box. + virtual bool isPasswordBox() const; + + //! Updates the absolute position, splits text if required + virtual void updateAbsolutePosition(); + + //! Writes attributes of the element. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; + + //! Reads attributes of the element + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); + + protected: + //! Breaks the single text line. + void breakText(); + //! sets the area of the given line + void setTextRect(s32 line); + //! returns the line number that the cursor is on + s32 getLineFromPos(s32 pos); + //! adds a letter to the edit box + void inputChar(wchar_t c); + //! calculates the current scroll position + void calculateScrollPos(); + //! send some gui event to parent + void sendGuiEvent(EGUI_EVENT_TYPE type); + //! set text markers + void setTextMarkers(s32 begin, s32 end); + + bool processKey(const SEvent& event); + bool processMouse(const SEvent& event); + s32 getCursorPos(s32 x, s32 y); + + bool MouseMarking; + bool Border; + bool OverrideColorEnabled; + s32 MarkBegin; + s32 MarkEnd; + + video::SColor OverrideColor; + gui::IGUIFont *OverrideFont, *LastBreakFont; + IOSOperator* Operator; + + u32 BlinkStartTime; + s32 CursorPos; + s32 HScrollPos, VScrollPos; // scroll position in characters + u32 Max; + + bool WordWrap, MultiLine, AutoScroll, PasswordBox; + wchar_t PasswordChar; + EGUI_ALIGNMENT HAlign, VAlign; + + core::array< core::stringw > BrokenText; + core::array< s32 > BrokenTextPositions; + + core::rect<s32> CurrentTextRect, FrameRect; // temporary values + }; + + +} // end namespace gui +} // end namespace irr + +//#endif // _IRR_COMPILE_WITH_GUI_ +#endif // __C_GUI_EDIT_BOX_H_INCLUDED__ diff --git a/src/localplayer.cpp b/src/localplayer.cpp index b6dd0f42e..8b6d7e2f6 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -90,37 +90,39 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, */ /* - Check if player is in water (the oscillating value) + Check if player is in liquid (the oscillating value) */ try{ - // If in water, the threshold of coming out is at higher y - if(in_water) + // If in liquid, the threshold of coming out is at higher y + if(in_liquid) { v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS); - in_water = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); + in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); + liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity; } - // If not in water, the threshold of going in is at lower y + // If not in liquid, the threshold of going in is at lower y else { v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS); - in_water = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); + in_liquid = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); + liquid_viscosity = nodemgr->get(map.getNode(pp).getContent()).liquid_viscosity; } } catch(InvalidPositionException &e) { - in_water = false; + in_liquid = false; } /* - Check if player is in water (the stable value) + Check if player is in liquid (the stable value) */ try{ v3s16 pp = floatToInt(position + v3f(0,0,0), BS); - in_water_stable = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); + in_liquid_stable = nodemgr->get(map.getNode(pp).getContent()).isLiquid(); } catch(InvalidPositionException &e) { - in_water_stable = false; + in_liquid_stable = false; } /* @@ -159,7 +161,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, If sneaking, keep in range from the last walked node and don't fall off from it */ - if(control.sneak && m_sneak_node_exists && !g_settings->getBool("free_move")) + if(control.sneak && m_sneak_node_exists && !(fly_allowed && g_settings->getBool("free_move")) && !in_liquid) { f32 maxd = 0.5*BS + sneak_max; v3f lwn_f = intToFloat(m_sneak_node, BS); @@ -315,7 +317,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, } if(bouncy_jump && control.jump){ - m_speed.Y += 6.5*BS; + m_speed.Y += movement_speed_jump*BS; touching_ground = false; MtEvent *e = new SimpleTriggerEvent("PlayerJump"); m_gamedef->event()->put(e); @@ -348,7 +350,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, */ const ContentFeatures &f = nodemgr->get(map.getNodeNoEx(getStandingNodePos())); // Determine if jumping is possible - m_can_jump = touching_ground; + m_can_jump = touching_ground && !in_liquid; if(itemgroup_get(f.groups, "disable_jump")) m_can_jump = false; } @@ -361,12 +363,8 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d) void LocalPlayer::applyControl(float dtime) { // Clear stuff - swimming_up = false; + swimming_vertical = false; - // Random constants - f32 walk_acceleration = 4.0 * BS; - f32 walkspeed_max = 4.0 * BS; - setPitch(control.pitch); setYaw(control.yaw); @@ -380,22 +378,17 @@ void LocalPlayer::applyControl(float dtime) v3f move_direction = v3f(0,0,1); move_direction.rotateXZBy(getYaw()); - v3f speed = v3f(0,0,0); + v3f speedH = v3f(0,0,0); // Horizontal (X, Z) + v3f speedV = v3f(0,0,0); // Vertical (Y) bool fly_allowed = m_gamedef->checkLocalPrivilege("fly"); bool fast_allowed = m_gamedef->checkLocalPrivilege("fast"); bool free_move = fly_allowed && g_settings->getBool("free_move"); bool fast_move = fast_allowed && g_settings->getBool("fast_move"); + bool fast_or_aux1_descends = (fast_move && control.aux1) || (fast_move && g_settings->getBool("aux1_descends")); bool continuous_forward = g_settings->getBool("continuous_forward"); - if(free_move || is_climbing) - { - v3f speed = getSpeed(); - speed.Y = 0; - setSpeed(speed); - } - // Whether superspeed mode is used or not bool superspeed = false; @@ -415,18 +408,21 @@ void LocalPlayer::applyControl(float dtime) if(free_move) { // In free movement mode, aux1 descends - v3f speed = getSpeed(); if(fast_move) - speed.Y = -20*BS; + speedV.Y = -movement_speed_fast; else - speed.Y = -walkspeed_max; - setSpeed(speed); + speedV.Y = -movement_speed_walk; + } + else if(in_liquid || in_liquid_stable) + { + // Always use fast when aux1_descends & fast_move are enabled in liquid, since the aux1 button would mean both turbo and "swim down" causing a conflict + speedV.Y = -movement_speed_fast; + swimming_vertical = true; } else if(is_climbing) { - v3f speed = getSpeed(); - speed.Y = -3*BS; - setSpeed(speed); + // Always use fast when aux1_descends & fast_move are enabled when climbing, since the aux1 button would mean both turbo and "descend" causing a conflict + speedV.Y = -movement_speed_fast; } else { @@ -456,66 +452,69 @@ void LocalPlayer::applyControl(float dtime) if(free_move) { // In free movement mode, sneak descends - v3f speed = getSpeed(); - if(fast_move && (control.aux1 || - g_settings->getBool("always_fly_fast"))) - speed.Y = -20*BS; + if(fast_move && (control.aux1 || g_settings->getBool("always_fly_fast"))) + speedV.Y = -movement_speed_fast; else - speed.Y = -walkspeed_max; - setSpeed(speed); + speedV.Y = -movement_speed_walk; + } + else if(in_liquid || in_liquid_stable) + { + if(fast_or_aux1_descends) + // Always use fast when aux1_descends & fast_move are enabled in liquid, since the aux1 button would mean both turbo and "swim down" causing a conflict + speedV.Y = -movement_speed_fast; + else + speedV.Y = -movement_speed_walk; + swimming_vertical = true; } else if(is_climbing) { - v3f speed = getSpeed(); - speed.Y = -3*BS; - setSpeed(speed); + if(fast_or_aux1_descends) + // Always use fast when aux1_descends & fast_move are enabled when climbing, since the aux1 button would mean both turbo and "descend" causing a conflict + speedV.Y = -movement_speed_fast; + else + speedV.Y = -movement_speed_climb; } } } if(continuous_forward) - speed += move_direction; + speedH += move_direction; if(control.up) { if(continuous_forward) superspeed = true; else - speed += move_direction; + speedH += move_direction; } if(control.down) { - speed -= move_direction; + speedH -= move_direction; } if(control.left) { - speed += move_direction.crossProduct(v3f(0,1,0)); + speedH += move_direction.crossProduct(v3f(0,1,0)); } if(control.right) { - speed += move_direction.crossProduct(v3f(0,-1,0)); + speedH += move_direction.crossProduct(v3f(0,-1,0)); } if(control.jump) { if(free_move) - { - v3f speed = getSpeed(); - - if(g_settings->getBool("aux1_descends") || - g_settings->getBool("always_fly_fast")) + { + if(g_settings->getBool("aux1_descends") || g_settings->getBool("always_fly_fast")) { if(fast_move) - speed.Y = 20*BS; + speedV.Y = movement_speed_fast; else - speed.Y = walkspeed_max; + speedV.Y = movement_speed_walk; } else { if(fast_move && control.aux1) - speed.Y = 20*BS; + speedV.Y = movement_speed_fast; else - speed.Y = walkspeed_max; + speedV.Y = movement_speed_walk; } - - setSpeed(speed); } else if(m_can_jump) { @@ -524,49 +523,66 @@ void LocalPlayer::applyControl(float dtime) raising the height at which the jump speed is kept at its starting value */ - v3f speed = getSpeed(); - if(speed.Y >= -0.5*BS) + v3f speedJ = getSpeed(); + if(speedJ.Y >= -0.5 * BS) { - speed.Y = 6.5*BS; - setSpeed(speed); + speedJ.Y = movement_speed_jump; + setSpeed(speedJ); MtEvent *e = new SimpleTriggerEvent("PlayerJump"); m_gamedef->event()->put(e); } } - // Use the oscillating value for getting out of water - // (so that the player doesn't fly on the surface) - else if(in_water) + else if(in_liquid) { - v3f speed = getSpeed(); - speed.Y = 1.5*BS; - setSpeed(speed); - swimming_up = true; + if(fast_or_aux1_descends) + // Always use fast when aux1_descends & fast_move are enabled in liquid, since the aux1 button would mean both turbo and "swim down" causing a conflict + speedV.Y = movement_speed_fast; + else + speedV.Y = movement_speed_walk; + swimming_vertical = true; } else if(is_climbing) { - v3f speed = getSpeed(); - speed.Y = 3*BS; - setSpeed(speed); + if(fast_or_aux1_descends) + // Always use fast when aux1_descends & fast_move are enabled when climbing, since the aux1 button would mean both turbo and "descend" causing a conflict + speedV.Y = movement_speed_fast; + else + speedV.Y = movement_speed_climb; } } // The speed of the player (Y is ignored) - if(superspeed) - speed = speed.normalize() * walkspeed_max * 5.0; - else if(control.sneak && !free_move) - speed = speed.normalize() * walkspeed_max / 3.0; + if(superspeed || (is_climbing && fast_or_aux1_descends) || ((in_liquid || in_liquid_stable) && fast_or_aux1_descends)) + speedH = speedH.normalize() * movement_speed_fast; + else if(control.sneak && !free_move && !in_liquid && !in_liquid_stable) + speedH = speedH.normalize() * movement_speed_crouch; else - speed = speed.normalize() * walkspeed_max; - - f32 inc = walk_acceleration * BS * dtime; - - // Faster acceleration if fast and free movement - if(free_move && fast_move && superspeed) - inc = walk_acceleration * BS * dtime * 10; - + speedH = speedH.normalize() * movement_speed_walk; + + // Acceleration increase + f32 incH = 0; // Horizontal (X, Z) + f32 incV = 0; // Vertical (Y) + if((!touching_ground && !free_move && !is_climbing && !in_liquid) || (!free_move && m_can_jump && control.jump)) + { + // Jumping and falling + if(superspeed || (fast_move && control.aux1)) + incH = movement_acceleration_fast * BS * dtime; + else + incH = movement_acceleration_air * BS * dtime; + incV = 0; // No vertical acceleration in air + } + else if(superspeed || (fast_move && control.aux1)) + incH = incV = movement_acceleration_fast * BS * dtime; + else if ((in_liquid || in_liquid_stable) && fast_or_aux1_descends) + // Always use fast when aux1_descends & fast_move are enabled in liquid, since the aux1 button would mean both turbo and "swim down" causing a conflict + incH = incV = movement_acceleration_fast * BS * dtime; + else + incH = incV = movement_acceleration_default * BS * dtime; + // Accelerate to target speed with maximum increment - accelerate(speed, inc); + accelerateHorizontal(speedH, incH); + accelerateVertical(speedV, incV); } v3s16 LocalPlayer::getStandingNodePos() diff --git a/src/main.cpp b/src/main.cpp index 6f4095148..968dc8d60 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -68,6 +68,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "profiler.h" #include "log.h" #include "mods.h" +#if USE_FREETYPE +#include "xCGUITTFont.h" +#endif #include "util/string.h" #include "subgame.h" #include "quicktune.h" @@ -767,11 +770,19 @@ int main(int argc, char *argv[]) log_register_thread("main"); - // Set locale. This is for forcing '.' as the decimal point. - std::locale::global(std::locale("C")); - // This enables printing all characters in bitmap font - setlocale(LC_CTYPE, "en_US"); + // This enables internatonal characters input + if( setlocale(LC_ALL, "") == NULL ) + { + fprintf( stderr, "%s: warning: could not set default locale\n", argv[0] ); + } + // Set locale. This is for forcing '.' as the decimal point. + try { + std::locale::global(std::locale(std::locale(""), "C", std::locale::numeric)); + setlocale(LC_NUMERIC, "C"); + } catch (const std::exception& ex) { + errorstream<<"Could not set numeric locale to C"<<std::endl; + } /* Parse command line */ @@ -875,7 +886,7 @@ int main(int argc, char *argv[]) // Create user data directory fs::CreateDir(porting::path_user); - init_gettext((porting::path_share+DIR_DELIM+".."+DIR_DELIM+"locale").c_str()); + init_gettext((porting::path_share + DIR_DELIM + "locale").c_str()); // Initialize debug streams #define DEBUGFILE "debug.txt" @@ -1329,7 +1340,13 @@ int main(int argc, char *argv[]) guienv = device->getGUIEnvironment(); gui::IGUISkin* skin = guienv->getSkin(); + #if USE_FREETYPE + std::string font_path = g_settings->get("font_path"); + u16 font_size = g_settings->getU16("font_size"); + gui::IGUIFont *font = gui::CGUITTFont::createTTFont(guienv, font_path.c_str(), font_size); + #else gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str()); + #endif if(font) skin->setFont(font); else diff --git a/src/map.cpp b/src/map.cpp index ea82194b8..717b0cf9b 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2013,10 +2013,10 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emer if (g_settings->get("fixed_map_seed").empty()) { - m_seed = (((u64)(myrand()%0xffff)<<0) - + ((u64)(myrand()%0xffff)<<16) - + ((u64)(myrand()%0xffff)<<32) - + ((u64)(myrand()&0xffff)<<48)); + m_seed = (((u64)(myrand() & 0xffff) << 0) + | ((u64)(myrand() & 0xffff) << 16) + | ((u64)(myrand() & 0xffff) << 32) + | ((u64)(myrand() & 0xffff) << 48)); m_mgparams->seed = m_seed; } @@ -3078,14 +3078,7 @@ void ServerMap::saveMapMeta() Settings params; - params.set("mg_name", m_emerge->params->mg_name); - params.setU64("seed", m_emerge->params->seed); - params.setS16("water_level", m_emerge->params->water_level); - params.setS16("chunksize", m_emerge->params->chunksize); - params.setS32("mg_flags", m_emerge->params->flags); - - m_emerge->params->writeParams(¶ms); - + m_emerge->setParamsToSettings(¶ms); params.writeLines(os); os<<"[end_of_params]\n"; diff --git a/src/mapgen.cpp b/src/mapgen.cpp index f2745bdb4..b19073e90 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -35,6 +35,15 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "treegen.h" #include "mapgen_v6.h" +FlagDesc flagdesc_mapgen[] = { + {"trees", MG_TREES}, + {"caves", MG_CAVES}, + {"dungeons", MG_DUNGEONS}, + {"v6_forests", MGV6_FORESTS}, + {"v6_biome_blend", MGV6_BIOME_BLEND}, + {"flat", MG_FLAT}, + {NULL, 0} +}; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// Emerge Manager //////////////////////////////// @@ -149,7 +158,7 @@ MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) { mgparams->seed = settings->getU64(settings == g_settings ? "fixed_map_seed" : "seed"); mgparams->water_level = settings->getS16("water_level"); mgparams->chunksize = settings->getS16("chunksize"); - mgparams->flags = settings->getS32("mg_flags"); + mgparams->flags = settings->getFlagStr("mg_flags", flagdesc_mapgen); if (!mgparams->readParams(settings)) { delete mgparams; @@ -159,7 +168,18 @@ MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) { } -bool EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { +void EmergeManager::setParamsToSettings(Settings *settings) { + settings->set("mg_name", params->mg_name); + settings->setU64("seed", params->seed); + settings->setS16("water_level", params->water_level); + settings->setS16("chunksize", params->chunksize); + settings->setFlagStr("mg_flags", params->flags, flagdesc_mapgen); + + params->writeParams(settings); +} + + +void EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { mglist.insert(std::make_pair(mgname, mgfactory)); infostream << "EmergeManager: registered mapgen " << mgname << std::endl; } diff --git a/src/mapgen.h b/src/mapgen.h index 728290ffc..4f1ab4ebd 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MG_DUNGEONS 0x04 #define MGV6_FORESTS 0x08 #define MGV6_BIOME_BLEND 0x10 +#define MG_FLAT 0x20 class BiomeDefManager; class Biome; @@ -121,8 +122,9 @@ public: Mapgen *getMapgen(); void addBlockToQueue(); - bool registerMapgen(std::string name, MapgenFactory *mgfactory); + void registerMapgen(std::string name, MapgenFactory *mgfactory); MapgenParams *getParamsFromSettings(Settings *settings); + void setParamsToSettings(Settings *settings); //mapgen helper methods Biome *getBiomeAtPoint(v3s16 p); diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index 30df1673c..3a5e10930 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -278,6 +278,9 @@ bool MapgenV6::block_is_underground(u64 seed, v3s16 blockpos) double MapgenV6::base_rock_level_2d(u64 seed, v2s16 p) { + if (flags & MG_FLAT) + return water_level; + int index = (p.Y - node_min.Z) * ystride + (p.X - node_min.X); // The base ground level @@ -333,6 +336,9 @@ double MapgenV6::base_rock_level_2d(u64 seed, v2s16 p) } double MapgenV6::baseRockLevelFromNoise(v2s16 p) { + if (flags & MG_FLAT) + return water_level; + double base = water_level + NoisePerlin2DPosOffset(noise_terrain_base->np, p.X, 0.5, p.Y, 0.5, seed); double higher = water_level + @@ -370,6 +376,9 @@ s16 MapgenV6::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) double MapgenV6::get_mud_add_amount(u64 seed, v2s16 p) { + if (flags & MG_FLAT) + return AVERAGE_MUD_AMOUNT; + /*return ((float)AVERAGE_MUD_AMOUNT + 2.0 * noise2d_perlin( 0.5+(float)p.X/200, 0.5+(float)p.Y/200, seed+91013, 3, 0.55));*/ @@ -491,34 +500,37 @@ void MapgenV6::makeChunk(BlockMakeData *data) int z = node_min.Z; // Need to adjust for the original implementation's +.5 offset... - noise_terrain_base->perlinMap2D( - x + 0.5 * noise_terrain_base->np->spread.X, - z + 0.5 * noise_terrain_base->np->spread.Z); - noise_terrain_base->transformNoiseMap(); - - noise_terrain_higher->perlinMap2D( - x + 0.5 * noise_terrain_higher->np->spread.X, - z + 0.5 * noise_terrain_higher->np->spread.Z); - noise_terrain_higher->transformNoiseMap(); - - noise_steepness->perlinMap2D( - x + 0.5 * noise_steepness->np->spread.X, - z + 0.5 * noise_steepness->np->spread.Z); - noise_steepness->transformNoiseMap(); - - noise_height_select->perlinMap2D( - x + 0.5 * noise_height_select->np->spread.X, - z + 0.5 * noise_height_select->np->spread.Z); - + if (!(flags & MG_FLAT)) { + noise_terrain_base->perlinMap2D( + x + 0.5 * noise_terrain_base->np->spread.X, + z + 0.5 * noise_terrain_base->np->spread.Z); + noise_terrain_base->transformNoiseMap(); + + noise_terrain_higher->perlinMap2D( + x + 0.5 * noise_terrain_higher->np->spread.X, + z + 0.5 * noise_terrain_higher->np->spread.Z); + noise_terrain_higher->transformNoiseMap(); + + noise_steepness->perlinMap2D( + x + 0.5 * noise_steepness->np->spread.X, + z + 0.5 * noise_steepness->np->spread.Z); + noise_steepness->transformNoiseMap(); + + noise_height_select->perlinMap2D( + x + 0.5 * noise_height_select->np->spread.X, + z + 0.5 * noise_height_select->np->spread.Z); + } + noise_trees->perlinMap2D( x + 0.5 * noise_trees->np->spread.X, z + 0.5 * noise_trees->np->spread.Z); - - noise_mud->perlinMap2D( - x + 0.5 * noise_mud->np->spread.X, - z + 0.5 * noise_mud->np->spread.Z); - noise_mud->transformNoiseMap(); - + + if (!(flags & MG_FLAT)) { + noise_mud->perlinMap2D( + x + 0.5 * noise_mud->np->spread.X, + z + 0.5 * noise_mud->np->spread.Z); + noise_mud->transformNoiseMap(); + } noise_beach->perlinMap2D( x + 0.2 * noise_beach->np->spread.X, z + 0.7 * noise_beach->np->spread.Z); diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 560c6090d..729c69c92 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -604,9 +604,12 @@ public: } } break; + case NDT_PLANTLIKE: + f->solidness = 0; + f->backface_culling = false; + break; case NDT_TORCHLIKE: case NDT_SIGNLIKE: - case NDT_PLANTLIKE: case NDT_FENCELIKE: case NDT_RAILLIKE: case NDT_NODEBOX: diff --git a/src/noise.cpp b/src/noise.cpp index de9d48808..bfb1960c8 100644 --- a/src/noise.cpp +++ b/src/noise.cpp @@ -367,6 +367,7 @@ void Noise::resizeNoiseBuf(bool is3d) { * values from the previous noise lattice as midpoints in the new lattice for the * next octave. */ +#define idx(x, y) ((y) * nlx + (x)) void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed) { float v00, v01, v10, v11, u, v, orig_u; int index, i, j, x0, y0, noisex, noisey; @@ -387,25 +388,26 @@ void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed noisebuf[index++] = noise2d(x0 + i, y0 + j, seed); //calculate interpolations + index = 0; noisey = 0; for (j = 0; j != sy; j++) { - v00 = noisebuf[noisey * nlx]; - v10 = noisebuf[noisey * nlx + 1]; - v01 = noisebuf[(noisey + 1) * nlx]; - v11 = noisebuf[(noisey + 1) * nlx + 1]; + v00 = noisebuf[idx(0, noisey)]; + v10 = noisebuf[idx(1, noisey)]; + v01 = noisebuf[idx(0, noisey + 1)]; + v11 = noisebuf[idx(1, noisey + 1)]; u = orig_u; noisex = 0; for (i = 0; i != sx; i++) { - buf[j * sx + i] = biLinearInterpolation(v00, v10, v01, v11, u, v); + buf[index++] = biLinearInterpolation(v00, v10, v01, v11, u, v); u += step_x; if (u >= 1.0) { u -= 1.0; noisex++; v00 = v10; v01 = v11; - v10 = noisebuf[noisey * nlx + noisex + 1]; - v11 = noisebuf[(noisey + 1) * nlx + noisex + 1]; + v10 = noisebuf[idx(noisex + 1, noisey)]; + v11 = noisebuf[idx(noisex + 1, noisey + 1)]; } } @@ -416,14 +418,16 @@ void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed } } } +#undef idx +#define idx(x, y, z) ((z) * nly * nlx + (y) * nlx + (x)) void Noise::gradientMap3D(float x, float y, float z, float step_x, float step_y, float step_z, int seed) { float v000, v010, v100, v110; float v001, v011, v101, v111; - float u, v, w, orig_u, orig_w; + float u, v, w, orig_u, orig_v; int index, i, j, k, x0, y0, z0, noisex, noisey, noisez; int nlx, nly, nlz; @@ -434,49 +438,39 @@ void Noise::gradientMap3D(float x, float y, float z, v = y - (float)y0; w = z - (float)z0; orig_u = u; - orig_w = w; + orig_v = v; //calculate noise point lattice nlx = (int)(u + sx * step_x) + 2; nly = (int)(v + sy * step_y) + 2; - nlz = (int)(v + sy * step_z) + 2; + nlz = (int)(w + sz * step_z) + 2; index = 0; for (k = 0; k != nlz; k++) for (j = 0; j != nly; j++) for (i = 0; i != nlx; i++) noisebuf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed); -#define index(x, y, z) ((z) * nly * nlx + (y) * nlx + (x)) - //calculate interpolations + index = 0; noisey = 0; noisez = 0; for (k = 0; k != sz; k++) { - v000 = noisebuf[index(0, noisey, noisez)]; - v100 = noisebuf[index(1, noisey, noisez)]; - v010 = noisebuf[index(0, noisey + 1, noisez)]; - v110 = noisebuf[index(1, noisey + 1, noisez)]; - v001 = noisebuf[index(0, noisey, noisez + 1)]; - v101 = noisebuf[index(1, noisey, noisez + 1)]; - v011 = noisebuf[index(0, noisey + 1, noisez + 1)]; - v111 = noisebuf[index(1, noisey + 1, noisez + 1)]; - - w = orig_w; + v = orig_v; noisey = 0; for (j = 0; j != sy; j++) { - v000 = noisebuf[index(0, noisey, noisez)]; - v100 = noisebuf[index(1, noisey, noisez)]; - v010 = noisebuf[index(0, noisey + 1, noisez)]; - v110 = noisebuf[index(1, noisey + 1, noisez)]; - v001 = noisebuf[index(0, noisey, noisez + 1)]; - v101 = noisebuf[index(1, noisey, noisez + 1)]; - v011 = noisebuf[index(0, noisey + 1, noisez + 1)]; - v111 = noisebuf[index(1, noisey + 1, noisez + 1)]; + v000 = noisebuf[idx(0, noisey, noisez)]; + v100 = noisebuf[idx(1, noisey, noisez)]; + v010 = noisebuf[idx(0, noisey + 1, noisez)]; + v110 = noisebuf[idx(1, noisey + 1, noisez)]; + v001 = noisebuf[idx(0, noisey, noisez + 1)]; + v101 = noisebuf[idx(1, noisey, noisez + 1)]; + v011 = noisebuf[idx(0, noisey + 1, noisez + 1)]; + v111 = noisebuf[idx(1, noisey + 1, noisez + 1)]; u = orig_u; noisex = 0; for (i = 0; i != sx; i++) { - buf[j * sx + i] = triLinearInterpolation( + buf[index++] = triLinearInterpolation( v000, v100, v010, v110, v001, v101, v011, v111, u, v, w); @@ -486,12 +480,12 @@ void Noise::gradientMap3D(float x, float y, float z, noisex++; v000 = v100; v010 = v110; - v100 = noisebuf[index(noisex + 1, noisey, noisez)]; - v110 = noisebuf[index(noisex + 1, noisey + 1, noisez)]; + v100 = noisebuf[idx(noisex + 1, noisey, noisez)]; + v110 = noisebuf[idx(noisex + 1, noisey + 1, noisez)]; v001 = v101; v011 = v111; - v101 = noisebuf[index(noisex + 1, noisey, noisez + 1)]; - v111 = noisebuf[index(noisex + 1, noisey + 1, noisez + 1)]; + v101 = noisebuf[idx(noisex + 1, noisey, noisez + 1)]; + v111 = noisebuf[idx(noisex + 1, noisey + 1, noisez + 1)]; } } @@ -509,6 +503,7 @@ void Noise::gradientMap3D(float x, float y, float z, } } } +#undef idx float *Noise::perlinMap2D(float x, float y) { diff --git a/src/player.cpp b/src/player.cpp index 36f12c77b..86d3ae184 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -27,10 +27,11 @@ with this program; if not, write to the Free Software Foundation, Inc., Player::Player(IGameDef *gamedef): touching_ground(false), - in_water(false), - in_water_stable(false), + in_liquid(false), + in_liquid_stable(false), + liquid_viscosity(0), is_climbing(false), - swimming_up(false), + swimming_vertical(false), camera_barely_in_ceiling(false), inventory(gamedef->idef()), hp(PLAYER_MAX_HP), @@ -56,19 +57,35 @@ Player::Player(IGameDef *gamedef): "list[current_player;main;0,3.5;8,4;]" "list[current_player;craft;3,0;3,3;]" "list[current_player;craftpreview;7,1;1,1;]"; + + // Initialize movement settings at default values, so movement can work if the server fails to send them + movement_acceleration_default = 3 * BS; + movement_acceleration_air = 2 * BS; + movement_acceleration_fast = 10 * BS; + movement_speed_walk = 4 * BS; + movement_speed_crouch = 1.35 * BS; + movement_speed_fast = 20 * BS; + movement_speed_climb = 2 * BS; + movement_speed_jump = 6.5 * BS; + movement_liquid_fluidity = 1 * BS; + movement_liquid_fluidity_smooth = 0.5 * BS; + movement_liquid_sink = 10 * BS; + movement_gravity = 9.81 * BS; } Player::~Player() { } -// Y direction is ignored -void Player::accelerate(v3f target_speed, f32 max_increase) +// Horizontal acceleration (X and Z), Y direction is ignored +void Player::accelerateHorizontal(v3f target_speed, f32 max_increase) { + if(max_increase == 0) + return; + v3f d_wanted = target_speed - m_speed; d_wanted.Y = 0; - f32 dl_wanted = d_wanted.getLength(); - f32 dl = dl_wanted; + f32 dl = d_wanted.getLength(); if(dl > max_increase) dl = max_increase; @@ -76,7 +93,6 @@ void Player::accelerate(v3f target_speed, f32 max_increase) m_speed.X += d.X; m_speed.Z += d.Z; - //m_speed += d; #if 0 // old code if(m_speed.X < target_speed.X - max_increase) @@ -99,6 +115,32 @@ void Player::accelerate(v3f target_speed, f32 max_increase) #endif } +// Vertical acceleration (Y), X and Z directions are ignored +void Player::accelerateVertical(v3f target_speed, f32 max_increase) +{ + if(max_increase == 0) + return; + + f32 d_wanted = target_speed.Y - m_speed.Y; + if(d_wanted > max_increase) + d_wanted = max_increase; + else if(d_wanted < -max_increase) + d_wanted = -max_increase; + + m_speed.Y += d_wanted; + +#if 0 // old code + if(m_speed.Y < target_speed.Y - max_increase) + m_speed.Y += max_increase; + else if(m_speed.Y > target_speed.Y + max_increase) + m_speed.Y -= max_increase; + else if(m_speed.Y < target_speed.Y) + m_speed.Y = target_speed.Y; + else if(m_speed.Y > target_speed.Y) + m_speed.Y = target_speed.Y; +#endif +} + v3s16 Player::getLightPosition() const { return floatToInt(m_position + v3f(0,BS+BS/2,0), BS); diff --git a/src/player.h b/src/player.h index 67b02c344..770afdb37 100644 --- a/src/player.h +++ b/src/player.h @@ -108,8 +108,8 @@ public: m_speed = speed; } - // Y direction is ignored - void accelerate(v3f target_speed, f32 max_increase); + void accelerateHorizontal(v3f target_speed, f32 max_increase); + void accelerateVertical(v3f target_speed, f32 max_increase); v3f getPosition() { @@ -196,17 +196,32 @@ public: bool touching_ground; // This oscillates so that the player jumps a bit above the surface - bool in_water; + bool in_liquid; // This is more stable and defines the maximum speed of the player - bool in_water_stable; + bool in_liquid_stable; + // Gets the viscosity of water to calculate friction + u8 liquid_viscosity; bool is_climbing; - bool swimming_up; + bool swimming_vertical; bool camera_barely_in_ceiling; u8 light; Inventory inventory; + f32 movement_acceleration_default; + f32 movement_acceleration_air; + f32 movement_acceleration_fast; + f32 movement_speed_walk; + f32 movement_speed_crouch; + f32 movement_speed_fast; + f32 movement_speed_climb; + f32 movement_speed_jump; + f32 movement_liquid_fluidity; + f32 movement_liquid_fluidity_smooth; + f32 movement_liquid_sink; + f32 movement_gravity; + u16 hp; float hurt_tilt_timer; diff --git a/src/porting.cpp b/src/porting.cpp index de15de9ce..f8a2cca5c 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -220,7 +220,7 @@ void initializePaths() //TODO: Test this code char buf[BUFSIZ]; uint32_t len = sizeof(buf); - assert(_NSGetExecutablePath(buf, &len) != 0); + assert(_NSGetExecutablePath(buf, &len) != -1); pathRemoveFile(buf, '/'); diff --git a/src/porting.h b/src/porting.h index c8d19154c..9ba3394bb 100644 --- a/src/porting.h +++ b/src/porting.h @@ -56,6 +56,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define strtof(x, y) (float)strtod(x, y) #define strtoll(x, y, z) _strtoi64(x, y, z) #define strtoull(x, y, z) _strtoui64(x, y, z) + #define strcasecmp(x, y) stricmp(x, y) #else #define ALIGNOF(x) __alignof__(x) #endif diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 6e2a0a314..020709cab 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -694,6 +694,30 @@ static NodeBox read_nodebox(lua_State *L, int index) } /* + NoiseParams +*/ +static NoiseParams *read_noiseparams(lua_State *L, int index) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; + + if (!lua_istable(L, index)) + return NULL; + + NoiseParams *np = new NoiseParams; + + np->offset = getfloatfield_default(L, index, "offset", 0.0); + np->scale = getfloatfield_default(L, index, "scale", 0.0); + lua_getfield(L, index, "spread"); + np->spread = read_v3f(L, -1); + np->seed = getintfield_default(L, index, "seed", 0); + np->octaves = getintfield_default(L, index, "octaves", 0); + np->persist = getfloatfield_default(L, index, "persist", 0.0); + + return np; +} + +/* Groups */ static void read_groups(lua_State *L, int index, @@ -3241,11 +3265,6 @@ static void objectref_get_or_create(lua_State *L, } } - -/* - PerlinNoise - */ - class LuaPerlinNoise { private: @@ -3356,6 +3375,145 @@ const luaL_reg LuaPerlinNoise::methods[] = { }; /* + PerlinNoiseMap + */ +class LuaPerlinNoiseMap +{ +private: + Noise *noise; + static const char className[]; + static const luaL_reg methods[]; + + static int gc_object(lua_State *L) + { + LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1)); + delete o; + return 0; + } + + static int l_get2dMap(lua_State *L) + { + int i = 0; + + LuaPerlinNoiseMap *o = checkobject(L, 1); + v2f p = read_v2f(L, 2); + + Noise *n = o->noise; + n->perlinMap2D(p.X, p.Y); + + lua_newtable(L); + for (int y = 0; y != n->sy; y++) { + lua_newtable(L); + for (int x = 0; x != n->sx; x++) { + float noiseval = n->np->offset + n->np->scale * n->result[i++]; + lua_pushnumber(L, noiseval); + lua_rawseti(L, -2, x + 1); + } + lua_rawseti(L, -2, y + 1); + } + return 1; + } + + static int l_get3dMap(lua_State *L) + { + int i = 0; + + LuaPerlinNoiseMap *o = checkobject(L, 1); + v3f p = read_v3f(L, 2); + + Noise *n = o->noise; + n->perlinMap3D(p.X, p.Y, p.Z); + + lua_newtable(L); + for (int z = 0; z != n->sz; z++) { + lua_newtable(L); + for (int y = 0; y != n->sy; y++) { + lua_newtable(L); + for (int x = 0; x != n->sx; x++) { + lua_pushnumber(L, n->np->offset + n->np->scale * n->result[i++]); + lua_rawseti(L, -2, x + 1); + } + lua_rawseti(L, -2, y + 1); + } + lua_rawseti(L, -2, z + 1); + } + return 1; + } + +public: + LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size) { + noise = new Noise(np, seed, size.X, size.Y, size.Z); + } + + ~LuaPerlinNoiseMap() + { + delete noise->np; + delete noise; + } + + // LuaPerlinNoiseMap(np, size) + // Creates an LuaPerlinNoiseMap and leaves it on top of stack + static int create_object(lua_State *L) + { + NoiseParams *np = read_noiseparams(L, 1); + if (!np) + return 0; + v3s16 size = read_v3s16(L, 2); + + LuaPerlinNoiseMap *o = new LuaPerlinNoiseMap(np, 0, size); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; + } + + static LuaPerlinNoiseMap *checkobject(lua_State *L, int narg) + { + luaL_checktype(L, narg, LUA_TUSERDATA); + + void *ud = luaL_checkudata(L, narg, className); + if (!ud) + luaL_typerror(L, narg, className); + + return *(LuaPerlinNoiseMap **)ud; // unbox pointer + } + + static void Register(lua_State *L) + { + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from Lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // drop methodtable + + // Can be created from Lua (PerlinNoiseMap(np, size) + lua_register(L, className, create_object); + } +}; +const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap"; +const luaL_reg LuaPerlinNoiseMap::methods[] = { + method(LuaPerlinNoiseMap, get2dMap), + method(LuaPerlinNoiseMap, get3dMap), + {0,0} +}; + +/* NodeTimerRef */ @@ -4019,6 +4177,28 @@ private: lua_setmetatable(L, -2); return 1; } + + // EnvRef:get_perlin_map(noiseparams, size) + // returns world-specific PerlinNoiseMap + static int l_get_perlin_map(lua_State *L) + { + EnvRef *o = checkobject(L, 1); + ServerEnvironment *env = o->m_env; + if (env == NULL) + return 0; + + NoiseParams *np = read_noiseparams(L, 2); + if (!np) + return 0; + v3s16 size = read_v3s16(L, 3); + + int seed = (int)(env->getServerMap().getSeed()); + LuaPerlinNoiseMap *n = new LuaPerlinNoiseMap(np, seed, size); + *(void **)(lua_newuserdata(L, sizeof(void *))) = n; + luaL_getmetatable(L, "PerlinNoiseMap"); + lua_setmetatable(L, -2); + return 1; + } // EnvRef:clear_objects() // clear all objects in the environment @@ -4158,8 +4338,7 @@ const luaL_reg EnvRef::methods[] = { method(EnvRef, find_node_near), method(EnvRef, find_nodes_in_area), method(EnvRef, get_perlin), - //method{EnvRef, get_perlin_map_2d}, - //method{EnvRef, get_perlin_map_3d}, + method(EnvRef, get_perlin_map), method(EnvRef, clear_objects), method(EnvRef, spawn_tree), {0,0} @@ -5424,6 +5603,7 @@ void scriptapi_export(lua_State *L, Server *server) EnvRef::Register(L); LuaPseudoRandom::Register(L); LuaPerlinNoise::Register(L); + LuaPerlinNoiseMap::Register(L); } bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath, diff --git a/src/server.cpp b/src/server.cpp index a8640ad10..572ef4d82 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2344,6 +2344,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) infostream<<"Server: Sending content to " <<getPlayerName(peer_id)<<std::endl; + // Send player movement settings + SendMovement(m_con, peer_id); + // Send item definitions SendItemDef(m_con, peer_id, m_itemdef); @@ -3534,6 +3537,32 @@ void Server::deletingPeer(con::Peer *peer, bool timeout) Static send methods */ +void Server::SendMovement(con::Connection &con, u16 peer_id) +{ + DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); + + writeU16(os, TOCLIENT_MOVEMENT); + writeF1000(os, g_settings->getFloat("movement_acceleration_default")); + writeF1000(os, g_settings->getFloat("movement_acceleration_air")); + writeF1000(os, g_settings->getFloat("movement_acceleration_fast")); + writeF1000(os, g_settings->getFloat("movement_speed_walk")); + writeF1000(os, g_settings->getFloat("movement_speed_crouch")); + writeF1000(os, g_settings->getFloat("movement_speed_fast")); + writeF1000(os, g_settings->getFloat("movement_speed_climb")); + writeF1000(os, g_settings->getFloat("movement_speed_jump")); + writeF1000(os, g_settings->getFloat("movement_liquid_fluidity")); + writeF1000(os, g_settings->getFloat("movement_liquid_fluidity_smooth")); + writeF1000(os, g_settings->getFloat("movement_liquid_sink")); + writeF1000(os, g_settings->getFloat("movement_gravity")); + + // Make data buffer + std::string s = os.str(); + SharedBuffer<u8> data((u8*)s.c_str(), s.size()); + // Send as reliable + con.Send(peer_id, 0, data, true); +} + void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp) { DSTACK(__FUNCTION_NAME); diff --git a/src/server.h b/src/server.h index 86d5513d8..29d47337d 100644 --- a/src/server.h +++ b/src/server.h @@ -602,6 +602,7 @@ private: Static send methods */ + static void SendMovement(con::Connection &con, u16 peer_id); static void SendHP(con::Connection &con, u16 peer_id, u8 hp); static void SendAccessDenied(con::Connection &con, u16 peer_id, const std::wstring &reason); diff --git a/src/settings.h b/src/settings.h index 2b46676c6..addd9980c 100644 --- a/src/settings.h +++ b/src/settings.h @@ -569,6 +569,12 @@ public: return value; } + u32 getFlagStr(std::string name, FlagDesc *flagdesc) + { + std::string val = get(name); + return (isdigit(val[0])) ? stoi(val) : readFlagString(val, flagdesc); + } + template <class T> T *getStruct(std::string name, std::string format) { size_t len = sizeof(T); @@ -831,6 +837,11 @@ fail: set(name, std::string(sbuf)); return true; } + + void setFlagStr(std::string name, u32 flags, FlagDesc *flagdesc) + { + set(name, writeFlagString(flags, flagdesc)); + } void setBool(std::string name, bool value) { diff --git a/src/util/string.cpp b/src/util/string.cpp index c10755ae1..61b307c60 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "../sha1.h" #include "../base64.h" +#include "../porting.h" // Get an sha-1 hash of the player's name combined with // the password entered. That's what the server uses as @@ -48,6 +49,45 @@ size_t curl_write_data(char *ptr, size_t size, size_t nmemb, void *userdata) { return count; } +u32 readFlagString(std::string str, FlagDesc *flagdesc) { + u32 result = 0; + char *s = &str[0]; + char *flagstr, *strpos = NULL; + + while ((flagstr = strtok_r(s, ",", &strpos))) { + s = NULL; + + while (*flagstr == ' ' || *flagstr == '\t') + flagstr++; + + for (int i = 0; flagdesc[i].name; i++) { + if (!strcasecmp(flagstr, flagdesc[i].name)) { + result |= flagdesc[i].flag; + break; + } + } + } + + return result; +} + +std::string writeFlagString(u32 flags, FlagDesc *flagdesc) { + std::string result; + + for (int i = 0; flagdesc[i].name; i++) { + if (flags & flagdesc[i].flag) { + result += flagdesc[i].name; + result += ", "; + } + } + + size_t len = result.length(); + if (len >= 2) + result.erase(len - 2, 2); + + return result; +} + char *mystrtok_r(char *s, const char *sep, char **lasts) { char *t; diff --git a/src/util/string.h b/src/util/string.h index d081b365b..a469a074a 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -28,6 +28,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <vector> #include <sstream> +struct FlagDesc { + const char *name; + u32 flag; +}; + static inline std::string padStringRight(std::string s, size_t len) { if(len > s.size()) @@ -283,6 +288,8 @@ inline std::string wrap_rows(const std::string &from, u32 rowlen) std::string translatePassword(std::string playername, std::wstring password); size_t curl_write_data(char *ptr, size_t size, size_t nmemb, void *userdata); +u32 readFlagString(std::string str, FlagDesc *flagdesc); +std::string writeFlagString(u32 flags, FlagDesc *flagdesc); char *mystrtok_r(char *s, const char *sep, char **lasts); #endif |