OpenClonk
C4ComponentHost.cpp
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 1998-2000, Matthes Bender
5  * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
6  * Copyright (c) 2009-2016, The OpenClonk Team and contributors
7  *
8  * Distributed under the terms of the ISC license; see accompanying file
9  * "COPYING" for details.
10  *
11  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
12  * See accompanying file "TRADEMARK" for details.
13  *
14  * To redistribute this file separately, substitute the full license texts
15  * for the above references.
16  */
17 
18 /* Holds a single text file component from a group */
19 
20 #include "C4Include.h"
22 
24  const char *fname,
25  const char *szLanguage)
26 {
27  // Clear any old stuff
28  Clear();
29  // Store filename
30  if (fname)
31  Filename.Copy(fname);
32  // Load component - try all segmented filenames
33  char strEntry[_MAX_FNAME_LEN];
34  StdStrBuf strEntryWithLanguage;
35  for (int iFilename = 0; SCopySegment(Filename.getData(), iFilename, strEntry, '|'); iFilename++)
36  {
37  // Try to insert all language codes provided into the filename
38  char strCode[3] = "";
39  for (int iLang = 0; SCopySegment(szLanguage ? szLanguage : "", iLang, strCode, ',', 2); iLang++)
40  {
41  // Insert language code
42  strEntryWithLanguage.Format(strEntry, strCode);
43  if (hGroup.LoadEntryString(strEntryWithLanguage, &Data))
44  {
45  FinishLoad(strEntryWithLanguage, hGroup);
46  // Got it
47  return true;
48  }
49  // Couldn't insert language code anyway - no point in trying other languages
50  if (!SSearch(strEntry, "%s")) break;
51  }
52  }
53  // Truncate any additional segments from stored filename
54  SReplaceChar(Filename.getMData(), '|', 0);
55  CopyFilePathFromGroup(hGroup);
56  // Not loaded
57  return false;
58 }
59 
61  const char *fname,
62  const char *szLanguage)
63 {
64  // Clear any old stuff
65  Clear();
66  // Store filename
67  if (fname)
68  Filename.Copy(fname);
69  // Load component - try all segmented filenames
70  char strEntry[_MAX_FNAME_LEN];
71  StdStrBuf strEntryWithLanguage;
72  for (int iFilename = 0; SCopySegment(Filename.getData(), iFilename, strEntry, '|'); iFilename++)
73  {
74  // Try to insert all language codes provided into the filename
75  char strCode[3] = "";
76  for (int iLang = 0; SCopySegment(szLanguage ? szLanguage : "", iLang, strCode, ',', 2); iLang++)
77  {
78  // Insert language code
79  strEntryWithLanguage.Format(strEntry, strCode);
80  if (hGroupSet.LoadEntryString(strEntryWithLanguage, &Data))
81  {
82  C4Group *pGroup = hGroupSet.FindEntry(strEntryWithLanguage.getData());
83  FinishLoad(strEntryWithLanguage, *pGroup);
84  // Got it
85  return true;
86  }
87  // Couldn't insert language code anyway - no point in trying other languages
88  if (!SSearch(strEntry, "%s")) break;
89  }
90  }
91  // Truncate any additional segments from stored filename
92  SReplaceChar(Filename.getMData(), '|', 0);
93  // for error message purposes, the first group failed to provide the desired file
94  CopyFilePathFromGroup(*hGroupSet.GetGroup(0));
95  // Not loaded
96  return false;
97 }
98 
99 void C4ComponentHost::FinishLoad(const StdStrBuf & name, C4Group &hGroup)
100 {
101  // Store actual filename
102  hGroup.FindEntry(name.getData(), &Filename);
103  CopyFilePathFromGroup(hGroup);
104 
105  if (Data.EnsureUnicode())
106  {
107  LogF("WARNING: File is not encoded as UTF-8 (%s)", FilePath.getData());
108  }
109  // Skip those stupid "zero width no-break spaces" (also known as Byte Order Marks)
110  if (Data[0] == '\xEF' && Data[1] == '\xBB' && Data[2] == '\xBF')
111  {
112  Data.Move(3,Data.getSize()-3);
113  Data.Shrink(3);
114  }
115  // Notify
116  OnLoad();
117 }
118 
119 // Construct full path
121 {
125 }
126 
127 bool C4ComponentHost::GetLanguageString(const char *szLanguage, StdStrBuf &rTarget)
128 {
129  const char *cptr;
130  // No good parameters
131  if (!szLanguage || !Data) return false;
132  // Search for two-letter language identifier in text body, i.e. "DE:"
133  char langindex[4] = "";
134  for (int clseg=0; SCopySegment(szLanguage ? szLanguage : "", clseg, langindex, ',', 2); clseg++)
135  {
136  SAppend(":",langindex);
137  if ((cptr = SSearch(Data.getData(),langindex)))
138  {
139  // Return the according string
140  int iEndPos = SCharPos('\r', cptr);
141  if (iEndPos<0) iEndPos = SCharPos('\n', cptr);
142  if (iEndPos<0) iEndPos = strlen(cptr);
143  rTarget.Copy(cptr, iEndPos);
144  return true;
145  }
146  }
147  // Language string not found
148  return false;
149 }
C4Config Config
Definition: C4Config.cpp:930
bool LogF(const char *strMessage,...)
Definition: C4Log.cpp:262
#define _MAX_FNAME_LEN
void SReplaceChar(char *str, char fc, char tc)
Definition: Standard.cpp:354
const char * SSearch(const char *szString, const char *szIndex)
Definition: Standard.cpp:369
int SCharPos(char cTarget, const char *szInStr, int iIndex)
Definition: Standard.cpp:239
bool SCopySegment(const char *szString, int iSegment, char *sTarget, char cSeparator, int iMaxL, bool fSkipWhitespace)
Definition: Standard.cpp:279
void SAppend(const char *szSource, char *szTarget, int iMaxL)
Definition: Standard.cpp:263
bool Load(C4Group &hGroup, const char *szFilename, const char *szLanguage=nullptr)
StdCopyStrBuf Filename
void CopyFilePathFromGroup(const C4Group &hGroup)
virtual void OnLoad()
void FinishLoad(const StdStrBuf &, C4Group &hGroup)
StdCopyStrBuf FilePath
StdCopyStrBuf Data
bool GetLanguageString(const char *szLanguage, StdStrBuf &rTarget)
const char * AtRelativePath(const char *filename)
Definition: C4Config.cpp:741
StdStrBuf GetFullName() const
Definition: C4Group.cpp:2638
bool LoadEntryString(const char *entry_name, StdStrBuf *buffer)
Definition: C4Group.cpp:2430
bool FindEntry(const char *wildcard, StdStrBuf *filename=nullptr, size_t *size=nullptr)
Definition: C4Group.cpp:2211
bool LoadEntryString(const char *szEntryName, StdStrBuf *rBuf)
Definition: C4GroupSet.cpp:225
C4Group * GetGroup(int32_t iIndex)
Definition: C4GroupSet.cpp:259
C4Group * FindEntry(const char *szWildcard, int32_t *pPriority=nullptr, int32_t *pID=nullptr)
Definition: C4GroupSet.cpp:175
size_t getSize() const
Definition: StdBuf.h:444
void Move(size_t iFrom, size_t inSize, size_t iTo=0)
Definition: StdBuf.h:471
void Shrink(size_t iShrink)
Definition: StdBuf.h:503
const char * getData() const
Definition: StdBuf.h:442
char * getMData()
Definition: StdBuf.h:443
bool EnsureUnicode()
Definition: StdBuf.cpp:421
void AppendBackslash()
Definition: StdBuf.cpp:248
void Copy()
Definition: StdBuf.h:467
void Append(const char *pnData, size_t iChars)
Definition: StdBuf.h:519
void Format(const char *szFmt,...) GNUC_FORMAT_ATTRIBUTE_O
Definition: StdBuf.cpp:174