Merge branch 'next'

Conflicts:
	apps/openmw/main.cpp
actorid
Marc Zinnschlag 14 years ago
commit b157273cd9

4
.gitignore vendored

@ -1,4 +1,6 @@
build
*~
Doxygen
prebuilt
prebuilt
apps/openmw/config.hpp
Docs/mainpage.hpp

@ -7,6 +7,18 @@ IF (APPLE)
set(CMAKE_OSX_SYSROOT "/Developer/SDKs/MacOSX10.6.sdk")
ENDIF (APPLE)
# Version
set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 12)
set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
# doxygen main page
configure_file ("${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/Docs/mainpage.hpp")
# Sound source selection
option(USE_AUDIERE "use Audiere for sound" OFF)
option(USE_FFMPEG "use ffmpeg for sound" OFF)
@ -58,7 +70,7 @@ IF(EXISTS "${CMAKE_SOURCE_DIR}/prebuilt/vc100-mt-gd/ogre_1_7_1")
set(AUDIERE_LIBRARY "${PREBUILT_DIR}/audiere-1.9.4/lib/audiere.lib")
set(ENV{OPENALDIR} "${PREBUILT_DIR}/OpenAL 1.1 SDK")
set(BULLET_ROOT "${PREBUILT_DIR}/bullet")
ELSE()
message (STATUS "OpenMW pre-built binaries not found. Using standard locations.")
@ -436,8 +448,7 @@ if(DPKG_PROGRAM)
exec_program("git" ARGS "config --get user.email" OUTPUT_VARIABLE GIT_EMAIL)
set(PACKAGE_MAINTAINER "${GIT_NAME} <${GIT_EMAIL}>")
else()
#FIXME this should probably be read from some file like ${CMAKE_CURRENT_SOURCE_DIR}/VERSION or something that gets updated when changing version
set(VERSION_STRING "0.10.0")
set(VERSION_STRING "${OPENMW_VERSION}")
set(PACKAGE_MAINTAINER "unknown")
endif()

@ -576,6 +576,7 @@ WARN_LOGFILE =
INPUT = apps \
components \
libs \
Docs
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

@ -576,6 +576,7 @@ WARN_LOGFILE =
INPUT = apps \
components \
libs \
Docs
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is

@ -0,0 +1,5 @@
/// \mainpage
///
/// This is the source documentation for:
///
/// OpenMW @OPENMW_VERSION@

@ -1,5 +1,9 @@
project(OpenMW)
# config file
configure_file ("${OpenMW_SOURCE_DIR}/config.hpp.cmake" "${OpenMW_SOURCE_DIR}/config.hpp")
# local files
set(GAME
@ -7,7 +11,8 @@ set(GAME
engine.cpp
)
set(GAME_HEADER
engine.hpp)
engine.hpp
config.hpp)
source_group(game FILES ${GAME} ${GAME_HEADER})
set(GAMEREND
@ -50,6 +55,7 @@ set(GAMEGUI_HEADER
mwgui/dialogue_history.hpp
mwgui/window_base.hpp
mwgui/stats_window.hpp
mwgui/messagebox.hpp
)
set(GAMEGUI
mwgui/window_manager.cpp
@ -65,6 +71,7 @@ set(GAMEGUI
mwgui/dialogue_history.cpp
mwgui/window_base.cpp
mwgui/stats_window.cpp
mwgui/messagebox.cpp
)
source_group(apps\\openmw\\mwgui FILES ${GAMEGUI_HEADER} ${GAMEGUI})

@ -0,0 +1,9 @@
#ifndef CONFIG_H
#define CONFIG_H
#define OPENMW_VERSION_MAJOR @OPENMW_VERSION_MAJOR@
#define OPENMW_VERSION_MINOR @OPENMW_VERSION_MINOR@
#define OPENMW_VERSION_RELEASE @OPENMW_VERSION_RELEASE@
#define OPENMW_VERSION "@OPENMW_VERSION@"
#endif

@ -7,6 +7,7 @@
#include <utility>
#include <OgreVector3.h>
#include <Ogre.h>
#include "components/esm/records.hpp"
#include <components/esm_store/cell_store.hpp>
@ -88,6 +89,8 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
std::string effect;
MWWorld::Ptr::CellStore *current = mEnvironment.mWorld->getPlayer().getPlayer().getCell();
//If the region has changed
if(!(current->cell->data.flags & current->cell->Interior) && timer.elapsed() >= 10){
timer.restart();
@ -149,6 +152,9 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
{
mEnvironment.mFrameDuration = evt.timeSinceLastFrame;
//
mEnvironment.mWindowManager->onFrame(mEnvironment.mFrameDuration);
// global scripts
mEnvironment.mGlobalScripts->run (mEnvironment);
@ -244,6 +250,10 @@ void OMW::Engine::loadBSA()
std::cout << "Adding " << iter->second.string() << std::endl;
Bsa::addBSA (iter->second.string());
}
std::string m = mDataDir.string();
std::cout << "Data dir" << m << "\n";
Bsa::addDir(m, mFSStrict);
}
// add resources directory
@ -341,9 +351,6 @@ void OMW::Engine::go()
mOgre.configure(!Misc::isFile(ogreCfg.c_str()), cfgUserDir, plugCfg, false);
addResourcesDirectory (mDataDir / "Meshes");
addResourcesDirectory (mDataDir / "Textures");
// This has to be added BEFORE MyGUI is initialized, as it needs
// to find core.xml here.
addResourcesDirectory(mResDir / "mygui");
@ -359,7 +366,7 @@ void OMW::Engine::go()
// Create the world
mEnvironment.mWorld = new MWWorld::World (mOgre, mPhysicEngine, mFileCollections, mMaster,
mResDir, mNewGame, mEnvironment);
mResDir, mNewGame, mEnvironment, mEncoding);
// Set up the GUI system
mGuiManager = new OEngine::GUI::MyGUIManager(mOgre.getWindow(), mOgre.getScene(), false, cfgDir);
@ -380,7 +387,7 @@ void OMW::Engine::go()
mOgre.getCamera(),
mEnvironment.mWorld->getStore(),
(mDataDir),
mUseSound);
mUseSound, mFSStrict);
// Create script system
mScriptContext = new MWScript::CompilerContext (MWScript::CompilerContext::Type_Full,
@ -508,3 +515,8 @@ void OMW::Engine::setCompileAll (bool all)
{
mCompileAll = all;
}
void OMW::Engine::setEncoding(const std::string& encoding)
{
mEncoding = encoding;
}

@ -56,6 +56,7 @@ namespace OMW
class Engine : private Ogre::FrameListener
{
std::string mEncoding;
boost::filesystem::path mDataDir;
boost::filesystem::path mResDir;
OEngine::Render::OgreRenderer mOgre;
@ -157,6 +158,9 @@ namespace OMW
/// Compile all scripts (excludign dialogue scripts) at startup?
void setCompileAll (bool all);
/// Font encoding
void setEncoding(const std::string& encoding);
};
}

@ -31,6 +31,8 @@
#include <OSX/macUtils.h>
#endif
#include "config.hpp"
using namespace std;
/// Parse command line options and openmw.cfg file (if one exists). Results are directly
@ -46,7 +48,8 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
"Syntax: openmw <options>\nAllowed options");
desc.add_options()
("help", "print help message")
("help", "print help message and quit")
("version", "print version information and quit")
("data", bpo::value<std::vector<std::string> >()
->default_value (std::vector<std::string>(), "data")
->multitoken(),
@ -82,6 +85,13 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
( "fs-strict", boost::program_options::value<bool>()->
implicit_value (true)->default_value (false),
"strict file system handling (no case folding)")
( "encoding", boost::program_options::value<std::string>()->
default_value("win1252"),
"Character encoding used in OpenMW game messages:\n"
"\n\twin1250 - Central and Eastern European such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian languages\n"
"\n\twin1251 - Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages\n"
"\n\twin1252 - Western European (Latin) alphabet, used by default")
;
bpo::variables_map variables;
@ -110,10 +120,39 @@ bool parseOptions (int argc, char**argv, OMW::Engine& engine)
if (globalConfigFile.is_open())
bpo::store ( bpo::parse_config_file (globalConfigFile, desc), variables);
bool run = true;
if (variables.count ("help"))
{
std::cout << desc << std::endl;
run = false;
}
if (variables.count ("version"))
{
std::cout << "OpenMW version " << OPENMW_VERSION << std::endl;
run = false;
}
if (!run)
return false;
// Font encoding settings
std::string encoding(variables["encoding"].as<std::string>());
if (encoding == "win1250")
{
std::cout << "Using Central and Eastern European font encoding." << std::endl;
engine.setEncoding(encoding);
}
else if (encoding == "win1251")
{
std::cout << "Using Cyrillic font encoding." << std::endl;
engine.setEncoding(encoding);
}
else
{
std::cout << "Using default (English) font encoding." << std::endl;
engine.setEncoding("win1252");
}
// directory settings

@ -34,7 +34,7 @@ namespace MWClass
if (!model.empty())
{
MWRender::Rendering rendering (cellRender, ref->ref);
cellRender.insertMesh ("meshes\\" + model);
cellRender.insertMesh("meshes\\" + model);
cellRender.insertActorPhysics();
ref->mData.setHandle (rendering.end (ref->mData.isEnabled()));
}

@ -95,8 +95,7 @@ namespace MWClass
upperright[uppernumbers++] = npcName + "chest";
neckandup[neckNumbers++] = npcName + "chest";
}
//std::cout << "GETTING NPC PART";
//Orgre::SceneNode test = cellRender.getNpcPart();
const ESM::BodyPart *upperleg = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "upper leg");
const ESM::BodyPart *groin = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "groin");
@ -113,8 +112,6 @@ namespace MWClass
const ESM::BodyPart *hands = environment.mWorld->getStore().bodyParts.search (bodyRaceID + "hands.1st");
//std::cout << "RACE" << bodyRaceID << "\n";
Ogre::Vector3 pos2 = Ogre::Vector3( 0, .5, 75);
if (groin){
@ -124,10 +121,9 @@ namespace MWClass
}
if (tail) {
cellRender.insertMesh("tail\\" + tail->model, Ogre::Vector3(0 , 0, -76), axis, kOgrePi, npcName + "tail", addresses, numbers, "tail");
//std::cout << "TAIL\n";
}
//addresses[1] = npcName + "groin";
if(upperleg){
cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( 6, 0, -16), axis, kOgrePi, npcName + "upper leg", addresses, numbers); //-18
cellRender.insertMesh ("meshes\\" + upperleg->model, Ogre::Vector3( -6, 0, -16), axis, Ogre::Radian(0), npcName + "upper leg2", addresses2, numbers);
@ -218,9 +214,6 @@ namespace MWClass
if(hand)
{
//std::cout << "WE FOUND A HAND\n";
//-50, 0, -120
//std::cout << "WE FOUND HANDS\n";
std::string pass;
if(hand->model.compare("b\\B_N_Dark Elf_F_Hands.1st.NIF")==0 && bodyRaceID.compare("b_n_dark elf_m_") == 0)
pass = "b\\B_N_Dark Elf_M_Hands.1st.NIF";
@ -230,7 +223,6 @@ namespace MWClass
cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0,0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120
upperleft[uppernumbers] = npcName + "hand";
upperright[uppernumbers++] = npcName + "hand2";
//cellRender.rotateMesh(Ogre::Vector3(0, 0,0), kOgrePi, upperleft, uppernumbers);
cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperleft, uppernumbers);
cellRender.scaleMesh(Ogre::Vector3(1, -1, 1), upperright, uppernumbers);
}
@ -244,7 +236,6 @@ namespace MWClass
else
pass =hands->model; //-50, 0, -120
cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1,-110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110
//cellRender.insertMesh("meshes\\" + hands->model, Ogre::Vector3(42, 0,110), Ogre::Vector3(1, 0, 0), kOgrePi, npcName + "hand", upperleft, uppernumbers, false); //0, 100, -100 42, 0, -110
cellRender.insertMesh("meshes\\" + pass, Ogre::Vector3(42, 1, -110), Ogre::Vector3(0, 0, 0), kOgrePi, npcName + "hand2", upperright, uppernumbers, false); //0, 100, -100 0,0,120
upperleft[uppernumbers] = npcName + "hand";
upperright[uppernumbers++] = npcName + "hand2";

@ -171,6 +171,22 @@ namespace MWGui
MyGUI::KeyCode key,
MyGUI::Char _char)
{
if( key == MyGUI::KeyCode::Tab)
{
std::vector<std::string> matches;
listNames();
command->setCaption(complete( command->getCaption(), matches ));
#if 0
int i = 0;
for(std::vector<std::string>::iterator it=matches.begin(); it < matches.end(); it++,i++ )
{
printOK( *it );
if( i == 50 )
break;
}
#endif
}
if(command_history.empty()) return;
// Traverse history with up and down arrows
@ -237,4 +253,119 @@ namespace MWGui
command->setCaption("");
}
std::string Console::complete( std::string input, std::vector<std::string> &matches )
{
using namespace std;
string output=input;
string tmp=input;
bool has_front_quote = false;
/* Does the input string contain things that don't have to be completed? If yes erase them. */
/* Are there quotation marks? */
if( tmp.find('"') != string::npos ) {
int numquotes=0;
for(string::iterator it=tmp.begin(); it < tmp.end(); it++) {
if( *it == '"' )
numquotes++;
}
/* Is it terminated?*/
if( numquotes % 2 ) {
tmp.erase( 0, tmp.rfind('"')+1 );
has_front_quote = true;
}
else {
size_t pos;
if( ( ((pos = tmp.rfind(' ')) != string::npos ) ) && ( pos > tmp.rfind('"') ) ) {
tmp.erase( 0, tmp.rfind(' ')+1);
}
else {
tmp.clear();
}
has_front_quote = false;
}
}
/* No quotation marks. Are there spaces?*/
else {
size_t rpos;
if( (rpos=tmp.rfind(' ')) != string::npos ) {
if( rpos == 0 ) {
tmp.clear();
}
else {
tmp.erase(0, rpos+1);
}
}
}
/* Erase the input from the output string so we can easily append the completed form later. */
output.erase(output.end()-tmp.length(), output.end());
/* Is there still something in the input string? If not just display all commands and return the unchanged input. */
if( tmp.length() == 0 ) {
matches=mNames;
return input;
}
/* Iterate through the vector. */
for(vector<string>::iterator it=mNames.begin(); it < mNames.end();it++) {
bool string_different=false;
/* Is the string shorter than the input string? If yes skip it. */
if( (*it).length() < tmp.length() )
continue;
/* Is the beginning of the string different from the input string? If yes skip it. */
for( string::iterator iter=tmp.begin(), iter2=(*it).begin(); iter < tmp.end();iter++, iter2++) {
if( tolower(*iter) != tolower(*iter2) ) {
string_different=true;
break;
}
}
if( string_different )
continue;
/* The beginning of the string matches the input string, save it for the next test. */
matches.push_back(*it);
}
/* There are no matches. Return the unchanged input. */
if( matches.empty() )
{
return input;
}
/* Only one match. We're done. */
if( matches.size() == 1 ) {
/* Adding quotation marks when the input string started with a quotation mark or has spaces in it*/
if( ( matches.front().find(' ') != string::npos ) ) {
if( !has_front_quote )
output.append(string("\""));
return output.append(matches.front() + string("\" "));
}
else if( has_front_quote ) {
return output.append(matches.front() + string("\" "));
}
else {
return output.append(matches.front() + string(" "));
}
}
/* Check if all matching strings match further than input. If yes complete to this match. */
int i = tmp.length();
for(string::iterator iter=matches.front().begin()+tmp.length(); iter < matches.front().end(); iter++, i++) {
for(vector<string>::iterator it=matches.begin(); it < matches.end();it++) {
if( tolower((*it)[i]) != tolower(*iter) ) {
/* Append the longest match to the end of the output string*/
output.append(matches.front().substr( 0, i));
return output;
}
}
}
/* All keywords match with the shortest. Append it to the output string and return it. */
return output.append(matches.front());
}
}

@ -80,6 +80,8 @@ namespace MWGui
MyGUI::Char _char);
void acceptCommand(MyGUI::EditPtr _sender);
std::string complete( std::string input, std::vector<std::string> &matches );
};
}
#endif

@ -0,0 +1,394 @@
#include "messagebox.hpp"
using namespace MWGui;
MessageBoxManager::MessageBoxManager (WindowManager *windowManager)
{
mWindowManager = windowManager;
// defines
mMessageBoxSpeed = 0.1;
mInterMessageBoxe = NULL;
}
void MessageBoxManager::onFrame (float frameDuration)
{
std::vector<MessageBoxManagerTimer>::iterator it;
for(it = mTimers.begin(); it != mTimers.end();)
{
it->current += frameDuration;
if(it->current >= it->max)
{
it->messageBox->mMarkedToDelete = true;
if(*mMessageBoxes.begin() == it->messageBox) // if this box is the last one
{
// collect all with mMarkedToDelete and delete them.
// and place the other messageboxes on the right position
int height = 0;
std::vector<MessageBox*>::iterator it2 = mMessageBoxes.begin();
while(it2 != mMessageBoxes.end())
{
if((*it2)->mMarkedToDelete)
{
delete (*it2);
it2 = mMessageBoxes.erase(it2);
}
else {
(*it2)->update(height);
height += (*it2)->getHeight();
it2++;
}
}
}
it = mTimers.erase(it);
}
else
{
it++;
}
}
if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) {
delete mInterMessageBoxe;
mInterMessageBoxe = NULL;
mWindowManager->setNextMode(GM_Game);
}
}
void MessageBoxManager::createMessageBox (const std::string& message)
{
std::cout << "MessageBox: " << message << std::endl;
MessageBox *box = new MessageBox(*this, message);
removeMessageBox(message.length()*mMessageBoxSpeed, box);
mMessageBoxes.push_back(box);
std::vector<MessageBox*>::iterator it;
if(mMessageBoxes.size() > 3) {
delete *mMessageBoxes.begin();
mMessageBoxes.erase(mMessageBoxes.begin());
}
int height = 0;
for(it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it)
{
(*it)->update(height);
height += (*it)->getHeight();
}
}
bool MessageBoxManager::createInteractiveMessageBox (const std::string& message, const std::vector<std::string>& buttons)
{
if(mInterMessageBoxe != NULL) {
std::cout << "there is a MessageBox already" << std::endl;
return false;
}
std::cout << "interactive MessageBox: " << message << " - ";
std::copy (buttons.begin(), buttons.end(), std::ostream_iterator<std::string> (std::cout, ", "));
std::cout << std::endl;
mInterMessageBoxe = new InteractiveMessageBox(*this, message, buttons);
return true;
}
bool MessageBoxManager::isInteractiveMessageBox ()
{
return mInterMessageBoxe != NULL;
}
void MessageBoxManager::removeMessageBox (float time, MessageBox *msgbox)
{
MessageBoxManagerTimer timer;
timer.current = 0;
timer.max = time;
timer.messageBox = msgbox;
mTimers.insert(mTimers.end(), timer);
}
bool MessageBoxManager::removeMessageBox (MessageBox *msgbox)
{
std::vector<MessageBox*>::iterator it;
for(it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it)
{
if((*it) == msgbox)
{
delete (*it);
mMessageBoxes.erase(it);
return true;
}
}
return false;
}
void MessageBoxManager::setMessageBoxSpeed (int speed)
{
mMessageBoxSpeed = speed;
}
int MessageBoxManager::readPressedButton ()
{
if(mInterMessageBoxe != NULL)
{
return mInterMessageBoxe->readPressedButton();
}
return -1;
}
MessageBox::MessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message)
: Layout("openmw_messagebox_layout.xml")
, mMessageBoxManager(parMessageBoxManager)
, cMessage(message)
{
// defines
mFixedWidth = 300;
mBottomPadding = 20;
mNextBoxPadding = 20;
mMarkedToDelete = false;
getWidget(mMessageWidget, "message");
mMessageWidget->setOverflowToTheLeft(true);
mMessageWidget->addText(cMessage);
MyGUI::IntSize size;
size.width = mFixedWidth;
size.height = 100; // dummy
MyGUI::IntCoord coord;
coord.left = 10; // dummy
coord.top = 10; // dummy
mMessageWidget->setSize(size);
MyGUI::IntSize textSize = mMessageWidget->_getTextSize();
size.height = mHeight = textSize.height + 20; // this is the padding between the text and the box
mMainWidget->setSize(size);
size.width -= 15; // this is to center the text (see messagebox_layout.xml, Widget type="Edit" position="-2 -3 0 0")
mMessageWidget->setSize(size);
}
void MessageBox::update (int height)
{
MyGUI::IntSize gameWindowSize = mMessageBoxManager.mWindowManager->getGui()->getViewSize();
MyGUI::IntCoord coord;
coord.left = (gameWindowSize.width - mFixedWidth)/2;
coord.top = (gameWindowSize.height - mHeight - height - mBottomPadding);
MyGUI::IntSize size;
size.width = mFixedWidth;
size.height = mHeight;
mMainWidget->setCoord(coord);
mMainWidget->setSize(size);
mMainWidget->setVisible(true);
}
int MessageBox::getHeight ()
{
return mHeight+mNextBoxPadding; // 20 is the padding between this and the next MessageBox
}
InteractiveMessageBox::InteractiveMessageBox(MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons)
: Layout("openmw_interactive_messagebox_layout.xml")
, mMessageBoxManager(parMessageBoxManager)
, mButtonPressed(-1)
{
int fixedWidth = 500;
int textPadding = 10; // padding between text-widget and main-widget
int textButtonPadding = 20; // padding between the text-widget und the button-widget
int buttonLeftPadding = 10; // padding between the buttons if horizontal
int buttonTopPadding = 5; // ^-- if vertical
int buttonPadding = 5; // padding between button label and button itself
int buttonMainPadding = 10; // padding between buttons and bottom of the main widget
mMarkedToDelete = false;
getWidget(mMessageWidget, "message");
getWidget(mButtonsWidget, "buttons");
mMessageWidget->setOverflowToTheLeft(true);
mMessageWidget->addText(message);
MyGUI::IntSize textSize = mMessageWidget->_getTextSize();
MyGUI::IntSize gameWindowSize = mMessageBoxManager.mWindowManager->getGui()->getViewSize();
int biggestButtonWidth = 0;
int buttonWidth = 0;
int buttonsWidth = 0;
int buttonHeight = 0;
MyGUI::IntCoord dummyCoord(0, 0, 0, 0);
std::vector<std::string>::const_iterator it;
for(it = buttons.begin(); it != buttons.end(); ++it)
{
MyGUI::ButtonPtr button = mButtonsWidget->createWidget<MyGUI::Button>(
MyGUI::WidgetStyle::Child,
std::string("MW_Button"),
dummyCoord,
MyGUI::Align::Default);
button->setCaption(*it);
button->eventMouseButtonClick = MyGUI::newDelegate(this, &InteractiveMessageBox::mousePressed);
mButtons.push_back(button);
buttonWidth = button->_getTextSize().width + 2*buttonPadding + buttonLeftPadding;
buttonsWidth += buttonWidth;
buttonHeight = button->_getTextSize().height + 2*buttonPadding + buttonTopPadding;
if(buttonWidth > biggestButtonWidth)
{
biggestButtonWidth = buttonWidth;
}
}
buttonsWidth += buttonLeftPadding;
MyGUI::IntSize mainWidgetSize;
if(buttonsWidth < fixedWidth)
{
// on one line
std::cout << "on one line" << std::endl;
if(textSize.width + 2*textPadding < buttonsWidth)
{
std::cout << "width = buttonsWidth" << std::endl;
mainWidgetSize.width = buttonsWidth;
}
else
{
mainWidgetSize.width = textSize.width + 3*textPadding;
}
mainWidgetSize.height = textSize.height + textButtonPadding + buttonHeight + buttonMainPadding;
MyGUI::IntCoord absCoord;
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
std::cout << "left " << absCoord.left << " top " << absCoord.top << std::endl;
mMainWidget->setCoord(absCoord);
mMainWidget->setSize(mainWidgetSize);
MyGUI::IntCoord messageWidgetCoord;
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
messageWidgetCoord.top = textPadding;
mMessageWidget->setCoord(messageWidgetCoord);
mMessageWidget->setSize(textSize);
MyGUI::IntCoord buttonCord;
MyGUI::IntSize buttonSize(0, buttonHeight);
int left = (mainWidgetSize.width - buttonsWidth)/2 + buttonPadding;
std::vector<MyGUI::ButtonPtr>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
buttonCord.left = left;
buttonCord.top = textSize.height + textButtonPadding;
buttonSize.width = (*button)->_getTextSize().width + 2*buttonPadding;
buttonSize.height = (*button)->_getTextSize().height + 2*buttonPadding;
(*button)->setCoord(buttonCord);
(*button)->setSize(buttonSize);
left += buttonSize.width + buttonLeftPadding;
}
}
else
{
// among each other
if(biggestButtonWidth > textSize.width) {
mainWidgetSize.width = biggestButtonWidth + buttonTopPadding;
}
else {
mainWidgetSize.width = textSize.width + 3*textPadding;
}
mainWidgetSize.height = textSize.height + 2*textPadding + textButtonPadding + buttonHeight * buttons.size() + buttonMainPadding;
std::cout << "biggestButtonWidth " << biggestButtonWidth << " textSize.width " << textSize.width << std::endl;
std::cout << "width " << mainWidgetSize.width << " height " << mainWidgetSize.height << std::endl;
mMainWidget->setSize(mainWidgetSize);
MyGUI::IntCoord absCoord;
absCoord.left = (gameWindowSize.width - mainWidgetSize.width)/2;
absCoord.top = (gameWindowSize.height - mainWidgetSize.height)/2;
mMainWidget->setCoord(absCoord);
mMainWidget->setSize(mainWidgetSize);
MyGUI::IntCoord messageWidgetCoord;
messageWidgetCoord.left = (mainWidgetSize.width - textSize.width)/2;
messageWidgetCoord.top = textPadding;
mMessageWidget->setCoord(messageWidgetCoord);
mMessageWidget->setSize(textSize);
MyGUI::IntCoord buttonCord;
MyGUI::IntSize buttonSize(0, buttonHeight);
int top = textButtonPadding + buttonTopPadding + textSize.height;
std::vector<MyGUI::ButtonPtr>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
buttonSize.width = (*button)->_getTextSize().width + buttonPadding*2;
buttonSize.height = (*button)->_getTextSize().height + buttonPadding*2;
buttonCord.top = top;
buttonCord.left = (mainWidgetSize.width - buttonSize.width)/2 - 5; // FIXME: -5 is not so nice :/
(*button)->setCoord(buttonCord);
(*button)->setSize(buttonSize);
top += buttonSize.height + 2*buttonTopPadding;
}
}
}
void InteractiveMessageBox::mousePressed (MyGUI::Widget* pressed)
{
mMarkedToDelete = true;
int index = 0;
std::vector<MyGUI::ButtonPtr>::const_iterator button;
for(button = mButtons.begin(); button != mButtons.end(); ++button)
{
if(*button == pressed)
{
mButtonPressed = index;
return;
}
index++;
}
std::cout << "Cant be possible :/" << std::endl;
}
int InteractiveMessageBox::readPressedButton ()
{
int pressed = mButtonPressed;
mButtonPressed = -1;
return pressed;
}

@ -0,0 +1,89 @@
#ifndef MWGUI_MESSAGE_BOX_H
#define MWGUI_MESSAGE_BOX_H
#include <openengine/gui/layout.hpp>
#include <MyGUI.h>
#include "window_base.hpp"
#include "window_manager.hpp"
namespace MWGui
{
class InteractiveMessageBox;
class MessageBoxManager;
class MessageBox;
struct MessageBoxManagerTimer {
float current;
float max;
MessageBox *messageBox;
};
class MessageBoxManager
{
public:
MessageBoxManager (WindowManager* windowManager);
void onFrame (float frameDuration);
void createMessageBox (const std::string& message);
bool createInteractiveMessageBox (const std::string& message, const std::vector<std::string>& buttons);
bool isInteractiveMessageBox ();
void removeMessageBox (float time, MessageBox *msgbox);
bool removeMessageBox (MessageBox *msgbox);
void setMessageBoxSpeed (int speed);
int readPressedButton ();
WindowManager *mWindowManager;
private:
std::vector<MessageBox*> mMessageBoxes;
InteractiveMessageBox* mInterMessageBoxe;
std::vector<MessageBoxManagerTimer> mTimers;
float mMessageBoxSpeed;
};
class MessageBox : public OEngine::GUI::Layout
{
public:
MessageBox (MessageBoxManager& parMessageBoxManager, const std::string& message);
void setMessage (const std::string& message);
int getHeight ();
void update (int height);
bool mMarkedToDelete;
protected:
MessageBoxManager& mMessageBoxManager;
int mHeight;
const std::string& cMessage;
MyGUI::EditPtr mMessageWidget;
int mFixedWidth;
int mBottomPadding;
int mNextBoxPadding;
};
class InteractiveMessageBox : public OEngine::GUI::Layout
{
public:
InteractiveMessageBox (MessageBoxManager& parMessageBoxManager, const std::string& message, const std::vector<std::string>& buttons);
void mousePressed (MyGUI::Widget* _widget);
int readPressedButton ();
bool mMarkedToDelete;
private:
MessageBoxManager& mMessageBoxManager;
MyGUI::EditPtr mMessageWidget;
MyGUI::WidgetPtr mButtonsWidget;
std::vector<MyGUI::ButtonPtr> mButtons;
int mTextButtonPadding;
int mButtonPressed;
};
}
#endif

@ -26,7 +26,10 @@ namespace MWGui
GM_ClassGenerate,
GM_ClassPick,
GM_ClassCreate,
GM_Review
GM_Review,
// interactive MessageBox
GM_InterMessageBox
};
// Windows shown in inventory mode

@ -8,6 +8,7 @@
#include "dialogue.hpp"
#include "dialogue_history.hpp"
#include "stats_window.hpp"
#include "messagebox.hpp"
#include "../mwmechanics/mechanicsmanager.hpp"
#include "../mwinput/inputmanager.hpp"
@ -60,6 +61,7 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment
inventory = new InventoryWindow ();
#endif
console = new Console(w,h, environment, extensions);
mMessageBoxManager = new MessageBoxManager(this);
// The HUD is always on
hud->setVisible(true);
@ -82,6 +84,7 @@ WindowManager::WindowManager(MyGUI::Gui *_gui, MWWorld::Environment& environment
WindowManager::~WindowManager()
{
delete console;
delete mMessageBoxManager;
delete hud;
delete map;
delete menu;
@ -326,6 +329,14 @@ void WindowManager::updateVisible()
dialogueWindow->open();
return;
}
if(mode == GM_InterMessageBox)
{
if(!mMessageBoxManager->isInteractiveMessageBox()) {
setGuiMode(GM_Game);
}
return;
}
// Unsupported mode, switch back to game
@ -446,16 +457,22 @@ void WindowManager::removeDialog(OEngine::GUI::Layout*dialog)
void WindowManager::messageBox (const std::string& message, const std::vector<std::string>& buttons)
{
std::cout << "message box: " << message << std::endl;
if (!buttons.empty())
if (buttons.empty())
{
mMessageBoxManager->createMessageBox(message);
}
else
{
std::cout << "buttons: ";
std::copy (buttons.begin(), buttons.end(), std::ostream_iterator<std::string> (std::cout, ", "));
std::cout << std::endl;
mMessageBoxManager->createInteractiveMessageBox(message, buttons);
setGuiMode(GM_InterMessageBox);
}
}
int WindowManager::readPressedButton ()
{
return mMessageBoxManager->readPressedButton();
}
const std::string &WindowManager::getGameSettingString(const std::string &id, const std::string &default_)
{
const ESM::GameSetting *setting = environment.mWorld->getStore().gameSettings.search(id);
@ -555,6 +572,11 @@ void WindowManager::onClassChoice(int _index)
};
}
void WindowManager::onFrame (float frameDuration)
{
mMessageBoxManager->onFrame(frameDuration);
}
namespace MWGui
{

@ -62,6 +62,7 @@ namespace MWGui
class CreateClassDialog;
class BirthDialog;
class ReviewDialog;
class MessageBoxManager;
struct ClassPoint
{
@ -84,6 +85,7 @@ namespace MWGui
MapWindow *map;
MainMenu *menu;
StatsWindow *stats;
MessageBoxManager *mMessageBoxManager;
#if 0
InventoryWindow *inventory;
#endif
@ -245,8 +247,13 @@ namespace MWGui
void removeDialog(OEngine::GUI::Layout* dialog);
///< Hides dialog and schedules dialog to be deleted.
void messageBox (const std::string& message, const std::vector<std::string>& buttons);
int readPressedButton ();
///< returns the index of the pressed button or -1 if no button was pressed (->MessageBoxmanager->InteractiveMessageBox)
void onFrame (float frameDuration);
/**
* Fetches a GMST string from the store, if there is no setting with the given

@ -6,6 +6,7 @@
#include "OgreColourValue.h"
#include <OgreMath.h>
#include <Ogre.h>
namespace Ogre
{
@ -74,6 +75,7 @@ namespace MWRender
virtual void insertMesh(const std::string &mesh, Ogre::Vector3 vec, Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName, std::string sceneParent[], int elements, bool translateFirst);
virtual void insertMesh(const std::string &mesh);
virtual void rotateMesh(Ogre::Vector3 axis, Ogre::Radian angle, std::string sceneNodeName[], int elements);
virtual void scaleMesh(Ogre::Vector3 axis, std::string sceneNodeName[], int elements);

@ -182,11 +182,11 @@ void InteriorCellRender::insertMesh(const std::string &mesh, Ogre::Vector3 vec,
void InteriorCellRender::insertMesh(const std::string &mesh)
{
assert (insert);
assert (insert);
NifOgre::NIFLoader::load(mesh);
MovableObject *ent = scene.getMgr()->createEntity(mesh);
insert->attachObject(ent);
NifOgre::NIFLoader::load(mesh);
MovableObject *ent = scene.getMgr()->createEntity(mesh);
insert->attachObject(ent);
if (mInsertMesh.empty())
mInsertMesh = mesh;

@ -108,4 +108,5 @@ op 0x2000133: Journal
op 0x2000134: SetJournalIndex
op 0x2000135: GetJournalIndex
op 0x2000136: GetPCCell
opcodes 0x2000137-0x3ffffff unused
op 0x2000137: GetButtonPressed
opcodes 0x2000138-0x3ffffff unused

@ -15,42 +15,57 @@
namespace MWScript
{
namespace Gui
{
{
class OpEnableWindow : public Interpreter::Opcode0
{
MWGui::GuiWindow mWindow;
public:
OpEnableWindow (MWGui::GuiWindow window) : mWindow (window) {}
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
context.getWindowManager().allow (mWindow);
}
};
}
};
class OpShowDialogue : public Interpreter::Opcode0
{
MWGui::GuiMode mDialogue;
public:
OpShowDialogue (MWGui::GuiMode dialogue)
: mDialogue (dialogue)
{}
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
context.getInputManager().setGuiMode(mDialogue);
}
};
}
};
class OpGetButtonPressed : public Interpreter::Opcode0
{
public:
virtual void execute (Interpreter::Runtime& runtime)
{
InterpreterContext& context =
static_cast<InterpreterContext&> (runtime.getContext());
MWWorld::Ptr ptr = context.getReference();
runtime.push (context.getWindowManager().readPressedButton());
}
};
const int opcodeEnableBirthMenu = 0x200000e;
const int opcodeEnableClassMenu = 0x200000f;
@ -63,7 +78,8 @@ namespace MWScript
const int opcodeEnableStatsMenu = 0x2000016;
const int opcodeEnableRest = 0x2000017;
const int opcodeShowRestMenu = 0x2000018;
const int opcodeGetButtonPressed = 0x2000137;
void registerExtensions (Compiler::Extensions& extensions)
{
extensions.registerInstruction ("enablebirthmenu", "", opcodeEnableBirthMenu);
@ -80,10 +96,12 @@ namespace MWScript
extensions.registerInstruction ("enablerestmenu", "", opcodeEnableRest);
extensions.registerInstruction ("enablelevelupmenu", "", opcodeEnableRest);
extensions.registerInstruction ("showrestmenu", "", opcodeShowRestMenu);
extensions.registerFunction ("getbuttonpressed", 'l', "", opcodeGetButtonPressed);
}
void installOpcodes (Interpreter::Interpreter& interpreter)
{
interpreter.installSegment5 (opcodeEnableBirthMenu,
@ -115,6 +133,8 @@ namespace MWScript
interpreter.installSegment5 (opcodeShowRestMenu,
new OpShowDialogue (MWGui::GM_Rest));
interpreter.installSegment5 (opcodeGetButtonPressed, new OpGetButtonPressed);
}
}
}

@ -84,20 +84,25 @@ namespace MWSound
// finding. It takes DOS paths (any case, \\ slashes or / slashes)
// relative to the sound dir, and translates them into full paths
// of existing files in the filesystem, if they exist.
bool FSstrict;
FileFinder::FileFinder files;
FileFinder::FileFinderStrict strict;
FileFinder::FileFinder musicpath;
FileFinder::FileFinderStrict musicpathStrict;
SoundImpl(Ogre::Root *root, Ogre::Camera *camera,
const ESMS::ESMStore &str,
const std::string &soundDir)
const std::string &soundDir, const std::string &musicDir, bool fsstrict)
: mgr(new OEManager(SoundFactoryPtr(new SOUND_FACTORY)))
, updater(mgr)
, cameraTracker(mgr)
, store(str)
, files(soundDir)
, files(soundDir), strict(soundDir)
,musicpath(musicDir), musicpathStrict(musicDir)
{
FSstrict = fsstrict;
cout << "Sound output: " << SOUND_OUT << endl;
cout << "Sound decoder: " << SOUND_IN << endl;
// Attach the camera to the camera tracker
cameraTracker.followCamera(camera);
@ -111,6 +116,8 @@ namespace MWSound
cameraTracker.unfollowCamera();
}
static std::string toMp3(std::string str)
{
std::string::size_type i = str.rfind('.');
@ -122,28 +129,76 @@ namespace MWSound
return str;
}
bool hasFile(const std::string &str)
bool hasFile(const std::string &str, bool music = false)
{
if(files.has(str)) return true;
// Not found? Try with .mp3
return files.has(toMp3(str));
if(FSstrict == false)
{
if(music)
{
if(musicpath.has(str)) return true;
// Not found? Try with .mp3
return musicpath.has(toMp3(str));
}
else
{
if(files.has(str)) return true;
return files.has(toMp3(str));
}
}
else
{
if(music)
{
if(musicpathStrict.has(str)) return true;
// Not found? Try with .mp3
return musicpathStrict.has(toMp3(str));
}
else
{
if(strict.has(str)) return true;
return strict.has(toMp3(str));
}
}
}
// Convert a Morrowind sound path (eg. Fx\funny.wav) to full path
// with proper slash conversion (eg. datadir/Sound/Fx/funny.wav)
std::string convertPath(const std::string &str)
std::string convertPath(const std::string &str, bool music = false)
{
// Search and return
if(files.has(str))
return files.lookup(str);
// Try mp3 if the wav wasn't found
std::string mp3 = toMp3(str);
if(files.has(mp3))
return files.lookup(mp3);
if(FSstrict == false)
{
// Search and return
if(music && musicpath.has(str))
return musicpath.lookup(str);
else if(files.has(str))
return files.lookup(str);
// Try mp3 if the wav wasn't found
std::string mp3 = toMp3(str);
if(music && musicpath.has(mp3))
return musicpath.lookup(mp3);
else if(files.has(mp3))
return files.lookup(mp3);
}
else
{
if(music && musicpathStrict.has(str))
return musicpathStrict.lookup(str);
else if(strict.has(str))
return strict.lookup(str);
// Try mp3 if the wav wasn't found
std::string mp3 = toMp3(str);
if(music && musicpathStrict.has(mp3))
return musicpathStrict.lookup(mp3);
else if(strict.has(str))
return strict.lookup(mp3);
}
// Give up
return "";
// Give up
return "";
}
// Convert a soundId to file name, and modify the volume
@ -304,15 +359,31 @@ namespace MWSound
}
};
void SoundManager::streamMusicFull (const std::string& filename)
{
if(!mData) return;
// Play the sound and tell it to stream, if possible. TODO:
// Store the reference, the jukebox will need to check status,
// control volume etc.
if (mData->music)
mData->music->stop();
mData->music = mData->mgr->load(filename);
mData->music->setStreaming(true);
mData->music->setVolume(0.4);
mData->music->play();
}
SoundManager::SoundManager(Ogre::Root *root, Ogre::Camera *camera,
const ESMS::ESMStore &store,
boost::filesystem::path dataDir,
bool useSound)
: mData(NULL)
bool useSound, bool fsstrict)
: mData(NULL), fsStrict (fsstrict)
{
MP3Lookup(dataDir / "Music/Explore/");
if(useSound)
mData = new SoundImpl(root, camera, store, (dataDir / "Sound").string());
mData = new SoundImpl(root, camera, store, (dataDir / "Sound").string(), (dataDir / "Music").string(), fsstrict);
}
SoundManager::~SoundManager()
@ -321,6 +392,16 @@ namespace MWSound
delete mData;
}
void SoundManager::streamMusic(const std::string& filename)
{
if(mData->hasFile(filename, true))
{
std::string fullpath = mData->convertPath(filename, true);
streamMusicFull(fullpath);
}
}
void SoundManager::MP3Lookup(boost::filesystem::path dir)
{
boost::filesystem::directory_iterator dir_iter(dir), dir_end;
@ -353,7 +434,7 @@ namespace MWSound
try
{
std::cout << "Playing " << music << "\n";
streamMusic(music);
streamMusicFull(music);
}
catch(std::exception &e)
{
@ -397,21 +478,6 @@ namespace MWSound
return !mData->isPlaying(ptr, "_say_sound");
}
void SoundManager::streamMusic (const std::string& filename)
{
if(!mData) return;
// Play the sound and tell it to stream, if possible. TODO:
// Store the reference, the jukebox will need to check status,
// control volume etc.
if (mData->music)
mData->music->stop();
mData->music = mData->mgr->load(filename);
mData->music->setStreaming(true);
mData->music->setVolume(0.4);
mData->music->play();
}
void SoundManager::playSound (const std::string& soundId, float volume, float pitch)
{

@ -27,19 +27,28 @@ namespace MWSound
// Hide implementation details - engine.cpp is compiling
// enough as it is.
struct SoundImpl;
SoundImpl *mData;
std::vector<boost::filesystem::path> files;
bool fsStrict;
void streamMusicFull (const std::string& filename);
///< Play a soundifle
/// \param absolute filename
public:
SoundManager(Ogre::Root*, Ogre::Camera*, const ESMS::ESMStore &store,
boost::filesystem::path dataDir, bool useSound);
boost::filesystem::path dataDir, bool useSound, bool fsstrict);
~SoundManager();
void streamMusic(const std::string& filename);
///< Play a soundifle
/// \param filename name of a sound file in "Music/" in the data directory.
void startRandomTitle();
void MP3Lookup(boost::filesystem::path dir);
//struct SoundImpl;
bool isMusicPlaying();
SoundImpl getMData();
@ -51,9 +60,7 @@ namespace MWSound
bool sayDone (MWWorld::Ptr reference) const;
///< Is actor not speaking?
void streamMusic (const std::string& filename);
///< Play a soundifle
/// \param filename name of a sound file in "Music/" in the data directory.
void playSound (const std::string& soundId, float volume, float pitch);
///< Play a sound, independently of 3D-position

@ -409,9 +409,9 @@ namespace MWWorld
World::World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng,
const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir,
bool newGame, Environment& environment)
bool newGame, Environment& environment, const std::string& encoding)
: mSkyManager (0), mScene (renderer,physEng), mPlayer (0), mCurrentCell (0), mGlobalVariables (0),
mSky (false), mCellChanged (false), mEnvironment (environment)
mSky (false), mCellChanged (false), mEnvironment (environment), mNextDynamicRecord (0)
{
mPhysEngine = physEng;
@ -420,6 +420,7 @@ namespace MWWorld
std::cout << "Loading ESM " << masterPath.string() << "\n";
// This parses the ESM file and loads a sample cell
mEsm.setEncoding(encoding);
mEsm.open (masterPath.string());
mStore.load (mEsm);
@ -870,4 +871,36 @@ namespace MWWorld
{
return mScene.toggleRenderMode (mode);
}
std::pair<std::string, const ESM::Potion *> World::createRecord (const ESM::Potion& record)
{
/// \todo Rewrite the ESMStore so that a dynamic 2nd ESMStore can be attached to it.
/// This function should then insert the record into the 2nd store (the code for this
/// should also be moved to the ESMStore class). It might be a good idea to review
/// the STL-container usage of the ESMStore before the rewrite.
std::ostringstream stream;
stream << "$dynamic" << mNextDynamicRecord++;
const ESM::Potion *created =
&mStore.potions.list.insert (std::make_pair (stream.str(), record)).first->second;
mStore.all.insert (std::make_pair (stream.str(), ESM::REC_ALCH));
return std::make_pair (stream.str(), created);
}
std::pair<std::string, const ESM::Class *> World::createRecord (const ESM::Class& record)
{
/// \todo See function above.
std::ostringstream stream;
stream << "$dynamic" << mNextDynamicRecord++;
const ESM::Class *created =
&mStore.classes.list.insert (std::make_pair (stream.str(), record)).first->second;
mStore.all.insert (std::make_pair (stream.str(), ESM::REC_CLAS));
return std::make_pair (stream.str(), created);
}
}

@ -79,6 +79,7 @@ namespace MWWorld
bool mSky;
bool mCellChanged;
Environment& mEnvironment;
int mNextDynamicRecord;
OEngine::Physic::PhysicEngine* mPhysEngine;
@ -115,7 +116,7 @@ namespace MWWorld
World (OEngine::Render::OgreRenderer& renderer, OEngine::Physic::PhysicEngine* physEng,
const Files::Collections& fileCollections,
const std::string& master, const boost::filesystem::path& resDir, bool newGame,
Environment& environment);
Environment& environment, const std::string& encoding);
~World();
@ -202,6 +203,14 @@ namespace MWWorld
bool toggleRenderMode (RenderMode mode);
///< Toggle a render mode.
///< \return Resulting mode
std::pair<std::string, const ESM::Potion *> createRecord (const ESM::Potion& record);
///< Create a new recrod (of type potion) in the ESM store.
/// \return ID, pointer to created record
std::pair<std::string, const ESM::Class *> createRecord (const ESM::Class& record);
///< Create a new recrod (of type class) in the ESM store.
/// \return ID, pointer to created record
};
}

@ -23,6 +23,7 @@
#include "bsa_archive.hpp"
#include <OgreFileSystem.h>
#include <OgreArchive.h>
#include <OgreArchiveFactory.h>
#include <OgreArchiveManager.h>
@ -36,7 +37,186 @@ using namespace Ogre;
using namespace Mangle::Stream;
using namespace Bsa;
struct ciLessBoost : std::binary_function<std::string, std::string, bool>
{
bool operator() (const std::string & s1, const std::string & s2) const {
//case insensitive version of is_less
return lexicographical_compare(s1, s2, boost::algorithm::is_iless());
}
};
static bool fsstrict = false;
/// An OGRE Archive wrapping a BSAFile archive
class DirArchive: public Ogre::FileSystemArchive
{
boost::filesystem::path currentdir;
std::map<std::string, std::vector<std::string>, ciLessBoost> m;
unsigned int cutoff;
bool comparePortion(std::string file1, std::string file2, int start, int size) const
{
for(int i = start; i < start+size; i++)
{
char one = file1.at(i);
char two = file2.at(i);
if(tolower(one) != tolower(two) )
return false;
}
return true;
}
public:
DirArchive(const String& name)
: FileSystemArchive(name, "Dir"), currentdir (name)
{
mType = "Dir";
std::string s = name;
cutoff = s.size() + 1;
if(fsstrict == false)
populateMap(currentdir);
}
void populateMap(boost::filesystem::path d){
//need to cut off first
boost::filesystem::directory_iterator dir_iter(d), dir_end;
std::vector<std::string> filesind;
boost::filesystem::path f;
for(;dir_iter != dir_end; dir_iter++)
{
if(boost::filesystem::is_directory(*dir_iter))
populateMap(*dir_iter);
else
{
f = *dir_iter;
std::string s = f.string();
std::string small;
if(cutoff < s.size())
small = s.substr(cutoff, s.size() - cutoff);
else
small = s.substr(cutoff - 1, s.size() - cutoff);
filesind.push_back(small);
}
}
std::string small;
std::string original = d.string();
if(cutoff < original.size())
small = original.substr(cutoff, original.size() - cutoff);
else
small = original.substr(cutoff - 1, original.size() - cutoff);
m[small] = filesind;
}
bool isCaseSensitive() const { return fsstrict; }
// The archive is loaded in the constructor, and never unloaded.
void load() {}
void unload() {}
bool exists(const String& filename) {
std::string copy = filename;
for (unsigned int i = 0; i < filename.size(); i++)
{
if(copy.at(i) == '\\' ){
copy.replace(i, 1, "/");
}
}
if(copy.at(0) == '\\' || copy.at(0) == '/')
{
copy.erase(0, 1);
}
if(fsstrict == true)
{
//std::cout << "fsstrict " << copy << "\n";
return FileSystemArchive::exists(copy);
}
int last = copy.size() - 1;
int i = last;
for (;last >= 0; i--)
{
if(copy.at(i) == '/' || copy.at(i) == '\\')
break;
}
std::string folder = copy.substr(0, i); //folder with no slash
std::vector<std::string>& current = m[folder];
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
{
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
return FileSystemArchive::exists(*iter);
}
}
return false;
}
DataStreamPtr open(const String& filename, bool readonly = true) const
{
std::map<std::string, std::vector<std::string>, ciLessBoost> mlocal = m;
std::string copy = filename;
for (unsigned int i = 0; i < filename.size(); i++)
{
if(copy.at(i) == '\\' ){
copy.replace(i, 1, "/");
}
}
if(copy.at(0) == '\\' || copy.at(0) == '/')
{
copy.erase(0, 1);
}
if(fsstrict == true)
{
return FileSystemArchive::open(copy, readonly);
}
int last = copy.size() - 1;
int i = last;
for (;last >= 0; i--)
{
if(copy.at(i) == '/' || copy.at(i) == '\\')
break;
}
std::string folder = copy.substr(0, i); //folder with no slash
std::vector<std::string> current = mlocal[folder];
for(std::vector<std::string>::iterator iter = current.begin(); iter != current.end(); iter++)
{
if(comparePortion(*iter, copy, i + 1, copy.size() - i -1) == true){
return FileSystemArchive::open(*iter, readonly);
}
}
DataStreamPtr p;
return p;
}
};
class BSAArchive : public Archive
{
BSAFile arc;
@ -149,7 +329,27 @@ public:
void destroyInstance( Archive* arch) { delete arch; }
};
class DirArchiveFactory : public FileSystemArchiveFactory
{
public:
const String& getType() const
{
static String name = "Dir";
return name;
}
Archive *createInstance( const String& name )
{
return new DirArchive(name);
}
void destroyInstance( Archive* arch) { delete arch; }
};
static bool init = false;
static bool init2 = false;
static void insertBSAFactory()
{
if(!init)
@ -159,6 +359,15 @@ static void insertBSAFactory()
}
}
static void insertDirFactory()
{
if(!init2)
{
ArchiveManager::getSingleton().addArchiveFactory( new DirArchiveFactory );
init2 = true;
}
}
}
namespace Bsa
@ -173,4 +382,13 @@ void addBSA(const std::string& name, const std::string& group)
addResourceLocation(name, "BSA", group);
}
void addDir(const std::string& name, const bool& fs, const std::string& group)
{
fsstrict = fs;
insertDirFactory();
ResourceGroupManager::getSingleton().
addResourceLocation(name, "Dir", group);
}
}

@ -22,6 +22,9 @@
*/
#include <string>
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <algorithm>
#ifndef BSA_BSA_ARCHIVE_H
#define BSA_BSA_ARCHIVE_H
@ -32,6 +35,7 @@ namespace Bsa
/// Add the given BSA file as an input archive in the Ogre resource
/// system.
void addBSA(const std::string& file, const std::string& group="General");
void addDir(const std::string& file, const bool& fs, const std::string& group="General");
}

@ -326,7 +326,7 @@ std::string ESMReader::getString(int size)
mEsm->read(ptr, size);
// Convert to UTF8 and return
return ToUTF8::getUtf8(ToUTF8::WINDOWS_1252);
return ToUTF8::getUtf8(mEncoding);
}
void ESMReader::fail(const std::string &msg)
@ -344,4 +344,21 @@ void ESMReader::fail(const std::string &msg)
throw std::runtime_error(ss.str());
}
void ESMReader::setEncoding(const std::string& encoding)
{
if (encoding == "win1250")
{
mEncoding = ToUTF8::WINDOWS_1250;
}
else if (encoding == "win1251")
{
mEncoding = ToUTF8::WINDOWS_1251;
}
else
{
// Default Latin encoding
mEncoding = ToUTF8::WINDOWS_1252;
}
}
}

@ -350,6 +350,9 @@ public:
/// Used for error handling
void fail(const std::string &msg);
/// Sets font encoding for ESM strings
void setEncoding(const std::string& encoding);
private:
Mangle::Stream::StreamPtr mEsm;
@ -360,6 +363,7 @@ private:
SaveData mSaveData;
MasterList mMasters;
ToUTF8::FromType mEncoding;
};
}
#endif

@ -85,7 +85,13 @@ void ESMStore::load(ESMReader &esm)
dialogue = 0;
// Insert the reference into the global lookup
if(!id.empty())
if(!id.empty() &&
(n.val==REC_ACTI || n.val==REC_ALCH || n.val==REC_APPA || n.val==REC_ARMO ||
n.val==REC_BOOK || n.val==REC_CLOT || n.val==REC_CONT || n.val==REC_CREA ||
n.val==REC_DOOR || n.val==REC_INGR || n.val==REC_LEVC || n.val==REC_LEVI ||
n.val==REC_LIGH || n.val==REC_LOCK || n.val==REC_MISC || n.val==REC_NPC_ ||
n.val==REC_PROB || n.val==REC_REPA || n.val==REC_STAT || n.val==REC_WEAP)
)
all[id] = n.val;
}
}

@ -20,9 +20,9 @@ class FileFinderT
void add(const boost::filesystem::path &pth)
{
std::string file = pth.string();
std::string key = file.substr(cut);
owner->table[key] = file;
std::string file = pth.string();
std::string key = file.substr(cut);
owner->table[key] = file;
}
};
@ -50,17 +50,18 @@ public:
bool has(const std::string& file) const
{
return table.find(file) != table.end();
return table.find(file) != table.end();
}
// Find the full path from a relative path.
const std::string &lookup(const std::string& file) const
{
return table.find(file)->second;
return table.find(file)->second;
}
};
// The default is to use path_less for equality checks
typedef FileFinderT<path_less> FileFinder;
typedef FileFinderT<path_slash> FileFinderStrict;
}
#endif

@ -44,6 +44,41 @@ struct path_less
return compareString(a.c_str(), b.c_str()) < 0;
}
};
struct path_slash
{
int compareChar(char a, char b) const
{
if(a>b) return 1;
else if(a<b) return -1;
return 0;
}
int comparePathChar(char a, char b) const
{
if(a == '\\') a = '/';
if(b == '\\') b = '/';
return compareChar(a,b);
}
int compareString(const char *a, const char *b) const
{
while(*a && *b)
{
int i = comparePathChar(*a,*b);
if(i != 0) return i;
a++; b++;
}
// At this point, one or both of the chars is a null terminator.
// Normal char comparison will get the correct final result here.
return compareChar(*a,*b);
}
bool operator() (const std::string& a, const std::string& b) const
{
return compareString(a.c_str(), b.c_str()) < 0;
}
};
}
#endif

@ -23,11 +23,12 @@ namespace Files
return left<right;
std::size_t min = std::min (left.length(), right.length());
std::locale loc;
for (std::size_t i=0; i<min; ++i)
{
char l = std::tolower (left[i],std::locale());
char r = std::tolower (right[i],std::locale());
char l = std::tolower (left[i], loc);
char r = std::tolower (right[i], loc);
if (l<r)
return true;

@ -25,6 +25,7 @@
#define _NIF_DATA_H_
#include "controlled.hpp"
#include <iostream>
namespace Nif
{
@ -433,67 +434,70 @@ public:
class NiKeyframeData : public Record
{
public:
void read(NIFFile *nif)
{
// Rotations first
int count = nif->getInt();
if(count)
{
int type = nif->getInt();
if(type == 1)
nif->skip(count*4*5); // time + quaternion
else if(type == 3)
nif->skip(count*4*8); // rot1 + tension+bias+continuity
else if(type == 4)
{
for(int j=0;j<count;j++)
{
nif->getFloat(); // time
for(int i=0; i<3; i++)
{
int cnt = nif->getInt();
int type = nif->getInt();
if(type == 1)
nif->skip(cnt*4*2); // time + unknown
else if(type == 2)
nif->skip(cnt*4*4); // time + unknown vector
else nif->fail("Unknown sub-rotation type");
}
}
}
else nif->fail("Unknown rotation type in NiKeyframeData");
}
// Then translation
count = nif->getInt();
if(count)
{
int type = nif->getInt();
if(type == 1) nif->getFloatLen(count*4); // time + translation
else if(type == 2)
nif->getFloatLen(count*10); // trans1 + forward + backward
else if(type == 3)
nif->getFloatLen(count*7); // trans1 + tension,bias,continuity
else nif->fail("Unknown translation type");
}
// Finally, scalings
count = nif->getInt();
if(count)
{
int type = nif->getInt();
int size = 0;
if(type == 1) size = 2; // time+scale
else if(type == 2) size = 4; // 1 + forward + backward (floats)
else if(type == 3) size = 5; // 1 + tbc
else nif->fail("Unknown scaling type");
nif->getFloatLen(count*size);
}
}
public:
void read(NIFFile *nif)
{
// Rotations first
int count = nif->getInt();
if(count)
{
int type = nif->getInt();
if(type == 1)
nif->skip(count*4*5); // time + quaternion
else if(type == 3)
nif->skip(count*4*8); // rot1 + tension+bias+continuity
else if(type == 4)
{
for(int j=0;j<count;j++)
{
nif->getFloat(); // time
for(int i=0; i<3; i++)
{
int cnt = nif->getInt();
int type = nif->getInt();
if(type == 1)
nif->skip(cnt*4*2); // time + unknown
else if(type == 2)
nif->skip(cnt*4*4); // time + unknown vector
else nif->fail("Unknown sub-rotation type");
}
}
}
else nif->fail("Unknown rotation type in NiKeyframeData");
}
// Then translation
count = nif->getInt();
if(count)
{
int type = nif->getInt();
if(type == 1)
nif->getFloatLen(count*4); // time + translation
else if(type == 2)
nif->getFloatLen(count*10); // trans1 + forward + backward
else if(type == 3)
nif->getFloatLen(count*7); // trans1 + tension,bias,continuity
else nif->fail("Unknown translation type");
}
// Finally, scalings
count = nif->getInt();
if(count)
{
int type = nif->getInt();
int size = 0;
if(type == 1) size = 2; // time+scale
else if(type == 2) size = 4; // 1 + forward + backward (floats)
else if(type == 3) size = 5; // 1 + tbc
else nif->fail("Unknown scaling type");
nif->getFloatLen(count*size);
}
}
};
} // Namespace

@ -83,11 +83,11 @@ Vector3 NIFLoader::convertVector3(const Nif::Vector& vec)
Quaternion NIFLoader::convertRotation(const Nif::Matrix& rot)
{
Real matrix[3][3];
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
matrix[i][j] = rot.v[i].array[j];
return Quaternion(Matrix3(matrix));
}
@ -267,7 +267,7 @@ void NIFLoader::createMaterial(const String &name,
}
else
pass->setDepthWriteEnabled(true); */
// Add transparency if NiAlphaProperty was present
if (alphaFlags != -1)
@ -348,16 +348,16 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std
sub->vertexData = new VertexData();
sub->vertexData->vertexCount = numVerts;
sub->useSharedVertices = false;
VertexDeclaration *decl = sub->vertexData->vertexDeclaration;
decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION);
HardwareVertexBufferSharedPtr vbuf =
HardwareBufferManager::getSingleton().createVertexBuffer(
VertexElement::getTypeSize(VET_FLOAT3),
numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY);
vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true);
VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding;
bind->setBinding(nextBuf++, vbuf);
@ -694,7 +694,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou
if (verIndex < data->normals.length)
{
Vector3 absNormalsPos = vecRot * Vector3(ptrNormals + verIndex *3);
for (int j=0; j<3; j++)
(ptrNormals + verIndex*3)[j] = absNormalsPos[j];
}
@ -854,7 +854,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
}
for (; i<n; i++)
{
if (list.has(i))
handleNode(&list[i], flags, node->trafo, bounds, bone);
}
@ -869,7 +869,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
Tri Chest
*/
if((isChest && stack < 10 ) || (isHands && counter < 3) || !(isChest || isHands)){ //(isBeast && isChest && stack < 10 && counter == skincounter )
std::string name = node->name.toString();
//if (isChest)
//std::cout << "NAME: " << name << "\n";
@ -896,15 +896,15 @@ void NIFLoader::handleNode(Nif::Node *node, int flags,
//if(isBeast && isChest)
//cout << "Handling Shape, Stack " << stack <<"\n";
counter++;
}
/*if(isHands){
//cout << "Handling Shape, Stack " << stack <<"\n";
counter++;
}*/
}
stack--;
@ -925,7 +925,7 @@ void NIFLoader::loadResource(Resource *resource)
//std::cout <<"NAME:" << name;
//if(name.length() >= 20)
// {std::string split = name.substr(name.length() - 20, 20);
//if(name ==
//if(name ==
//std::cout <<"NAME:" << name << "LEN: " << name.length() << "\n";
const std::string test ="meshes\\b\\B_N_Dark Elf_M_Skins.NIF";
const std::string test2 ="meshes\\b\\B_N_Dark Elf_M_Skins.nif";
@ -953,15 +953,15 @@ void NIFLoader::loadResource(Resource *resource)
const std::string test24 ="meshes\\b\\B_N_High Elf_M_Skins.nif";
//std::cout <<"LEN1:" << test.length() << "TEST: " << test << "\n";
if(name.compare(test) == 0 || name.compare(test2) == 0 || name.compare(test3) == 0 || name.compare(test4) == 0 ||
name.compare(test5) == 0 || name.compare(test6) == 0 || name.compare(test7) == 0 || name.compare(test8) == 0 || name.compare(test9) == 0 ||
name.compare(test10) == 0 || name.compare(test11) == 0 || name.compare(test12) == 0 || name.compare(test13) == 0 ||
name.compare(test14) == 0 || name.compare(test15) == 0 || name.compare(test16) == 0 || name.compare(test17) == 0 ||
name.compare(test18) == 0 || name.compare(test19) == 0 || name.compare(test20) == 0 || name.compare(test21) == 0 ||
name.compare(test22) == 0 || name.compare(test23) == 0 || name.compare(test24) == 0
){
//std::cout << "Welcome Chest\n";
isChest = true;
@ -1030,7 +1030,7 @@ void NIFLoader::loadResource(Resource *resource)
std::cout << "\n\n\nWelcome FRedguard Chest\n\n\n";
isChest = true;
}*/
//if(split== "Skins.NIF")
// std::cout << "\nSPECIAL PROPS\n";
resourceName = "";
@ -1102,14 +1102,14 @@ void NIFLoader::loadResource(Resource *resource)
// mesh->setSkeletonName(getSkeletonName());
}
MeshPtr NIFLoader::load(const std::string &name,
MeshPtr NIFLoader::load(const std::string &name,
const std::string &group)
{
MeshManager *m = MeshManager::getSingletonPtr();
// Check if the resource already exists
ResourcePtr ptr = m->getByName(name, group);
MeshPtr resize;
const std::string beast1 ="meshes\\b\\B_N_Khajiit_F_Skins.nif";
const std::string beast2 ="meshes\\b\\B_N_Khajiit_M_Skins.nif";
const std::string beast3 ="meshes\\b\\B_N_Argonian_F_Skins.nif";
@ -1120,8 +1120,8 @@ MeshPtr NIFLoader::load(const std::string &name,
const std::string beasttail3 ="tail\\b\\B_N_Argonian_F_Skins.nif";
const std::string beasttail4 ="tail\\b\\B_N_Argonian_M_Skins.nif";
if (!ptr.isNull()){
if (!ptr.isNull()){
//if(pieces > 1)
//cout << "It exists\n";
resize = MeshPtr(ptr);
@ -1132,17 +1132,17 @@ MeshPtr NIFLoader::load(const std::string &name,
{
resize = MeshManager::getSingleton().createManual(name, group, NIFLoader::getSingletonPtr());
//cout <<"EXISTING" << name << "\n";
//if(pieces > 1)
//cout << "Creating it\n";
//resize->load();
//resize->reload();
//return 0;
ResourcePtr ptr = m->getByName(name, group);
resize = MeshPtr(ptr);
//NIFLoader::getSingletonPtr()->
/*ResourcePtr ptr = m->getByName(name, group);
if (!ptr.isNull()){
@ -1153,7 +1153,7 @@ MeshPtr NIFLoader::load(const std::string &name,
}
return resize;
}
/* More code currently not in use, from the old D source. This was
used in the first attempt at loading NIF meshes, where each submesh

@ -76,11 +76,11 @@ class NIFLoader : Ogre::ManualResourceLoader
virtual void loadResource(Ogre::Resource *resource);
static Ogre::MeshPtr load(const std::string &name,
static Ogre::MeshPtr load(const std::string &name,
const std::string &group="General");
Ogre::Vector3 convertVector3(const Nif::Vector& vec);
Ogre::Quaternion convertRotation(const Nif::Matrix& rot);
@ -116,7 +116,7 @@ class NIFLoader : Ogre::ManualResourceLoader
{
return resourceName + ".skel";
}
// This is the interface to the Ogre resource system. It allows us to
// load NIFs from BSAs, in the file system and in any other place we
// tell Ogre to look (eg. in zip or rar files.) It's also used to
@ -134,8 +134,7 @@ class NIFLoader : Ogre::ManualResourceLoader
int counter;
int numbers;
int stack;
std::multimap<std::string,std::string> MaterialMap;
std::multimap<std::string,std::string> MaterialMap;
// pointer to the ogre mesh which is currently build
Ogre::Mesh *mesh;

@ -88,7 +88,23 @@ int main()
// Write namespace
cout << "namespace ToUTF8\n{\n\n";
// Central European and Eastern European languages that use Latin script, such as
// Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian, Serbian (Latin script), Romanian and Albanian.
cout << "\n/// Central European and Eastern European languages that use Latin script,"
"\n/// such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian,"
"\n/// Serbian (Latin script), Romanian and Albanian."
"\n";
write_table("WINDOWS-1250", "windows_1250");
// Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic and other languages
cout << "\n/// Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic"
"\n/// and other languages"
"\n";
write_table("WINDOWS-1251", "windows_1251");
// English
cout << "\n/// Latin alphabet used by English and some other Western languages"
"\n";
write_table("WINDOWS-1252", "windows_1252");
// Close namespace

@ -4,6 +4,533 @@
namespace ToUTF8
{
/// Central European and Eastern European languages that use Latin script,
/// such as Polish, Czech, Slovak, Hungarian, Slovene, Bosnian, Croatian,
/// Serbian (Latin script), Romanian and Albanian.
static char windows_1250[] =
{
0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7, 0x0, 0x0, 0x0, 0x0,
0x1, 0x8, 0x0, 0x0, 0x0, 0x0,
0x1, 0x9, 0x0, 0x0, 0x0, 0x0,
0x1, 0xa, 0x0, 0x0, 0x0, 0x0,
0x1, 0xb, 0x0, 0x0, 0x0, 0x0,
0x1, 0xc, 0x0, 0x0, 0x0, 0x0,
0x1, 0xd, 0x0, 0x0, 0x0, 0x0,
0x1, 0xe, 0x0, 0x0, 0x0, 0x0,
0x1, 0xf, 0x0, 0x0, 0x0, 0x0,
0x1, 0x10, 0x0, 0x0, 0x0, 0x0,
0x1, 0x11, 0x0, 0x0, 0x0, 0x0,
0x1, 0x12, 0x0, 0x0, 0x0, 0x0,
0x1, 0x13, 0x0, 0x0, 0x0, 0x0,
0x1, 0x14, 0x0, 0x0, 0x0, 0x0,
0x1, 0x15, 0x0, 0x0, 0x0, 0x0,
0x1, 0x16, 0x0, 0x0, 0x0, 0x0,
0x1, 0x17, 0x0, 0x0, 0x0, 0x0,
0x1, 0x18, 0x0, 0x0, 0x0, 0x0,
0x1, 0x19, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x20, 0x0, 0x0, 0x0, 0x0,
0x1, 0x21, 0x0, 0x0, 0x0, 0x0,
0x1, 0x22, 0x0, 0x0, 0x0, 0x0,
0x1, 0x23, 0x0, 0x0, 0x0, 0x0,
0x1, 0x24, 0x0, 0x0, 0x0, 0x0,
0x1, 0x25, 0x0, 0x0, 0x0, 0x0,
0x1, 0x26, 0x0, 0x0, 0x0, 0x0,
0x1, 0x27, 0x0, 0x0, 0x0, 0x0,
0x1, 0x28, 0x0, 0x0, 0x0, 0x0,
0x1, 0x29, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x30, 0x0, 0x0, 0x0, 0x0,
0x1, 0x31, 0x0, 0x0, 0x0, 0x0,
0x1, 0x32, 0x0, 0x0, 0x0, 0x0,
0x1, 0x33, 0x0, 0x0, 0x0, 0x0,
0x1, 0x34, 0x0, 0x0, 0x0, 0x0,
0x1, 0x35, 0x0, 0x0, 0x0, 0x0,
0x1, 0x36, 0x0, 0x0, 0x0, 0x0,
0x1, 0x37, 0x0, 0x0, 0x0, 0x0,
0x1, 0x38, 0x0, 0x0, 0x0, 0x0,
0x1, 0x39, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x40, 0x0, 0x0, 0x0, 0x0,
0x1, 0x41, 0x0, 0x0, 0x0, 0x0,
0x1, 0x42, 0x0, 0x0, 0x0, 0x0,
0x1, 0x43, 0x0, 0x0, 0x0, 0x0,
0x1, 0x44, 0x0, 0x0, 0x0, 0x0,
0x1, 0x45, 0x0, 0x0, 0x0, 0x0,
0x1, 0x46, 0x0, 0x0, 0x0, 0x0,
0x1, 0x47, 0x0, 0x0, 0x0, 0x0,
0x1, 0x48, 0x0, 0x0, 0x0, 0x0,
0x1, 0x49, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x50, 0x0, 0x0, 0x0, 0x0,
0x1, 0x51, 0x0, 0x0, 0x0, 0x0,
0x1, 0x52, 0x0, 0x0, 0x0, 0x0,
0x1, 0x53, 0x0, 0x0, 0x0, 0x0,
0x1, 0x54, 0x0, 0x0, 0x0, 0x0,
0x1, 0x55, 0x0, 0x0, 0x0, 0x0,
0x1, 0x56, 0x0, 0x0, 0x0, 0x0,
0x1, 0x57, 0x0, 0x0, 0x0, 0x0,
0x1, 0x58, 0x0, 0x0, 0x0, 0x0,
0x1, 0x59, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x60, 0x0, 0x0, 0x0, 0x0,
0x1, 0x61, 0x0, 0x0, 0x0, 0x0,
0x1, 0x62, 0x0, 0x0, 0x0, 0x0,
0x1, 0x63, 0x0, 0x0, 0x0, 0x0,
0x1, 0x64, 0x0, 0x0, 0x0, 0x0,
0x1, 0x65, 0x0, 0x0, 0x0, 0x0,
0x1, 0x66, 0x0, 0x0, 0x0, 0x0,
0x1, 0x67, 0x0, 0x0, 0x0, 0x0,
0x1, 0x68, 0x0, 0x0, 0x0, 0x0,
0x1, 0x69, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x70, 0x0, 0x0, 0x0, 0x0,
0x1, 0x71, 0x0, 0x0, 0x0, 0x0,
0x1, 0x72, 0x0, 0x0, 0x0, 0x0,
0x1, 0x73, 0x0, 0x0, 0x0, 0x0,
0x1, 0x74, 0x0, 0x0, 0x0, 0x0,
0x1, 0x75, 0x0, 0x0, 0x0, 0x0,
0x1, 0x76, 0x0, 0x0, 0x0, 0x0,
0x1, 0x77, 0x0, 0x0, 0x0, 0x0,
0x1, 0x78, 0x0, 0x0, 0x0, 0x0,
0x1, 0x79, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7f, 0x0, 0x0, 0x0, 0x0,
0x3, 0xe2, 0x82, 0xac, 0x0, 0x0,
0x1, 0x20, 0x0, 0x0, 0x0, 0x0, // not part of this charset
0x3, 0xe2, 0x80, 0x9a, 0x0, 0x0,
0x1, 0x20, 0x0, 0x0, 0x0, 0x0, // not part of this charset
0x3, 0xe2, 0x80, 0x9e, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xa6, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xa0, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xa1, 0x0, 0x0,
0x1, 0x20, 0x0, 0x0, 0x0, 0x0, // not part of this charset
0x3, 0xe2, 0x80, 0xb0, 0x0, 0x0,
0x2, 0xc5, 0xa0, 0x0, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xb9, 0x0, 0x0,
0x2, 0xc5, 0x9a, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xa4, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xbd, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xb9, 0x0, 0x0, 0x0,
0x1, 0x20, 0x0, 0x0, 0x0, 0x0, // not part of this charset
0x3, 0xe2, 0x80, 0x98, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x99, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x9c, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x9d, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xa2, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x93, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x94, 0x0, 0x0,
0x1, 0x20, 0x0, 0x0, 0x0, 0x0, // not part of this charset
0x3, 0xe2, 0x84, 0xa2, 0x0, 0x0,
0x2, 0xc5, 0xa1, 0x0, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xba, 0x0, 0x0,
0x2, 0xc5, 0x9b, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xa5, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xbe, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xba, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa0, 0x0, 0x0, 0x0,
0x2, 0xcb, 0x87, 0x0, 0x0, 0x0,
0x2, 0xcb, 0x98, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x81, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa4, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x84, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa6, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa7, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa8, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa9, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x9e, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xab, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xac, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xad, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xae, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xbb, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb0, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb1, 0x0, 0x0, 0x0,
0x2, 0xcb, 0x9b, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x82, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb4, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb5, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb6, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb7, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb8, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x85, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x9f, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xbb, 0x0, 0x0, 0x0,
0x2, 0xc4, 0xbd, 0x0, 0x0, 0x0,
0x2, 0xcb, 0x9d, 0x0, 0x0, 0x0,
0x2, 0xc4, 0xbe, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xbc, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x94, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x81, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x82, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x82, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x84, 0x0, 0x0, 0x0,
0x2, 0xc4, 0xb9, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x86, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x87, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x8c, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x89, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x98, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x8b, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x9a, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x8d, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x8e, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x8e, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x90, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x83, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x87, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x93, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x94, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x90, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x96, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x97, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x98, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xae, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x9a, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xb0, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x9c, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x9d, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xa2, 0x0, 0x0, 0x0,
0x2, 0xc3, 0x9f, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x95, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xa1, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xa2, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x83, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xa4, 0x0, 0x0, 0x0,
0x2, 0xc4, 0xba, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x87, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xa7, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x8d, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xa9, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x99, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xab, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x9b, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xad, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xae, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x8f, 0x0, 0x0, 0x0,
0x2, 0xc4, 0x91, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x84, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x88, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xb3, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xb4, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x91, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xb6, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xb7, 0x0, 0x0, 0x0,
0x2, 0xc5, 0x99, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xaf, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xba, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xb1, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xbc, 0x0, 0x0, 0x0,
0x2, 0xc3, 0xbd, 0x0, 0x0, 0x0,
0x2, 0xc5, 0xa3, 0x0, 0x0, 0x0,
0x2, 0xcb, 0x99, 0x0, 0x0, 0x0
};
/// Cyrillic alphabet such as Russian, Bulgarian, Serbian Cyrillic
/// and other languages
static char windows_1251[] =
{
0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7, 0x0, 0x0, 0x0, 0x0,
0x1, 0x8, 0x0, 0x0, 0x0, 0x0,
0x1, 0x9, 0x0, 0x0, 0x0, 0x0,
0x1, 0xa, 0x0, 0x0, 0x0, 0x0,
0x1, 0xb, 0x0, 0x0, 0x0, 0x0,
0x1, 0xc, 0x0, 0x0, 0x0, 0x0,
0x1, 0xd, 0x0, 0x0, 0x0, 0x0,
0x1, 0xe, 0x0, 0x0, 0x0, 0x0,
0x1, 0xf, 0x0, 0x0, 0x0, 0x0,
0x1, 0x10, 0x0, 0x0, 0x0, 0x0,
0x1, 0x11, 0x0, 0x0, 0x0, 0x0,
0x1, 0x12, 0x0, 0x0, 0x0, 0x0,
0x1, 0x13, 0x0, 0x0, 0x0, 0x0,
0x1, 0x14, 0x0, 0x0, 0x0, 0x0,
0x1, 0x15, 0x0, 0x0, 0x0, 0x0,
0x1, 0x16, 0x0, 0x0, 0x0, 0x0,
0x1, 0x17, 0x0, 0x0, 0x0, 0x0,
0x1, 0x18, 0x0, 0x0, 0x0, 0x0,
0x1, 0x19, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x1f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x20, 0x0, 0x0, 0x0, 0x0,
0x1, 0x21, 0x0, 0x0, 0x0, 0x0,
0x1, 0x22, 0x0, 0x0, 0x0, 0x0,
0x1, 0x23, 0x0, 0x0, 0x0, 0x0,
0x1, 0x24, 0x0, 0x0, 0x0, 0x0,
0x1, 0x25, 0x0, 0x0, 0x0, 0x0,
0x1, 0x26, 0x0, 0x0, 0x0, 0x0,
0x1, 0x27, 0x0, 0x0, 0x0, 0x0,
0x1, 0x28, 0x0, 0x0, 0x0, 0x0,
0x1, 0x29, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x2f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x30, 0x0, 0x0, 0x0, 0x0,
0x1, 0x31, 0x0, 0x0, 0x0, 0x0,
0x1, 0x32, 0x0, 0x0, 0x0, 0x0,
0x1, 0x33, 0x0, 0x0, 0x0, 0x0,
0x1, 0x34, 0x0, 0x0, 0x0, 0x0,
0x1, 0x35, 0x0, 0x0, 0x0, 0x0,
0x1, 0x36, 0x0, 0x0, 0x0, 0x0,
0x1, 0x37, 0x0, 0x0, 0x0, 0x0,
0x1, 0x38, 0x0, 0x0, 0x0, 0x0,
0x1, 0x39, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x3f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x40, 0x0, 0x0, 0x0, 0x0,
0x1, 0x41, 0x0, 0x0, 0x0, 0x0,
0x1, 0x42, 0x0, 0x0, 0x0, 0x0,
0x1, 0x43, 0x0, 0x0, 0x0, 0x0,
0x1, 0x44, 0x0, 0x0, 0x0, 0x0,
0x1, 0x45, 0x0, 0x0, 0x0, 0x0,
0x1, 0x46, 0x0, 0x0, 0x0, 0x0,
0x1, 0x47, 0x0, 0x0, 0x0, 0x0,
0x1, 0x48, 0x0, 0x0, 0x0, 0x0,
0x1, 0x49, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x4f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x50, 0x0, 0x0, 0x0, 0x0,
0x1, 0x51, 0x0, 0x0, 0x0, 0x0,
0x1, 0x52, 0x0, 0x0, 0x0, 0x0,
0x1, 0x53, 0x0, 0x0, 0x0, 0x0,
0x1, 0x54, 0x0, 0x0, 0x0, 0x0,
0x1, 0x55, 0x0, 0x0, 0x0, 0x0,
0x1, 0x56, 0x0, 0x0, 0x0, 0x0,
0x1, 0x57, 0x0, 0x0, 0x0, 0x0,
0x1, 0x58, 0x0, 0x0, 0x0, 0x0,
0x1, 0x59, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x5f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x60, 0x0, 0x0, 0x0, 0x0,
0x1, 0x61, 0x0, 0x0, 0x0, 0x0,
0x1, 0x62, 0x0, 0x0, 0x0, 0x0,
0x1, 0x63, 0x0, 0x0, 0x0, 0x0,
0x1, 0x64, 0x0, 0x0, 0x0, 0x0,
0x1, 0x65, 0x0, 0x0, 0x0, 0x0,
0x1, 0x66, 0x0, 0x0, 0x0, 0x0,
0x1, 0x67, 0x0, 0x0, 0x0, 0x0,
0x1, 0x68, 0x0, 0x0, 0x0, 0x0,
0x1, 0x69, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x6f, 0x0, 0x0, 0x0, 0x0,
0x1, 0x70, 0x0, 0x0, 0x0, 0x0,
0x1, 0x71, 0x0, 0x0, 0x0, 0x0,
0x1, 0x72, 0x0, 0x0, 0x0, 0x0,
0x1, 0x73, 0x0, 0x0, 0x0, 0x0,
0x1, 0x74, 0x0, 0x0, 0x0, 0x0,
0x1, 0x75, 0x0, 0x0, 0x0, 0x0,
0x1, 0x76, 0x0, 0x0, 0x0, 0x0,
0x1, 0x77, 0x0, 0x0, 0x0, 0x0,
0x1, 0x78, 0x0, 0x0, 0x0, 0x0,
0x1, 0x79, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7a, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7b, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7c, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7d, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7e, 0x0, 0x0, 0x0, 0x0,
0x1, 0x7f, 0x0, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x82, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x83, 0x0, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x9a, 0x0, 0x0,
0x2, 0xd1, 0x93, 0x0, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x9e, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xa6, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xa0, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xa1, 0x0, 0x0,
0x3, 0xe2, 0x82, 0xac, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xb0, 0x0, 0x0,
0x2, 0xd0, 0x89, 0x0, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xb9, 0x0, 0x0,
0x2, 0xd0, 0x8a, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x8c, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x8b, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x8f, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x92, 0x0, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x98, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x99, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x9c, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x9d, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xa2, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x93, 0x0, 0x0,
0x3, 0xe2, 0x80, 0x94, 0x0, 0x0,
0x1, 0x20, 0x0, 0x0, 0x0, 0x0, // not part of this charset
0x3, 0xe2, 0x84, 0xa2, 0x0, 0x0,
0x2, 0xd1, 0x99, 0x0, 0x0, 0x0,
0x3, 0xe2, 0x80, 0xba, 0x0, 0x0,
0x2, 0xd1, 0x9a, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x9c, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x9b, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x9f, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa0, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x8e, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x9e, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x88, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa4, 0x0, 0x0, 0x0,
0x2, 0xd2, 0x90, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa6, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa7, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x81, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xa9, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x84, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xab, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xac, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xad, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xae, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x87, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb0, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb1, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x86, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x96, 0x0, 0x0, 0x0,
0x2, 0xd2, 0x91, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb5, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb6, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xb7, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x91, 0x0, 0x0, 0x0,
0x3, 0xe2, 0x84, 0x96, 0x0, 0x0,
0x2, 0xd1, 0x94, 0x0, 0x0, 0x0,
0x2, 0xc2, 0xbb, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x98, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x85, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x95, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x97, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x90, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x91, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x92, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x93, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x94, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x95, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x96, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x97, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x98, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x99, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x9a, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x9b, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x9c, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x9d, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x9e, 0x0, 0x0, 0x0,
0x2, 0xd0, 0x9f, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa0, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa1, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa2, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa3, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa4, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa5, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa6, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa7, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa8, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xa9, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xaa, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xab, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xac, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xad, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xae, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xaf, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb0, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb1, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb2, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb3, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb4, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb5, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb6, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb7, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb8, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xb9, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xba, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xbb, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xbc, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xbd, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xbe, 0x0, 0x0, 0x0,
0x2, 0xd0, 0xbf, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x80, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x81, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x82, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x83, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x84, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x85, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x86, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x87, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x88, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x89, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x8a, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x8b, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x8c, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x8d, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x8e, 0x0, 0x0, 0x0,
0x2, 0xd1, 0x8f, 0x0, 0x0, 0x0
};
/// Latin alphabet used by English and some other Western languages
static char windows_1252[] =
{
0x1, 0x0, 0x0, 0x0, 0x0, 0x0,

@ -130,10 +130,28 @@ std::string ToUTF8::getUtf8(ToUTF8::FromType from)
{
// Pick translation array
const char *arr;
if(from == ToUTF8::WINDOWS_1252)
arr = ToUTF8::windows_1252;
else
assert(0);
switch (from)
{
case ToUTF8::WINDOWS_1252:
{
arr = ToUTF8::windows_1252;
break;
}
case ToUTF8::WINDOWS_1250:
{
arr = ToUTF8::windows_1250;
break;
}
case ToUTF8::WINDOWS_1251:
{
arr = ToUTF8::windows_1251;
break;
}
default:
{
assert(0);
}
}
// Double check that the input string stops at some point (it might
// contain zero terminators before this, inside its own data, which

@ -8,8 +8,10 @@ namespace ToUTF8
// These are all the currently supported code pages
enum FromType
{
WINDOWS_1252 // Used by English version of Morrowind (and
// probably others)
WINDOWS_1250, // Central ane Eastern European languages
WINDOWS_1251, // Cyrillic languages
WINDOWS_1252 // Used by English version of Morrowind (and
// probably others)
};
// Return a writable buffer of at least 'size' bytes. The buffer

@ -64,6 +64,8 @@ configure_file("${SDIR}/openmw_progress.skin.xml" "${DDIR}/openmw_progress.skin.
configure_file("${SDIR}/openmw_stats_window_layout.xml" "${DDIR}/openmw_stats_window_layout.xml" COPYONLY)
configure_file("${SDIR}/openmw_text.skin.xml" "${DDIR}/openmw_text.skin.xml" COPYONLY)
configure_file("${SDIR}/openmw_windows.skin.xml" "${DDIR}/openmw_windows.skin.xml" COPYONLY)
configure_file("${SDIR}/openmw_messagebox_layout.xml" "${DDIR}/openmw_messagebox_layout.xml" COPYONLY)
configure_file("${SDIR}/openmw_interactive_messagebox_layout.xml" "${DDIR}/openmw_interactive_messagebox_layout.xml" COPYONLY)
configure_file("${SDIR}/smallbars.png" "${DDIR}/smallbars.png" COPYONLY)
configure_file("${SDIR}/transparent.png" "${DDIR}/transparent.png" COPYONLY)
configure_file("${SDIR}/VeraMono.ttf" "${DDIR}/VeraMono.ttf" COPYONLY)

@ -2,8 +2,9 @@
<MyGUI type="Font">
<Font name="MyGUI_CoreFont.18" source="Comic.TTF" size="18" resolution="72" antialias_colour="false" space_width="4" tab_count="4" spacer="5">
<Font name="MyGUI_CoreFont.18" source="Comic.TTF" size="18" resolution="72" antialias_colour="false" space_width="4" tab_count="4" spacer="5" distance="10">
<Code range="33 126"/>
<Code range="192 382"/><!-- Central and Eastern European languages glyphs -->
<Code range="1025 1105"/>
<Code range="8470 8470" help="№"/>
<Code hide="128"/>
@ -11,15 +12,16 @@
<Code hide="1104"/>
</Font>
<Font name="MonoFont" default_height="17" source="VeraMono.ttf" size="18" resolution="50" antialias_colour="false" space_width="4" tab_width="8" cursor_width="2" distance="5" offset_height="0">
<Font name="MonoFont" default_height="17" source="VeraMono.ttf" size="18" resolution="50" antialias_colour="false" space_width="4" tab_width="8" cursor_width="2" distance="10" offset_height="0">
<Code range="33 126"/>
<Code range="192 382"/><!-- Central and Eastern European glyphs -->
<Code range="1025 1105"/>
</Font>
<!-- Useful for youtube videos :) -->
<Font name="youtube" default_height="34" source="VeraMono.ttf" size="36" resolution="50" antialias_colour="false" space_width="8" tab_width="16" cursor_width="4" distance="10" offset_height="0">
<Font name="youtube" default_height="34" source="VeraMono.ttf" size="36" resolution="50" antialias_colour="false" space_width="8" tab_width="16" cursor_width="4" distance="15" offset_height="0">
<Code range="33 126"/>
<Code range="192 382"/><!-- Central and Eastern European languages glyphs -->
<Code range="1025 1105"/>
</Font>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 500 400" name="_Main">
<Widget type="Edit" skin="MW_TextEditClient" position="10 10 490 20" align="ALIGN_LEFT ALIGN_TOP STRETCH" name="message">
<Property key="Edit_Static" value="true"/>
<Property key="Edit_WordWrap" value="true"/>
<Property key="Text_FontHeight" value="18"/>
<Property key="Edit_MultiLine" value="1" />
<Property key="Edit_VisibleVScroll" value="1" />
<Property key="Widget_AlignText" value="ALIGN_CENTER" />
<Property key="FontName" value = "MyGUI_CoreFont.18" />
<Property key="TextColour" value = "0.7 0.7 0.7" />
</Widget>
<Widget type="Widget" skin="" position="0 0 500 400" align="ALIGN_STRETCH" name="buttons">
<!-- Widget type="Button" skin="MW_Button" position="0 0 30 18" name="somefunnybutton"/ -->
</Widget>
</Widget>
</MyGUI>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<MyGUI type="Layout">
<!--Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 0 0" name="_Main">
<Widget type="StaticText" skin="StaticText" position="4 4 4 4" name="message" />
</Widget-->
<Widget type="Window" skin="MW_Dialog" layer="Windows" position="0 0 0 0" name="_Main">
<Widget type="Edit" skin="MW_TextEditClient" position="5 -5 0 0" name="message" align="ALIGN_LEFT ALIGN_TOP STRETCH">
<Property key="Edit_Static" value="true"/>
<Property key="Edit_WordWrap" value="true"/>
<Property key="Text_FontHeight" value="18"/>
<Property key="Edit_MultiLine" value="1" />
<Property key="Edit_VisibleVScroll" value="1" />
<Property key="Widget_AlignText" value="ALIGN_CENTER" />
<Property key="FontName" value = "MyGUI_CoreFont.18" />
<Property key="TextColour" value = "0.7 0.7 0.7" />
</Widget>
</Widget>
</MyGUI>
Loading…
Cancel
Save