forked from teamnwah/openmw-tes3coop
Merge branch 'master' into NonTableFields
This commit is contained in:
commit
851effb0e3
32 changed files with 159 additions and 132 deletions
10
.travis.yml
10
.travis.yml
|
@ -21,6 +21,14 @@ addons:
|
||||||
build_command_prepend: "cmake ."
|
build_command_prepend: "cmake ."
|
||||||
build_command: "make -j3"
|
build_command: "make -j3"
|
||||||
branch_pattern: coverity_scan
|
branch_pattern: coverity_scan
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: linux
|
||||||
|
env:
|
||||||
|
ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 "
|
||||||
|
compiler: clang
|
||||||
|
allow_failures:
|
||||||
|
- env: ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 "
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi
|
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi
|
||||||
|
@ -30,7 +38,7 @@ before_script:
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
|
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
|
||||||
script:
|
script:
|
||||||
- cd ./build
|
- cd ./build
|
||||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then make -j4; fi
|
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j4; fi
|
||||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
||||||
after_script:
|
after_script:
|
||||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
export CXX=g++
|
if [ "${ANALYZE}" ]; then
|
||||||
export CC=gcc
|
if [ $(lsb_release -sc) = "precise" ]; then
|
||||||
|
echo "yes" | sudo apt-add-repository ppa:ubuntu-toolchain-r/test
|
||||||
|
fi
|
||||||
|
echo "yes" | sudo add-apt-repository "deb http://llvm.org/apt/`lsb_release -sc`/ llvm-toolchain-`lsb_release -sc`-3.6 main"
|
||||||
|
wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add -
|
||||||
|
fi
|
||||||
|
|
||||||
echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
|
echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
|
||||||
echo "yes" | sudo apt-add-repository ppa:openmw/openmw
|
echo "yes" | sudo apt-add-repository ppa:openmw/openmw
|
||||||
|
@ -10,6 +15,7 @@ sudo apt-get install -qq libgtest-dev google-mock
|
||||||
sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev
|
sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev
|
||||||
sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev
|
sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev
|
||||||
sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev
|
sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev
|
||||||
|
if [ "${ANALYZE}" ]; then sudo apt-get install -qq clang-3.6; fi
|
||||||
sudo mkdir /usr/src/gtest/build
|
sudo mkdir /usr/src/gtest/build
|
||||||
cd /usr/src/gtest/build
|
cd /usr/src/gtest/build
|
||||||
sudo cmake .. -DBUILD_SHARED_LIBS=1
|
sudo cmake .. -DBUILD_SHARED_LIBS=1
|
||||||
|
|
|
@ -2,4 +2,6 @@
|
||||||
|
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE
|
export CODE_COVERAGE=1
|
||||||
|
if [ "${CC}" = "clang" ]; then export CODE_COVERAGE=0; fi
|
||||||
|
${ANALYZE}cmake .. -DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE
|
||||||
|
|
|
@ -353,6 +353,14 @@ endif()
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long")
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE)
|
||||||
|
execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE CLANG_VERSION)
|
||||||
|
string(REGEX REPLACE ".*version ([0-9\\.]*).*" "\\1" CLANG_VERSION ${CLANG_VERSION})
|
||||||
|
if ("${CLANG_VERSION}" VERSION_GREATER 3.6 OR "${CLANG_VERSION}" VERSION_EQUAL 3.6)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression")
|
||||||
|
endif ("${CLANG_VERSION}" VERSION_GREATER 3.6 OR "${CLANG_VERSION}" VERSION_EQUAL 3.6)
|
||||||
|
endif(CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE)
|
||||||
|
|
||||||
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
|
||||||
OUTPUT_VARIABLE GCC_VERSION)
|
OUTPUT_VARIABLE GCC_VERSION)
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
|
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
|
||||||
|
|
|
@ -48,10 +48,6 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if referenced object is in valid cell
|
|
||||||
if (mCells.searchId(cellRef.mCell) == -1)
|
|
||||||
messages.push_back(std::make_pair(id, " is referencing object from non existing cell " + cellRef.mCell));
|
|
||||||
|
|
||||||
// If object have owner, check if that owner reference is valid
|
// If object have owner, check if that owner reference is valid
|
||||||
if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1)
|
if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1)
|
||||||
messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner));
|
messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner));
|
||||||
|
|
|
@ -153,11 +153,13 @@ void CSVDoc::FileDialog::slotUpdateAcceptButton(const QString &name, bool)
|
||||||
|
|
||||||
if (isNew)
|
if (isNew)
|
||||||
success = success && !(name.isEmpty());
|
success = success && !(name.isEmpty());
|
||||||
else
|
else if (success)
|
||||||
{
|
{
|
||||||
ContentSelectorModel::EsmFile *file = mSelector->selectedFiles().back();
|
ContentSelectorModel::EsmFile *file = mSelector->selectedFiles().back();
|
||||||
mAdjusterWidget->setName (file->filePath(), !file->isGameFile());
|
mAdjusterWidget->setName (file->filePath(), !file->isGameFile());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
mAdjusterWidget->setName ("", true);
|
||||||
|
|
||||||
ui.projectButtonBox->button (QDialogButtonBox::Ok)->setEnabled (success);
|
ui.projectButtonBox->button (QDialogButtonBox::Ok)->setEnabled (success);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event)
|
||||||
CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
|
CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
|
||||||
: mDocument (document), mAborted (false), mMessages (0), mTotalRecords (0)
|
: mDocument (document), mAborted (false), mMessages (0), mTotalRecords (0)
|
||||||
{
|
{
|
||||||
setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str());
|
setWindowTitle (QString::fromUtf8((std::string("Opening ") + document->getSavePath().filename().string()).c_str()));
|
||||||
|
|
||||||
setMinimumWidth (400);
|
setMinimumWidth (400);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ void CSVDoc::SubView::updateUserSetting (const QString &, const QStringList &)
|
||||||
void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
|
void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id)
|
||||||
{
|
{
|
||||||
mUniversalId = id;
|
mUniversalId = id;
|
||||||
setWindowTitle (mUniversalId.toString().c_str());
|
setWindowTitle (QString::fromUtf8(mUniversalId.toString().c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::SubView::closeEvent (QCloseEvent *event)
|
void CSVDoc::SubView::closeEvent (QCloseEvent *event)
|
||||||
|
|
|
@ -324,7 +324,7 @@ void CSVDoc::View::updateTitle()
|
||||||
if (hideTitle)
|
if (hideTitle)
|
||||||
stream << " - " << mSubViews.at (0)->getTitle();
|
stream << " - " << mSubViews.at (0)->getTitle();
|
||||||
|
|
||||||
setWindowTitle (stream.str().c_str());
|
setWindowTitle (QString::fromUtf8(stream.str().c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::View::updateSubViewIndicies(SubView *view)
|
void CSVDoc::View::updateSubViewIndicies(SubView *view)
|
||||||
|
@ -485,6 +485,8 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
|
||||||
(!isReferenceable && id == sb->getUniversalId()))
|
(!isReferenceable && id == sb->getUniversalId()))
|
||||||
{
|
{
|
||||||
sb->setFocus();
|
sb->setFocus();
|
||||||
|
if (!hint.empty())
|
||||||
|
sb->useHint (hint);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -515,8 +517,6 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
|
||||||
assert(view);
|
assert(view);
|
||||||
view->setParent(this);
|
view->setParent(this);
|
||||||
mSubViews.append(view); // only after assert
|
mSubViews.append(view); // only after assert
|
||||||
if (!hint.empty())
|
|
||||||
view->useHint (hint);
|
|
||||||
|
|
||||||
int minWidth = userSettings.setting ("window/minimum-width", QString("325")).toInt();
|
int minWidth = userSettings.setting ("window/minimum-width", QString("325")).toInt();
|
||||||
view->setMinimumWidth(minWidth);
|
view->setMinimumWidth(minWidth);
|
||||||
|
@ -538,6 +538,9 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
|
||||||
this, SLOT (updateSubViewIndicies (SubView *)));
|
this, SLOT (updateSubViewIndicies (SubView *)));
|
||||||
|
|
||||||
view->show();
|
view->show();
|
||||||
|
|
||||||
|
if (!hint.empty())
|
||||||
|
view->useHint (hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVDoc::View::newView()
|
void CSVDoc::View::newView()
|
||||||
|
|
|
@ -248,7 +248,7 @@ bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view)
|
||||||
QMessageBox messageBox(view);
|
QMessageBox messageBox(view);
|
||||||
CSMDoc::Document *document = view->getDocument();
|
CSMDoc::Document *document = view->getDocument();
|
||||||
|
|
||||||
messageBox.setWindowTitle (document->getSavePath().filename().string().c_str());
|
messageBox.setWindowTitle (QString::fromUtf8(document->getSavePath().filename().string().c_str()));
|
||||||
messageBox.setText ("The document has been modified.");
|
messageBox.setText ("The document has been modified.");
|
||||||
messageBox.setInformativeText ("Do you want to save your changes?");
|
messageBox.setInformativeText ("Do you want to save your changes?");
|
||||||
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
#include "../../model/world/columns.hpp"
|
#include "../../model/world/columns.hpp"
|
||||||
#include "../../model/world/data.hpp"
|
#include "../../model/world/data.hpp"
|
||||||
|
#include "../../model/world/refcollection.hpp"
|
||||||
#include "../world/physicssystem.hpp"
|
#include "../world/physicssystem.hpp"
|
||||||
|
|
||||||
#include "elements.hpp"
|
#include "elements.hpp"
|
||||||
|
@ -30,26 +31,19 @@ bool CSVRender::Cell::removeObject (const std::string& id)
|
||||||
|
|
||||||
bool CSVRender::Cell::addObjects (int start, int end)
|
bool CSVRender::Cell::addObjects (int start, int end)
|
||||||
{
|
{
|
||||||
CSMWorld::IdTable& references = dynamic_cast<CSMWorld::IdTable&> (
|
|
||||||
*mData.getTableModel (CSMWorld::UniversalId::Type_References));
|
|
||||||
|
|
||||||
int idColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
|
||||||
int cellColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Cell);
|
|
||||||
int stateColumn = references.findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
|
|
||||||
|
|
||||||
bool modified = false;
|
bool modified = false;
|
||||||
|
|
||||||
|
const CSMWorld::RefCollection& collection = mData.getReferences();
|
||||||
|
|
||||||
for (int i=start; i<=end; ++i)
|
for (int i=start; i<=end; ++i)
|
||||||
{
|
{
|
||||||
std::string cell = Misc::StringUtils::lowerCase (references.data (
|
std::string cell = Misc::StringUtils::lowerCase (collection.getRecord (i).get().mCell);
|
||||||
references.index (i, cellColumn)).toString().toUtf8().constData());
|
|
||||||
|
|
||||||
int state = references.data (references.index (i, stateColumn)).toInt();
|
CSMWorld::RecordBase::State state = collection.getRecord (i).mState;
|
||||||
|
|
||||||
if (cell==mId && state!=CSMWorld::RecordBase::State_Deleted)
|
if (cell==mId && state!=CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
std::string id = Misc::StringUtils::lowerCase (references.data (
|
std::string id = Misc::StringUtils::lowerCase (collection.getRecord (i).get().mId);
|
||||||
references.index (i, idColumn)).toString().toUtf8().constData());
|
|
||||||
|
|
||||||
mObjects.insert (std::make_pair (id, new Object (mData, mCellNode, id, false, mPhysics)));
|
mObjects.insert (std::make_pair (id, new Object (mData, mCellNode, id, false, mPhysics)));
|
||||||
modified = true;
|
modified = true;
|
||||||
|
|
|
@ -68,6 +68,7 @@ void CSVWorld::ScriptSubView::useHint (const std::string& hint)
|
||||||
if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line))
|
if (cursor.movePosition (QTextCursor::Down, QTextCursor::MoveAnchor, line))
|
||||||
cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column);
|
cursor.movePosition (QTextCursor::Right, QTextCursor::MoveAnchor, column);
|
||||||
|
|
||||||
|
mEditor->setFocus();
|
||||||
mEditor->setTextCursor (cursor);
|
mEditor->setTextCursor (cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,27 @@
|
||||||
#include "android_commandLine.h"
|
#include "android_commandLine.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
const char *argvData[15];
|
const char **argvData;
|
||||||
int argcData;
|
int argcData;
|
||||||
|
|
||||||
|
extern "C" void releaseArgv();
|
||||||
|
|
||||||
|
void releaseArgv() {
|
||||||
|
delete[] argvData;
|
||||||
|
}
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_ui_activity_GameActivity_commandLine(JNIEnv *env,
|
JNIEXPORT void JNICALL Java_ui_activity_GameActivity_commandLine(JNIEnv *env,
|
||||||
jobject obj, jint argc, jobjectArray stringArray) {
|
jobject obj, jint argc, jobjectArray stringArray) {
|
||||||
jboolean iscopy;
|
jboolean iscopy;
|
||||||
argcData = (int) argc;
|
argcData = (int) argc;
|
||||||
argvData[0]="openmw";
|
argvData = new const char *[argcData + 1];
|
||||||
for (int i = 0; i < argcData; i++) {
|
argvData[0] = "openmw";
|
||||||
jstring string = (jstring) (*env).GetObjectArrayElement(stringArray, i);
|
for (int i = 1; i < argcData + 1; i++) {
|
||||||
argvData[i+1] = (env)->GetStringUTFChars(string, &iscopy);
|
jstring string = (jstring) (env)->GetObjectArrayElement(stringArray,
|
||||||
|
i - 1);
|
||||||
|
argvData[i] = (env)->GetStringUTFChars(string, &iscopy);
|
||||||
|
(env)->DeleteLocalRef(string);
|
||||||
}
|
}
|
||||||
|
(env)->DeleteLocalRef(stringArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,8 @@
|
||||||
|
|
||||||
extern void SDL_Android_Init(JNIEnv* env, jclass cls);
|
extern void SDL_Android_Init(JNIEnv* env, jclass cls);
|
||||||
extern int argcData;
|
extern int argcData;
|
||||||
extern const char *argvData[15];
|
extern const char **argvData;
|
||||||
|
void releaseArgv();
|
||||||
|
|
||||||
int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls,
|
int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls,
|
||||||
jobject obj) {
|
jobject obj) {
|
||||||
|
@ -26,7 +27,7 @@ int Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls,
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
status = main(argcData+1, argvData);
|
status = main(argcData+1, argvData);
|
||||||
|
releaseArgv();
|
||||||
/* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
|
/* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
|
||||||
/* exit(status); */
|
/* exit(status); */
|
||||||
|
|
||||||
|
|
|
@ -142,13 +142,13 @@ namespace MWGui
|
||||||
|
|
||||||
for (unsigned int i=0; i<mAvailableHeads.size(); ++i)
|
for (unsigned int i=0; i<mAvailableHeads.size(); ++i)
|
||||||
{
|
{
|
||||||
if (mAvailableHeads[i] == proto.mHead)
|
if (Misc::StringUtils::ciEqual(mAvailableHeads[i], proto.mHead))
|
||||||
mFaceIndex = i;
|
mFaceIndex = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int i=0; i<mAvailableHairs.size(); ++i)
|
for (unsigned int i=0; i<mAvailableHairs.size(); ++i)
|
||||||
{
|
{
|
||||||
if (mAvailableHairs[i] == proto.mHair)
|
if (Misc::StringUtils::ciEqual(mAvailableHairs[i], proto.mHair))
|
||||||
mHairIndex = i;
|
mHairIndex = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -581,7 +581,7 @@ namespace MWMechanics
|
||||||
buildNewPath(actor, target); //may fail to build a path, check before use
|
buildNewPath(actor, target); //may fail to build a path, check before use
|
||||||
|
|
||||||
//delete visited path node
|
//delete visited path node
|
||||||
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2]);
|
mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1]);
|
||||||
|
|
||||||
// This works on the borders between the path grid and areas with no waypoints.
|
// This works on the borders between the path grid and areas with no waypoints.
|
||||||
if(inLOS && mPathFinder.getPath().size() > 1)
|
if(inLOS && mPathFinder.getPath().size() > 1)
|
||||||
|
|
|
@ -86,7 +86,7 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po
|
||||||
//************************
|
//************************
|
||||||
/// Checks if you aren't moving; attempts to unstick you
|
/// Checks if you aren't moving; attempts to unstick you
|
||||||
//************************
|
//************************
|
||||||
if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1],pos.pos[2])) //Path finished?
|
if(mPathFinder.checkPathCompleted(pos.pos[0],pos.pos[1])) //Path finished?
|
||||||
return true;
|
return true;
|
||||||
else if(mStuckTimer>0.5) //Every half second see if we need to take action to avoid something
|
else if(mStuckTimer>0.5) //Every half second see if we need to take action to avoid something
|
||||||
{
|
{
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace MWMechanics
|
||||||
mPathFinder.buildPath(start, dest, actor.getCell(), true);
|
mPathFinder.buildPath(start, dest, actor.getCell(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2]))
|
if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1]))
|
||||||
{
|
{
|
||||||
movement.mPosition[1] = 0;
|
movement.mPosition[1] = 0;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -31,6 +31,18 @@ namespace MWMechanics
|
||||||
static const int GREETING_SHOULD_START = 4; //how many reaction intervals should pass before NPC can greet player
|
static const int GREETING_SHOULD_START = 4; //how many reaction intervals should pass before NPC can greet player
|
||||||
static const int GREETING_SHOULD_END = 10;
|
static const int GREETING_SHOULD_END = 10;
|
||||||
|
|
||||||
|
const std::string AiWander::sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1] =
|
||||||
|
{
|
||||||
|
std::string("idle2"),
|
||||||
|
std::string("idle3"),
|
||||||
|
std::string("idle4"),
|
||||||
|
std::string("idle5"),
|
||||||
|
std::string("idle6"),
|
||||||
|
std::string("idle7"),
|
||||||
|
std::string("idle8"),
|
||||||
|
std::string("idle9"),
|
||||||
|
};
|
||||||
|
|
||||||
/// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive.
|
/// \brief This class holds the variables AiWander needs which are deleted if the package becomes inactive.
|
||||||
struct AiWanderStorage : AiTemporaryBase
|
struct AiWanderStorage : AiTemporaryBase
|
||||||
{
|
{
|
||||||
|
@ -205,7 +217,7 @@ namespace MWMechanics
|
||||||
// Are we there yet?
|
// Are we there yet?
|
||||||
bool& chooseAction = storage.mChooseAction;
|
bool& chooseAction = storage.mChooseAction;
|
||||||
if(walking &&
|
if(walking &&
|
||||||
storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], pos.pos[2], 64.f))
|
storage.mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1], 64.f))
|
||||||
{
|
{
|
||||||
stopWalking(actor, storage);
|
stopWalking(actor, storage);
|
||||||
moveNow = false;
|
moveNow = false;
|
||||||
|
@ -580,44 +592,24 @@ namespace MWMechanics
|
||||||
|
|
||||||
void AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
void AiWander::playIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
||||||
{
|
{
|
||||||
if(idleSelect == 2)
|
if ((GroupIndex_MinIdle <= idleSelect) && (idleSelect <= GroupIndex_MaxIdle))
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle2", 0, 1);
|
{
|
||||||
else if(idleSelect == 3)
|
const std::string& groupName = sIdleSelectToGroupName[idleSelect - GroupIndex_MinIdle];
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle3", 0, 1);
|
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, groupName, 0, 1);
|
||||||
else if(idleSelect == 4)
|
}
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle4", 0, 1);
|
|
||||||
else if(idleSelect == 5)
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle5", 0, 1);
|
|
||||||
else if(idleSelect == 6)
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle6", 0, 1);
|
|
||||||
else if(idleSelect == 7)
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle7", 0, 1);
|
|
||||||
else if(idleSelect == 8)
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle8", 0, 1);
|
|
||||||
else if(idleSelect == 9)
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->playAnimationGroup(actor, "idle9", 0, 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AiWander::checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
bool AiWander::checkIdle(const MWWorld::Ptr& actor, unsigned short idleSelect)
|
||||||
{
|
{
|
||||||
if(idleSelect == 2)
|
if ((GroupIndex_MinIdle <= idleSelect) && (idleSelect <= GroupIndex_MaxIdle))
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle2");
|
{
|
||||||
else if(idleSelect == 3)
|
const std::string& groupName = sIdleSelectToGroupName[idleSelect - GroupIndex_MinIdle];
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle3");
|
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, groupName);
|
||||||
else if(idleSelect == 4)
|
}
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle4");
|
|
||||||
else if(idleSelect == 5)
|
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle5");
|
|
||||||
else if(idleSelect == 6)
|
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle6");
|
|
||||||
else if(idleSelect == 7)
|
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle7");
|
|
||||||
else if(idleSelect == 8)
|
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle8");
|
|
||||||
else if(idleSelect == 9)
|
|
||||||
return MWBase::Environment::get().getMechanicsManager()->checkAnimationPlaying(actor, "idle9");
|
|
||||||
else
|
else
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AiWander::setReturnPosition(const Ogre::Vector3& position)
|
void AiWander::setReturnPosition(const Ogre::Vector3& position)
|
||||||
|
@ -694,7 +686,8 @@ namespace MWMechanics
|
||||||
// If there is no path this actor doesn't go anywhere. See:
|
// If there is no path this actor doesn't go anywhere. See:
|
||||||
// https://forum.openmw.org/viewtopic.php?t=1556
|
// https://forum.openmw.org/viewtopic.php?t=1556
|
||||||
// http://www.fliggerty.com/phpBB3/viewtopic.php?f=30&t=5833
|
// http://www.fliggerty.com/phpBB3/viewtopic.php?f=30&t=5833
|
||||||
if(!pathgrid || pathgrid->mPoints.empty())
|
// Note: In order to wander, need at least two points.
|
||||||
|
if(!pathgrid || (pathgrid->mPoints.size() < 2))
|
||||||
mDistance = 0;
|
mDistance = 0;
|
||||||
|
|
||||||
// A distance value passed into the constructor indicates how far the
|
// A distance value passed into the constructor indicates how far the
|
||||||
|
@ -738,12 +731,37 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
mCurrentNode = mAllowedNodes[index];
|
mCurrentNode = mAllowedNodes[index];
|
||||||
mAllowedNodes.erase(mAllowedNodes.begin() + index);
|
mAllowedNodes.erase(mAllowedNodes.begin() + index);
|
||||||
|
|
||||||
mStoredAvailableNodes = true; // set only if successful in finding allowed nodes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In vanilla Morrowind, sometimes distance is too small to include at least two points,
|
||||||
|
// in which case, we will take the two closest points regardless of the wander distance
|
||||||
|
// This is a backup option, as std::sort is potentially O(n^2) in time.
|
||||||
|
if (mAllowedNodes.empty())
|
||||||
|
{
|
||||||
|
// Start with list of PathGrid nodes, sorted by distance from actor
|
||||||
|
std::vector<PathDistance> nodeDistances;
|
||||||
|
for (unsigned int counter = 0; counter < pathgrid->mPoints.size(); counter++)
|
||||||
|
{
|
||||||
|
float distance = npcPos.squaredDistance(PathFinder::MakeOgreVector3(pathgrid->mPoints[counter]));
|
||||||
|
nodeDistances.push_back(std::make_pair(distance, &pathgrid->mPoints.at(counter)));
|
||||||
|
}
|
||||||
|
std::sort(nodeDistances.begin(), nodeDistances.end(), sortByDistance);
|
||||||
|
|
||||||
|
// make closest node the current node
|
||||||
|
mCurrentNode = *nodeDistances[0].second;
|
||||||
|
|
||||||
|
// give Actor a 2nd node to walk to
|
||||||
|
mAllowedNodes.push_back(*nodeDistances[1].second);
|
||||||
|
}
|
||||||
|
mStoredAvailableNodes = true; // set only if successful in finding allowed nodes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AiWander::sortByDistance(const PathDistance& left, const PathDistance& right)
|
||||||
|
{
|
||||||
|
return left.first < right.first;
|
||||||
|
}
|
||||||
|
|
||||||
void AiWander::writeState(ESM::AiSequence::AiSequence &sequence) const
|
void AiWander::writeState(ESM::AiSequence::AiSequence &sequence) const
|
||||||
{
|
{
|
||||||
std::auto_ptr<ESM::AiSequence::AiWander> wander(new ESM::AiSequence::AiWander());
|
std::auto_ptr<ESM::AiSequence::AiWander> wander(new ESM::AiSequence::AiWander());
|
||||||
|
|
|
@ -113,7 +113,22 @@ namespace MWMechanics
|
||||||
float mDoorCheckDuration;
|
float mDoorCheckDuration;
|
||||||
int mStuckCount;
|
int mStuckCount;
|
||||||
|
|
||||||
|
// constants for converting idleSelect values into groupNames
|
||||||
|
enum GroupIndex
|
||||||
|
{
|
||||||
|
GroupIndex_MinIdle = 2,
|
||||||
|
GroupIndex_MaxIdle = 9
|
||||||
|
};
|
||||||
|
|
||||||
|
/// lookup table for converting idleSelect value to groupName
|
||||||
|
static const std::string sIdleSelectToGroupName[GroupIndex_MaxIdle - GroupIndex_MinIdle + 1];
|
||||||
|
|
||||||
|
/// record distances of pathgrid point nodes to actor
|
||||||
|
/// first value is distance between actor and node, second value is PathGrid node
|
||||||
|
typedef std::pair<float, const ESM::Pathgrid::Point*> PathDistance;
|
||||||
|
|
||||||
|
/// used to sort array of PathDistance objects into ascending order
|
||||||
|
static bool sortByDistance(const PathDistance& left, const PathDistance& right);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -90,12 +90,11 @@ namespace
|
||||||
|
|
||||||
namespace MWMechanics
|
namespace MWMechanics
|
||||||
{
|
{
|
||||||
float sqrDistanceZCorrected(ESM::Pathgrid::Point point, float x, float y, float z)
|
float sqrDistanceIgnoreZ(ESM::Pathgrid::Point point, float x, float y)
|
||||||
{
|
{
|
||||||
x -= point.mX;
|
x -= point.mX;
|
||||||
y -= point.mY;
|
y -= point.mY;
|
||||||
z -= point.mZ;
|
return (x * x + y * y);
|
||||||
return (x * x + y * y + 0.1f * z * z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float distance(ESM::Pathgrid::Point point, float x, float y, float z)
|
float distance(ESM::Pathgrid::Point point, float x, float y, float z)
|
||||||
|
@ -283,13 +282,13 @@ namespace MWMechanics
|
||||||
return Ogre::Math::ATan2(directionX,directionY).valueDegrees();
|
return Ogre::Math::ATan2(directionX,directionY).valueDegrees();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathFinder::checkPathCompleted(float x, float y, float z, float tolerance)
|
bool PathFinder::checkPathCompleted(float x, float y, float tolerance)
|
||||||
{
|
{
|
||||||
if(mPath.empty())
|
if(mPath.empty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
ESM::Pathgrid::Point nextPoint = *mPath.begin();
|
ESM::Pathgrid::Point nextPoint = *mPath.begin();
|
||||||
if(sqrDistanceZCorrected(nextPoint, x, y, z) < tolerance*tolerance)
|
if (sqrDistanceIgnoreZ(nextPoint, x, y) < tolerance*tolerance)
|
||||||
{
|
{
|
||||||
mPath.pop_front();
|
mPath.pop_front();
|
||||||
if(mPath.empty())
|
if(mPath.empty())
|
||||||
|
|
|
@ -41,7 +41,7 @@ namespace MWMechanics
|
||||||
void buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint,
|
void buildPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint,
|
||||||
const MWWorld::CellStore* cell, bool allowShortcuts = true);
|
const MWWorld::CellStore* cell, bool allowShortcuts = true);
|
||||||
|
|
||||||
bool checkPathCompleted(float x, float y, float z, float tolerance=32.f);
|
bool checkPathCompleted(float x, float y, float tolerance=32.f);
|
||||||
///< \Returns true if we are within \a tolerance units of the last path point.
|
///< \Returns true if we are within \a tolerance units of the last path point.
|
||||||
|
|
||||||
float getZAngleToNext(float x, float y) const;
|
float getZAngleToNext(float x, float y) const;
|
||||||
|
|
|
@ -111,7 +111,7 @@ void BSAFile::readHeader()
|
||||||
// Each file must take up at least 21 bytes of data in the bsa. So
|
// Each file must take up at least 21 bytes of data in the bsa. So
|
||||||
// if files*21 overflows the file size then we are guaranteed that
|
// if files*21 overflows the file size then we are guaranteed that
|
||||||
// the archive is corrupt.
|
// the archive is corrupt.
|
||||||
if((filenum*21 > fsize -12) || (dirsize+8*filenum > fsize -12) )
|
if((filenum*21 > unsigned(fsize -12)) || (dirsize+8*filenum > unsigned(fsize -12)) )
|
||||||
fail("Directory information larger than entire archive");
|
fail("Directory information larger than entire archive");
|
||||||
|
|
||||||
// Read the offset info into a temporary buffer
|
// Read the offset info into a temporary buffer
|
||||||
|
|
|
@ -449,7 +449,7 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path)
|
||||||
ToUTF8::Utf8Encoder encoder =
|
ToUTF8::Utf8Encoder encoder =
|
||||||
ToUTF8::calculateEncoding(mEncoding.toStdString());
|
ToUTF8::calculateEncoding(mEncoding.toStdString());
|
||||||
fileReader.setEncoder(&encoder);
|
fileReader.setEncoder(&encoder);
|
||||||
fileReader.open(dir.absoluteFilePath(path).toStdString());
|
fileReader.open(std::string(dir.absoluteFilePath(path).toUtf8().constData()));
|
||||||
|
|
||||||
EsmFile *file = new EsmFile(path);
|
EsmFile *file = new EsmFile(path);
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <libs/platform/string.h>
|
#include <string.h>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define OPENMW_ESM_READER_H
|
#define OPENMW_ESM_READER_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <libs/platform/string.h>
|
#include <string.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -31,6 +31,7 @@ JNIEXPORT void JNICALL Java_ui_activity_GameActivity_getPathToJni(JNIEnv *env, j
|
||||||
{
|
{
|
||||||
jboolean iscopy;
|
jboolean iscopy;
|
||||||
Buffer::setData((env)->GetStringUTFChars(prompt, &iscopy));
|
Buffer::setData((env)->GetStringUTFChars(prompt, &iscopy));
|
||||||
|
(env)->DeleteLocalRef(prompt);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
|
|
|
@ -7,10 +7,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
/**
|
|
||||||
* FIXME: Someone with MacOS system should check this and correct if necessary
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
boost::filesystem::path getUserHome()
|
boost::filesystem::path getUserHome()
|
||||||
|
@ -49,9 +45,8 @@ boost::filesystem::path MacOsPath::getUserConfigPath() const
|
||||||
|
|
||||||
boost::filesystem::path MacOsPath::getUserDataPath() const
|
boost::filesystem::path MacOsPath::getUserDataPath() const
|
||||||
{
|
{
|
||||||
// TODO: probably wrong?
|
|
||||||
boost::filesystem::path userPath (getUserHome());
|
boost::filesystem::path userPath (getUserHome());
|
||||||
userPath /= "Library/Preferences/";
|
userPath /= "Library/Application Support/";
|
||||||
|
|
||||||
return userPath / mName;
|
return userPath / mName;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "runtime.hpp"
|
#include "runtime.hpp"
|
||||||
#include "defines.hpp"
|
#include "defines.hpp"
|
||||||
|
|
||||||
|
#include <openengine/misc/rng.hpp>
|
||||||
|
|
||||||
namespace Interpreter
|
namespace Interpreter
|
||||||
{
|
{
|
||||||
inline std::string formatMessage (const std::string& message, Runtime& runtime)
|
inline std::string formatMessage (const std::string& message, Runtime& runtime)
|
||||||
|
@ -140,15 +142,13 @@ namespace Interpreter
|
||||||
|
|
||||||
virtual void execute (Runtime& runtime)
|
virtual void execute (Runtime& runtime)
|
||||||
{
|
{
|
||||||
double r = static_cast<double> (std::rand()) / RAND_MAX; // [0, 1)
|
|
||||||
|
|
||||||
Type_Integer limit = runtime[0].mInteger;
|
Type_Integer limit = runtime[0].mInteger;
|
||||||
|
|
||||||
if (limit<0)
|
if (limit<0)
|
||||||
throw std::runtime_error (
|
throw std::runtime_error (
|
||||||
"random: argument out of range (Don't be so negative!)");
|
"random: argument out of range (Don't be so negative!)");
|
||||||
|
|
||||||
Type_Integer value = static_cast<Type_Integer> (r*limit); // [o, limit)
|
Type_Integer value = OEngine::Misc::Rng::rollDice(limit); // [o, limit)
|
||||||
|
|
||||||
runtime[0].mInteger = value;
|
runtime[0].mInteger = value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,10 @@ void Node::getProperties(const Nif::NiTexturingProperty *&texprop,
|
||||||
wireprop = static_cast<const Nif::NiWireframeProperty*>(pr);
|
wireprop = static_cast<const Nif::NiWireframeProperty*>(pr);
|
||||||
else if (pr->recType == Nif::RC_NiStencilProperty)
|
else if (pr->recType == Nif::RC_NiStencilProperty)
|
||||||
stencilprop = static_cast<const Nif::NiStencilProperty*>(pr);
|
stencilprop = static_cast<const Nif::NiStencilProperty*>(pr);
|
||||||
else
|
// the following are unused by the MW engine
|
||||||
|
else if (pr->recType != Nif::RC_NiFogProperty
|
||||||
|
&& pr->recType != Nif::RC_NiDitherProperty
|
||||||
|
&& pr->recType != Nif::RC_NiShadeProperty)
|
||||||
std::cerr<< "Unhandled property type: "<<pr->recName <<std::endl;
|
std::cerr<< "Unhandled property type: "<<pr->recName <<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,4 +26,4 @@ namespace Misc {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
// Wrapper for string.h on Mac and MinGW
|
|
||||||
#ifndef _STRING_WRAPPER_H
|
|
||||||
#define _STRING_WRAPPER_H
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#include <Availability.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#if (defined(__APPLE__) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070) || defined(__MINGW32__)
|
|
||||||
// need our own implementation of strnlen
|
|
||||||
#ifdef __MINGW32__
|
|
||||||
static size_t strnlen(const char *s, size_t n)
|
|
||||||
{
|
|
||||||
const char *p = (const char *)memchr(s, 0, n);
|
|
||||||
return(p ? p-s : n);
|
|
||||||
}
|
|
||||||
#elif (defined(__APPLE__) && __MAC_OS_X_VERSION_MIN_REQUIRED < 1070)
|
|
||||||
static size_t mw_strnlen(const char *s, size_t n)
|
|
||||||
{
|
|
||||||
if (strnlen != NULL) {
|
|
||||||
return strnlen(s, n);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const char *p = (const char *)memchr(s, 0, n);
|
|
||||||
return(p ? p-s : n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#define strnlen mw_strnlen
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in a new issue