vdr 2.8.1
themes.c
Go to the documentation of this file.
1/*
2 * themes.c: Color themes used by skins
3 *
4 * See the main source file 'vdr.c' for copyright information and
5 * how to reach the author.
6 *
7 * $Id: themes.c 5.2 2026/01/19 11:09:43 kls Exp $
8 */
9
10#include "themes.h"
11#include <dirent.h>
12#include <string.h>
13#include "config.h"
14
15// --- cTheme ----------------------------------------------------------------
16
18{
19 name = "default";
20}
21
22bool cTheme::FileNameOk(const char *FileName, bool SetName)
23{
24 const char *error = NULL;
25 if (!isempty(FileName)) {
26 const char *d = strrchr(FileName, '/');
27 if (d)
28 FileName = d + 1;
29 const char *n = strchr(FileName, '-');
30 if (n) {
31 if (n > FileName) {
32 if (!strchr(++n, '-')) {
33 const char *e = strchr(n, '.');
34 if (e && strcmp(e, ".theme") == 0) {
35 if (e - n >= 1) {
36 // FileName is ok
37 if (SetName)
38 name = cString(n, e);
39 }
40 else
41 error = "missing theme name";
42 }
43 else
44 error = "invalid extension";
45 }
46 else
47 error = "too many '-'";
48 }
49 else
50 error = "missing skin name";
51 }
52 else
53 error = "missing '-'";
54 }
55 else
56 error = "empty";
57 if (error)
58 esyslog("ERROR: invalid theme file name (%s): '%s'", error, FileName);
59 return !error;
60}
61
62const char *cTheme::Description(void)
63{
65 if (!s)
66 s = descriptions[0];
67 return s ? s : *name;
68}
69
70bool cTheme::Load(const char *FileName, bool OnlyDescriptions)
71{
72 if (!FileNameOk(FileName, true))
73 return false;
74 bool result = false;
75 if (!OnlyDescriptions)
76 isyslog("loading %s", FileName);
77 FILE *f = fopen(FileName, "r");
78 if (f) {
79 int line = 0;
80 result = true;
81 char *s;
82 const char *error = NULL;
83 descriptions.Clear();
84 cReadLine ReadLine;
85 while ((s = ReadLine.Read(f)) != NULL) {
86 line++;
87 char *p = strchr(s, '#');
88 if (p)
89 *p = 0;
90 s = stripspace(skipspace(s));
91 if (!isempty(s)) {
92 char *n = s;
93 char *v = strchr(s, '=');
94 if (v) {
95 *v++ = 0;
96 n = stripspace(skipspace(n));
97 v = stripspace(skipspace(v));
98 if (strstr(n, "Description") == n) {
99 int lang = 0;
100 char *l = strchr(n, '.');
101 if (l)
102 lang = I18nLanguageIndex(++l);
103 if (lang >= 0) {
104 free(descriptions[lang]);
105 descriptions[lang] = strdup(v);
106 }
107 else
108 error = "invalid language code";
109 }
110 else if (!OnlyDescriptions) {
111 for (int i = 0; i < colorNames.Size(); i++) {
112 if (colorNames[i]) {
113 if (strcmp(n, colorNames[i]) == 0) {
114 char *p = NULL;
115 errno = 0;
116 tColor c = strtoul(v, &p, 16);
117 if (!errno && !*p)
118 colorValues[i] = c;
119 else
120 error = "invalid color value";
121 break;
122 }
123 }
124 else {
125 error = "unknown color name";
126 break;
127 }
128 }
129 }
130 }
131 else
132 error = "missing value";
133 }
134 if (error) {
135 result = false;
136 break;
137 }
138 }
139 if (!result)
140 esyslog("ERROR: error in %s, line %d%s%s", FileName, line, error ? ": " : "", error ? error : "");
141 fclose(f);
142 }
143 else
144 LOG_ERROR_STR(FileName);
145 return result;
146}
147
148bool cTheme::Save(const char *FileName)
149{
150 if (!FileNameOk(FileName))
151 return false;
152 bool result = true;
153 cSafeFile f(FileName);
154 if (f.Open()) {
155 for (int i = 0; i < I18nLanguages()->Size(); i++) {
156 if (descriptions[i])
157 fprintf(f, "Description%s%.*s = %s\n", i ? "." : "", 3, i ? I18nLanguageCode(i) : "", descriptions[i]);
158 }
159 for (int i = 0; i < colorNames.Size(); i++)
160 fprintf(f, "%s = %08X\n", colorNames[i], colorValues[i]);
161 if (!f.Close())
162 result = false;
163 }
164 else
165 result = false;
166 return result;
167}
168
170{
171 for (int i = 0; i < colorNames.Size(); i++) {
172 if (strcmp(Name, colorNames[i]) == 0) {
173 colorValues[i] = Color;
174 return i;
175 }
176 }
177 colorNames.Append(strdup(Name));
178 colorValues.Append(Color);
179 return colorValues.Size() - 1;
180}
181
183{
184 return (Subject >= 0 && Subject < colorValues.Size()) ? colorValues[Subject] : 0;
185}
186
187// --- cThemes ---------------------------------------------------------------
188
190
192{
193 numThemes = 0;
194}
195
197{
198 Clear();
199}
200
202{
203 names.Clear();
204 fileNames.Clear();
205 descriptions.Clear();
206 numThemes = 0;
207}
208
209bool cThemes::Load(const char *SkinName)
210{
211 Clear();
212 if (*themesDirectory) {
213 cStringList Data;
215 struct dirent *e;
216 while ((e = d.Next()) != NULL) {
217 if (strstr(e->d_name, SkinName) == e->d_name && e->d_name[strlen(SkinName)] == '-') {
220 if (Theme.Load(FileName, true))
221 Data.Append(strdup(cString::sprintf("%s\t%s\t%s", Theme.Description(), Theme.Name(), *FileName)));
222 }
223 }
224 Data.Sort();
225 for (int i = 0; i < Data.Size(); i++) {
226 char *s = Data[i];
227 char *t = strchr(s, '\t');
228 *t = 0;
229 if (descriptions.Find(s) >= 0)
230 esyslog("ERROR: duplicate themes '%s' in skin '%s'", s, SkinName);
231 descriptions.Append(strdup(s));
232 s = t + 1;
233 t = strchr(s, '\t');
234 *t = 0;
235 names.Append(strdup(s));
236 s = t + 1;
237 fileNames.Append(strdup(s));
238 numThemes++;
239 }
240 return numThemes > 0;
241 }
242 return false;
243}
244
245int cThemes::GetThemeIndex(const char *Description)
246{
247 int index = 0;
248 for (int i = 0; i < numThemes; i++) {
249 if (strcmp(descriptions[i], Description) == 0)
250 return i;
251 if (strcmp(descriptions[i], "Default") == 0)
252 index = i;
253 }
254 return index;
255}
256
257void cThemes::SetThemesDirectory(const char *ThemesDirectory)
258{
259 themesDirectory = ThemesDirectory;
261}
262
263void cThemes::Load(const char *SkinName, const char *ThemeName, cTheme *Theme)
264{
265 cString FileName = cString::sprintf("%s/%s-%s.theme", *themesDirectory, SkinName, ThemeName);
266 if (access(FileName, F_OK) == 0) // the file exists
267 Theme->Load(FileName);
268}
269
270void cThemes::Save(const char *SkinName, cTheme *Theme)
271{
272 cString FileName = cString::sprintf("%s/%s-%s.theme", *themesDirectory, SkinName, Theme->Name());
273 if (access(FileName, F_OK) != 0) // the file does not exist
274 Theme->Save(FileName);
275}
struct dirent * Next(void)
Definition tools.c:1627
char * Read(FILE *f)
Definition tools.c:1544
bool Open(void)
Definition tools.c:1778
bool Close(void)
Definition tools.c:1788
void Sort(bool IgnoreCase=false)
Definition tools.h:859
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition tools.c:1212
cString name
Definition themes.h:22
const char * Description(void)
Returns a user visible, single line description of this theme.
Definition themes.c:62
const char * Name(void)
Definition themes.h:30
bool Save(const char *FileName)
Saves the theme data to the given file.
Definition themes.c:148
cStringList descriptions
Definition themes.h:23
bool FileNameOk(const char *FileName, bool SetName=false)
Definition themes.c:22
cStringList colorNames
Definition themes.h:24
int AddColor(const char *Name, tColor Color)
Adds a color with the given Name to this theme, initializes it with Color and returns an index into t...
Definition themes.c:169
tColor Color(int Subject)
Returns the color for the given Subject.
Definition themes.c:182
cTheme(void)
Creates a new theme class.
Definition themes.c:17
cVector< tColor > colorValues
Definition themes.h:25
bool Load(const char *FileName, bool OnlyDescriptions=false)
Loads the theme data from the given file.
Definition themes.c:70
cStringList fileNames
Definition themes.h:65
static void SetThemesDirectory(const char *ThemesDirectory)
Definition themes.c:257
int numThemes
Definition themes.h:63
cStringList names
Definition themes.h:64
static cString themesDirectory
Definition themes.h:67
int GetThemeIndex(const char *Description)
Definition themes.c:245
~cThemes()
Definition themes.c:196
cThemes(void)
Definition themes.c:191
void Clear(void)
Definition themes.c:201
bool Load(const char *SkinName)
Definition themes.c:209
static void Save(const char *SkinName, cTheme *Theme)
Definition themes.c:270
cStringList descriptions
Definition themes.h:66
const char * FileName(int Index)
Definition themes.h:75
int Size(void) const
Definition tools.h:767
virtual void Append(T Data)
Definition tools.h:787
uint32_t tColor
Definition font.h:30
const cStringList * I18nLanguages(void)
Returns the list of available languages.
Definition i18n.c:263
int I18nLanguageIndex(const char *Code)
Returns the index of the language with the given three letter language Code.
Definition i18n.c:290
int I18nCurrentLanguage(void)
Returns the index of the current language.
Definition i18n.c:245
const char * I18nLanguageCode(int Language)
Returns the three letter language code of the given Language (which is an index as returned by I18nCu...
Definition i18n.c:285
static cTheme Theme
Definition skinclassic.c:21
bool isempty(const char *s)
Definition tools.c:357
bool MakeDirs(const char *FileName, bool IsDirectory)
Definition tools.c:512
char * stripspace(char *s)
Definition tools.c:227
cString AddDirectory(const char *DirName, const char *FileName)
Definition tools.c:415
#define LOG_ERROR_STR(s)
Definition tools.h:40
char * skipspace(const char *s)
Definition tools.h:244
#define esyslog(a...)
Definition tools.h:35
#define isyslog(a...)
Definition tools.h:36