Exemple #1
1
wxCoord
wxGridCellAutoWrapStringRenderer::BreakWord(wxDC& dc,
                                            const wxString& word,
                                            wxCoord maxWidth,
                                            wxArrayString& lines,
                                            wxString& line)
{
    wxArrayInt widths;
    dc.GetPartialTextExtents(word, widths);

    // TODO: Use binary search to find the first element > maxWidth.
    const unsigned count = widths.size();
    unsigned n;
    for ( n = 0; n < count; n++ )
    {
        if ( widths[n] > maxWidth )
            break;
    }

    if ( n == 0 )
    {
        // This is a degenerate case: the first character of the word is
        // already wider than the available space, so we just can't show it
        // completely and have to put the first character in this line.
        n = 1;
    }

    lines.push_back(word.substr(0, n));

    // Check if the remainder of the string fits in one line.
    //
    // Unfortunately we can't use the existing partial text extents as the
    // extent of the remainder may be different when it's rendered in a
    // separate line instead of as part of the same one, so we have to
    // recompute it.
    const wxString rest = word.substr(n);
    const wxCoord restWidth = dc.GetTextExtent(rest).x;
    if ( restWidth <= maxWidth )
    {
        line = rest;
        return restWidth;
    }

    // Break the rest of the word into lines.
    //
    // TODO: Perhaps avoid recursion? The code is simpler like this but using a
    // loop in this function would probably be more efficient.
    return BreakWord(dc, rest, maxWidth, lines, line);
}
 void getFlags(const Model::GameConfig::FlagConfigList& flags, wxArrayString& names, wxArrayString& descriptions) {
     Model::GameConfig::FlagConfigList::const_iterator it, end;
     for (it = flags.begin(), end = flags.end(); it != end; ++it) {
         const Model::GameConfig::FlagConfig& flag = *it;
         names.push_back(flag.name);
         descriptions.push_back(flag.description);
     }
 }
Exemple #3
0
bool GuideCamera::EnumCameras(wxArrayString& names, wxArrayString& ids)
{
    names.clear();
    names.push_back(wxString::Format(_("Camera %d"), 1));
    ids.clear();
    ids.push_back(DEFAULT_CAMERA_ID);

    return false;
}
Exemple #4
0
void wxCmdLineParserData::SetArguments(const wxString& cmdLine)
{
    m_arguments.clear();

    if(wxTheApp && wxTheApp->argc > 0)
        m_arguments.push_back(wxTheApp->argv[0]);
    else
        m_arguments.push_back(wxEmptyString);

    wxArrayString args = wxCmdLineParser::ConvertStringToArgs(cmdLine);

    WX_APPEND_ARRAY(m_arguments, args);
}
wxString
wxGUIAppTraits::GetStandardCmdLineOptions(wxArrayString& names,
                                          wxArrayString& desc) const
{
    wxString usage;

#ifdef __WXGTK26__
#ifndef __WXGTK3__
    if (!gtk_check_version(2,6,0))
#endif
    {
        // since GTK>=2.6, we can use the glib_check_version() symbol...

        // check whether GLib version is greater than 2.6 but also lower than 2.33
        // because, as we use the undocumented _GOptionGroup struct, we don't want
        // to run this code with future versions which might change it (2.32 is the
        // latest one at the time of this writing)
        if (glib_check_version(2,6,0) == NULL && glib_check_version(2,33,0))
        {
            usage << _("The following standard GTK+ options are also supported:\n");

            // passing true here means that the function can open the default
            // display while parsing (not really used here anyhow)
            GOptionGroup *gtkOpts = gtk_get_option_group(true);

            // WARNING: here we access the internals of GOptionGroup:
            GOptionEntry *entries = ((_GOptionGroup*)gtkOpts)->entries;
            unsigned int n_entries = ((_GOptionGroup*)gtkOpts)->n_entries;
            wxArrayString namesOptions, descOptions;

            for ( size_t n = 0; n < n_entries; n++ )
            {
                if ( entries[n].flags & G_OPTION_FLAG_HIDDEN )
                    continue;       // skip

                names.push_back(wxGetNameFromGtkOptionEntry(&entries[n]));

                const gchar * const entryDesc = entries[n].description;
                desc.push_back(wxString(entryDesc));
            }

            g_option_group_free (gtkOpts);
        }
    }
#else
    wxUnusedVar(names);
    wxUnusedVar(desc);
#endif // __WXGTK26__

    return usage;
}
Exemple #6
0
void
wxGridCellAutoWrapStringRenderer::BreakLine(wxDC& dc,
                                            const wxString& logicalLine,
                                            wxCoord maxWidth,
                                            wxArrayString& lines)
{
    wxCoord lineWidth = 0;
    wxString line;

    // For each word
    wxStringTokenizer wordTokenizer(logicalLine, wxS(" \t"), wxTOKEN_RET_DELIMS);
    while ( wordTokenizer.HasMoreTokens() )
    {
        const wxString word = wordTokenizer.GetNextToken();
        const wxCoord wordWidth = dc.GetTextExtent(word).x;
        if ( lineWidth + wordWidth < maxWidth )
        {
            // Word fits, just add it to this line.
            line += word;
            lineWidth += wordWidth;
        }
        else
        {
            // Word does not fit, check whether the word is itself wider that
            // available width
            if ( wordWidth < maxWidth )
            {
                // Word can fit in a new line, put it at the beginning
                // of the new line.
                lines.push_back(line);
                line = word;
                lineWidth = wordWidth;
            }
            else // Word cannot fit in available width at all.
            {
                if ( !line.empty() )
                {
                    lines.push_back(line);
                    line.clear();
                    lineWidth = 0;
                }

                // Break it up in several lines.
                lineWidth = BreakWord(dc, word, maxWidth, lines, line);
            }
        }
    }

    if ( !line.empty() )
        lines.push_back(line);
}
Exemple #7
0
void wxCmdLineParserData::SetArguments(int argc, char **argv)
{
    m_arguments.clear();

    // Command-line arguments are supposed to be in the user locale encoding
    // (what else?) but wxLocale probably wasn't initialized yet as we're
    // called early during the program startup and so our locale might not have
    // been set from the environment yet. To work around this problem we
    // temporarily change the locale here. The only drawback is that changing
    // the locale is thread-unsafe but precisely because we're called so early
    // it's hopefully safe to assume that no other threads had been created yet.
    char * const locOld = SetAllLocaleFacets("");
    wxON_BLOCK_EXIT1( SetAllLocaleFacets, locOld );

    for ( int n = 0; n < argc; n++ )
    {
        // try to interpret the string as being in the current locale
        wxString arg(argv[n]);

        // but just in case we guessed wrongly and the conversion failed, do
        // try to salvage at least something
        if ( arg.empty() && argv[n][0] != '\0' )
            arg = wxString(argv[n], wxConvISO8859_1);

        m_arguments.push_back(arg);
    }
}
Exemple #8
0
// Handle command line options
//
bool TestApp::OnCmdLineParsed(wxCmdLineParser& parser)
{
    if (parser.GetParamCount())
    {
        for (size_t i = 0; i < parser.GetParamCount(); i++)
            m_registries.push_back(parser.GetParam(i));
    }

    m_longlist = parser.Found("longlist");
    m_list = m_longlist || parser.Found("list");
    m_timing = parser.Found("timing");
    m_detail = !m_timing && parser.Found("detail");

    wxString loc;
    if ( parser.Found("locale", &loc) )
    {
        const wxLanguageInfo * const info = wxLocale::FindLanguageInfo(loc);
        if ( !info )
        {
            cerr << "Locale \"" << string(loc.mb_str()) << "\" is unknown.\n";
            return false;
        }

        m_locale = new wxLocale(info->Language);
        if ( !m_locale->IsOk() )
        {
            cerr << "Using locale \"" << string(loc.mb_str()) << "\" failed.\n";
            return false;
        }
    }

    return TestAppBase::OnCmdLineParsed(parser);
}
Exemple #9
0
bool Materials::unserializeTileset(xmlNodePtr node, wxArrayString& warnings)
{
	std::string strVal;

	if(readXMLString(node, "name", strVal))
	{
		Tileset* ts;
		TilesetContainer::iterator iter = tilesets.find(strVal);
		if(iter != tilesets.end())
		{
			ts = iter->second;
		}
		else
		{
			ts = newd Tileset(brushes, strVal);
			tilesets.insert(make_pair(strVal, ts));
		}

		xmlNodePtr child = node->children;
		while(child)
		{
			ts->loadCategory(child, warnings);
			child = child->next;
		}
	}
	else
	{
		warnings.push_back(wxT("Couldn't read tileset name"));
		return false;
	}
	return true;
}
Exemple #10
0
bool CreatureDatabase::loadFromXML(const FileName& filename, bool standard, wxString& error, wxArrayString& warnings)
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file(filename.GetFullPath().mb_str());
	if (!result) {
		error = wxT("Couldn't open file \"") + filename.GetFullName() + wxT("\", invalid format?");
		return false;
	}

	pugi::xml_node node = doc.child("creatures");
	if (!node) {
		error = wxT("Invalid file signature, this file is not a valid creatures file.");
		return false;
	}

	for (pugi::xml_node creatureNode = node.first_child(); creatureNode; creatureNode = creatureNode.next_sibling()) {
		if (as_lower_str(creatureNode.name()) != "creature") {
			continue;
		}

		CreatureType* creatureType = CreatureType::loadFromXML(creatureNode, warnings);
		if (creatureType) {
			creatureType->standard = standard;
			if ((*this)[creatureType->name]) {
				warnings.push_back(wxT("Duplicate creature type name \"") + wxstr(creatureType->name) + wxT("\"! Discarding..."));
				delete creatureType;
			} else {
				creature_map[as_lower_str(creatureType->name)] = creatureType;
			}
		}
	}
	return true;
}
void ModuleManager::FindAllPlugins(PluginIDList & providers, wxArrayString & paths)
{
   PluginManager & pm = PluginManager::Get();

   wxArrayString modIDs;
   wxArrayString modPaths;
   const PluginDescriptor *plug = pm.GetFirstPlugin(PluginTypeModule);
   while (plug)
   {
      modIDs.push_back(plug->GetID());
      modPaths.push_back(plug->GetPath());
      plug = pm.GetNextPlugin(PluginTypeModule);
   }

   for (size_t i = 0, cnt = modIDs.size(); i < cnt; i++)
   {
      PluginID providerID = modIDs[i];

      ModuleInterface *module =
         static_cast<ModuleInterface *>(CreateProviderInstance(providerID, modPaths[i]));
      
      wxArrayString newpaths = module->FindPlugins(pm);
      for (size_t i = 0, cnt = newpaths.size(); i < cnt; i++)
      {
         providers.push_back(providerID);
         paths.push_back(newpaths[i]);
      }
   }
}
Exemple #12
0
bool Materials::unserializeMaterials(const FileName& filename, xmlNodePtr root, wxString& error, wxArrayString& warnings)
{
	xmlNodePtr materialNode = root->children;
	wxString warning;

	while(materialNode)
	{
		warning = wxT("");

		if(xmlStrcmp(materialNode->name,(const xmlChar*)"include") == 0)
		{
			std::string include_file;
			if(readXMLValue(materialNode, "file", include_file))
			{
				FileName include_name;
				include_name.SetPath(filename.GetPath());
				include_name.SetFullName(wxstr(include_file));
				wxString suberror;
				bool success = loadMaterials(include_name, suberror, warnings);
				if(!success)
					warnings.push_back(wxT("Error while loading file \"") + wxstr(include_file) + wxT("\": ") + suberror);
			}
		}
		else if(xmlStrcmp(materialNode->name,(const xmlChar*)"metaitem") == 0)
		{
			item_db.loadMetaItem(materialNode);
		}
		else if(xmlStrcmp(materialNode->name,(const xmlChar*)"border") == 0)
		{
			brushes.unserializeBorder(materialNode, warnings);
			if(warning.size()) warnings.push_back(wxT("materials.xml: ") + warning);
		}
		else if(xmlStrcmp(materialNode->name,(const xmlChar*)"brush") == 0)
		{
			brushes.unserializeBrush(materialNode, warnings);
			if(warning.size()) warnings.push_back(wxT("materials.xml: ") + warning);
		}
		else if(xmlStrcmp(materialNode->name,(const xmlChar*)"tileset") == 0)
		{
			unserializeTileset(materialNode, warnings);
		}
		materialNode = materialNode->next;
	}
	return true;
}
Exemple #13
0
void wxCmdLineParserData::SetArguments(int argc, wxChar **argv)
{
    m_arguments.clear();

    for ( int n = 0; n < argc; n++ )
    {
        m_arguments.push_back(argv[n]);
    }
}
Exemple #14
0
void wxCmdLineParserData::SetArguments(int argc, char **argv)
{
    m_arguments.clear();

    for ( int n = 0; n < argc; n++ )
    {
        m_arguments.push_back(wxString::FromAscii(argv[n]));
    }
}
Exemple #15
0
bool Materials::loadMaterials(const FileName& identifier, wxString& error, wxArrayString& warnings)
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file(identifier.GetFullPath().mb_str());
	if(!result) {
		warnings.push_back("Could not open " + identifier.GetFullName() + " (file not found or syntax error)");
		return false;
	}

	pugi::xml_node node = doc.child("materials");
	if(!node) {
		warnings.push_back(identifier.GetFullName() + ": Invalid rootheader.");
		return false;
	}

	unserializeMaterials(identifier, node, error, warnings);
	return true;
}
Exemple #16
0
void wxCmdLineParserData::SetArguments(const wxString& cmdLine)
{
    m_arguments.clear();

    m_arguments.push_back(wxTheApp->GetAppName());

    wxArrayString args = wxCmdLineParser::ConvertStringToArgs(cmdLine);

    WX_APPEND_ARRAY(m_arguments, args);
}
void tcScenarioDialog::GetSideList(wxArrayString& sideList)
{
    sideList.clear();

    for (size_t n=0; n<countrySelection.size(); n++)
    {
        wxString s = countrySelection[n]->GetValue();
        if (s.size() > 0) sideList.push_back(s);
    }
}
Exemple #18
0
bool Brushes::unserializeBorder(pugi::xml_node node, wxArrayString& warnings)
{
	pugi::xml_attribute attribute = node.attribute("id");
	if (!attribute) {
		warnings.push_back(wxT("Couldn't read border id node"));
		return false;
	}

	int32_t id = pugi::cast<int32_t>(attribute.value());
	if (borders[id]) {
		warnings.push_back(wxT("Border ID ") + std::to_string(id) + wxT(" already exists"));
		return false;
	}

	AutoBorder* border = newd AutoBorder(id);
	border->load(node, warnings);
	borders[id] = border;
	return true;
}
Exemple #19
0
bool Config::getValue(const wxString& key, wxArrayString& value)
{
    wxString s;
    if (!getValue(key, s))
        return false;

    value.clear();
    wxString item;
    size_t pos = 0, sep = s.find(',');
    while (sep != wxString::npos)
    {
        item = s.substr(pos, sep - pos);
        if (!item.empty())
            value.push_back(item);
        sep = s.find(',', pos = sep + 1);
    }
    if (!(item = s.substr(pos)).empty())
        value.push_back(item);
    return true;
}
Exemple #20
0
void
wxGenericFileCtrl::DoGetFilenames(wxArrayString& filenames, bool fullPath) const
{
    filenames.clear();

    const wxString dir = m_list->GetDir();

    const wxString value = m_text->GetValue();
    if ( !value.empty() )
    {
        wxFileName fn(value);
        if ( fn.IsRelative() )
            fn.MakeAbsolute(dir);

        filenames.push_back(GetFileNameOrPath(fn, fullPath));
        return;
    }

    const int numSel = m_list->GetSelectedItemCount();
    if ( !numSel )
        return;

    filenames.reserve(numSel);

    wxListItem item;
    item.m_mask = wxLIST_MASK_TEXT;
    item.m_itemId = -1;
    for ( ;; )
    {
        item.m_itemId = m_list->GetNextItem(item.m_itemId, wxLIST_NEXT_ALL,
                                            wxLIST_STATE_SELECTED);

        if ( item.m_itemId == -1 )
            break;

        m_list->GetItem(item);

        const wxFileName fn(dir, item.m_text);
        filenames.push_back(GetFileNameOrPath(fn, fullPath));
    }
}
Exemple #21
0
void wxGenericDirCtrl::GetPaths(wxArrayString& paths) const
{
    paths.clear();

    wxArrayTreeItemIds items;
    m_treeCtrl->GetSelections(items);
    for ( unsigned n = 0; n < items.size(); n++ )
    {
        wxTreeItemId treeid = items[n];
        paths.push_back(GetPath(treeid));
    }
}
Exemple #22
0
void NetInfoClass::GetAllChannelNames(wxArrayString& names)
{
    int ChNum=0;
    for(size_t NetNum=0; NetNum < NetMaxChannel.size(); NetNum++)
    {
        for(size_t NetCh=0; NetCh < NetMaxChannel[NetNum]; NetCh++)
        {
            names.push_back(string_format("Ch %d: Net %d #%d",int(ChNum+1),int(NetNum+1),int(NetCh+1)));
            ChNum++;
        }
    }
}
Exemple #23
0
bool Materials::unserializeMaterials(const FileName& filename, pugi::xml_node node, wxString& error, wxArrayString& warnings)
{
	wxString warning;
	pugi::xml_attribute attribute;
	for(pugi::xml_node childNode = node.first_child(); childNode; childNode = childNode.next_sibling()) {
		const std::string& childName = as_lower_str(childNode.name());
		if(childName == "include") {
			if(!(attribute = childNode.attribute("file"))) {
				continue;
			}

			FileName includeName;
			includeName.SetPath(filename.GetPath());
			includeName.SetFullName(wxString(attribute.as_string(), wxConvUTF8));

			wxString subError;
			if(!loadMaterials(includeName, subError, warnings)) {
				warnings.push_back("Error while loading file \"" + includeName.GetFullName() + "\": " + subError);
			}
		} else if(childName == "metaitem") {
			g_items.loadMetaItem(childNode);
		} else if(childName == "border") {
			g_brushes.unserializeBorder(childNode, warnings);
			if(warning.size()) {
				warnings.push_back("materials.xml: " + warning);
			}
		} else if(childName == "brush") {
			g_brushes.unserializeBrush(childNode, warnings);
			if(warning.size()) {
				warnings.push_back("materials.xml: " + warning);
			}
		} else if(childName == "tileset") {
			unserializeTileset(childNode, warnings);
		}
	}
	return true;
}
Exemple #24
0
bool SourceDigger::DigFiles(TempDirectory& tmpdir,
                            wxArrayString& outFiles,
                            const wxArrayString& files,
                            Extractor &extract, const wxArrayString& keywords,
                            const wxString& charset)
{
    wxArrayString batchfiles;
    wxArrayString tempfiles;
    size_t i, last = 0;

    while (last < files.GetCount())
    {
        batchfiles.clear();
        for (i = last; i < last + BATCH_SIZE && i < files.size(); i++)
            batchfiles.Add(files[i]);
        last = i;

        wxString tempfile = tmpdir.CreateFileName("extracted.pot");
        if (!ExecuteGettext(
                    extract.GetCommand(batchfiles, keywords, tempfile, charset)))
        {
            return false;
        }

        tempfiles.push_back(tempfile);

        m_progressInfo->UpdateGauge((int)batchfiles.GetCount());

        if (m_progressInfo->Cancelled())
            return false;
    }

    if ( tempfiles.empty() )
        return false; // failed to parse any source files

    wxString outfile = tmpdir.CreateFileName("merged_chunks.pot");
    if ( !ConcatCatalogs(tempfiles, outfile) )
        return false;

    outFiles.push_back(outfile);
    return true;
}
Exemple #25
0
// Handle command line options
//
bool TestApp::OnCmdLineParsed(wxCmdLineParser& parser)
{
    if (parser.GetParamCount())
    {
#if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */
#   pragma ivdep
#   pragma swp
#   pragma unroll
#   pragma prefetch
#   if 0
#       pragma simd noassert
#   endif
#endif /* VDM auto patch */
        for (size_t i = 0; i < parser.GetParamCount(); i++)
            m_registries.push_back(parser.GetParam(i));
    }

    m_longlist = parser.Found("longlist");
    m_list = m_longlist || parser.Found("list");
    m_timing = parser.Found("timing");
    m_detail = !m_timing && parser.Found("detail");

    wxString loc;
    if ( parser.Found("locale", &loc) )
    {
        const wxLanguageInfo * const info = wxLocale::FindLanguageInfo(loc);
        if ( !info )
        {
            cerr << "Locale \"" << string(loc.mb_str()) << "\" is unknown.\n";
            return false;
        }

        m_locale = new wxLocale(info->Language);
        if ( !m_locale->IsOk() )
        {
            cerr << "Using locale \"" << string(loc.mb_str()) << "\" failed.\n";
            return false;
        }
    }

    return TestAppBase::OnCmdLineParsed(parser);
}
Exemple #26
0
// this function is used to properly interpret '..' in path
void wxSplitPath(wxArrayString& aParts, const wxString& path)
{
  aParts.clear();

  wxString strCurrent;
  wxString::const_iterator pc = path.begin();
  for ( ;; ) {
    if ( pc == path.end() || *pc == wxCONFIG_PATH_SEPARATOR ) {
      if ( strCurrent == wxT(".") ) {
        // ignore
      }
      else if ( strCurrent == wxT("..") ) {
        // go up one level
        if ( aParts.size() == 0 )
        {
          wxLogWarning(_("'%s' has extra '..', ignored."), path);
        }
        else
        {
          aParts.erase(aParts.end() - 1);
        }

        strCurrent.Empty();
      }
      else if ( !strCurrent.empty() ) {
        aParts.push_back(strCurrent);
        strCurrent.Empty();
      }
      //else:
        // could log an error here, but we prefer to ignore extra '/'

      if ( pc == path.end() )
        break;
    }
    else
      strCurrent += *pc;

    ++pc;
  }
}
Exemple #27
0
bool Spring::LaunchEngine(const std::string& cmd, wxArrayString& params)
{
	if ( m_running ) {
		wxLogError( _T("Spring already running!") );
		return false;
	}

	if (cfg().ReadBool(_T( "/Spring/Safemode" ))) {
		params.push_back(_T("--safemode"));
	}
	wxLogMessage( _T("spring call params: %s"), TowxString(cmd).c_str() );
	wxSetWorkingDirectory( TowxString(SlPaths::GetDataDir()) );

	if ( m_process == 0 ) {
		m_process = new SpringProcess( *this );
	}
	m_process->Create();
	m_process->SetCommand(TowxString(cmd), params );
	m_process->Run();
	m_running = true;
	GlobalEvent::Send(GlobalEvent::OnSpringStarted);
	return true;
}
Exemple #28
0
bool Materials::unserializeTileset(pugi::xml_node node, wxArrayString& warnings)
{
	pugi::xml_attribute attribute;
	if(!(attribute = node.attribute("name"))) {
		warnings.push_back("Couldn't read tileset name");
		return false;
	}

	const std::string& name = attribute.as_string();

	Tileset* tileset;
	auto it = tilesets.find(name);
	if(it != tilesets.end()) {
		tileset = it->second;
	} else {
		tileset = newd Tileset(g_brushes, name);
		tilesets.insert(std::make_pair(name, tileset));
	}

	for(pugi::xml_node childNode = node.first_child(); childNode; childNode = childNode.next_sibling()) {
		tileset->loadCategory(childNode, warnings);
	}
	return true;
}
Exemple #29
0
// this function is used to properly interpret '..' in path
void wxSplitPath(wxArrayString& aParts, const wxChar *sz)
{
  aParts.clear();

  wxString strCurrent;
  const wxChar *pc = sz;
  for ( ;; ) {
    if ( *pc == wxT('\0') || *pc == wxCONFIG_PATH_SEPARATOR ) {
      if ( strCurrent == wxT(".") ) {
        // ignore
      }
      else if ( strCurrent == wxT("..") ) {
        // go up one level
        if ( aParts.size() == 0 )
          wxLogWarning(_("'%s' has extra '..', ignored."), sz);
        else
          aParts.erase(aParts.end() - 1);

        strCurrent.Empty();
      }
      else if ( !strCurrent.empty() ) {
        aParts.push_back(strCurrent);
        strCurrent.Empty();
      }
      //else:
        // could log an error here, but we prefer to ignore extra '/'

      if ( *pc == wxT('\0') )
        break;
    }
    else
      strCurrent += *pc;

    pc++;
  }
}
Exemple #30
0
bool GraphicManager::loadSpriteData(const FileName& datafile, wxString& error, wxArrayString& warnings)
{
	FileReadHandle fh(nstr(datafile.GetFullPath()));

	if(!fh.isOk()) {
		error = "Failed to open file for reading";
		return false;
	}

#define safe_get(func, ...) do {\
		if(!fh.get##func(__VA_ARGS__)) {\
			error = wxstr(fh.getErrorMessage()); \
			return false; \
		} \
	} while(false)


	uint32_t sprSignature;
	safe_get(U32, sprSignature);

	uint32_t total_pics = 0;
	if(is_extended) {
		safe_get(U32, total_pics);
	} else {
		uint16_t u16 = 0;
		safe_get(U16, u16);
		total_pics = u16;
	}

	if(!g_settings.getInteger(Config::USE_MEMCACHED_SPRITES)) {
		spritefile = nstr(datafile.GetFullPath());
		unloaded = false;
		return true;
	}

	std::vector<uint32_t> sprite_indexes;
	for(uint32_t i = 0; i < total_pics; ++i) {
		uint32_t index;
		safe_get(U32, index);
		sprite_indexes.push_back(index);
	}

	// Now read individual sprites
	int id = 1;
	for(std::vector<uint32_t>::iterator sprite_iter = sprite_indexes.begin(); sprite_iter != sprite_indexes.end(); ++sprite_iter, ++id) {
		uint32_t index = *sprite_iter + 3;
		fh.seek(index);
		uint16_t size;
		safe_get(U16, size);

		ImageMap::iterator it = image_space.find(id);
		if(it != image_space.end()) {
			GameSprite::NormalImage* spr = dynamic_cast<GameSprite::NormalImage*>(it->second);
			if(spr && size > 0) {
				if(spr->size > 0) {
					wxString ss;
					ss << "items.spr: Duplicate GameSprite id " << id;
					warnings.push_back(ss);
					fh.seekRelative(size);
				} else {
					spr->id = id;
					spr->size = size;
					spr->dump = newd uint8_t[size];
					if(!fh.getRAW(spr->dump, size)) {
						error = wxstr(fh.getErrorMessage()); \
						return false;
					}
				}
			}
		} else {
			fh.seekRelative(size);
		}
	}
#undef safe_get
	unloaded = false;
	return true;
}