summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlordjaxom <lordjaxom>2004-12-08 18:48:39 +0000
committerlordjaxom <lordjaxom>2004-12-08 18:48:39 +0000
commit5382d18d05d358bb1c313c642395e835aa44a6a0 (patch)
tree2b5ef58620b3640c5b21e8eafe92ee4b266b1d30
parenteb2f2c9600e8f69788232582191b141002bcd522 (diff)
downloadvdr-plugin-text2skin-5382d18d05d358bb1c313c642395e835aa44a6a0.tar.gz
vdr-plugin-text2skin-5382d18d05d358bb1c313c642395e835aa44a6a0.tar.bz2
1.0-pre1v1.0-pre1
-rw-r--r--00-DEVELOPMENT0
-rw-r--r--HISTORY4
-rw-r--r--Makefile53
-rw-r--r--bitmap.c32
-rw-r--r--bitmap.h18
-rw-r--r--cache.c4
-rw-r--r--cache.h10
-rw-r--r--common.c187
-rw-r--r--common.h177
-rwxr-xr-xcontrib/list_items.pl2
-rwxr-xr-xcontrib/skin_to_10.pl254
-rw-r--r--data.c159
-rw-r--r--data.h103
-rw-r--r--display.c826
-rw-r--r--display.h116
-rw-r--r--file.c4
-rw-r--r--file.h8
-rw-r--r--font.c142
-rw-r--r--font.h44
-rw-r--r--graphtft/font.c173
-rw-r--r--graphtft/font.h48
-rw-r--r--i18n.c8
-rw-r--r--i18n.h8
-rw-r--r--loader.c45
-rw-r--r--loader.h27
-rw-r--r--menu.c34
-rw-r--r--menu.h24
-rw-r--r--render.c1129
-rw-r--r--render.h185
-rw-r--r--screen.c80
-rw-r--r--screen.h11
-rw-r--r--scroller.c4
-rw-r--r--scroller.h2
-rw-r--r--setup.c30
-rw-r--r--setup.h15
-rw-r--r--status.c13
-rw-r--r--status.h28
-rw-r--r--text2skin.c9
-rw-r--r--text2skin.h6
-rw-r--r--theme.c4
-rw-r--r--theme.h11
-rw-r--r--xml/display.c42
-rw-r--r--xml/display.h58
-rw-r--r--xml/function.c212
-rw-r--r--xml/function.h66
-rw-r--r--xml/object.c169
-rw-r--r--xml/object.h148
-rw-r--r--xml/parser.c310
-rw-r--r--xml/parser.h14
-rw-r--r--xml/skin.c44
-rw-r--r--xml/skin.h64
-rw-r--r--xml/string.c161
-rw-r--r--xml/string.h128
-rw-r--r--xml/type.c20
-rw-r--r--xml/type.h42
-rw-r--r--xml/xml.c295
-rw-r--r--xml/xml.h63
57 files changed, 3793 insertions, 2080 deletions
diff --git a/00-DEVELOPMENT b/00-DEVELOPMENT
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/00-DEVELOPMENT
diff --git a/HISTORY b/HISTORY
index 0f1e925..ca50bc6 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,10 +1,6 @@
VDR Plugin 'text2skin' Revision History
---------------------------------------
-2004-07-27: Version 0.0.8.1
-
-- fixed ugly race conditions that appears to occur more often with VDR >= 1.3.14
-
2004-07-14: Version 0.0.8
- fixed display of scrollbar if there is no text present
diff --git a/Makefile b/Makefile
index 097cd02..2439122 100644
--- a/Makefile
+++ b/Makefile
@@ -5,11 +5,15 @@
HAVE_IMAGEMAGICK=1
#HAVE_IMLIB2=1
+# comment this out if you don't want to use FreeType font rendering
+
+HAVE_FREETYPE=1
+
# DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU'RE DOING
# -------------------------------------------------------------
#
-# $Id: Makefile,v 1.15 2004/07/02 19:00:22 lordjaxom Exp $
+# $Id: Makefile,v 1.7 2004/12/08 18:47:37 lordjaxom Exp $
#
# The official name of this plugin.
@@ -25,7 +29,7 @@ VERSION = $(shell grep 'const char \*cText2SkinPlugin::VERSION *=' $(PLUGIN).c |
### The C++ compiler and options:
CXX ?= g++
-CXXFLAGS ?= -O2 -Wall -Woverloaded-virtual
+CXXFLAGS ?= -Wall -Woverloaded-virtual
### The directory environment:
@@ -43,10 +47,21 @@ VDRVERSION = $(shell grep 'define VDRVERSION ' $(VDRDIR)/config.h | awk '{ print
ARCHIVE = $(PLUGIN)-$(VERSION)
PACKAGE = vdr-$(ARCHIVE)
-### Includes and Defines (add further entries here):
+### Allow user defined options to overwrite defaults:
-include $(VDRDIR)/Make.config
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o loader.o display.o render.o common.o bitmap.o \
+ file.o i18n.o theme.o cache.o setup.o status.o scroller.o screen.o \
+ menu.o font.o \
+ \
+ xml/skin.o xml/parser.o xml/string.o xml/object.o xml/function.o \
+ xml/type.o xml/display.o xml/xml.o
+
+### Includes and Defines (add further entries here):
+
ifdef HAVE_IMLIB2
DEFINES += -DHAVE_IMLIB2
LIBS += -lImlib2
@@ -54,31 +69,32 @@ endif
ifdef HAVE_IMAGEMAGICK
DEFINES += -DHAVE_IMAGEMAGICK
-# LIBS += -lMagick -lMagick++
- LIBS += $(shell Magick++-config --ldflags --libs)
+ LIBS += -lMagick -lMagick++
+# LIBS += $(shell Magick++-config --ldflags --libs)
+endif
+
+ifdef HAVE_FREETYPE
+ INCLUDES += $(shell freetype-config --cflags)
+ LIBS += $(shell freetype-config --libs)
+ DEFINES += -DHAVE_FREETYPE
+ OBJS += graphtft/font.o
endif
ifdef DEBUG
+ CXXFLAGS += -O2 -g
DEFINES += -DDEBUG
+else
+ CXXFLAGS += -O2
endif
-INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include
+INCLUDES += -I$(VDRDIR)/include -I$(DVBDIR)/include -I.
DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
-### Allow user defined options to overwrite defaults:
-
--include $(VDRDIR)/Make.config
-
-### The object files (add further files here):
-
-OBJS = $(PLUGIN).o loader.o data.o display.o render.o common.o bitmap.o \
- file.o i18n.o theme.o cache.o setup.o status.o scroller.o screen.o
-
### Implicit rules:
%.o: %.c
- $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+ $(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) -o $@ $<
# Dependencies:
@@ -107,8 +123,9 @@ dist: clean
@-rm -rf $(TMPDIR)/$(ARCHIVE)
@mkdir $(TMPDIR)/$(ARCHIVE)
@cp -a * $(TMPDIR)/$(ARCHIVE)
- @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
- @-rm -rf $(TMPDIR)/$(ARCHIVE)
+ @ln -s $(ARCHIVE) $(TMPDIR)/$(PLUGIN)
+ @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE) $(PLUGIN)
+ @-rm -rf $(TMPDIR)/$(ARCHIVE) $(TMPDIR)/$(PLUGIN)
@echo Distribution package created as $(PACKAGE).tgz
clean:
diff --git a/bitmap.c b/bitmap.c
index 4a2ab27..fa76c29 100644
--- a/bitmap.c
+++ b/bitmap.c
@@ -1,5 +1,5 @@
/*
- * $Id: bitmap.c,v 1.18 2004/07/13 13:52:51 lordjaxom Exp $
+ * $Id: bitmap.c,v 1.3 2004/12/08 18:47:37 lordjaxom Exp $
*/
#include "bitmap.h"
@@ -16,29 +16,29 @@ using namespace Magick;
cText2SkinCache cText2SkinBitmap::mCache(Text2SkinSetup.MaxCacheFill);
-cText2SkinBitmap *cText2SkinBitmap::Load(const char *Filename, int Alpha) {
+cText2SkinBitmap *cText2SkinBitmap::Load(const std::string &Filename, int Alpha) {
if (mCache.Contains(Filename))
return mCache[Filename];
else {
cText2SkinBitmap *bmp = new cText2SkinBitmap;
- int len = strlen(Filename);
+ int len = Filename.length();
bool result = false;
if (len > 4) {
- if (strcmp(Filename + len - 4, ".xpm") == 0)
- result = bmp->LoadXpm(Filename, Alpha);
+ if (Filename.substr(len - 4, 4) == ".xpm")
+ result = bmp->LoadXpm(Filename.c_str());
else {
#ifdef HAVE_IMLIB2
- result = bmp->LoadImlib(Filename, Alpha);
+ result = bmp->LoadImlib(Filename.c_str());
#else
# ifdef HAVE_IMAGEMAGICK
- result = bmp->LoadMagick(Filename, Alpha);
+ result = bmp->LoadMagick(Filename.c_str());
+# else
+ esyslog("ERROR: text2skin: unknown file format for %s", Filename);
# endif
#endif
}
- //else
- //esyslog("ERROR: text2skin: unknown file format for %s", Filename);
} else
- esyslog("ERROR: text2skin: filename %s too short to identify format", Filename);
+ esyslog("ERROR: text2skin: filename %s too short to identify format", Filename.c_str());
if (result) {
bmp->SetAlpha(Alpha);
@@ -85,7 +85,7 @@ cBitmap &cText2SkinBitmap::Get(int &UpdateIn) {
void cText2SkinBitmap::SetAlpha(int Alpha) {
if (Alpha > 0) {
- vector<cBitmap*>::iterator it = mBitmaps.begin();
+ std::vector<cBitmap*>::iterator it = mBitmaps.begin();
for (; it != mBitmaps.end(); ++it) {
int count;
if ((*it)->Colors(count)) {
@@ -98,7 +98,7 @@ void cText2SkinBitmap::SetAlpha(int Alpha) {
}
}
-bool cText2SkinBitmap::LoadXpm(const char *Filename, int Alpha) {
+bool cText2SkinBitmap::LoadXpm(const char *Filename) {
cBitmap *bmp = new cBitmap(1,1,1);
if (bmp->LoadXpm(Filename)) {
mBitmaps.push_back(bmp);
@@ -109,7 +109,7 @@ bool cText2SkinBitmap::LoadXpm(const char *Filename, int Alpha) {
}
#ifdef HAVE_IMLIB2
-bool cText2SkinBitmap::LoadImlib(const char *Filename, int Alpha) {
+bool cText2SkinBitmap::LoadImlib(const char *Filename) {
Imlib_Image image;
cBitmap *bmp = NULL;
image = imlib_load_image(Filename);
@@ -136,12 +136,12 @@ bool cText2SkinBitmap::LoadImlib(const char *Filename, int Alpha) {
#endif
#ifdef HAVE_IMAGEMAGICK
-bool cText2SkinBitmap::LoadMagick(const char *Filename, int Alpha) {
- vector<Image> images;
+bool cText2SkinBitmap::LoadMagick(const char *Filename) {
+ std::vector<Image> images;
cBitmap *bmp = NULL;
try {
int w, h;
- vector<Image>::iterator it;
+ std::vector<Image>::iterator it;
readImages(&images, Filename);
if (images.size() == 0) {
esyslog("ERROR: text2skin: Couldn't load %s", Filename);
diff --git a/bitmap.h b/bitmap.h
index 79c44e7..af0fd42 100644
--- a/bitmap.h
+++ b/bitmap.h
@@ -1,5 +1,5 @@
/*
- * $Id: bitmap.h,v 1.12 2004/06/18 16:08:11 lordjaxom Exp $
+ * $Id: bitmap.h,v 1.2 2004/12/08 18:47:37 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_BITMAP_H
@@ -13,16 +13,16 @@ class cText2SkinBitmap {
private:
static cText2SkinCache mCache;
- vector<cBitmap*> mBitmaps;
- int mCurrent;
- time_t mDelay;
- time_t mLastGet;
+ std::vector<cBitmap*> mBitmaps;
+ int mCurrent;
+ time_t mDelay;
+ time_t mLastGet;
// disallow direct construction
cText2SkinBitmap(void);
public:
- static cText2SkinBitmap *Load(const char *Filename, int Alpha = 0);
+ static cText2SkinBitmap *Load(const std::string &Filename, int Alpha = 0);
static void ResetCache(void) { mCache.Reset(); }
static void FlushCache(void) { mCache.Flush(); }
@@ -33,12 +33,12 @@ public:
void SetColor(int Index, tColor Color);
void SetAlpha(int Alpha);
- bool LoadXpm(const char *Filename, int Alpha);
+ bool LoadXpm(const char *Filename);
#ifdef HAVE_IMLIB2
- bool LoadImlib(const char *Filename, int Alpha);
+ bool LoadImlib(const char *Filename);
#endif
#ifdef HAVE_IMAGEMAGICK
- bool LoadMagick(const char *Filename, int Alpha);
+ bool LoadMagick(const char *Filename);
#endif
};
diff --git a/cache.c b/cache.c
index 6c3f99a..b5026b7 100644
--- a/cache.c
+++ b/cache.c
@@ -1,5 +1,5 @@
/*
- * $Id: cache.c,v 1.2 2004/06/18 16:08:11 lordjaxom Exp $
+ * $Id: cache.c,v 1.2 2004/12/08 18:47:37 lordjaxom Exp $
*/
#include "cache.h"
@@ -13,7 +13,7 @@ cText2SkinCache::~cText2SkinCache() {
Flush();
}
-void cText2SkinCache::Delete(const key_type &Key, data_type &Data) {
+void cText2SkinCache::Delete(const key_type &/*Key*/, data_type &Data) {
delete Data;
}
diff --git a/cache.h b/cache.h
index 3f48de8..3734293 100644
--- a/cache.h
+++ b/cache.h
@@ -1,23 +1,25 @@
/*
- * $Id: cache.h,v 1.5 2004/06/18 16:08:11 lordjaxom Exp $
+ * $Id: cache.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_CACHE_HPP
#define VDR_TEXT2SKIN_CACHE_HPP
#include "common.h"
+#include <map>
+#include <vector>
#include <vdr/tools.h>
class cText2SkinBitmap;
class cText2SkinCache {
private:
- typedef string key_type;
+ typedef std::string key_type;
typedef cText2SkinBitmap* data_type;
- typedef map<key_type,data_type> item_map;
+ typedef std::map<key_type,data_type> item_map;
typedef item_map::iterator item_iterator;
- typedef vector<key_type> usage_list;
+ typedef std::vector<key_type> usage_list;
typedef usage_list::iterator usage_iterator;
item_map mItems;
diff --git a/common.c b/common.c
index de6f476..42e4e4f 100644
--- a/common.c
+++ b/common.c
@@ -1,43 +1,11 @@
/*
- * $Id: common.c,v 1.12 2004/06/25 17:51:34 lordjaxom Exp $
+ * $Id: common.c,v 1.2 2004/12/06 22:35:54 lordjaxom Exp $
*/
-#include "data.h"
#include "common.h"
#include <vdr/plugin.h>
-const string SectionNames[__SECTION_COUNT__] =
- { "Skin", "ChannelSmall", "Channel", "Volume", "ReplayMode", "Replay",
- "Message", "Menu" };
-
-const string ItemNames[__ITEM_COUNT__] =
- { "Unknown", "Skin", "Background", "Text", "Scrolltext", "Image", "Rectangle",
- "Ellipse", "Slope", "Progress", "Logo", "Symbol", "MenuArea", "MenuItem",
- "Scrollbar" };
-
-const string DisplayNames[__DISPLAY_COUNT__] =
- { "Always", "DateTimeF", "DateTime", "Date", "Time", "ChannelNumberName",
- "ChannelNumber", "ChannelName", "Language", "PresentDateTimeF",
- "PresentStartTime", "PresentDate", "PresentVPSTime", "PresentEndTime",
- "PresentDuration", "PresentVPS", "PresentRunning", "PresentTimer",
- "PresentTitle", "PresentShortText", "PresentDescription",
- "FollowingStartTime", "FollowingEndTime", "FollowingDuration",
- "FollowingTitle", "FollowingShortText", "Teletext", "Audio", "Dolby",
- "Encrypted", "Recording", "Radio", "VolumeCurrent", "VolumeTotal", "Mute",
- "ReplayTime", "ReplayDuration", "ReplayTitle", "ReplayPrompt", "Play",
- "Pause", "FastFwd", "FastRew", "SlowFwd", "SlowRew", "Message",
- "MessageStatus", "MessageInfo", "MessageWarning", "MessageError",
- "MenuTitle", "MenuRed", "MenuGreen", "MenuYellow", "MenuBlue", "MenuText",
- "MenuRecording", "MenuScrollUp", "MenuScrollDown", "MenuItems",
- "MenuCurrent", "MenuGroups", "ReplayMode", "PresentTextDescription" };
-
-const string ReplayNames[__REPLAY_COUNT__] =
- { "", "normal", "mp3", "mplayer", "dvd", "vcd" };
-
-const string BaseNames[__BASE_COUNT__] =
- { "rel", "abs" };
-
-const char *SkinPath(void) {
+std::string SkinPath(void) {
return cPlugin::ConfigDirectory(PLUGIN_NAME_I18N);
}
@@ -56,67 +24,69 @@ const char *ChannelNumber(const cChannel *Channel, int Number) {
const char *ChannelName(const cChannel *Channel, int Number) {
static char buffer[256];
buffer[0] = '\0';
- if (Channel)
- snprintf(buffer, sizeof(buffer), "%s", Channel->Name());
- else if (!Number)
- snprintf(buffer, sizeof(buffer), "%s", tr("*** Invalid Channel ***"));
- return buffer;
-}
-
-string ItemText(cText2SkinItem *Item, const string &Content) {
- string s;
- if (Item->Text() != "") {
- s = Item->Text();
- int pos;
- while ((pos = s.find('$')) != -1)
- s.replace(pos, 1, Content);
- } else
- s = Content;
- return s;
+ if (Channel)
+ snprintf(buffer, sizeof(buffer), "%s", Channel->Name());
+ else if (!Number)
+ snprintf(buffer, sizeof(buffer), "%s", tr("*** Invalid Channel ***"));
+
+ char *ptr;
+ if ((ptr = strchr(buffer, ',')) != NULL
+ || (ptr = strchr(buffer, ';')) != NULL)
+ *ptr = '\0';
+ return buffer;
}
-bool ParseVar(const char *Text, const char *Name, eSkinItem *Value) {
- string value;
- if (ParseVar(Text, Name, value)) {
- int i;
- for (i = 0; i < __ITEM_COUNT__; ++i) {
- if (ItemNames[i] == value) {
- *Value = (eSkinItem)i;
- return true;
- }
- if (i == __ITEM_COUNT__)
- esyslog("ERROR: text2skin: unknown item %s", value.c_str());
- }
- }
- return false;
+const char *ChannelShortName(const cChannel *Channel, int Number) {
+ static char buffer[256];
+ buffer[0] = '\0';
+ if (Channel)
+ snprintf(buffer, sizeof(buffer), "%s", Channel->Name());
+ else if (!Number)
+ snprintf(buffer, sizeof(buffer), "%s", tr("*** Invalid Channel ***"));
+
+ char *ptr;
+ if ((ptr = strchr(buffer, ',')) != NULL) {
+ char *start = ptr + 1;
+ if ((ptr = strchr(start, ';')) != NULL)
+ *ptr = '\0';
+ return start;
+ } else if ((ptr = strchr(buffer, ';')) != NULL)
+ *ptr = '\0';
+
+ return buffer;
}
-bool ParseVar(const char *Text, const char *Name, eSkinDisplay *Value) {
- string value;
- if (ParseVar(Text, Name, value)) {
- int i;
- for (i = 0; i < __DISPLAY_COUNT__; ++i) {
- if (DisplayNames[i] == value) {
- *Value = (eSkinDisplay)i;
- return true;
- }
- if (i == __DISPLAY_COUNT__)
- esyslog("ERROR: text2skin: unknown display parameter %s", value.c_str());
- }
- }
- return false;
+const char *ChannelBouquet(const cChannel *Channel, int Number) {
+ static char buffer[256];
+ buffer[0] = '\0';
+ if (Channel)
+ snprintf(buffer, sizeof(buffer), "%s", Channel->Name());
+ else if (!Number)
+ snprintf(buffer, sizeof(buffer), "%s", tr("*** Invalid Channel ***"));
+
+ char *ptr;
+ if ((ptr = strchr(buffer, ';')) != NULL)
+ return ptr + 1;
+ else
+ return "";
}
-bool ParseVar(const char *Text, const char *Name, int *Value) {
- string value;
- if (ParseVar(Text, Name, value)) {
- *Value = atoi(value.c_str());
- return true;
+cxType TimeType(time_t Time, const std::string &Format) {
+ static char result[1000];
+ struct tm tm_r, *tm;
+ tm = localtime_r(&Time, &tm_r);
+
+ if (Time > 0) {
+ if (Format.length() > 0) {
+ strftime(result, sizeof(result), Format.c_str(), tm);
+ return result;
+ } else
+ return Time;
}
- return false;
+ return "";
}
-bool ParseVar(const char *Text, const char *Name, string &Value){
+bool ParseVar(const char *Text, const char *Name, std::string &Value) {
const char *ptr1, *ptr2;
char *str;
bool res = false;
@@ -141,7 +111,7 @@ bool ParseVar(const char *Text, const char *Name, string &Value){
}
bool ParseVar(const char *Text, const char *Name, tColor *Value) {
- string value;
+ std::string value;
if (ParseVar(Text, Name, value) && value[0] == '#') {
*Value = (tColor)strtoul(value.c_str() + 1, NULL, 16);
return true;
@@ -149,48 +119,7 @@ bool ParseVar(const char *Text, const char *Name, tColor *Value) {
return false;
}
-bool ParseVar(const char *Text, const char *Name, eTextAlignment *Value) {
- string value;
- if (ParseVar(Text, Name, value)) {
- int v = atoi(value.c_str());
- if (v == 0)
- *Value = (eTextAlignment)(taTop|taLeft);
- else if (v == 1)
- *Value = (eTextAlignment)(taTop|taCenter);
- else if (v == 2)
- *Value = (eTextAlignment)(taTop|taRight);
- return true;
- }
- return false;
-}
-
-bool ParseVar(const char *Text, const char *Name, const cFont **Value) {
- string value;
- if (ParseVar(Text, Name, value)) {
- if (value == "Sml") *Value = cFont::GetFont(fontSml);
- else if (value == "Fix") *Value = cFont::GetFont(fontFix);
- return true;
- }
- return false;
-}
-
-bool ParseVar(const char *Text, const char *Name, eBaseCoordinate *Value) {
- string value;
- if (ParseVar(Text, Name, value)) {
- int i;
- for (i = 0; i < __BASE_COUNT__; ++i) {
- if (BaseNames[i] == value) {
- *Value = (eBaseCoordinate)i;
- return true;
- }
- if (i == __BASE_COUNT__)
- esyslog("ERROR: text2skin: unknown coordinate base %s", value.c_str());
- }
- }
- return false;
-}
-
-void SkipQuotes(string &Value) {
+void SkipQuotes(std::string &Value) {
char quote = Value[0];
int i;
Value.erase(0, 1);
diff --git a/common.h b/common.h
index 34b499b..12987d8 100644
--- a/common.h
+++ b/common.h
@@ -1,19 +1,14 @@
/*
- * $Id: common.h,v 1.13 2004/07/02 19:00:22 lordjaxom Exp $
+ * $Id: common.h,v 1.3 2004/12/08 17:13:25 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_COMMON_H
#define VDR_TEXT2SKIN_COMMON_H
+#include "xml/string.h"
#include <string>
-#include <vector>
-#include <map>
#include <vdr/osd.h>
-using std::string;
-using std::vector;
-using std::map;
-
#ifdef DEBUG
# define Dprintf(x...) fprintf(stderr, x);
# define Dbench(x) time_t bench_##x = time_ms();
@@ -24,173 +19,27 @@ using std::map;
# define Ddiff(x)
#endif
-// sections and items known by skin files
-
-enum eSkinSection {
- sectionSkin,
- sectionChannelSmall,
- sectionChannel,
- sectionVolume,
- sectionReplayMode,
- sectionReplay,
- sectionMessage,
- sectionMenu,
- __SECTION_COUNT__
-};
-
-enum eSkinItem {
- itemUnknown,
- itemSkin, // item identifying the Skin itself
- itemBackground,
- itemText,
- itemScrolltext,
- itemImage,
- itemRectangle,
- itemEllipse,
- itemSlope,
- itemProgress,
- itemLogo,
- itemSymbol,
- itemMenuArea,
- itemMenuItem,
- itemScrollbar,
- __ITEM_COUNT__
-};
-
-enum eSkinDisplay {
- displayAlways,
- displayDateTimeF, // exc: text
- displayDateTime, // exc: text
- displayDate, // exc: text
- displayTime, // exc: text
- displayChannelNumberName, // exc: text
- displayChannelNumber, // exc: text
- displayChannelName, // exc: text, logo
- displayLanguage, // exc: text, logo
- displayPresentDateTimeF, // exc: text
- displayPresentStartTime, // exc: text
- displayPresentDate, // exc: text
- displayPresentVPSTime, // exc: text
- displayPresentEndTime, // exc: text
- displayPresentDuration, // exc: text, progress
- displayPresentVPS, // exc: symbol
- displayPresentRunning, // exc: symbol
- displayPresentTimer, // exc: symbol
- displayPresentTitle, // exc: text
- displayPresentShortText, // exc: text
- displayPresentDescription, // exc: text
- displayFollowingStartTime, // exc: text
- displayFollowingEndTime, // exc: text
- displayFollowingDuration, // exc: text
- displayFollowingTitle, // exc: text
- displayFollowingShortText, // exc: text
- displayTeletext, // exc: symbol
- displayAudio, // exc: symbol
- displayDolby, // exc: symbol
- displayEncrypted, // exc: symbol
- displayRecording, // exc: symbol
- displayRadio, // exc: symbol
- displayVolumeCurrent, // exc: text, progress
- displayVolumeTotal, // exc: text, progress
- displayMute, // exc: symbol
- displayReplayTime, // exc: text, progress
- displayReplayDuration, // exc: text
- displayReplayTitle, // exc: text
- displayReplayPrompt, // exc: text
- displayPlay, // exc: symbol
- displayPause, // exc: symbol
- displayFastFwd, // exc: symbol
- displayFastRew, // exc: symbol
- displaySlowFwd, // exc: symbol
- displaySlowRew, // exc: symbol
- displayMessage, // exc: text
- displayMessageStatus, // exc: text
- displayMessageInfo, // exc: text
- displayMessageWarning, // exc: text
- displayMessageError, // exc: text
- displayMenuTitle, // exc: text (TODO: logo?)
- displayMenuRed, // exc: text
- displayMenuGreen, // exc: text
- displayMenuYellow, // exc: text
- displayMenuBlue, // exc: text
- displayMenuText, // exc: text
- displayMenuRecording, // exc: text
- displayMenuScrollUp, // exc: symbol
- displayMenuScrollDown, // exc: symbol
- displayMenuItems, // exc: text (TODO: logo?)
- displayMenuCurrent, // exc: text (TODO: logo?)
- displayMenuGroups, // exc: text (TODO: logo?)
- displayReplayMode, // exc: text, logo
- displayPresentTextDescription, // exc: text
- __DISPLAY_COUNT__
-};
-
-enum eReplayMode {
- replayNone,
- replayNormal,
- replayMP3,
- replayMPlayer,
- replayDVD,
- replayVCD,
- __REPLAY_COUNT__
-};
-
-enum eBaseCoordinate {
- baseRelative,
- baseAbsolute,
- __BASE_COUNT__
-};
-
-extern const string SectionNames[__SECTION_COUNT__];
-extern const string ItemNames[__ITEM_COUNT__];
-extern const string DisplayNames[__DISPLAY_COUNT__];
-extern const string ReplayNames[__REPLAY_COUNT__];
-extern const string BaseNames[__BASE_COUNT__];
+/* Check if a channel is a radio station. */
+#define ISRADIO(x) ((x)->Vpid()==0||(x)->Vpid()==1||(x)->Vpid()==0x1fff)
// class forwards
class cMarks;
class cChannel;
-class cText2SkinItem;
-
-// geometrical and helper structures
-
-struct POINT {
- int x, y;
- POINT(int _x = 0, int _y = 0) { x = _x; y = _y; }
- POINT &operator+=(const POINT &pt) { x += pt.x; y += pt.y; return *this; }
-};
-
-struct SIZE {
- int w, h;
- SIZE(int _w = 0, int _h = 0) { w = _w; h = _h; }
-};
-
-struct tItemData {
- string text;
- string path;
- int current;
- int shown;
- int total;
- const cMarks *marks;
- tItemData(void) { marks = NULL; }
-};
// helper functions
-const char *SkinPath(void);
+std::string SkinPath(void);
const char *ChannelNumber(const cChannel *Channel, int Number);
const char *ChannelName(const cChannel *Channel, int Number);
-
-bool ParseVar(const char *Text, const char *Name, eSkinItem *Value);
-bool ParseVar(const char *Text, const char *Name, eSkinDisplay *Value);
-bool ParseVar(const char *Text, const char *Name, int *Value);
-bool ParseVar(const char *Text, const char *Name, const cFont **Value);
-bool ParseVar(const char *Text, const char *Name, string &Value);
-bool ParseVar(const char *Text, const char *Name, tColor *Value);
-bool ParseVar(const char *Text, const char *Name, eTextAlignment *Value);
-bool ParseVar(const char *Text, const char *Name, eBaseCoordinate *Value);
+const char *ChannelShortName(const cChannel *Channel, int Number);
+const char *ChannelBouquet(const cChannel *Channel, int Number);
+
+cxType TimeType(time_t Time, const std::string &Format);
-void SkipQuotes(string &Value);
+bool ParseVar(const char *Text, const char *Name, std::string &Value);
+bool ParseVar(const char *Text, const char *Name, tColor *Value);
+
+void SkipQuotes(std::string &Value);
#endif // VDR_TEXT2SKIN_COMMON_H
diff --git a/contrib/list_items.pl b/contrib/list_items.pl
index a47803f..7b53231 100755
--- a/contrib/list_items.pl
+++ b/contrib/list_items.pl
@@ -1,7 +1,7 @@
#!/usr/bin/perl
$ITEMFILE="common.h";
-$PARMFILE="data.h";
+$PARMFILE="xml/object.h";
sub printo {
my $text = shift;
diff --git a/contrib/skin_to_10.pl b/contrib/skin_to_10.pl
new file mode 100755
index 0000000..014259b
--- /dev/null
+++ b/contrib/skin_to_10.pl
@@ -0,0 +1,254 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+my $DISPLAYS = {
+ Channel => 'channelInfo',
+ Volume => 'volume',
+ Message => 'message',
+ Replay => 'replayInfo',
+ ReplayMode => 'replaySmall',
+ Menu => 'menu',
+};
+
+my $TOKENS = {
+ DateTimeF => '{DateTime:%s}',
+ DateTime => '{DateTime:%a %e.%m. %H\:%M}',
+ Date => '{DateTime:%e.%m.}',
+ Time => '{DateTime:%H\:%M}',
+ ChannelNumberName => '{ChannelNumber} {ChannelName}',
+ PresentDateTimeF => '{PresentStartDateTime:%s}',
+ PresentStartTime => '{PresentStartDateTime:%H\:%M}',
+ PresentDate => '{PresentStartDateTime:%e.%m.}',
+ PresentVPSTime => '{PresentVPSDateTime:%H\:%M}',
+ PresentEndTime => '{PresentEndDateTime:%H\:%M}',
+ PresentDuration => '{PresentDuration:%H\:%M}',
+ PresentTextDescription => '{PresentText}\n\n{PresentDescription}',
+ FollowingStartTime => '{FollowingStartDateTime:%H\:%M}',
+ FollowingEndTime => '{FollowingEndDateTime:%H\:%M}',
+ FollowingDuration => '{FollowingDuration:%H\:%M}',
+ FollowingTextDescription => '{FollowingText}\n\n{FollowingDescription}',
+ FastFwd => '{IsFastForward}',
+ ReplayTime => '{ReplayPosition}',
+ ReplayDuration => '{ReplayDuration}',
+ MenuRed => '{ButtonRed}',
+ MenuGreen => '{ButtonGreen}',
+ MenuYellow => '{ButtonYellow}',
+ MenuBlue => '{ButtonBlue}',
+};
+
+my $ALIGNS = {
+ 0 => 'left',
+ 1 => 'center',
+ 2 => 'right'
+};
+
+my $SYMBOLS = {
+ Teletext => '{HasTeletext}',
+ Audio => '{HasMultilang}',
+ Dolby => '{HasDolby}',
+ Radio => '{IsRadio}',
+ Encrypted => '{IsEncrypted}',
+ Recording => '{IsRecording}',
+
+ Play => '{IsPlaying}',
+ Pause => '{IsPausing}',
+ FastFwd => '{IsFastForward}',
+ FastRew => '{IsFastRewind}',
+ SlowFwd => '{IsSlowForward}',
+ SlowRew => '{IsSlowRewind}',
+};
+
+my $data = { Skin => [] };
+my $section = "Skin";
+
+while (defined($_ = <>)) {
+ chomp $_;
+ $_ =~ s/;$//;
+ next if /^\s*$/;
+ next if /^\s*#/;
+
+ if ($_ =~ /\[([^\]]+)\]/) {
+ $section = $1;
+ $data->{$section} = [];
+ } else {
+ my @params = split(/,/, $_);
+ my $item = {};
+ foreach my $param (@params) {
+ my @param = split(/=/, $param);
+ $item->{$param[0]} = $param[1];
+ }
+ push @{$data->{$section}}, $item;
+ }
+}
+
+print "<?xml version=\"1.0\"?>\n";
+
+# skin tag
+print "<skin version=\"1.0\"";
+print " name=\"" . $data->{Skin}[0]{name} . "\"";
+if (defined($data->{Skin}[0]{base}) && $data->{Skin}[0]{base} eq 'abs') {
+ print " screenBase=\"absolute\"";
+} else {
+ print " screenBase=\"relative\"";
+}
+print ">\n";
+
+foreach my $display (keys %$data) {
+ next if (!defined($DISPLAYS->{$display}));
+
+ # display tag
+ print " <display id=\"" . $DISPLAYS->{$display} . "\">\n";
+
+ foreach my $window (@{$data->{$display}}) {
+ next if ($window->{Item} ne 'Background');
+
+ print " <window x1=\"" . $window->{x1} . "\" x2=\"" . $window->{x2}
+ . "\" y1=\"" . $window->{y1} . "\" y2=\"" . $window->{y2}
+ . "\" bpp=\"" . ($window->{bpp} || 4) . "\"/>\n";
+ }
+
+ foreach my $item (@{$data->{$display}}) {
+ local $_ = $item->{Item};
+ /^Background$/ and do {
+ if (defined($item->{bg})) {
+ print " <rectangle x1=\"" . $item->{x1} . "\" x2=\""
+ . $item->{x2} . "\" y1=\"" . $item->{y1} . "\" y2=\""
+ . $item->{y2} . "\" color=\"" . $item->{bg} . "\"/>\n";
+ }
+ if (defined($item->{path})) {
+ print " <image x=\"" . $item->{x1} . "\" y=\"" . $item->{y1}
+ . "\" path=\"" . $item->{path} . "\"";
+
+ if (defined($item->{alpha})) {
+ print " alpha=\"" . $item->{alpha} . "\"";
+ }
+ print "/>\n";
+ }
+ next;
+ };
+ /^Image$/ and do {
+ print " <image x=\"" . $item->{x1} . "\" y=\"" . $item->{y1}
+ . "\" path=\"" . $item->{path} . "\"";
+ if (defined($item->{alpha})) {
+ print " alpha=\"" . $item->{alpha} . "\"";
+ }
+ print "/>\n";
+ next;
+ };
+ /^Rectangle$/ and do {
+ $item->{x1} ||= 0;
+ $item->{y1} ||= 0;
+ $item->{x2} ||= -1;
+ $item->{y2} ||= -1;
+
+ print " <rectangle x1=\"" . $item->{x1} . "\" x2=\""
+ . $item->{x2} . "\" y1=\"" . $item->{y1} . "\" y2=\""
+ . $item->{y2} . "\" color=\"" . $item->{fg} . "\"";
+ if (defined($item->{display})) {
+ if (defined($TOKENS->{$item->{display}})) {
+ print " condition=\"" . $TOKENS->{$item->{display}} . "\"";
+ } else {
+ print " condition=\"{" . $item->{display} . "}\"";
+ }
+ }
+ print "/>\n";
+ next;
+ };
+ /^Logo$/ and do {
+ print " <image x=\"" . $item->{x1} . "\" y=\"" . $item->{y1}
+ . "\"";
+ if (defined($item->{alpha})) {
+ print " alpha=\"" . $item->{alpha} . "\"";
+ }
+ if ($item->{display} eq 'ChannelName') {
+ my $p = $item->{path} . "/{" . $item->{display} . "}."
+ . $item->{type};
+ print " condition=\"file('$p')\"" . " path=\"$p\"";
+ } elsif ($item->{display} eq 'ReplayMode') {
+ my $p = $item->{path} . "/{" . $item->{display} . "}."
+ . $item->{type};
+ print " condition=\"file('$p')\" path=\"$p\"";
+ }
+ print "/>\n";
+ next;
+ };
+ /^Text$/ and do {
+ $item->{x1} ||= 0;
+ $item->{y1} ||= 0;
+ $item->{x2} ||= -1;
+ $item->{y2} ||= -1;
+
+ print " <text x1=\"" . $item->{x1} . "\" x2=\""
+ . $item->{x2} . "\" y1=\"" . $item->{y1} . "\" y2=\""
+ . $item->{y2} . "\" color=\"" . $item->{fg} . "\"";
+ if (defined($item->{align})) {
+ print " align=\"" . $ALIGNS->{$item->{align}} . "\"";
+ }
+ if (defined($item->{font})) {
+ print " font=\"" . $item->{font} . "\"";
+ }
+ print ">";
+ if ($item->{display} eq 'DateTimeF'
+ || $item->{display} eq 'PresentDateTimeF') {
+ my $f = $item->{format};
+ $f =~ s/^"|"$//;
+ $f =~ s/([:\{\}])/\\$1/g;
+ print sprintf($TOKENS->{$item->{display}}, $f);
+ } elsif (defined($TOKENS->{$item->{display}})) {
+ print $TOKENS->{$item->{display}};
+ } else {
+ print "{" . $item->{display} . "}";
+ }
+ print "</text>\n";
+ next;
+ };
+ /^Symbol$/ and do {
+ print " <image x=\"" . $item->{x1} . "\" y=\"" . $item->{y1}
+ . "\"";
+ if (defined($item->{alpha})) {
+ print " alpha=\"" . $item->{alpha} . "\"";
+ }
+ print " condition=\"" . $SYMBOLS->{$item->{display}} . "\" path=\""
+ . $item->{path} . "\"/>\n";
+ if (defined($item->{altpath})) {
+ print " <image x=\"" . $item->{x1} . "\" y=\""
+ . $item->{y1} . "\"";
+ if (defined($item->{alpha})) {
+ print " alpha=\"" . $item->{alpha} . "\"";
+ }
+ print " condition=\"not(" . $SYMBOLS->{$item->{display}} . ")\""
+ ." path=\"" . $item->{path} . "\"/>\n";
+ }
+ next;
+ };
+ /^Progress$/ and do {
+ print " <progress x1=\"" . $item->{x1} . "\" x2=\""
+ . $item->{x2} . "\" y1=\"" . $item->{y1} . "\" y2=\""
+ . $item->{y2} . "\" color=\"" . $item->{fg} . "\"";
+ if (defined($item->{bg})) {
+ print " bgcolor=\"" . $item->{bg} . "\"";
+ }
+ if ($item->{display} eq 'VolumeCurrent') {
+ print " current=\"{VolumeCurrent}\" total=\"{VolumeTotal}\"";
+ }
+ if ($item->{display} eq 'PresentDuration') {
+ print " current=\"{PresentProgress}\" "
+ . " total=\"{PresentDuration}\"";
+ }
+ if ($item->{display} eq 'ReplayTime') {
+ print " current=\"{ReplayPositionIndex}\" "
+ . " total=\"{ReplayDurationIndex}\"";
+ }
+ print "/>\n";
+ next;
+ };
+ }
+
+ # display end tag
+ print " </display>\n";
+}
+
+# skin end tag
+print "</skin>\n";
diff --git a/data.c b/data.c
deleted file mode 100644
index c7053b1..0000000
--- a/data.c
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * $Id: data.c,v 1.21 2004/07/13 13:52:51 lordjaxom Exp $
- */
-
-#include "data.h"
-#include "common.h"
-#include "render.h"
-
-cText2SkinItem::cText2SkinItem(void) {
- mItem = itemUnknown;
- mDisplay = displayAlways;
- mBpp = 4;
- mArc = 0;
- mAlpha = 0;
- mSelected= "#FFFC1414";
- mMark = "#FF000000";
- mCurrent = "#FFFC1414";
- mFont = cFont::GetFont(fontOsd);
- mAlign = taDefault;
- mBase = baseRelative;
-}
-
-cText2SkinItem::~cText2SkinItem() {
-}
-
-bool cText2SkinItem::Parse(const char *Text) {
- const char *text = Text;
- const char *ptr = text;
- bool res = false;
-
- // check if this is an item
- if (ParseVar(ptr, "Item", &mItem) && mItem != itemUnknown) {
- ParseItem(ptr);
-
- if (mItem == itemSkin && (mName == "" || mVersion == ""))
- esyslog("ERROR: text2skin: Item=Skin is missing the name and/or version parameter(s)");
- else
- res = true;
- } else
- esyslog("ERROR: text2skin: unknown item in skin");
- return res;
-}
-
-bool cText2SkinItem::ParseItem(const char *Text) {
- ParseVar(Text, "name", mName);
- ParseVar(Text, "version", mVersion);
- ParseVar(Text, "base", &mBase);
- ParseVar(Text, "display", &mDisplay);
- ParseVar(Text, "x1", &mPos1.x);
- ParseVar(Text, "y1", &mPos1.y);
- ParseVar(Text, "x2", &mPos2.x);
- ParseVar(Text, "y2", &mPos2.y);
- ParseVar(Text, "bpp", &mBpp);
- ParseVar(Text, "arc", &mArc);
- ParseVar(Text, "alpha", &mAlpha);
- ParseVar(Text, "fg", mFg);
- ParseVar(Text, "bg", mBg);
- ParseVar(Text, "selected", mSelected);
- ParseVar(Text, "mark", mMark);
- ParseVar(Text, "current", mCurrent);
- ParseVar(Text, "font", &mFont);
- ParseVar(Text, "path", mPath);
- ParseVar(Text, "altpath", mAltPath);
- ParseVar(Text, "text", mText);
- ParseVar(Text, "type", mType);
- ParseVar(Text, "format", mFormat);
- ParseVar(Text, "align", &mAlign);
- return true;
-}
-
-const POINT cText2SkinItem::Pos(void) const {
- return cText2SkinRender::Transform(mPos1);
-}
-
-const SIZE cText2SkinItem::Size(void) const {
- POINT p1 = cText2SkinRender::Transform(mPos1);
- POINT p2 = cText2SkinRender::Transform(mPos2);
- return SIZE(p2.x - p1.x + 1, p2.y - p1.y + 1);
-}
-
-const tColor *cText2SkinItem::Fg(void) const {
- static tColor Fg;
- return cText2SkinRender::ItemColor(mFg, Fg) ? &Fg : NULL;
-}
-
-const tColor *cText2SkinItem::Bg(void) const {
- static tColor Bg;
- return cText2SkinRender::ItemColor(mBg, Bg) ? &Bg : NULL;
-}
-
-const tColor *cText2SkinItem::Selected(void) const {
- static tColor Selected;
- return cText2SkinRender::ItemColor(mSelected, Selected) ? &Selected : NULL;
-}
-
-const tColor *cText2SkinItem::Mark(void) const {
- static tColor Mark;
- return cText2SkinRender::ItemColor(mMark, Mark) ? &Mark : NULL;
-}
-
-const tColor *cText2SkinItem::Current(void) const {
- static tColor Current;
- return cText2SkinRender::ItemColor(mCurrent, Current) ? &Current : NULL;
-}
-
-// --- cText2SkinData ---------------------------------------------------------
-
-cText2SkinData::cText2SkinData(const char *Skin): cText2SkinFile(Skin) {
- mCurrentSection = sectionSkin;
-}
-
-cText2SkinData::~cText2SkinData() {
- for (int i = 0; i < __SECTION_COUNT__; ++i) {
- for (int j = 0; j < (int)mSections[i].size(); ++j)
- delete mSections[i][j];
- mSections[i].clear();
- }
-}
-
-bool cText2SkinData::Parse(const char *Text) {
- int l = strlen(Text);
- bool result = false;
- if (l) {
- if (Text[0] == '#') // comment
- result = true;
- else if (Text[0] == '[' && Text[l - 1] == ']') { // section
- char *s;
- int i;
- asprintf(&s, "%.*s", l - 2, Text + 1);
- for (i = 0; i < __SECTION_COUNT__; ++i) {
- if (SectionNames[i] == s) {
- mCurrentSection = (eSkinSection)i;
- result = true;
- break;
- }
- }
- if (i == __SECTION_COUNT__)
- esyslog("ERROR: text2skin: Unknown section %s", s);
- free(s);
- } else {
- cText2SkinItem *item = new cText2SkinItem;
- if (item->Parse(Text)) {
- mSections[mCurrentSection].push_back(item);
- result = true;
- } else
- delete item;
- }
- }
- return result;
-}
-
-cText2SkinItem *cText2SkinData::Get(eSkinSection Section, eSkinItem Item) {
- vector<cText2SkinItem*>::iterator it = mSections[Section].begin();
- for (; it != mSections[Section].end(); ++it) {
- if ((*it)->Item() == Item)
- return (*it);
- }
- return NULL;
-}
diff --git a/data.h b/data.h
deleted file mode 100644
index b71f63b..0000000
--- a/data.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * $Id: data.h,v 1.18 2004/07/13 13:52:51 lordjaxom Exp $
- */
-
-#ifndef VDR_TEXT2SKIN_DATA_H
-#define VDR_TEXT2SKIN_DATA_H
-
-#include "common.h"
-#include "file.h"
-#include <vdr/tools.h>
-#include <vdr/osd.h>
-#include <vdr/config.h>
-
-class cText2SkinItem {
-private:
- eSkinItem mItem;
- eSkinDisplay mDisplay;
- POINT mPos1;
- POINT mPos2;
- int mBpp;
- int mArc;
- int mAlpha;
- string mFg;
- string mBg;
- string mSelected;
- string mMark;
- string mCurrent;
- const cFont *mFont;
- string mName;
- string mVersion;
- string mPath;
- string mAltPath;
- string mText;
- string mType;
- string mFormat;
- eTextAlignment mAlign;
- eBaseCoordinate mBase;
-
-protected:
- bool ParseItem(const char *Text);
-
-public:
- cText2SkinItem(void);
- ~cText2SkinItem();
-
- bool Parse(const char *Text);
-
- // writeables
- POINT &Pos1(void) { return mPos1; }
- POINT &Pos2(void) { return mPos2; }
-
- // readables
- eSkinItem Item(void) const { return mItem; }
- eSkinDisplay Display(void) const { return mDisplay; }
- eBaseCoordinate Base(void) const { return mBase; }
- const POINT &Pos1(void) const { return mPos1; }
- const POINT &Pos2(void) const { return mPos2; }
- int Bpp(void) const { return mBpp; }
- int Arc(void) const { return mArc; }
- int Alpha(void) const { return mAlpha; }
- const cFont *Font(void) const { return mFont; }
- const string &Name(void) const { return mName; }
- const string &Version(void) const { return mVersion; }
- const string &Path(void) const { return mPath; }
- const string &AltPath(void) const { return mAltPath; }
- const string &Text(void) const { return mText; }
- const string &Type(void) const { return mType; }
- const string &Format(void) const { return mFormat; }
- eTextAlignment Align(void) const { return mAlign; }
-
- // auto-conversion
- const POINT Pos(void) const;
- const SIZE Size(void) const;
- const tColor *Fg(void) const;
- const tColor *Bg(void) const;
- const tColor *Selected(void)const;
- const tColor *Mark(void) const;
- const tColor *Current(void) const;
-};
-
-class cText2SkinData: public cText2SkinFile {
-public:
- typedef vector<cText2SkinItem*> tSection;
- typedef tSection::iterator tIterator;
-
-private:
- eSkinSection mCurrentSection;
- tSection mSections[__SECTION_COUNT__];
-
-protected:
- virtual bool Parse(const char *Text);
-
-public:
- cText2SkinData(const char *Skin);
- virtual ~cText2SkinData();
-
- tIterator First(eSkinSection Section) { return mSections[Section].begin(); }
- tIterator Last(eSkinSection Section) { return mSections[Section].end(); }
-
- cText2SkinItem *Get(eSkinSection Section, eSkinItem Item);
-};
-
-#endif // VDR_TEXT2SKIN_DATA_H
diff --git a/display.c b/display.c
index e2cdbc8..c8e2642 100644
--- a/display.c
+++ b/display.c
@@ -1,271 +1,554 @@
/*
- * $Id: display.c,v 1.19 2004/07/02 19:00:22 lordjaxom Exp $
+ * $Id: display.c,v 1.5 2004/12/08 18:47:37 lordjaxom Exp $
*/
#include "render.h"
-#include "data.h"
#include "loader.h"
#include "display.h"
#include "scroller.h"
+#include "status.h"
+#include "xml/string.h"
+#include <vdr/menu.h>
// --- cText2SkinDisplayChannel -----------------------------------------------
-cText2SkinDisplayChannel::cText2SkinDisplayChannel(cText2SkinLoader *Loader, bool WithInfo) {
- mWithInfo = WithInfo;
- mRender = new cText2SkinRender(Loader, WithInfo ? sectionChannel : sectionChannelSmall);
- mDirty = false;
+cText2SkinDisplayChannel::cText2SkinDisplayChannel(cText2SkinLoader *Loader, bool WithInfo):
+ cText2SkinRender(Loader, WithInfo ? cxDisplay::channelInfo : cxDisplay::channelSmall),
+ mChannel(NULL),
+ mNumber(0),
+ mPresent(NULL),
+ mFollowing(NULL),
+ mType(mtStatus),
+ mText("") {
}
cText2SkinDisplayChannel::~cText2SkinDisplayChannel() {
- delete mRender;
}
void cText2SkinDisplayChannel::SetChannel(const cChannel *Channel, int Number) {
- mRender->Lock();
- if (mRender->mChannel != Channel || mRender->mChannelNumber != Number) {
- mRender->mChannel = Channel;
- mRender->mChannelNumber = Number;
- mDirty = true;
+ if (mChannel != Channel || mNumber != Number) {
+ mChannel = Channel;
+ mNumber = Number;
+ SetDirty();
}
- mRender->Unlock();
}
-void cText2SkinDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following) {
- mRender->Lock();
- if (mRender->mChannelPresent != Present || mRender->mChannelFollowing != Following) {
- mRender->mChannelPresent = Present;
- mRender->mChannelFollowing = Following;
- mDirty = true;
+void cText2SkinDisplayChannel::SetEvents(const cEvent *Present,
+ const cEvent *Following) {
+ if (mPresent != Present || mFollowing != Following) {
+ mPresent = Present;
+ mFollowing = Following;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayChannel::SetMessage(eMessageType Type, const char *Text) {
if (Text == NULL) Text = "";
- mRender->Lock();
- if (mRender->mMessageType != Type || mRender->mMessageText != Text) {
- mRender->mMessageType = Type;
- mRender->mMessageText = Text;
- mDirty = true;
+ if (mType != Type || mText != Text) {
+ mType = Type;
+ mText = Text;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayChannel::Flush(void) {
- if (mDirty) {
- Dprintf("Flushing\n");
- mRender->Flush();
- Dprintf("Flushing done\n");
- mDirty = false;
+ cText2SkinRender::Flush();
+}
+
+cxType cText2SkinDisplayChannel::GetTokenData(const txToken &Token) {
+ switch (Token.Type) {
+ case tChannelNumber:
+ return mChannel != NULL
+ ? (cxType)ChannelNumber(mChannel, mNumber)
+ : (cxType)false;
+
+ case tChannelName:
+ return mChannel != NULL
+ ? (cxType)ChannelName(mChannel, mNumber)
+ : (cxType)false;
+
+ case tChannelShortName:
+ return mChannel != NULL
+ ? (cxType)ChannelShortName(mChannel, mNumber)
+ : (cxType)false;
+
+ case tChannelBouquet:
+ return mChannel != NULL
+ ? (cxType)ChannelBouquet(mChannel, mNumber)
+ : (cxType)false;
+
+ case tPresentStartDateTime:
+ return mPresent != NULL
+ ? (cxType)TimeType(mPresent->StartTime(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentVPSDateTime:
+ return mPresent != NULL
+ ? (cxType)TimeType(mPresent->Vps(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentEndDateTime:
+ return mPresent != NULL
+ ? (cxType)TimeType(mPresent->EndTime(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentProgress:
+ return mPresent != NULL
+ ? (cxType)TimeType(time(NULL) - mPresent->StartTime(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentDuration:
+ return mPresent != NULL
+ ? (cxType)TimeType(mPresent->Duration(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentTitle:
+ return mPresent != NULL
+ ? (cxType)mPresent->Title()
+ : (cxType)false;
+
+ case tPresentShortText:
+ return mPresent != NULL
+ ? (cxType)mPresent->ShortText()
+ : (cxType)false;
+
+ case tPresentDescription:
+ return mPresent != NULL
+ ? (cxType)mPresent->Description()
+ : (cxType)false;
+
+ case tFollowingStartDateTime:
+ return mFollowing != NULL
+ ? (cxType)TimeType(mFollowing->StartTime(), Token.Attrib)
+ : (cxType)false;
+
+ case tFollowingVPSDateTime:
+ return mFollowing != NULL
+ ? (cxType)TimeType(mFollowing->Vps(), Token.Attrib)
+ : (cxType)false;
+
+ case tFollowingEndDateTime:
+ return mFollowing != NULL
+ ? (cxType)TimeType(mFollowing->EndTime(), Token.Attrib)
+ : (cxType)false;
+
+ case tFollowingDuration:
+ return mFollowing != NULL
+ ? (cxType)TimeType(mFollowing->Duration(), Token.Attrib)
+ : (cxType)false;
+
+ case tFollowingTitle:
+ return mFollowing != NULL
+ ? (cxType)mFollowing->Title()
+ : (cxType)false;
+
+ case tFollowingShortText:
+ return mFollowing != NULL
+ ? (cxType)mFollowing->ShortText()
+ : (cxType)false;
+
+ case tFollowingDescription:
+ return mFollowing != NULL
+ ? (cxType)mFollowing->Description()
+ : (cxType)false;
+
+ case tLanguage: {
+ int cur;
+ const char **tracks = cDevice::PrimaryDevice()->GetAudioTracks(&cur);
+ if (tracks) {
+ int i = 0;
+ while (tracks[i] != NULL)
+ ++i;
+ if (cur < i)
+ return tracks[cur];
+ }
+ }
+ return false;
+
+ case tHasTeletext:
+ return mChannel != NULL && mChannel->Tpid() != 0;
+
+ case tHasMultilang:
+ return mChannel != NULL && mChannel->Apid2() != 0;
+
+ case tHasDolby:
+ return mChannel != NULL && mChannel->Dpid1() != 0;
+
+ case tIsEncrypted:
+ return mChannel != NULL && mChannel->Ca() != 0;
+
+ case tIsRadio:
+ return mChannel != NULL && ISRADIO(mChannel);
+
+ case tIsRecording:
+ return cRecordControls::Active();
+
+ case tHasVPS:
+ return mPresent != NULL && mPresent->Vps() != 0;
+
+ case tHasTimer:
+ return mPresent != NULL && mPresent->HasTimer();
+
+ case tIsRunning:
+ return mPresent != NULL && mPresent->IsRunning();
+
+ case tMessage:
+ return mText;
+
+ case tMessageInfo:
+ return mType == mtInfo
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tMessageWarning:
+ return mType == mtWarning
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tMessageStatus:
+ return mType == mtStatus
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tMessageError:
+ return mType == mtError
+ ? (cxType)mText
+ : (cxType)false;
+
+ default: break;
}
+
+ return cText2SkinRender::GetTokenData(Token);
}
// --- cText2SkinDisplayVolume ------------------------------------------------
-cText2SkinDisplayVolume::cText2SkinDisplayVolume(cText2SkinLoader *Loader) {
- mRender = new cText2SkinRender(Loader, sectionVolume);
- mDirty = false;
+cText2SkinDisplayVolume::cText2SkinDisplayVolume(cText2SkinLoader *Loader):
+ cText2SkinRender(Loader, cxDisplay::volume),
+ mCurrent(0),
+ mTotal(0),
+ mMute(false) {
}
cText2SkinDisplayVolume::~cText2SkinDisplayVolume() {
- delete mRender;
}
void cText2SkinDisplayVolume::SetVolume(int Current, int Total, bool Mute) {
- mRender->Lock();
- if (mRender->mVolumeCurrent != Current || mRender->mVolumeTotal != Total || mRender->mVolumeMute != Mute) {
- mRender->mVolumeCurrent = Current;
- mRender->mVolumeTotal = Total;
- mRender->mVolumeMute = Mute;
- mDirty = true;
+ if (mCurrent != Current || mTotal != Total || mMute != Mute) {
+ mCurrent = Current;
+ mTotal = Total;
+ mMute = Mute;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayVolume::Flush(void) {
- if (mDirty) {
- mRender->Flush();
- mDirty = false;
+ cText2SkinRender::Flush();
+}
+
+cxType cText2SkinDisplayVolume::GetTokenData(const txToken &Token) {
+ switch (Token.Type) {
+ case tVolumeCurrent:
+ return mCurrent;
+
+ case tVolumeTotal:
+ return mTotal;
+
+ case tIsMute:
+ return mMute;
+
+ default: break;
}
+
+ return cText2SkinRender::GetTokenData(Token);
}
// --- cText2SkinDisplayReplay ------------------------------------------------
-cText2SkinDisplayReplay::cText2SkinDisplayReplay(cText2SkinLoader *Loader, bool ModeOnly) {
- Dprintf("ModeOnly: %d\n", ModeOnly);
- mRender = new cText2SkinRender(Loader, ModeOnly ? sectionReplayMode : sectionReplay);
- mDirty = false;
+cText2SkinDisplayReplay::cText2SkinDisplayReplay(cText2SkinLoader *Loader, bool ModeOnly):
+ cText2SkinRender(Loader, ModeOnly ? cxDisplay::replaySmall : cxDisplay::replayInfo),
+ mTitle(""),
+ mStateInfo(false),
+ mPlay(false),
+ mForward(false),
+ mSpeed(0),
+ mCurrent(0),
+ mTotal(0),
+ mMarks(NULL),
+ mPrompt(""),
+ mType(mtStatus),
+ mText("") {
}
cText2SkinDisplayReplay::~cText2SkinDisplayReplay() {
- delete mRender;
}
void cText2SkinDisplayReplay::SetTitle(const char *Title) {
if (Title == NULL) Title = "";
- mRender->Lock();
- if (mRender->mReplayTitle != Title) {
- mRender->mReplayTitle = Title;
- mDirty = true;
+ if (mTitle != Title) {
+ mTitle = Title;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayReplay::SetMode(bool Play, bool Forward, int Speed) {
- Dprintf("speed: Play = %s, Forward = %s, Speed = %d\n", Play ? "true" : "false", Forward ? "true" : "false", Speed);
- mRender->Lock();
- if (mRender->mReplayInfo == false || mRender->mReplayPlay != Play || mRender->mReplayForward != Forward || mRender->mReplaySpeed != Speed) {
- mRender->mReplayInfo = true;
- mRender->mReplayPlay = Play;
- mRender->mReplayForward = Forward;
- mRender->mReplaySpeed = Speed;
- mDirty = true;
+ if (!mStateInfo || mPlay != Play || mForward != Forward || mSpeed != Speed) {
+ mStateInfo = true;
+ mPlay = Play;
+ mForward = Forward;
+ mSpeed = Speed;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayReplay::SetProgress(int Current, int Total) {
- mRender->Lock();
- if (mRender->mReplayCurrent != Current || mRender->mReplayTotal != Total) {
- mRender->mReplayCurrent = Current;
- mRender->mReplayTotal = Total;
- mDirty = true;
+ Dprintf("SetProgress: %d %d\n", Current, Total);
+ if (mCurrent != Current || mTotal != Total) {
+ mCurrent = Current;
+ mTotal = Total;
+ // SetDirty(); TODO: let this cause a display update every frame?
}
- mRender->Unlock();
}
void cText2SkinDisplayReplay::SetMarks(const cMarks *Marks) {
- mRender->Lock();
- if (mRender->mReplayMarks != Marks) {
- mRender->mReplayMarks = Marks;
- mDirty = true;
+ if (mMarks != Marks) {
+ mMarks = Marks;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayReplay::SetCurrent(const char *Current) {
if (Current == NULL) Current = "";
- mRender->Lock();
- if (mRender->mReplayCurrentText != Current) {
- mRender->mReplayCurrentText = Current;
- mDirty = true;
- }
- mRender->Unlock();
+ if (mPosition != Current) {
+ mPosition = Current;
+ SetDirty();
+ }
}
void cText2SkinDisplayReplay::SetTotal(const char *Total) {
if (Total == NULL) Total = "";
- mRender->Lock();
- if (mRender->mReplayTotalText != Total) {
- mRender->mReplayTotalText = Total;
- mDirty = true;
- }
- mRender->Unlock();
+ if (mDuration != Total) {
+ mDuration = Total;
+ SetDirty();
+ }
}
void cText2SkinDisplayReplay::SetJump(const char *Jump) {
if (Jump == NULL) Jump = "";
- mRender->Lock();
- if (mRender->mReplayJump != Jump) {
- mRender->mReplayJump = Jump;
- mDirty = true;
+ if (mPrompt != Jump) {
+ mPrompt = Jump;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayReplay::SetMessage(eMessageType Type, const char *Text) {
if (Text == NULL) Text = "";
- mRender->Lock();
- if (mRender->mMessageType != Type || mRender->mMessageText != Text) {
- mRender->mMessageType = Type;
- mRender->mMessageText = Text;
- mDirty = true;
+ if (mType != Type || mText != Text) {
+ mType = Type;
+ mText = Text;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayReplay::Flush(void) {
- if (mDirty) {
- mRender->Flush();
- mDirty = false;
+ cText2SkinRender::Flush();
+}
+
+cxType cText2SkinDisplayReplay::GetTokenData(const txToken &Token) {
+ switch (Token.Type) {
+ case tReplayTitle:
+ return mTitle;
+
+ case tReplayPositionIndex:
+ return TimeType(mCurrent, Token.Attrib);
+
+ case tReplayDurationIndex:
+ return TimeType(mTotal, Token.Attrib);
+
+ case tReplayPosition:
+ return mPosition;
+
+ case tReplayDuration:
+ return mDuration;
+
+ case tReplayPrompt:
+ return mPrompt;
+
+ case tIsPlaying:
+ return mStateInfo && (mSpeed == -1 && mPlay);
+
+ case tIsPausing:
+ return mStateInfo && (mSpeed == -1 && !mPlay);
+
+ case tIsFastForward:
+ if (mStateInfo && (mSpeed != -1 && mPlay && mForward)) {
+ return Token.Attrib.length() > 0
+ ? (cxType)(mSpeed == atoi(Token.Attrib.c_str()))
+ : (cxType)true;
+ }
+ return false;
+
+ case tIsFastRewind:
+ if (mStateInfo && (mSpeed != -1 && mPlay && !mForward)) {
+ return Token.Attrib.length() > 0
+ ? (cxType)(mSpeed == atoi(Token.Attrib.c_str()))
+ : (cxType)true;
+ }
+ return false;
+
+ case tIsSlowForward:
+ if (mStateInfo && (mSpeed != -1 && !mPlay && mForward)) {
+ return Token.Attrib.length() > 0
+ ? (cxType)(mSpeed == atoi(Token.Attrib.c_str()))
+ : (cxType)true;
+ }
+ return false;
+
+ case tIsSlowRewind:
+ if (mStateInfo && (mSpeed != -1 && !mPlay && !mForward)) {
+ return Token.Attrib.length() > 0
+ ? (cxType)(mSpeed == atoi(Token.Attrib.c_str()))
+ : (cxType)true;
+ }
+ return false;
+
+ case tMessage:
+ return mText;
+
+ case tMessageInfo:
+ return mType == mtInfo
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tMessageWarning:
+ return mType == mtWarning
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tMessageStatus:
+ return mType == mtStatus
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tMessageError:
+ return mType == mtError
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tReplayMode:
+ return cText2SkinStatus::ReplayMode();
+
+ default: break;
}
+
+ return cText2SkinRender::GetTokenData(Token);
}
// --- cText2SkinDisplayMessage -----------------------------------------------
-cText2SkinDisplayMessage::cText2SkinDisplayMessage(cText2SkinLoader *Loader) {
- mRender = new cText2SkinRender(Loader, sectionMessage);
- mDirty = false;
+cText2SkinDisplayMessage::cText2SkinDisplayMessage(cText2SkinLoader *Loader):
+ cText2SkinRender(Loader, cxDisplay::message),
+ mText("") {
}
cText2SkinDisplayMessage::~cText2SkinDisplayMessage() {
- delete mRender;
}
void cText2SkinDisplayMessage::SetMessage(eMessageType Type, const char *Text) {
if (Text == NULL) Text = "";
- mRender->Lock();
- if (mRender->mMessageType != Type || mRender->mMessageText != Text) {
- mRender->mMessageType = Type;
- mRender->mMessageText = Text;
- mDirty = true;
+ if (mType != Type || mText != Text) {
+ mType = Type;
+ mText = Text;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayMessage::Flush(void) {
- if (mDirty) {
- mRender->Flush();
- mDirty = false;
+ cText2SkinRender::Flush();
+}
+
+cxType cText2SkinDisplayMessage::GetTokenData(const txToken &Token) {
+ switch (Token.Type) {
+ case tMessage:
+ return mText;
+
+ case tMessageInfo:
+ return mType == mtInfo
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tMessageWarning:
+ return mType == mtWarning
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tMessageStatus:
+ return mType == mtStatus
+ ? (cxType)mText
+ : (cxType)false;
+
+ case tMessageError:
+ return mType == mtError
+ ? (cxType)mText
+ : (cxType)false;
+
+ default: break;
}
+
+ return cText2SkinRender::GetTokenData(Token);
}
// --- cText2SkinDisplayMenu --------------------------------------------------
-cText2SkinDisplayMenu::cText2SkinDisplayMenu(cText2SkinLoader *Loader) {
- mRender = new cText2SkinRender(Loader, sectionMenu);
- mDirty = false;
- mMaxItems = 0;
+cText2SkinDisplayMenu::cText2SkinDisplayMenu(cText2SkinLoader *Loader):
+ cText2SkinRender(Loader, cxDisplay::menu),
+ mMaxItems(0),
+ mTitle(""),
+ mButtonRed(""),
+ mButtonGreen(""),
+ mButtonYellow(""),
+ mButtonBlue(""),
+ mMessageType(mtStatus),
+ mMessageText(""),
+ mEvent(NULL),
+ mItems(),
+ mCurrentItem((uint)-1)
+{
+ cxDisplay *disp = Loader->Data()->Get(cxDisplay::menu);
+ const cxObject *area = NULL;
+ for (uint i = 0; i < disp->Objects(); ++i) {
+ const cxObject *o = disp->GetObject(i);
+ if (disp->GetObject(i)->Type() == cxObject::list) {
+ area = o;
+ break;
+ }
+ }
- cText2SkinItem *area = Loader->Data()->Get(sectionMenu, itemMenuArea);
- cText2SkinItem *item = Loader->Data()->Get(sectionMenu, itemMenuItem);
- if (area && item)
- mMaxItems = area->Size().h / item->Size().h;
- else
- esyslog("ERROR: text2skin: Skin is missing the items MenuArea and/or MenuItem");
+ if (area != NULL) {
+ const cxObject *item = area->GetObject(0);
+ if (item != NULL && item->Type() == cxObject::item)
+ mMaxItems = area->Size().h / item->Size().h;
+ }
}
cText2SkinDisplayMenu::~cText2SkinDisplayMenu() {
- delete mRender;
}
void cText2SkinDisplayMenu::Clear(void) {
- mRender->Lock();
- mRender->mMenuItems.clear();
- mRender->mMenuTitle = "";
- mRender->mMenuCurrent = -1;
- mRender->mMenuRed = "";
- mRender->mMenuGreen = "";
- mRender->mMenuYellow = "";
- mRender->mMenuBlue = "";
- mRender->mMenuEvent = NULL;
- mRender->mMenuRecording = NULL;
- mRender->mMenuText = "";
Dprintf("Clear\n");
- //mRender->mMessageText = "";
- DELETENULL(mRender->mScroller);
- mRender->Unlock();
- mDirty = true;
+ mItems.clear();
+ mEvent = NULL;
+ mRecording = NULL;
+ mText = "";
+ SetDirty();
}
void cText2SkinDisplayMenu::SetTitle(const char *Title) {
if (Title == NULL) Title = "";
- mRender->Lock();
- if (mRender->mMenuTitle != Title) {
- mRender->mMenuTitle = Title;
- mDirty = true;
+ if (mTitle != Title) {
+ mTitle = Title;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) {
@@ -273,33 +556,32 @@ void cText2SkinDisplayMenu::SetButtons(const char *Red, const char *Green, const
if (Green == NULL) Green = "";
if (Yellow == NULL) Yellow = "";
if (Blue == NULL) Blue = "";
- mRender->Lock();
- if (mRender->mMenuRed != Red || mRender->mMenuGreen != Green || mRender->mMenuYellow != Yellow || mRender->mMenuBlue != Blue) {
- mRender->mMenuRed = Red;
- mRender->mMenuGreen = Green;
- mRender->mMenuYellow = Yellow;
- mRender->mMenuBlue = Blue;
- mDirty = true;
+ if (mButtonRed != Red || mButtonGreen != Green || mButtonYellow != Yellow || mButtonBlue != Blue) {
+ mButtonRed = Red;
+ mButtonGreen = Green;
+ mButtonYellow = Yellow;
+ mButtonBlue = Blue;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayMenu::SetMessage(eMessageType Type, const char *Text) {
- Dprintf("SetMessage %s\n", Text);
if (Text == NULL) Text = "";
- mRender->Lock();
- if (mRender->mMessageType != Type || mRender->mMessageText != Text) {
- mRender->mMessageType = Type;
- mRender->mMessageText = Text;
- mDirty = true;
+ if (mMessageType != Type || mMessageText != Text) {
+ mMessageType = Type;
+ mMessageText = Text;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayMenu::SetItem(const char *Text, int Index, bool Current, bool Selectable) {
- cText2SkinRender::MenuItem item;
+ if (Text == NULL)
+ return;
+
+ tListItem item;
item.text = Text;
item.sel = Selectable;
+
for (int i = 0; i < MaxTabs; ++i) {
const char *tab = GetTabbedText(Text, i);
if (tab)
@@ -307,78 +589,202 @@ void cText2SkinDisplayMenu::SetItem(const char *Text, int Index, bool Current, b
if (!Tab(i + 1))
break;
}
- mRender->Lock();
- SetEditableWidth(mRender->GetEditableWidth(item, Current));
- if ((int)mRender->mMenuItems.size() <= Index) {
- mRender->mMenuItems.push_back(item);
- mDirty = true;
- } else if (mRender->mMenuItems[Index] != item) {
- mRender->mMenuItems[Index] = item;
- mDirty = true;
+
+ if (mItems.size() <= (uint)Index) {
+ mItems.push_back(item);
+ SetDirty();
}
- if (Current && mRender->mMenuCurrent != Index) {
- mRender->mMenuCurrent = Index;
- mDirty = true;
+ else if (mItems[Index] != item) {
+ mItems[Index] = item;
+ SetDirty();
+ }
+
+ if (Current && mCurrentItem != Index) {
+ mCurrentItem = Index;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayMenu::SetEvent(const cEvent *Event) {
- mRender->Lock();
- if (mRender->mMenuEvent != Event) {
- mRender->mMenuEvent = Event;
- mDirty = true;
+ if (mEvent != Event) {
+ mEvent = Event;
+ if (mEvent != NULL)
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayMenu::SetRecording(const cRecording *Recording) {
- mRender->Lock();
- if (mRender->mMenuRecording != Recording) {
- mRender->mMenuRecording = Recording;
- mDirty = true;
+ // yet unused
+ if (mRecording != Recording) {
+ mRecording = Recording;
+ if (mRecording != NULL)
+ SetDirty();
}
- mRender->Unlock();
}
-void cText2SkinDisplayMenu::SetText(const char *Text, bool FixedFont) {
+void cText2SkinDisplayMenu::SetText(const char *Text, bool /*FixedFont*/) {
if (Text == NULL) Text = "";
- mRender->Lock();
- if (mRender->mMenuText != Text || mRender->mMenuTextFixedFont != FixedFont) {
- mRender->mMenuText = Text;
- mRender->mMenuTextFixedFont = FixedFont;
- mDirty = true;
+ if (mText != Text) {
+ mText = Text;
+ SetDirty();
}
- mRender->Unlock();
}
void cText2SkinDisplayMenu::SetTabs(int Tab1, int Tab2, int Tab3, int Tab4, int Tab5) {
cSkinDisplayMenu::SetTabs(Tab1, Tab2, Tab3, Tab4, Tab5);
- mRender->Lock();
- mRender->mMenuTabs[0] = Tab(0);
- mRender->mMenuTabs[1] = Tab(1);
- mRender->mMenuTabs[2] = Tab(2);
- mRender->mMenuTabs[3] = Tab(3);
- mRender->mMenuTabs[4] = Tab(4);
- mRender->mMenuTabs[5] = Tab(5);
- mRender->Unlock();
}
void cText2SkinDisplayMenu::Scroll(bool Up, bool Page) {
- mRender->Lock();
- if (mRender->mScroller && (Up ? mRender->mScroller->CanScrollUp() : mRender->mScroller->CanScrollDown())) {
- mRender->mMenuScroll = true;
- mRender->mMenuScrollUp = Up;
- mRender->mMenuScrollPage = Page;
- mDirty = true;
- }
- mRender->Unlock();
+ cText2SkinRender::Scroll(Up, Page);
+ SetDirty();
}
void cText2SkinDisplayMenu::Flush(void) {
- if (mDirty) {
- mRender->Flush();
- mDirty = false;
+ cText2SkinRender::Flush();
+}
+
+cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) {
+ switch (Token.Type) {
+ case tMenuItem:
+ case tMenuGroup:
+ case tIsMenuItem:
+ case tIsMenuGroup:
+ case tIsMenuCurrent:
+ if (Token.Index < 0) return false;
+ case tMenuCurrent:
+ Dprintf("MenuCurrent: index %d\n", Token.Index);
+ if (Token.Index >= 0 && Token.Tab == -1) return false;
+ break;
+
+ default:
+ if (Token.Tab >= 0) return false;
+ break;
}
-}
+ switch (Token.Type) {
+ case tMenuTitle:
+ return mTitle;
+
+ case tMenuItem:
+ return mItems.size() > (uint)Token.Index && mItems[Token.Index].sel
+ && mCurrentItem != Token.Index
+ ? (cxType)mItems[Token.Index].tabs[Token.Tab]
+ : (cxType)false;
+
+ case tIsMenuItem:
+ return mItems.size() > (uint)Token.Index && mItems[Token.Index].sel
+ && mCurrentItem != Token.Index;
+
+ case tMenuCurrent:
+ if (Token.Index < 0)
+ return mItems[mCurrentItem].text;
+
+ return mItems.size() > (uint)Token.Index && mItems[Token.Index].sel
+ && mCurrentItem == Token.Index
+ ? (cxType)mItems[Token.Index].tabs[Token.Tab]
+ : (cxType)false;
+
+ case tIsMenuCurrent:
+ return mItems.size() > (uint)Token.Index && mItems[Token.Index].sel
+ && mCurrentItem == Token.Index;
+
+ case tMenuGroup:
+ return mItems.size() > (uint)Token.Index && !mItems[Token.Index].sel
+ ? (cxType)mItems[Token.Index].tabs[Token.Tab]
+ : (cxType)false;
+
+ case tIsMenuGroup:
+ return mItems.size() > (uint)Token.Index && !mItems[Token.Index].sel;
+
+ case tButtonRed:
+ return mButtonRed;
+
+ case tButtonGreen:
+ return mButtonGreen;
+
+ case tButtonYellow:
+ return mButtonYellow;
+
+ case tButtonBlue:
+ return mButtonBlue;
+
+ case tMessage:
+ return mMessageText;
+
+ case tMessageInfo:
+ return mMessageType == mtInfo
+ ? (cxType)mMessageText
+ : (cxType)false;
+
+ case tMessageWarning:
+ return mMessageType == mtWarning
+ ? (cxType)mMessageText
+ : (cxType)false;
+
+ case tMessageStatus:
+ return mMessageType == mtStatus
+ ? (cxType)mMessageText
+ : (cxType)false;
+
+ case tMessageError:
+ return mMessageType == mtError
+ ? (cxType)mMessageText
+ : (cxType)false;
+
+ case tPresentStartDateTime:
+ return mEvent != NULL
+ ? (cxType)TimeType(mEvent->StartTime(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentVPSDateTime:
+ return mEvent != NULL
+ ? (cxType)TimeType(mEvent->Vps(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentEndDateTime:
+ return mEvent != NULL
+ ? (cxType)TimeType(mEvent->EndTime(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentProgress:
+ return mEvent != NULL
+ ? (cxType)TimeType(time(NULL) - mEvent->StartTime(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentDuration:
+ return mEvent != NULL
+ ? (cxType)TimeType(mEvent->Duration(), Token.Attrib)
+ : (cxType)false;
+
+ case tPresentTitle:
+ return mEvent != NULL
+ ? (cxType)mEvent->Title()
+ : (cxType)false;
+
+ case tPresentShortText:
+ return mEvent != NULL
+ ? (cxType)mEvent->ShortText()
+ : (cxType)false;
+
+ case tPresentDescription:
+ return mEvent != NULL
+ ? (cxType)mEvent->Description()
+ : (cxType)false;
+
+ case tHasVPS:
+ return mEvent != NULL && mEvent->Vps() != 0;
+
+ case tHasTimer:
+ return mEvent != NULL && mEvent->HasTimer();
+
+ case tIsRunning:
+ return mEvent != NULL && mEvent->IsRunning();
+
+ case tMenuText:
+ return mText;
+
+ default: break;
+ }
+
+ return cText2SkinRender::GetTokenData(Token);
+}
diff --git a/display.h b/display.h
index aa3e23a..5e3df0b 100644
--- a/display.h
+++ b/display.h
@@ -1,23 +1,31 @@
/*
- * $Id: display.h,v 1.6 2004/06/07 18:23:11 lordjaxom Exp $
+ * $Id: display.h,v 1.4 2004/12/08 18:47:37 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_SKIN_H
#define VDR_TEXT2SKIN_SKIN_H
#include "common.h"
+#include "render.h"
+#include "xml/string.h"
#include <vdr/skins.h>
+#include <string>
class cText2SkinData;
class cText2SkinI18n;
-class cText2SkinRender;
class cText2SkinLoader;
-class cText2SkinDisplayChannel: public cSkinDisplayChannel {
+class cText2SkinDisplayChannel: public cSkinDisplayChannel, public cText2SkinRender {
private:
- bool mWithInfo;
- cText2SkinRender *mRender;
- bool mDirty;
+ const cChannel *mChannel;
+ int mNumber;
+ const cEvent *mPresent;
+ const cEvent *mFollowing;
+ eMessageType mType;
+ std::string mText;
+
+protected:
+ virtual cxType GetTokenData(const txToken &Token);
public:
cText2SkinDisplayChannel(cText2SkinLoader *Loader, bool WithInfo);
@@ -25,14 +33,18 @@ public:
virtual void SetChannel(const cChannel *Channel, int Number);
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
- virtual void SetMessage(eMessageType Type, const char *Text);
+ virtual void SetMessage(eMessageType Type, const char *Text);
virtual void Flush(void);
};
-class cText2SkinDisplayVolume: public cSkinDisplayVolume {
+class cText2SkinDisplayVolume: public cSkinDisplayVolume, public cText2SkinRender {
private:
- cText2SkinRender *mRender;
- bool mDirty;
+ int mCurrent;
+ int mTotal;
+ int mMute;
+
+protected:
+ virtual cxType GetTokenData(const txToken &Token);
public:
cText2SkinDisplayVolume(cText2SkinLoader *Loader);
@@ -41,10 +53,26 @@ public:
virtual void Flush(void);
};
-class cText2SkinDisplayReplay: public cSkinDisplayReplay {
+class cText2SkinDisplayReplay: public cSkinDisplayReplay, public cText2SkinRender {
private:
- cText2SkinRender *mRender;
- bool mDirty;
+ std::string mTitle;
+ bool mStateInfo;
+ bool mPlay;
+ bool mForward;
+ int mSpeed;
+ int mCurrent;
+ int mTotal;
+ std::string mPosition;
+ std::string mDuration;
+ const cMarks *mMarks;
+ std::string mPrompt;
+ eMessageType mType;
+ std::string mText;
+
+protected:
+ virtual cxType GetTokenData(const txToken &Token);
+ virtual const cMarks *GetMarks(void) const { return mMarks; }
+
public:
cText2SkinDisplayReplay(cText2SkinLoader *Loader, bool ModeOnly);
virtual ~cText2SkinDisplayReplay();
@@ -55,14 +83,17 @@ public:
virtual void SetCurrent(const char *Current);
virtual void SetTotal(const char *Total);
virtual void SetJump(const char *Jump);
- virtual void SetMessage(eMessageType Type, const char *Text);
+ virtual void SetMessage(eMessageType Type, const char *Text);
virtual void Flush(void);
};
-class cText2SkinDisplayMessage: public cSkinDisplayMessage {
+class cText2SkinDisplayMessage: public cSkinDisplayMessage, public cText2SkinRender {
private:
- cText2SkinRender *mRender;
- bool mDirty;
+ eMessageType mType;
+ std::string mText;
+
+protected:
+ virtual cxType GetTokenData(const txToken &Token);
public:
cText2SkinDisplayMessage(cText2SkinLoader *Loader);
@@ -71,18 +102,50 @@ public:
virtual void Flush(void);
};
-class cText2SkinDisplayMenu: public cSkinDisplayMenu {
+class cText2SkinDisplayMenu: public cSkinDisplayMenu, public cText2SkinRender {
private:
- cText2SkinRender *mRender;
- bool mDirty;
int mMaxItems;
+ // common for all menus
+ std::string mTitle;
+ std::string mButtonRed;
+ std::string mButtonGreen;
+ std::string mButtonYellow;
+ std::string mButtonBlue;
+ eMessageType mMessageType;
+ std::string mMessageText;
+
+ // detailed event view
+ const cEvent *mEvent;
+ // detailed recording
+ const cRecording *mRecording;
+ // long text
+ std::string mText;
+
+ // list view
+ struct tListItem {
+ std::string text;
+ std::string tabs[MaxTabs];
+ bool sel;
+
+ bool operator!=(const tListItem &b) { return b.text != text || b.sel != sel; }
+ };
+
+ std::vector<tListItem> mItems;
+ int mCurrentItem;
+
+protected:
+ virtual cxType GetTokenData(const txToken &Token);
+ virtual int GetTab(int n) { return cSkinDisplayMenu::Tab(n); }
+ virtual bool HasTabText(int Index, int n);
+ virtual void SetEditableWidth(int Width) { printf("seteditablewidth: %d\n", Width); cSkinDisplayMenu::SetEditableWidth(Width); }
+
public:
cText2SkinDisplayMenu(cText2SkinLoader *Loader);
virtual ~cText2SkinDisplayMenu();
- virtual int MaxItems(void) { return mMaxItems; }
- virtual void Clear(void);
+ virtual int MaxItems(void) { return mMaxItems; }
+ virtual void Clear(void);
virtual void SetTitle(const char *Title);
virtual void SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue);
virtual void SetMessage(eMessageType Type, const char *Text);
@@ -95,4 +158,13 @@ public:
virtual void Flush(void);
};
+inline bool cText2SkinDisplayMenu::HasTabText(int Index, int n)
+{
+ if (Index < 0 || mItems.size () > (uint)Index)
+ return n == -1
+ ? mItems[Index].text.length() > 0
+ : mItems[Index].tabs[n].length() > 0;
+ return false;
+}
+
#endif // VDR_TEXT2SKIN_SKIN_H
diff --git a/file.c b/file.c
index 083384d..4da0668 100644
--- a/file.c
+++ b/file.c
@@ -1,5 +1,5 @@
/*
- * $Id: file.c,v 1.1 2004/06/02 20:43:05 lordjaxom Exp $
+ * $Id: file.c,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#include "file.h"
@@ -12,7 +12,7 @@ cText2SkinFile::cText2SkinFile(const char *Skin) {
cText2SkinFile::~cText2SkinFile() {
}
-bool cText2SkinFile::Load(const string &Filename) {
+bool cText2SkinFile::Load(const std::string &Filename) {
bool result = true;
if (access(Filename.c_str(), F_OK) == 0) {
isyslog("text2skin: loading %s", Filename.c_str());
diff --git a/file.h b/file.h
index a941591..7f9a692 100644
--- a/file.h
+++ b/file.h
@@ -1,5 +1,5 @@
/*
- * $Id: file.h,v 1.1 2004/06/02 20:43:05 lordjaxom Exp $
+ * $Id: file.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_FILE_H
@@ -10,7 +10,7 @@
class cText2SkinFile {
private:
- string mSkin;
+ std::string mSkin;
protected:
virtual bool Parse(const char *Text) = 0;
@@ -19,9 +19,9 @@ public:
cText2SkinFile(const char *Skin);
virtual ~cText2SkinFile();
- virtual bool Load(const string &Filename);
+ virtual bool Load(const std::string &Filename);
- const string &Skin(void) const { return mSkin; }
+ const std::string &Skin(void) const { return mSkin; }
};
#endif // VDR_TEXT2SKIN_FILE_H
diff --git a/font.c b/font.c
index d15bd8b..7320f8a 100644
--- a/font.c
+++ b/font.c
@@ -1,127 +1,43 @@
/*
- * $Id: font.c,v 1.5 2004/05/30 21:48:21 austriancoder Exp $
+ * $Id: font.c,v 1.5 2004/12/08 17:23:17 lordjaxom Exp $
*/
#include "font.h"
+#include "render.h"
+#include <vdr/tools.h>
-// ==================================
-// constr.
-cText2SkinFont::cText2SkinFont()
-{
- m_library = 0;
- m_face = 0;
-
- // init freetype2 lib
- int error = FT_Init_FreeType(&m_library);
- if (error)
- {
- esyslog("ERROR: Could not init freetype library\n");
- }
-}
+#ifdef HAVE_FREETYPE
+cGraphtftFont cText2SkinFont::mFontCache;
+#endif
-// ==================================
-// deconstr.
-cText2SkinFont::~cText2SkinFont()
+cText2SkinFont::cText2SkinFont(void)
{
- if (m_face)
- {
- FT_Done_Face(m_face);
- }
-
- if (m_library)
- {
- FT_Done_FreeType(m_library);
- }
}
-// ==================================
-// try to load a font
-bool cText2SkinFont::LoadFontFile(string Filename)
-{
- int error = FT_New_Face(m_library, Filename.c_str(), 0, &m_face);
-
- // every thing ok?
- if (error == FT_Err_Unknown_File_Format)
- {
- esyslog("ERROR: Font file (%s) could be opened and read, but it appears that its font format is unsupported\n", Filename.c_str());
- return false;
- }
- else if (error)
- {
- esyslog("ERROR: Font file (%s) could be opened or read, or simply it is broken\n", Filename.c_str());
- return false;
- }
-
- // set slot
- m_slot = m_face->glyph;
-
- return true;
-}
-
-// ==================================
-// sets size of font
-void cText2SkinFont::SetFontSize(int size)
+cText2SkinFont::~cText2SkinFont()
{
- FT_Set_Char_Size
- (
- m_face, // handle to face object
- 0, // char_width in 1/64th of points
- size*64, // char_height in 1/64th of points
- 300, // horizontal device resolution (dpi)
- 300 // vertical device resolution (dpi)
- );
}
-// ==================================
-// write some text :)
-void cText2SkinFont::DrawTextTransparent(cOsd *Osd, int x, int y, const char *s, tColor ColorFg, int Width, int Height, int Alignment)
+const cFont *cText2SkinFont::Load(const std::string &Path, const std::string &Filename, int Size)
{
- // where to get this infos?
-// int w = Font->Width(s);
-// int h = Font->Height();
-
- int limit = 0;
- if (Width || Height)
- {
- int cw = Width ? Width : w;
- limit = x + cw;
- if (Width)
- {
- if ((Alignment & taLeft) != 0)
- ;
- else if ((Alignment & taRight) != 0)
- {
- if (w < Width)
- x += Width - w;
- }
- else
- {
- // taCentered
- if (w < Width)
- x += (Width - w) / 2;
- }
- }
-
- if (Height)
- {
- if ((Alignment & taTop) != 0)
- ;
- else if ((Alignment & taBottom) != 0)
- {
- if (h < Height)
- y += Height - h;
- }
- else
- {
- // taCentered
- if (h < Height)
- y += (Height - h) / 2;
- }
- }
- }
-
- // write text
- while (s && *s)
- {
- }
+ if (Filename == "Osd")
+ return cFont::GetFont(fontOsd);
+ else if (Filename == "Fix")
+ return cFont::GetFont(fontFix);
+ else if (Filename == "Sml")
+ return cFont::GetFont(fontSml);
+
+ const cFont *res = NULL;
+#ifdef HAVE_FREETYPE
+ char *cachename;
+ asprintf(&cachename, "%s_%d", Filename.c_str(), Size);
+ if (mFontCache.Load(Path + "/" + Filename, cachename, Size))
+ res = mFontCache.GetFont(cachename);
+ else
+ esyslog("ERROR: Text2Skin: Couldn't load font %s:%d", Filename.c_str(), Size);
+ free(cachename);
+#else
+ esyslog("ERROR: Text2Skin: Font engine not enabled at compile time!");
+#endif
+ return res;
}
diff --git a/font.h b/font.h
index dfc007f..160076c 100644
--- a/font.h
+++ b/font.h
@@ -1,39 +1,27 @@
/*
- * $Id: font.h,v 1.4 2004/06/02 20:43:05 lordjaxom Exp $
+ * $Id: font.h,v 1.5 2004/12/08 17:23:41 lordjaxom Exp $
*/
-#ifndef VDR_TEXT2SKIN_FREETYPE_H
-#define VDR_TEXT2SKIN_FREETYPE_H
+#ifndef VDR_TEXT2SKIN_FONT_H
+#define VDR_TEXT2SKIN_FONT_H
#include "common.h"
-#include "data.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
+#ifdef HAVE_FREETYPE
+# include "graphtft/font.h"
+#endif
+class cText2SkinFont {
+private:
+#ifdef HAVE_FREETYPE
+ static cGraphtftFont mFontCache;
+#endif
-// kannst noch einbauen, dass er die fonts "fontOsd" "fontSml" und "fontFix" aus VDR statt aus freetype nimmt
+ // disallow direct construction
+ cText2SkinFont(void);
+ virtual ~cText2SkinFont();
-// ==================================
-/* cText2SkinFont
-
- Adds interface to FreeTpye font lib.
-*/
-class cText2SkinFont
-{
public:
- cText2SkinFont();
- ~cText2SkinFont();
-
- // font handling
- bool LoadFontFile(string Filename);
- void SetFontSize(int size);
- void DrawTextTransparent(cOsd *Osd, int x, int y, const char *s, tColor ColorFg, int Width, int Height, int Alignment);
-
-private:
- FT_Library m_library;
- FT_Face m_face;
- FT_GlyphSlot m_slot;
-
+ static const cFont *Load(const std::string &Path, const std::string &Filename, int Size);
};
-#endif /*VDR_TEXT2SKIN_FREETYPE_H*/
+#endif // VDR_TEXT2SKIN_FONT_H
diff --git a/graphtft/font.c b/graphtft/font.c
new file mode 100644
index 0000000..f4657c3
--- /dev/null
+++ b/graphtft/font.c
@@ -0,0 +1,173 @@
+/*
+ * $Id: font.c,v 1.2 2004/12/06 21:19:07 lordjaxom Exp $
+ *
+ * Taken from GraphTFT
+ */
+
+#include "font.h"
+
+cGraphtftFont::cGraphtftFont()
+{
+ _library = 0;
+ _face = 0;
+
+ // init freetype2 lib
+ int error = FT_Init_FreeType(&_library);
+ if (error)
+ {
+ fprintf(stderr, "ERROR: Could not init freetyie library\n");
+ }
+}
+
+cGraphtftFont::~cGraphtftFont()
+{
+ Clear();
+
+ if (_face)
+ {
+ FT_Done_Face(_face);
+ }
+
+ if (_library)
+ {
+ FT_Done_FreeType(_library);
+ }
+}
+
+bool cGraphtftFont::Load(string Filename, string CacheName, int Size, int Width)
+{
+ if ( _cache.find(CacheName) != _cache.end() )
+ return true;
+
+ int error = FT_New_Face(_library, Filename.c_str(), 0, &_face);
+
+ // every thing ok?
+ if (error == FT_Err_Unknown_File_Format)
+ {
+ fprintf(stderr, "ERROR: Font file (%s) could be opened and read, but it appears that its font format is unsupported\n", Filename.c_str());
+ return false;
+ }
+ else if (error)
+ {
+ fprintf(stderr, "ERROR: Font file (%s) could be opened or read, or simply it is broken\n", Filename.c_str());
+ return false;
+ }
+
+ // set slot
+ _slot = _face->glyph;
+
+ // set Size
+ FT_Set_Char_Size
+ (
+ _face, // handle to face object
+ Width*64, // char_width in 1/64th of points
+ Size*64, // char_height in 1/64th of points
+ 0, // horizontal device resolution (dpi)
+ 0 // vertical device resolution (dpi)
+ );
+
+ /* load glyph image into the slot (erase previous one) */
+ error = FT_Load_Char( _face, '_', FT_LOAD_RENDER );
+ if ( error )
+ return false;
+
+ cFont::tPixelData value;
+ int num_rows_global = (_face->size->metrics.height / 64 )+1;
+ int num_rows = num_rows_global + 2;
+
+ cFont::tPixelData * font_data = new cFont::tPixelData[225 * num_rows];
+
+ for (int i = 0; i < 225; i++)
+ for (int j = 0; j < num_rows; j++)
+ font_data[(i*num_rows)+j]=0x00;
+
+ font_data[0+0]=_slot->bitmap.width+2;
+ font_data[0+1]=num_rows_global;
+
+ // Time to put char 33..255 in font_data
+ FT_UInt glyph_index;
+ for ( int num_char = 33, num_char_array = 1; num_char < 256; num_char++, num_char_array++ )
+ {
+
+ //Get FT char index
+ glyph_index = FT_Get_Char_Index( _face, num_char );
+
+ //Load the char
+ error = FT_Load_Glyph( _face, glyph_index, FT_LOAD_DEFAULT );
+ if ( error ) continue; /* ignore errors */
+
+ // convert to an mono bitmap
+ error = FT_Render_Glyph( _face->glyph, ft_render_mode_mono );
+ if ( error ) continue;
+
+ // now, convert to vdr font data
+ int width = ((_slot->bitmap.width+2) > (int)sizeof(cFont::tPixelData) * 8) ? (((int)sizeof(cFont::tPixelData) * 8) - 2) : _slot->bitmap.width;
+ int top = _slot->bitmap_top;
+ int y_off = Size - top;
+
+ font_data[(num_char_array*num_rows)+0]=width+2;
+ font_data[(num_char_array*num_rows)+1]=num_rows_global;
+
+ unsigned char *bmp = _slot->bitmap.buffer;
+
+ for (int y = 0; y < _slot->bitmap.rows; ++y , y_off++) {
+ int pos = 0;
+ int bit = 0x80;
+ value = 0x00;
+
+ for (int x = 0; x < _slot->bitmap.width; ++x) {
+ if (bmp[pos] & bit && x < width)
+ value = value | (cFont::tPixelData)1 << _slot->bitmap.width-x+1;
+
+ bit >>= 1;
+ if (bit == 0) {
+ bit = 0x80;
+ ++pos;
+ }
+ }
+ bmp += _slot->bitmap.pitch;
+ font_data[(num_char_array*num_rows)+y_off+2] = value;
+ }
+
+ }
+ // If all was ok, put the vdr font into the cache and return true
+ cFont* newFont = NULL;
+ newFont = new cFont(font_data);
+ if (newFont) {
+ _cache[CacheName] = newFont;
+ _del[CacheName] = font_data;
+ return true;
+ }
+ delete(font_data);
+ // Something went wrong!
+ return false;
+}
+
+const cFont* cGraphtftFont::GetFont(string CacheName){
+ if (CacheName == "Sml") return cFont::GetFont(fontSml);
+ else if (CacheName == "Fix") return cFont::GetFont(fontFix);
+ else if ( _cache.find(CacheName) != _cache.end() ){
+ return _cache[CacheName];
+ }
+ return cFont::GetFont(fontOsd);
+}
+
+void cGraphtftFont::Clear(string CacheName)
+{
+ Clear();
+}
+
+void cGraphtftFont::Clear()
+{
+ cache_map::iterator it = _cache.begin();
+ for (; it != _cache.end(); ++it)
+ delete((*it).second);
+ _cache.clear();
+
+ del_map::iterator del_it = _del.begin();
+ for (; del_it != _del.end(); ++del_it)
+ delete((*del_it).second);
+ _del.clear();
+}
+
+cGraphtftFont GraphtftFont;
diff --git a/graphtft/font.h b/graphtft/font.h
new file mode 100644
index 0000000..5e23498
--- /dev/null
+++ b/graphtft/font.h
@@ -0,0 +1,48 @@
+/*
+ * $Id: font.h,v 1.2 2004/12/06 21:19:07 lordjaxom Exp $
+ *
+ * Taken from GraphTFT
+ */
+
+#ifndef VDR__GRAPHTFTFONT_H
+#define VDR__GRAPHTFTFONT_H
+
+#include <map>
+#include <string>
+#include <vector>
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include <vdr/font.h>
+
+using std::map;
+using std::string;
+using std::vector;
+
+
+class cGraphtftFont
+{
+private:
+ typedef map<string,cFont*> cache_map;
+ typedef map<string,cFont::tPixelData*> del_map;
+
+public:
+ cGraphtftFont();
+ ~cGraphtftFont();
+
+ bool Load(string Filename, string CacheName, int Size, int Width = 0);
+ const cFont* GetFont(string CacheName);
+ void Clear(string CacheName);
+ void Clear();
+
+private:
+ FT_Library _library;
+ FT_Face _face;
+ FT_GlyphSlot _slot;
+ cache_map _cache;
+ del_map _del;
+
+};
+
+extern cGraphtftFont GraphtftFont;
+
+#endif
diff --git a/i18n.c b/i18n.c
index efe6d1e..b5612ed 100644
--- a/i18n.c
+++ b/i18n.c
@@ -1,5 +1,5 @@
/*
- * $Id: i18n.c,v 1.9 2004/06/22 16:48:03 lordjaxom Exp $
+ * $Id: i18n.c,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#include "i18n.h"
@@ -85,7 +85,7 @@ const tI18nPhrase Phrases[] = {
};
cText2SkinI18n::cText2SkinI18n(const char *Skin): cText2SkinFile(Skin) {
- mIdentity = (string)"text2skin_" + Skin;
+ mIdentity = (std::string)"text2skin_" + Skin;
mNumPhrases = 0;
mPhrases = (tI18nPhrase*)malloc(sizeof(tI18nPhrase));
memset(mPhrases[mNumPhrases], 0, sizeof(tI18nPhrase));
@@ -112,7 +112,7 @@ bool cText2SkinI18n::Parse(const char *Text) {
for (i = 0; i < I18nNumLanguages; ++i) {
char *langs = strdup(I18nLanguageCode(i));
char *ptr = langs, *ep;
- string text;
+ std::string text;
p[i] = strdup("");
do {
if ((ep = strchr(ptr, ',')) != NULL)
@@ -139,7 +139,7 @@ bool cText2SkinI18n::Parse(const char *Text) {
return result;
}
-bool cText2SkinI18n::Load(const string &Filename) {
+bool cText2SkinI18n::Load(const std::string &Filename) {
if (cText2SkinFile::Load(Filename)) {
I18nRegister(mPhrases, mIdentity.c_str());
return true;
diff --git a/i18n.h b/i18n.h
index 11abc13..4156007 100644
--- a/i18n.h
+++ b/i18n.h
@@ -1,5 +1,5 @@
/*
- * $Id: i18n.h,v 1.3 2004/06/22 16:48:03 lordjaxom Exp $
+ * $Id: i18n.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_I18N_H
@@ -13,7 +13,7 @@ extern const tI18nPhrase Phrases[];
class cText2SkinI18n: public cText2SkinFile {
private:
- string mIdentity;
+ std::string mIdentity;
tI18nPhrase *mPhrases;
int mNumPhrases;
@@ -24,8 +24,8 @@ public:
cText2SkinI18n(const char *Skin);
virtual ~cText2SkinI18n();
- virtual bool Load(const string &Filename);
- string Translate(const string &Text) { return I18nTranslate(Text.c_str(), mIdentity.c_str()); }
+ virtual bool Load(const std::string &Filename);
+ std::string Translate(const std::string &Text) { return I18nTranslate(Text.c_str(), mIdentity.c_str()); }
};
#endif // VDR_TEXT2SKIN_I18N_H
diff --git a/loader.c b/loader.c
index f74a6cc..c08c8f1 100644
--- a/loader.c
+++ b/loader.c
@@ -1,19 +1,20 @@
/*
- * $Id: loader.c,v 1.12 2004/06/22 16:48:03 lordjaxom Exp $
+ * $Id: loader.c,v 1.4 2004/12/08 17:13:25 lordjaxom Exp $
*/
#include "loader.h"
-#include "data.h"
#include "i18n.h"
#include "theme.h"
#include "display.h"
#include "text2skin.h"
+#include "xml/parser.h"
+#include "xml/skin.h"
#include <vdr/plugin.h>
#include <sys/types.h>
#include <dirent.h>
void cText2SkinLoader::Start(void) {
- DIR *d = opendir(SkinPath());
+ DIR *d = opendir(SkinPath().c_str());
if (d) {
struct dirent *ent;
while ((ent = readdir(d)) != NULL) {
@@ -21,7 +22,7 @@ void cText2SkinLoader::Start(void) {
struct stat buf;
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
- asprintf(&path, "%s/%s", SkinPath(), ent->d_name);
+ asprintf(&path, "%s/%s", SkinPath().c_str(), ent->d_name);
if (stat(path, &buf) == 0 && S_ISDIR(buf.st_mode))
Load(ent->d_name);
free(path);
@@ -32,7 +33,7 @@ void cText2SkinLoader::Start(void) {
void cText2SkinLoader::Load(const char *Skin) {
cText2SkinI18n *translations = NULL;
- string transfile = (string)SkinPath() + "/" + Skin + "/" + Skin + ".trans";
+ std::string transfile = (std::string)SkinPath() + "/" + Skin + "/" + Skin + ".trans";
if (access(transfile.c_str(), F_OK) == 0) {
translations = new cText2SkinI18n(Skin);
if (!translations->Load(transfile))
@@ -40,34 +41,33 @@ void cText2SkinLoader::Load(const char *Skin) {
}
cText2SkinTheme *theme = new cText2SkinTheme(Skin);
- string themefile = (string)SkinPath() + "/" + Skin + "/" + Skin + ".colors";
+ std::string themefile = SkinPath() + "/" + Skin + "/" + Skin + ".colors";
theme->Load(themefile);
- string skinfile = (string)SkinPath() + "/" + Skin + "/" + Skin + ".skin";
+ std::string skinfile = SkinPath() + "/" + Skin + "/" + Skin + ".skin";
if (access(skinfile.c_str(), F_OK) == 0) {
- cText2SkinData *data = new cText2SkinData(Skin);
- if (data->Load(skinfile)) {
- cText2SkinItem *skin = data->Get(sectionSkin, itemSkin);
- if (skin) {
- if (skin->Version() == cText2SkinPlugin::ThemeVersion()) {
- new cText2SkinLoader(data, translations, theme, Skin, skin->Name());
- return;
- } else
- esyslog("ERROR: text2skin: Skin is version %s, expecting %s", skin->Version().c_str(), cText2SkinPlugin::ThemeVersion());
+ isyslog("parsing %s", skinfile.c_str());
+
+ cxSkin *skin = xmlParse(Skin, skinfile);
+ if (skin) {
+ if (skin->Version() == cText2SkinPlugin::SkinVersion()) {
+ new cText2SkinLoader(skin, translations, theme, Skin, skin->Title());
return;
} else
- esyslog("ERROR: text2skin: Item=Skin is missing in Skin");
- }
- delete data;
- } else
- esyslog("ERROR: text2skin: %s/%s is not a valid skin directory", SkinPath(), Skin);
+ esyslog("ERROR: text2skin: Skin is version %s, expecting %s", skin->Version().c_str(),
+ cText2SkinPlugin::SkinVersion());
+ } else
+ esyslog("ERROR: error in skin file");
+ delete skin;
+ }
}
-cText2SkinLoader::cText2SkinLoader(cText2SkinData *Data, cText2SkinI18n *I18n, cText2SkinTheme *Theme, const string &Skin, const string &Description): cSkin(Skin.c_str(), Theme->Theme()) {
+cText2SkinLoader::cText2SkinLoader(cxSkin *Data, cText2SkinI18n *I18n, cText2SkinTheme *Theme, const std::string &Skin, const std::string &Description): cSkin(Skin.c_str(), Theme->Theme()) {
mData = Data;
mI18n = I18n;
mTheme = Theme;
mDescription = Description;
+
}
cText2SkinLoader::~cText2SkinLoader() {
@@ -77,7 +77,6 @@ cText2SkinLoader::~cText2SkinLoader() {
}
cSkinDisplayChannel *cText2SkinLoader::DisplayChannel(bool WithInfo) {
- Dprintf("WithInfo: %d\n", WithInfo);
return new cText2SkinDisplayChannel(this, WithInfo);
}
diff --git a/loader.h b/loader.h
index 5f22d7a..159f7fe 100644
--- a/loader.h
+++ b/loader.h
@@ -1,5 +1,5 @@
/*
- * $Id: loader.h,v 1.5 2004/06/07 18:23:11 lordjaxom Exp $
+ * $Id: loader.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_LOADER_H
@@ -8,33 +8,34 @@
#include "common.h"
#include <vdr/skins.h>
-class cText2SkinData;
+class cxSkin;
class cText2SkinI18n;
class cText2SkinTheme;
class cText2SkinLoader: public cSkin {
private:
- cText2SkinData *mData;
+ cxSkin *mData;
cText2SkinI18n *mI18n;
cText2SkinTheme *mTheme;
- string mDescription;
+ std::string mDescription;
public:
static void Start(void);
static void Load(const char *Skin);
- cText2SkinLoader(cText2SkinData *Data, cText2SkinI18n *I18n, cText2SkinTheme *Theme, const string &Skin, const string &Description);
+ cText2SkinLoader(cxSkin *Data, cText2SkinI18n *I18n, cText2SkinTheme *Theme,
+ const std::string &Skin, const std::string &Description);
~cText2SkinLoader();
virtual const char *Description(void) { return mDescription.c_str(); }
- virtual cSkinDisplayChannel *DisplayChannel(bool WithInfo);
- virtual cSkinDisplayMenu *DisplayMenu(void);
- virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
- virtual cSkinDisplayVolume *DisplayVolume(void);
- virtual cSkinDisplayMessage *DisplayMessage(void);
-
- cText2SkinData *Data(void) const { return mData; }
- cText2SkinI18n *I18n(void) const { return mI18n; }
+ virtual cSkinDisplayChannel *DisplayChannel(bool WithInfo);
+ virtual cSkinDisplayMenu *DisplayMenu(void);
+ virtual cSkinDisplayReplay *DisplayReplay(bool ModeOnly);
+ virtual cSkinDisplayVolume *DisplayVolume(void);
+ virtual cSkinDisplayMessage *DisplayMessage(void);
+
+ cxSkin *Data(void) const { return mData; }
+ cText2SkinI18n *I18n(void) const { return mI18n; }
cText2SkinTheme *Theme(void) const { return mTheme; }
};
diff --git a/menu.c b/menu.c
new file mode 100644
index 0000000..167b9b9
--- /dev/null
+++ b/menu.c
@@ -0,0 +1,34 @@
+/*
+ * $Id: menu.c,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
+ */
+
+#include "menu.h"
+#include "bitmap.h"
+
+// --- cText2SkinSetupPage ----------------------------------------------------
+
+cText2SkinSetupPage::cText2SkinSetupPage(void) {
+ mData = Text2SkinSetup;
+ Add(new cOsdItem(tr("Flush image cache"), osUser1));
+ Add(new cMenuEditIntItem(tr("Max. image cache size"), &mData.MaxCacheFill));
+}
+
+cText2SkinSetupPage::~cText2SkinSetupPage() {
+}
+
+void cText2SkinSetupPage::Store(void) {
+ SetupStore("MaxCacheFill", mData.MaxCacheFill);
+ Text2SkinSetup = mData;
+}
+
+eOSState cText2SkinSetupPage::ProcessKey(eKeys Key) {
+ eOSState state = cMenuSetupPage::ProcessKey(Key);
+ if (state == osUser1) {
+ Skins.Message(mtInfo, tr("Flushing image cache..."));
+ cText2SkinBitmap::FlushCache();
+ Skins.Message(mtInfo, NULL);
+ return osContinue;
+ }
+ return state;
+}
+
diff --git a/menu.h b/menu.h
new file mode 100644
index 0000000..5b4ffa1
--- /dev/null
+++ b/menu.h
@@ -0,0 +1,24 @@
+/*
+ * $Id: menu.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
+ */
+
+#ifndef VDR_TEXT2SKIN_MENU_H
+#define VDR_TEXT2SKIN_MENU_H
+
+#include "common.h"
+#include "setup.h"
+#include <vdr/menuitems.h>
+
+class cText2SkinSetupPage: public cMenuSetupPage {
+private:
+ cText2SkinSetup mData;
+
+public:
+ cText2SkinSetupPage(void);
+ virtual ~cText2SkinSetupPage();
+
+ virtual void Store(void);
+ eOSState ProcessKey(eKeys Key);
+};
+
+#endif // VDR_TEXT2SKIN_MENU_H
diff --git a/render.c b/render.c
index 02b97a0..2e0fda5 100644
--- a/render.c
+++ b/render.c
@@ -1,5 +1,5 @@
/*
- * $Id: render.c,v 1.39 2004/07/14 16:29:48 lordjaxom Exp $
+ * $Id: render.c,v 1.6 2004/12/08 18:47:37 lordjaxom Exp $
*/
#include "render.h"
@@ -10,87 +10,57 @@
#include "status.h"
#include "screen.h"
#include "scroller.h"
+#include "xml/display.h"
#include <vdr/channels.h>
#include <vdr/epg.h>
#include <vdr/menu.h>
cText2SkinRender *cText2SkinRender::mRender = NULL;
-cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Section) {
- tArea areas[MAXOSDAREAS];
- int numAreas = 0;
-
- SetDescription("Text2Skin: %s display update", SectionNames[Section].c_str());
-
- mData = Loader->Data();
- mI18n = Loader->I18n();
- mTheme = Loader->Theme();
- mSection = Section;
- mScreen = NULL;
- mScroller = NULL;
- mChannel = NULL;
- mChannelNumber = 0;
- mVolumeCurrent = -1;
- mVolumeTotal = -1;
- mVolumeMute = false;
- mReplayInfo = false;
- mReplayPlay = false;
- mReplayForward = false;
- mReplaySpeed = 0;
- mReplayCurrent = 0;
- mReplayTotal = 0;
- mReplayMarks = NULL;
- mMessageType = (eMessageType)-1;
- mChannelPresent = NULL;
- mChannelFollowing = NULL;
- mMenuCurrent = 0;
- mMenuEvent = NULL;
- mMenuRecording = NULL;
- mMenuTextFixedFont = false;
- mMenuScroll = false;
- mMenuScrollUp = false;
- mMenuScrollPage = false;
- mActive = false;
- mUpdateIn = 0;
- mBase = baseRelative;
-
- mRender = this;
-
- cText2SkinItem *item = mData->Get(sectionSkin, itemSkin);
- switch (mBase = item->Base()) {
- case baseRelative:
- mScreen = new cText2SkinScreen(Setup.OSDLeft, Setup.OSDTop);
- mBaseSize = SIZE(Setup.OSDWidth, Setup.OSDHeight);
- break;
- case baseAbsolute:
- mScreen = new cText2SkinScreen(0, 0);
- mBaseSize = SIZE(720, 576); //XXX
- break;
- default:
- break;
- }
-
- Dprintf("base: %d\n", item->Base());
+cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, cxDisplay::eType Display, const std::string &BasePath, bool OffScreen):
+ mSkin(Loader->Data()),
+ mDisplay(mSkin->Get(Display)),
+ mI18n(Loader->I18n()),
+ mTheme(Loader->Theme()),
+ mScreen(NULL),
+ mScroller(NULL),
+ mBasePath(BasePath),
+ mDirty(true),
+ mActive(false),
+ mDoUpdate(),
+ mMutex(),
+ mStarted(),
+ mUpdateIn(0),
+ mBaseSize()
+{
+ mRender = this;
+
+ SetDescription("Text2Skin: %s display update", mDisplay->GetType().c_str());
+
+ if (mBasePath.length() == 0)
+ mBasePath = SkinPath() + "/" + mSkin->Name();
+
+ if (mDisplay == NULL)
+ return;
+
+ mScreen = new cText2SkinScreen(OffScreen);
+ mBaseSize = mSkin->BaseSize();
eOsdError res;
- cText2SkinData::tIterator it = mData->First(mSection);
- for (; it != mData->Last(mSection); ++it) {
- if ((*it)->Item() == itemBackground) {
- if (numAreas < MAXOSDAREAS) {
- POINT p = (*it)->Pos();
- SIZE s = (*it)->Size();
- areas[numAreas].x1 = p.x;
- areas[numAreas].y1 = p.y;
- areas[numAreas].x2 = p.x + s.w - 1;
- areas[numAreas].y2 = p.y + s.h - 1;
- areas[numAreas].bpp = (*it)->Bpp();
- ++numAreas;
- } else
- esyslog("ERROR: text2skin: too many background areas\n");
- }
- }
- res = mScreen->SetAreas(areas, numAreas);
- Dprintf("areas set, res = %d\n", res);
+ tArea areas[mDisplay->NumWindows()];
+ for (int i = 0; i < mDisplay->NumWindows(); ++i) {
+ txPoint pos1 = Transform(mDisplay->Windows()[i].pos1);
+ txPoint pos2 = Transform(mDisplay->Windows()[i].pos2);
+ areas[i].x1 = mSkin->BaseOffset().x + pos1.x;
+ areas[i].y1 = mSkin->BaseOffset().y + pos1.y;
+ areas[i].x2 = mSkin->BaseOffset().x + pos2.x;
+ areas[i].y2 = mSkin->BaseOffset().y + pos2.y;
+ areas[i].bpp = mDisplay->Windows()[i].bpp;
+ Dprintf("setting area: %d, %d, %d, %d, %d\n",
+ areas[i].x1, areas[i].y1, areas[i].x2, areas[i].y2,
+ areas[i].bpp);
+ }
+ res = mScreen->SetAreas(areas, mDisplay->NumWindows());
if (res != oeOk) {
const char *emsg = NULL;
@@ -113,23 +83,25 @@ cText2SkinRender::cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Sectio
break;
}
esyslog("ERROR: text2skin: OSD provider can't handle skin: %s\n", emsg);
+ return;
}
- Lock();
- Start();
- mStarted.Wait(mMutex);
- Unlock();
- // Make sure this constructor returns when the thread is running
+ if (!OffScreen) {
+ Lock();
+ Start();
+ mStarted.Wait(mMutex);
+ Unlock();
+ }
}
cText2SkinRender::~cText2SkinRender() {
if (mActive) {
mActive = false;
- Flush();
+ Flush(true);
Cancel(3);
}
delete mScroller;
- delete mScreen;
+ delete mScreen;
cText2SkinBitmap::ResetCache();
mRender = NULL;
}
@@ -137,13 +109,10 @@ cText2SkinRender::~cText2SkinRender() {
void cText2SkinRender::Action(void) {
mActive = true;
Lock();
- mStarted.Broadcast(); // signal the constructor
+ mStarted.Broadcast();
while (mActive) {
- Dprintf("mutex locked? %d\n", mMutex.locked);
- int b = time_ms();
if (mUpdateIn) mDoUpdate.TimedWait(mMutex, mUpdateIn);
else mDoUpdate.Wait(mMutex);
- Dprintf("waited %d\n", time_ms() - b);
if (!mActive) break; // fall out if thread to be stopped
@@ -154,181 +123,163 @@ void cText2SkinRender::Action(void) {
}
void cText2SkinRender::Update(void) {
- // Dbench(update);
+ Dbench(update);
- cText2SkinData::tIterator it = mData->First(mSection);
- for (; it != mData->Last(mSection); ++it) {
- switch ((*it)->Display()) {
- case displayAlways:
- DisplayItem(*it);
- break;
- case displayDateTimeF:
- case displayDateTime:
- case displayDate:
- case displayTime:
- DisplayDateTime(*it);
- break;
- case displayChannelNumberName:
- case displayChannelNumber:
- case displayChannelName:
- DisplayChannelNumberName(*it);
- break;
- case displayPresentDateTimeF:
- case displayPresentStartTime:
- case displayPresentDate:
- case displayPresentVPSTime:
- case displayPresentEndTime:
- case displayPresentDuration:
- DisplayPresentTime(*it);
- break;
- case displayPresentVPS:
- case displayPresentRunning:
- case displayPresentTimer:
- DisplayPresentIcon(*it);
- break;
- case displayPresentTitle:
- case displayPresentShortText:
- case displayPresentDescription:
- case displayPresentTextDescription:
- DisplayPresentText(*it);
- break;
- case displayFollowingStartTime:
- case displayFollowingEndTime:
- case displayFollowingDuration:
- DisplayFollowingTime(*it);
- break;
- case displayFollowingTitle:
- DisplayFollowingTitle(*it);
- break;
- case displayFollowingShortText:
- DisplayFollowingShortText(*it);
- break;
- case displayLanguage:
- DisplayLanguage(*it);
- break;
- case displayTeletext:
- case displayAudio:
- case displayDolby:
- case displayEncrypted:
- case displayRecording:
- case displayRadio:
- DisplayChannelIcon(*it);
- break;
- case displayVolumeCurrent:
- case displayVolumeTotal:
- DisplayVolume(*it);
- break;
- case displayMute:
- DisplayMuteIcon(*it);
- break;
- case displayReplayTime:
- case displayReplayDuration:
- DisplayReplayTime(*it);
- break;
- case displayReplayTitle:
- DisplayReplayTitle(*it);
- break;
- case displayReplayPrompt:
- DisplayReplayPrompt(*it);
- break;
- case displayPlay:
- case displayPause:
- case displayFastFwd:
- case displayFastRew:
- case displaySlowFwd:
- case displaySlowRew:
- DisplayReplaySymbol(*it);
- break;
- case displayReplayMode:
- DisplayReplayMode(*it);
- break;
- case displayMessage:
- case displayMessageStatus:
- case displayMessageInfo:
- case displayMessageWarning:
- case displayMessageError:
- DisplayMessage(*it);
- break;
- case displayMenuTitle:
- DisplayMenuTitle(*it);
- break;
- case displayMenuRed:
- case displayMenuGreen:
- case displayMenuYellow:
- case displayMenuBlue:
- DisplayMenuButton(*it);
- break;
- case displayMenuText:
- case displayMenuRecording:
- DisplayMenuText(*it);
- break;
- case displayMenuScrollUp:
- case displayMenuScrollDown:
- DisplayMenuScrollIcon(*it);
- break;
- case displayMenuItems:
- case displayMenuCurrent:
- case displayMenuGroups:
- DisplayMenuItems(*it);
- break;
- default:
- break;
- }
- }
- // Dbench(flush);
+ for (uint i = 0; i < mDisplay->Objects(); ++i)
+ DrawObject(mDisplay->GetObject(i));
+
+ Dbench(flush);
mScreen->Flush();
- // Dprintf("flush only took %d ms\n", Ddiff(flush));
- // Dprintf("complete flush took %d ms\n", Ddiff(update));
+ Dprintf("flush only took %ld ms\n", Ddiff(flush));
+ Dprintf("complete flush took %ld ms\n", Ddiff(update));
}
-void cText2SkinRender::DrawBackground(const POINT &Pos, const SIZE &Size, const tColor *Bg, const tColor *Fg, int Alpha, const string &Path) {
- cText2SkinBitmap *bmp = NULL;
- if (Path != "") {
- char *p;
- asprintf(&p, "%s/%s/%s", SkinPath(), mData->Skin().c_str(), Path.c_str());
- if ((bmp = cText2SkinBitmap::Load(p, Alpha)) != NULL) {
- if (Bg) bmp->SetColor(0, *Bg);
- if (Fg) bmp->SetColor(1, *Fg);
+void cText2SkinRender::DrawObject(const cxObject *Object)
+{
+ if (Object->Condition() != NULL && !Object->Condition()->EvaluateToBool())
+ return;
+
+ switch (Object->Type()) {
+ case cxObject::image:
+ DrawImage(Object->Pos(), Object->Bg(), Object->Fg(), Object->Alpha(), Object->Path());
+ break;
+
+ case cxObject::text:
+ DrawText(Object->Pos(), Object->Size(), Object->Fg(), Object->Text(), Object->Font(), Object->Align());
+ break;
+
+ case cxObject::rectangle:
+ DrawRectangle(Object->Pos(), Object->Size(), Object->Fg());
+ break;
+
+ case cxObject::ellipse:
+ DrawEllipse(Object->Pos(), Object->Size(), Object->Fg(), Object->Arc());
+ break;
+
+ case cxObject::slope:
+ DrawSlope(Object->Pos(), Object->Size(), Object->Fg(), Object->Arc());
+ break;
+
+ case cxObject::progress:
+ DrawProgressbar(Object->Pos(), Object->Size(), Object->Current(), Object->Total(), Object->Bg(), Object->Fg(), Object->Active(), Object->Mark(), Object->Keep(), GetMarks());
+ break;
+
+ case cxObject::scrolltext:
+ DrawScrolltext(Object->Pos(), Object->Size(), Object->Fg(), Object->Text(), Object->Font(), Object->Align());
+ break;
+
+ case cxObject::scrollbar:
+ DrawScrollbar(Object->Pos(), Object->Size(), Object->Bg(), Object->Fg());
+
+ case cxObject::block:
+ for (uint i = 0; i < Object->Objects(); ++i)
+ DrawObject(Object->GetObject(i));
+ break;
+
+ case cxObject::list: {
+ const cxObject *item = Object->GetObject(0);
+ if (item && item->Type() == cxObject::item) {
+ txSize areasize = Object->Size();
+ uint itemheight = item->Size().h;
+ uint maxitems = areasize.h / itemheight;
+ uint yoffset = 0;
+
+ for (uint i = 0; i < maxitems; ++i, yoffset += itemheight) {
+ for (uint j = 0; j < Object->Objects(); ++j) {
+ const cxObject *o = Object->GetObject(j);
+ if (o->Type() == cxObject::item)
+ continue;
+
+ for (int t = -1; t < cSkinDisplayMenu::MaxTabs; ++t) {
+ if (!HasTabText(i, t))
+ continue;
+
+ int thistab = GetTab(t);
+ int nexttab = GetTab(t + 1);
+
+ cxObject obj(*o);
+ obj.SetIndex(i, t);
+ if (obj.Condition() != NULL && !obj.Condition()->EvaluateToBool())
+ continue;
+
+ obj.mPos1.x += Object->mPos1.x + (t >= 0 ? thistab : 0);
+ obj.mPos1.y += Object->mPos1.y + yoffset;
+
+ // get end position
+ if (t >= 0 && nexttab > 0) {
+ // there is a "next tab".. see if it contains text
+ int n = t + 1;
+ while (n < cSkinDisplayMenu::MaxTabs && !HasTabText(i, n))
+ ++n;
+ nexttab = GetTab(n);
+ }
+
+ if (t >= 0 && nexttab > 0 && nexttab < obj.mPos2.x)
+ // there is a "next tab" with text
+ obj.mPos2.x = Object->mPos1.x + o->mPos1.x + nexttab;
+ else {
+ // there is no "next tab", use the rightmost edge
+ obj.mPos2.x += Object->mPos1.x;
+ SetEditableWidth(obj.Size().w);
+ }
+
+ obj.mPos2.y += Object->mPos1.y + yoffset;
+ DrawObject(&obj);
+ }
+ }
+ }
+ }
}
- free(p);
- }
+ break;
- if (bmp)
- mScreen->DrawBitmap(Pos.x, Pos.y, bmp->Get(mUpdateIn));
- else if (Bg)
- mScreen->DrawRectangle(Pos.x, Pos.y, Pos.x + Size.w - 1, Pos.y + Size.h - 1, *Bg);
+ case cxObject::item:
+ // ignore
+ break;
+
+ }
}
-void cText2SkinRender::DrawImage(const POINT &Pos, const SIZE &Size, const tColor *Bg, const tColor *Fg, int Alpha, const string &Path) {
+void cText2SkinRender::DrawImage(const txPoint &Pos, const tColor *Bg, const tColor *Fg, int Alpha,
+ const std::string &Path)
+{
cText2SkinBitmap *bmp;
- char *p;
- asprintf(&p, "%s/%s/%s", SkinPath(), mData->Skin().c_str(), Path.c_str());
- // Dprintf("Trying to load image: %s\n", p);
- if ((bmp = cText2SkinBitmap::Load(p, Alpha)) != NULL) {
+ Dprintf("trying to draw image %s to %dx%d\n", ImagePath(Path).c_str(), Pos.x, Pos.y);
+ if ((bmp = cText2SkinBitmap::Load(ImagePath(Path), Alpha)) != NULL) {
+ Dprintf("success loading image\n");
if (Bg) bmp->SetColor(0, *Bg);
if (Fg) bmp->SetColor(1, *Fg);
mScreen->DrawBitmap(Pos.x, Pos.y, bmp->Get(mUpdateIn));
}
- free(p);
}
-void cText2SkinRender::DrawText(const POINT &Pos, const SIZE &Size, const tColor *Fg, const string &Text, const cFont *Font, int Align) {
+void cText2SkinRender::DrawText(const txPoint &Pos, const txSize &Size, const tColor *Fg,
+ const std::string &Text, const cFont *Font, int Align)
+{
+ Dprintf("trying to draw text %s to %d,%d size %d,%d, color %x\n", Text.c_str(), Pos.x, Pos.y, Size.w, Size.h, Fg ? *Fg : 0);
mScreen->DrawText(Pos.x, Pos.y, Text.c_str(), Fg ? *Fg : 0, 0, Font, Size.w, Size.h, Align);
}
-void cText2SkinRender::DrawRectangle(const POINT &Pos, const SIZE &Size, const tColor *Fg) {
+void cText2SkinRender::DrawRectangle(const txPoint &Pos, const txSize &Size, const tColor *Fg)
+{
mScreen->DrawRectangle(Pos.x, Pos.y, Pos.x + Size.w - 1, Pos.y + Size.h - 1, Fg ? *Fg : 0);
}
-void cText2SkinRender::DrawEllipse(const POINT &Pos, const SIZE &Size, const tColor *Fg, int Arc) {
+void cText2SkinRender::DrawEllipse(const txPoint &Pos, const txSize &Size, const tColor *Fg,
+ int Arc)
+{
mScreen->DrawEllipse(Pos.x, Pos.y, Pos.x + Size.w - 1, Pos.y + Size.h - 1, Fg ? *Fg : 0, Arc);
}
-void cText2SkinRender::DrawSlope(const POINT &Pos, const SIZE &Size, const tColor *Fg, int Arc) {
+void cText2SkinRender::DrawSlope(const txPoint &Pos, const txSize &Size, const tColor *Fg, int Arc) {
mScreen->DrawSlope(Pos.x, Pos.y, Pos.x + Size.w - 1, Pos.y + Size.h - 1, Fg ? *Fg : 0, Arc);
}
-void cText2SkinRender::DrawProgressbar(const POINT &Pos, const SIZE &Size, int Current, int Total, const tColor *Bg, const tColor *Fg, const tColor *Selected, const tColor *Mark, const tColor *Cur, const cMarks *Marks) {
+void cText2SkinRender::DrawProgressbar(const txPoint &Pos, const txSize &Size, int Current,
+ int Total, const tColor *Bg, const tColor *Fg,
+ const tColor *Selected, const tColor *Mark,
+ const tColor *Cur, const cMarks *Marks)
+{
+ Dprintf("trying to draw Progressbar, Current = %d, Total = %d\n", Current, Total);
if (Bg)
DrawRectangle(Pos, Size, Bg);
if (Total == 0)
@@ -336,30 +287,30 @@ void cText2SkinRender::DrawProgressbar(const POINT &Pos, const SIZE &Size, int C
if (Current > Total)
Current = Total;
if (Size.w > Size.h) {
- DrawRectangle(Pos, SIZE(Size.w * Current / Total, Size.h), Fg);
+ DrawRectangle(Pos, txSize(Size.w * Current / Total, Size.h), Fg);
if (Marks) {
bool start = true;
for (const cMark *m = Marks->First(); m; m = Marks->Next(m)) {
- POINT pt(Pos.x + m->position * Size.w / Total, Pos.y);
+ txPoint pt(Pos.x + m->position * Size.w / Total, Pos.y);
if (Selected && start) {
const cMark *m2 = Marks->Next(m);
- DrawRectangle(POINT(pt.x, Pos.y + Size.h / 3), SIZE(((m2 ? m2->position : Total) - m->position) * Size.w / Total, Size.h / 3), Selected);
+ DrawRectangle(txPoint(pt.x, Pos.y + Size.h / 3), txSize(((m2 ? m2->position : Total) - m->position) * Size.w / Total, Size.h / 3), Selected);
}
DrawMark(pt, Size, start, m->position == Current, false, Mark, Cur);
start = !start;
}
}
} else {
- DrawRectangle(Pos, SIZE(Size.w, Size.h * Current / Total), Fg);
+ DrawRectangle(Pos, txSize(Size.w, Size.h * Current / Total), Fg);
if (Marks) {
bool start = true;
for (const cMark *m = Marks->First(); m; m = Marks->Next(m)) {
- POINT pt(Pos.x, Pos.y + m->position * Size.h / Total);
+ txPoint pt(Pos.x, Pos.y + m->position * Size.h / Total);
if (Selected && start) {
const cMark *m2 = Marks->Next(m);
- DrawRectangle(POINT(Pos.x + Size.w / 3, pt.y), SIZE(Size.w / 3, ((m2 ? m2->position : Total) - m->position) * Size.h / Total), Selected);
+ DrawRectangle(txPoint(Pos.x + Size.w / 3, pt.y), txSize(Size.w / 3, ((m2 ? m2->position : Total) - m->position) * Size.h / Total), Selected);
}
DrawMark(pt, Size, start, m->position == Current, true, Mark, Cur);
start = !start;
@@ -368,660 +319,138 @@ void cText2SkinRender::DrawProgressbar(const POINT &Pos, const SIZE &Size, int C
}
}
-void cText2SkinRender::DrawMark(const POINT &Pos, const SIZE &Size, bool Start, bool Current, bool Horizontal, const tColor *Mark, const tColor *Cur) {
- POINT p1 = Pos;
+void cText2SkinRender::DrawMark(const txPoint &Pos, const txSize &Size, bool Start, bool Current,
+ bool Horizontal, const tColor *Mark, const tColor *Cur)
+{
+ txPoint p1 = Pos;
if (Horizontal) {
if (Mark)
- DrawRectangle(p1, SIZE(Size.w, 1), Mark);
+ DrawRectangle(p1, txSize(Size.w, 1), Mark);
const int d = Size.w / (Current ? 3 : 9);
for (int i = 0; i < d; i++) {
const tColor *col = Current ? Cur : Mark;
int h = Start ? i : Size.w - 1 - i;
if (col)
- DrawRectangle(POINT(Pos.x + h, Pos.y - d + i), SIZE(1, (d - i) * 2), col);
+ DrawRectangle(txPoint(Pos.x + h, Pos.y - d + i), txSize(1, (d - i) * 2), col);
}
} else {
if (Mark)
- DrawRectangle(p1, SIZE(1, Size.h), Mark);
+ DrawRectangle(p1, txSize(1, Size.h), Mark);
const int d = Size.h / (Current ? 3 : 9);
for (int i = 0; i < d; i++) {
const tColor *col = Current ? Cur : Mark;
int h = Start ? i : Size.h - 1 - i;
- if (col)
- DrawRectangle(POINT(Pos.x - d + i, Pos.y + h), SIZE((d - i) * 2, 1), col);
+ if (col)
+ DrawRectangle(txPoint(Pos.x - d + i, Pos.y + h), txSize((d - i) * 2, 1), col);
}
}
}
-void cText2SkinRender::DrawScrolltext(const POINT &Pos, const SIZE &Size, const tColor *Fg, const string &Text, const cFont *Font, int Align) {
+void cText2SkinRender::DrawScrolltext(const txPoint &Pos, const txSize &Size, const tColor *Fg,
+ const std::string &Text, const cFont *Font, int /*Align*/)
+{
+ Dprintf("trying to draw scrolltext %s\n", Text.c_str());
if (mScroller == NULL)
mScroller = new cText2SkinScroller(mScreen, Pos.x, Pos.y, Size.w, Size.h, Text.c_str(), Font, Fg ? *Fg : 0, clrTransparent);
- else if (mMenuScroll) {
- mScroller->Scroll(mMenuScrollUp, mMenuScrollPage);
- mMenuScroll = false;
- } else
+ else
mScroller->DrawText();
}
-void cText2SkinRender::DrawScrollbar(const POINT &Pos, const SIZE &Size, int Offset, int Shown, int Total, const tColor *Bg, const tColor *Fg) {
- DrawRectangle(Pos, Size, Bg);
- if (Total == 0)
- Total = 1;
- if (Size.h > Size.w) {
- POINT sp = Pos;
- SIZE ss = Size;
- sp.y += Size.h * Offset / Total;
- ss.h = Size.h * Shown / Total + 1;
- DrawRectangle(sp, ss, Fg);
- } else {
- POINT sp = Pos;
- SIZE ss = Size;
- sp.x += Size.w * Offset / Total;
- ss.w = Size.w * Shown / Total + 1;
- DrawRectangle(sp, ss, Fg);
- }
-}
-
-void cText2SkinRender::DisplayItem(cText2SkinItem *Item, const tItemData *Data) {
- static tItemData dummyData;
- if (Data == NULL) Data = &dummyData;
- switch (Item->Item()) {
- case itemBackground:
- DrawBackground(Item->Pos(), Item->Size(), Item->Bg(), Item->Fg(), Item->Alpha(), Item->Path());
- break;
- case itemText:
- DrawText(Item->Pos(), Item->Size(), Item->Fg(), ItemText(Item, Data->text), Item->Font(), Item->Align());
- break;
- case itemScrolltext:
- DrawScrolltext(Item->Pos(), Item->Size(), Item->Fg(), Data->text, Item->Font(), Item->Align());
- break;
- case itemImage:
- DrawImage(Item->Pos(), Item->Size(), Item->Bg(), Item->Fg(), Item->Alpha(), Item->Path());
- break;
- case itemLogo:
- case itemSymbol:
- if (Data->path != "")
- DrawImage(Item->Pos(), Item->Size(), Item->Bg(), Item->Fg(), Item->Alpha(), Data->path);
- break;
- case itemRectangle:
- DrawRectangle(Item->Pos(), Item->Size(), Item->Fg());
- break;
- case itemEllipse:
- DrawEllipse(Item->Pos(), Item->Size(), Item->Fg(), Item->Arc());
- break;
- case itemSlope:
- DrawSlope(Item->Pos(), Item->Size(), Item->Fg(), Item->Arc());
- break;
- case itemProgress:
- DrawProgressbar(Item->Pos(), Item->Size(), Data->current, Data->total, Item->Bg(), Item->Fg(), Item->Selected(), Item->Mark(), Item->Current(), Data->marks);
- break;
- case itemScrollbar:
- DrawScrollbar(Item->Pos(), Item->Size(), Data->current, Data->shown, Data->total, Item->Bg(), Item->Fg());
- default:
- break;
- }
-}
-
-void cText2SkinRender::DisplayDateTime(cText2SkinItem *Item) {
- tItemData data;
- char text[1000];
- time_t t = time(NULL);
- struct tm tm_r, *tm;
- *text = '\0';
- tm = localtime_r(&t, &tm_r);
-
- switch (Item->Display()) {
- case displayDateTimeF:
- strftime(text, 1000, Item->Format().c_str(), tm);
- break;
- case displayDateTime:
- strftime(text, 1000, "%a %e.%m. %H:%M", tm);
- break;
- case displayDate:
- strftime(text, 1000, "%e.%m.", tm);
- break;
- case displayTime:
- strftime(text, 1000, "%H:%M", tm);
- break;
- default:
- break;
- }
-
- data.text = text;
- DisplayItem(Item, &data);
-}
-
-void cText2SkinRender::DisplayChannelNumberName(cText2SkinItem *Item) {
- if (mChannel || mChannelNumber) {
- tItemData data;
- data.path = Item->Path() + "/" + ChannelName(mChannel, mChannelNumber) + "." + Item->Type();
- switch (Item->Display()) {
- case displayChannelNumberName:
- data.text = ChannelString(mChannel, mChannelNumber);
- break;
- case displayChannelNumber:
- data.text = ChannelNumber(mChannel, mChannelNumber);
- break;
- case displayChannelName:
- data.text = ChannelName(mChannel, mChannelNumber);
- break;
- default:
- break;
- }
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayPresentTime(cText2SkinItem *Item) {
- const cEvent *event = NULL;
- switch (mSection) {
- case sectionChannel:
- case sectionChannelSmall:
- event = mChannelPresent;
- break;
- case sectionMenu:
- event = mMenuEvent;
- break;
- default:
- break;
- }
-
- if (event && event->StartTime()) {
- tItemData data;
- char text[1000];
- const char *f = "%H:%M";
- time_t t = 0, n = time(NULL);
- struct tm tm_r, *tm;
- *text = '\0';
- data.path = Item->Path();
-
- switch (Item->Display()) {
- case displayPresentDateTimeF:
- f = Item->Format().c_str();
- t = event->StartTime();
- break;
- case displayPresentStartTime:
- t = event->StartTime();
- break;
- case displayPresentDate:
- f = "%e.%m.";
- t = event->StartTime();
- break;
- case displayPresentVPSTime:
- t = event->StartTime() != event->Vps() ? event->Vps() : 0;
- break;
- case displayPresentEndTime:
- t = event->EndTime();
- break;
- case displayPresentDuration:
- t = event->Duration();
- break;
- default:
- break;
- }
-
- if (t) {
- tm = localtime_r(&t, &tm_r);
- strftime(text, 1000, f, tm);
- data.text = text;
- data.total = event->Duration();
- data.current = n - event->StartTime();
- DisplayItem(Item, &data);
- }
- }
-}
-
-void cText2SkinRender::DisplayPresentIcon(cText2SkinItem *Item) {
- const cEvent *event = NULL;
- switch (mSection) {
- case sectionChannel:
- case sectionChannelSmall:
- event = mChannelPresent;
- break;
- case sectionMenu:
- event = mMenuEvent;
- break;
- default:
- break;
- }
-
- if (event) {
- tItemData data;
- switch (Item->Display()) {
- case displayPresentVPS:
- data.path = event->Vps() && event->Vps() != event->StartTime() ? Item->Path() : Item->AltPath();
- break;
- case displayPresentRunning:
- data.path = event->IsRunning() ? Item->Path() : Item->AltPath();
- break;
- case displayPresentTimer:
- data.path = event->HasTimer() ? Item->Path() : Item->AltPath();
- break;
- default:
- break;
- }
- if (data.path != "")
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayPresentText(cText2SkinItem *Item) {
- const cEvent *event = NULL;
- switch (mSection) {
- case sectionChannel:
- case sectionChannelSmall:
- event = mChannelPresent;
- break;
- case sectionMenu:
- event = mMenuEvent;
- break;
- default:
- break;
- }
-
- if (event) {
- string text;
- switch (Item->Display()) {
- case displayPresentTitle:
- text = event->Title() ? event->Title() : "";
- break;
- case displayPresentShortText:
- text = event->ShortText() ? event->ShortText() : "";
- break;
- case displayPresentDescription:
- text = event->Description() ? event->Description() : "";
- break;
- case displayPresentTextDescription:
- if (event->ShortText())
- text += (string)event->ShortText() + "\n\n";
- if (event->Description())
- text += event->Description();
- default:
- break;
- }
-
- if (text != "") {
- tItemData data;
- data.text = text;
- DisplayItem(Item, &data);
- }
- }
-}
-
-void cText2SkinRender::DisplayFollowingTime(cText2SkinItem *Item) {
- if (mChannelFollowing && mChannelFollowing->StartTime()) {
- tItemData data;
- char text[1000];
- time_t t = 0, n = time(NULL);
- struct tm tm_r, *tm;
- *text = '\0';
-
- switch (Item->Display()) {
- case displayFollowingStartTime:
- t = mChannelFollowing->StartTime();
- break;
- case displayFollowingEndTime:
- t = mChannelFollowing->EndTime();
- break;
- case displayFollowingDuration:
- t = mChannelFollowing->Duration();
- break;
- default:
- break;
+void cText2SkinRender::DrawScrollbar(const txPoint &Pos, const txSize &Size, const tColor *Bg,
+ const tColor *Fg)
+{
+ if (mScroller != NULL) {
+ int total = mScroller->Total();
+ DrawRectangle(Pos, Size, Bg);
+ if (total == 0)
+ total = 1;
+ if (Size.h > Size.w) {
+ txPoint sp = Pos;
+ txSize ss = Size;
+ sp.y += Size.h * mScroller->Offset() / total;
+ ss.h = Size.h * mScroller->Shown() / total + 1;
+ DrawRectangle(sp, ss, Fg);
+ } else {
+ txPoint sp = Pos;
+ txSize ss = Size;
+ sp.x += Size.w * mScroller->Offset() / total;
+ ss.w = Size.w * mScroller->Shown() / total + 1;
+ DrawRectangle(sp, ss, Fg);
}
-
- tm = localtime_r(&t, &tm_r);
- strftime(text, 1000, "%H:%M", tm);
- data.text = text;
- data.total = mChannelFollowing->Duration();
- data.current = n - mChannelFollowing->StartTime();
- DisplayItem(Item, &data);
}
}
-void cText2SkinRender::DisplayFollowingTitle(cText2SkinItem *Item) {
- if (mChannelFollowing && mChannelFollowing->Title()) {
- tItemData data;
- data.text = mChannelFollowing->Title();
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayFollowingShortText(cText2SkinItem *Item) {
- if (mChannelFollowing && mChannelFollowing->ShortText()) {
- tItemData data;
- data.text = mChannelFollowing->ShortText();
- DisplayItem(Item, &data);
- }
+txPoint cText2SkinRender::Transform(const txPoint &Pos)
+{
+ txSize base = mRender->mBaseSize;
+ return txPoint(Pos.x < 0 ? base.w + Pos.x : Pos.x, Pos.y < 0 ? base.h + Pos.y : Pos.y);
}
-void cText2SkinRender::DisplayLanguage(cText2SkinItem *Item) {
- int current;
- const char **tracks = cDevice::PrimaryDevice()->GetAudioTracks(&current);
- if (tracks) {
- Dprintf("Languages: ");
- int i;
- for (i = 0; tracks[i] != NULL; ++i)
- Dprintf("%s%s, ", tracks[i], i == current ? " (current)" : "");
- Dprintf("\n");
-
- if (current < i) {
- tItemData data;
- data.text = tracks[current];
- data.path = Item->Path() + "/" + tracks[current] + "." + Item->Type();
- DisplayItem(Item, &data);
- }
- }
+bool cText2SkinRender::ItemColor(const std::string &Color, tColor &Result)
+{
+ if (Color != "" && Color != "None") {
+ if (Color[0] == '#')
+ Result = strtoul(Color.c_str() + 1, NULL, 16);
+ else
+ Result = mRender->mTheme->Color(Color);
+ } else
+ return false;
+ return true;
}
-void cText2SkinRender::DisplayChannelIcon(cText2SkinItem *Item) {
- if (mChannel && !mChannel->GroupSep()) {
- tItemData data;
- switch (Item->Display()) {
- case displayTeletext:
- data.path = mChannel->Tpid() ? Item->Path() : Item->AltPath();
- break;
- case displayAudio:
- data.path = mChannel->Apid2() ? Item->Path() : Item->AltPath();
- break;
- case displayDolby:
- data.path = mChannel->Dpid1() ? Item->Path() : Item->AltPath();
- break;
- case displayEncrypted:
- data.path = mChannel->Ca() ? Item->Path() : Item->AltPath();
- break;
- case displayRadio:
- data.path = mChannel->Vpid() == 0 || mChannel->Vpid() == 1 || mChannel->Vpid() == 0x1FFF ? Item->Path() : Item->AltPath();
- break;
- case displayRecording:
- data.path = cRecordControls::Active() ? Item->Path() : Item->AltPath();
- break;
- default:
- break;
- }
- if (data.path != "")
- DisplayItem(Item, &data);
- }
+std::string cText2SkinRender::ImagePath(const std::string &Filename)
+{
+ if (mRender)
+ return mRender->mBasePath + "/" + Filename;
+ return "";
}
-void cText2SkinRender::DisplayVolume(cText2SkinItem *Item) {
- if (mVolumeTotal && mVolumeCurrent <= mVolumeTotal && !mVolumeMute) {
- tItemData data;
- char *text = NULL;
- data.total = mVolumeTotal;
- data.current = mVolumeCurrent;
- switch (Item->Display()) {
- case displayVolumeCurrent:
- asprintf(&text, "%d", mVolumeCurrent);
- break;
- case displayVolumeTotal:
- asprintf(&text, "%d", mVolumeTotal);
- break;
- default:
- break;
- }
- if (text) {
- data.text = text;
- free(text);
- }
- DisplayItem(Item, &data);
+/* TODO: translation when parsing
+string cText2SkinRender::Translate(const string &Text) {
+ if (mRender != NULL) {
+ string result;
+ if (mRender->mI18n != NULL)
+ result = mRender->mI18n->Translate(Text);
+ else
+ result = Text;
+ return result;
}
+ return Text;
}
+*/
-void cText2SkinRender::DisplayMuteIcon(cText2SkinItem *Item) {
- tItemData data;
- data.path = mVolumeMute ? Item->Path() : Item->AltPath();
- if (data.path != "")
- DisplayItem(Item, &data);
-}
-
-void cText2SkinRender::DisplayReplayTime(cText2SkinItem *Item) {
- if (mReplayTotal && mReplayCurrent <= mReplayTotal) {
- tItemData data;
- data.total = mReplayTotal;
- data.current = mReplayCurrent;
- data.marks = mReplayMarks;
- switch (Item->Display()) {
- case displayReplayTime:
- data.text = mReplayCurrentText;
- break;
- case displayReplayDuration:
- data.text = mReplayTotalText;
- break;
- default:
- break;
- }
- DisplayItem(Item, &data);
- }
-}
+cxType cText2SkinRender::GetToken(const txToken &Token)
+{
+ if (mRender != NULL) {
+ cxType res = mRender->GetTokenData(Token);
+ if (Token.Attrib.length() > 0) {
+ if (Token.Attrib == "clean") {
+ std::string str = res.String();
+ int pos = -1;
-void cText2SkinRender::DisplayReplayTitle(cText2SkinItem *Item) {
- if (mReplayTitle != "") {
- tItemData data;
- data.text = mReplayTitle;
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayReplayPrompt(cText2SkinItem *Item) {
- if (mReplayJump != "") {
- tItemData data;
- data.text = mReplayJump;
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayReplaySymbol(cText2SkinItem *Item) {
- if (mReplayInfo) {
- tItemData data;
- switch (Item->Display()) {
- case displayPlay:
- data.path = (mReplaySpeed == -1 && mReplayPlay) ? Item->Path() : Item->AltPath();
- break;
- case displayPause:
- data.path = (mReplaySpeed == -1 && !mReplayPlay) ? Item->Path() : Item->AltPath();
- break;
- case displayFastFwd:
- data.path = (mReplaySpeed != -1 && mReplayPlay && mReplayForward) ? Item->Path() : Item->AltPath();
- break;
- case displayFastRew:
- data.path = (mReplaySpeed != -1 && mReplayPlay && !mReplayForward) ? Item->Path() : Item->AltPath();
- break;
- case displaySlowFwd:
- data.path = (mReplaySpeed != -1 && !mReplayPlay && mReplayForward) ? Item->Path() : Item->AltPath();
- break;
- case displaySlowRew:
- data.path = (mReplaySpeed != -1 && !mReplayPlay && !mReplayForward) ? Item->Path() : Item->AltPath();
- break;
- default:
- break;
- }
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayReplayMode(cText2SkinItem *Item) {
- if (cText2SkinStatus::ReplayMode() != replayNone) {
- tItemData data;
- Dprintf("Replay Type is %s\n", ReplayNames[cText2SkinStatus::ReplayMode()].c_str());
- data.path = Item->Path() + "/" + ReplayNames[cText2SkinStatus::ReplayMode()] + "." + Item->Type();
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayMessage(cText2SkinItem *Item) {
- if (mMessageText != "" && (Item->Display() == displayMessage || (Item->Display() - displayMessageStatus) == mMessageType)) {
- tItemData data;
- data.text = mMessageText;
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayMenuTitle(cText2SkinItem *Item) {
- if (mMenuTitle != "") {
- tItemData data;
- data.text = mMenuTitle;
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayMenuButton(cText2SkinItem *Item) {
- tItemData data;
- switch (Item->Display()) {
- case displayMenuRed:
- data.text = mMenuRed;
- break;
- case displayMenuGreen:
- data.text = mMenuGreen;
- break;
- case displayMenuYellow:
- data.text = mMenuYellow;
- break;
- case displayMenuBlue:
- data.text = mMenuBlue;
- break;
- default:
- break;
- }
- if (data.text != "")
- DisplayItem(Item, &data);
-}
-
-void cText2SkinRender::DisplayMenuText(cText2SkinItem *Item) {
- tItemData data;
-
- switch (Item->Display()) {
- case displayMenuText:
- data.text = mMenuText;
- break;
- case displayMenuRecording:
- if (mMenuRecording && mMenuRecording->Summary())
- data.text = mMenuRecording->Summary();
- break;
- default:
- break;
- }
- if (data.text != "") {
- // HACK: make sure the scroller exists!
- if (mScroller) {
- data.current = mScroller->Offset();
- data.shown = mScroller->Shown();
- data.total = mScroller->Total();
- }
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayMenuScrollIcon(cText2SkinItem *Item) {
- if (mScroller) {
- tItemData data;
- switch (Item->Display()) {
- case displayMenuScrollUp:
- data.path = mScroller->CanScrollUp() ? Item->Path() : Item->AltPath();
- break;
- case displayMenuScrollDown:
- data.path = mScroller->CanScrollDown() ? Item->Path() : Item->AltPath();
- break;
- default:
- break;
- }
- if (data.path != "")
- DisplayItem(Item, &data);
- }
-}
-
-void cText2SkinRender::DisplayMenuItems(cText2SkinItem *Item) {
- cText2SkinItem *area = mData->Get(sectionMenu, itemMenuArea);
- cText2SkinItem *item = mData->Get(sectionMenu, itemMenuItem);
-
- if (item && area) {
- POINT pos = area->Pos1();
-
- int max = area->Size().h / item->Size().h;
- for (int i = 0; i < min((int)mMenuItems.size(), max); ++i) {
- switch (Item->Display()) {
- case displayMenuItems:
- if (i == mMenuCurrent || !mMenuItems[i].sel)
- continue;
- break;
- case displayMenuCurrent:
- if (i != mMenuCurrent)
- continue;
- break;
- case displayMenuGroups:
- if (mMenuItems[i].sel)
- continue;
- break;
- default:
- break;
- }
-
- POINT itempos = pos;
- itempos.y += i * item->Size().h;
- if (Item->Item() == itemText) { // draw tabs
- for (int t = 0; t < cSkinDisplayMenu::MaxTabs; ++t) {
- if (mMenuItems[i].tabs[t] != "") {
- tItemData data;
- cText2SkinItem cur = *Item;
- cur.Pos1() = itempos;
- cur.Pos1() += Item->Pos1();
- cur.Pos1().x += mMenuTabs[t];
- cur.Pos2() += itempos;
- if (t + 1 < cSkinDisplayMenu::MaxTabs && mMenuItems[i].tabs[t + 1] != "")
- cur.Pos2().x = itempos.x + mMenuTabs[t + 1];
- data.text = mMenuItems[i].tabs[t];
- // Dprintf("Menuitem: x = %d, w = %d, f = %08x\n", cur.Pos().x, cur.Pos2().x - cur.Pos1().x + 1, *ItemFg(&cur));
- DisplayItem(&cur, &data);
- }
- if (!mMenuTabs[t + 1])
- break;
- }
- } else {
- tItemData data;
- cText2SkinItem cur = *Item;
- cur.Pos1() = itempos;
- cur.Pos1() += Item->Pos1();
- cur.Pos2() += itempos;
- DisplayItem(&cur, &data);
+ if (Token.Type == tMenuCurrent && (pos = str.rfind(' ')) != -1)
+ return str.substr(pos + 1);
+ else if (Token.Type == tMenuTitle && (pos = str.find(' ')) != -1)
+ return str.substr(0, pos);
}
}
+ return res;
}
+ return false;
}
-string cText2SkinRender::ItemText(cText2SkinItem *Item) {
- return mI18n ? mI18n->Translate(Item->Text()) : Item->Text();
-}
+cxType cText2SkinRender::GetTokenData(const txToken &Token)
+{
+ switch (Token.Type) {
+ case tDateTime: return TimeType(time(NULL), Token.Attrib);
+
+ case tCanScrollUp: return mScroller != NULL && mScroller->CanScrollUp();
-string cText2SkinRender::ItemText(cText2SkinItem *Item, const string &Content) {
- if (Item->Text() != "") {
- string s = mI18n ? mI18n->Translate(Item->Text()) : Item->Text();
- int pos;
- while ((pos = s.find("{*}")) != -1)
- s.replace(pos, 3, Content);
- return s;
+ case tCanScrollDown: return mScroller != NULL && mScroller->CanScrollDown();
+
+ //default: return txToken::Token(Token); // return literal token
+ default: break;
}
- return Content;
-}
-int cText2SkinRender::GetEditableWidth(MenuItem Item, bool Current) {
- cText2SkinItem *item;
- item = mData->Get(sectionMenu, itemMenuItem);
- return item->Size().w - mMenuTabs[1];
+ return false;
}
-
-POINT cText2SkinRender::Transform(const POINT &Pos) {
- SIZE base = mRender->mBaseSize;
- return POINT(Pos.x < 0 ? base.w + Pos.x : Pos.x, Pos.y < 0 ? base.h + Pos.y : Pos.y);
-}
-
-bool cText2SkinRender::ItemColor(const string &Color, tColor &Result) {
- if (Color != "" && Color != "None") {
- if (Color[0] == '#')
- Result = strtoul(Color.c_str() + 1, NULL, 16);
- else
- Result = mRender->mTheme->Color(Color);
- } else
- return false;
- return true;
-}
-
diff --git a/render.h b/render.h
index 7057315..2cb7562 100644
--- a/render.h
+++ b/render.h
@@ -1,12 +1,14 @@
/*
- * $Id: render.h,v 1.26 2004/07/13 13:52:51 lordjaxom Exp $
+ * $Id: render.h,v 1.5 2004/12/08 18:47:37 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_RENDER_H
#define VDR_TEXT2SKIN_RENDER_H
#include "common.h"
-#include "data.h"
+#include "scroller.h"
+#include "xml/skin.h"
+#include "xml/type.h"
#include <vdr/osd.h>
#include <vdr/skins.h>
#include <vdr/thread.h>
@@ -14,10 +16,8 @@
class cChannel;
class cEvent;
class cText2SkinLoader;
-class cText2SkinData;
class cText2SkinI18n;
class cText2SkinTheme;
-class cText2SkinScroller;
class cText2SkinScreen;
class cText2SkinRender: public cThread {
@@ -27,77 +27,31 @@ class cText2SkinRender: public cThread {
friend class cText2SkinDisplayMessage;
friend class cText2SkinDisplayMenu;
+ /* Skin Editor */
+ friend class VSkinnerScreen;
+
private:
static cText2SkinRender *mRender;
- cText2SkinData *mData;
+ cxSkin *mSkin;
+ cxDisplay *mDisplay;
cText2SkinI18n *mI18n;
cText2SkinTheme *mTheme;
- eSkinSection mSection;
cText2SkinScreen *mScreen;
cText2SkinScroller *mScroller;
- // channel display
- const cChannel *mChannel;
- int mChannelNumber;
- const cEvent *mChannelPresent;
- const cEvent *mChannelFollowing;
-
- // volume display
- int mVolumeCurrent;
- int mVolumeTotal;
- bool mVolumeMute;
-
- // replay display
- string mReplayTitle;
- bool mReplayInfo;
- bool mReplayPlay;
- bool mReplayForward;
- int mReplaySpeed;
- int mReplayCurrent;
- int mReplayTotal;
- const cMarks *mReplayMarks;
- string mReplayCurrentText;
- string mReplayTotalText;
- string mReplayJump;
-
- // message display
- eMessageType mMessageType;
- string mMessageText;
-
- // menu
- struct MenuItem {
- string text;
- string tabs[cSkinDisplayMenu::MaxTabs];
- bool sel;
- bool operator!=(const MenuItem &b) { return b.text != text || b.sel != sel; }
- };
- string mMenuTitle;
- vector<MenuItem> mMenuItems;
- int mMenuCurrent;
- string mMenuRed;
- string mMenuGreen;
- string mMenuYellow;
- string mMenuBlue;
- const cEvent *mMenuEvent;
- const cRecording *mMenuRecording;
- string mMenuText;
- bool mMenuTextFixedFont;
- bool mMenuScroll;
- bool mMenuScrollUp;
- bool mMenuScrollPage;
- int mMenuTabs[cSkinDisplayMenu::MaxTabs];
+ std::string mBasePath;
+ bool mDirty;
// update thread
- bool mActive;
- cCondVar mDoUpdate;
- cCondVar mStarted;
- cMutex mMutex;
- int mUpdateIn;
+ bool mActive;
+ cCondVar mDoUpdate;
+ cMutex mMutex;
+ cCondVar mStarted;
+ int mUpdateIn;
// coordinate transformation
- eBaseCoordinate mBase;
- SIZE mBaseSize;
+ txSize mBaseSize;
protected:
// Update thread
@@ -105,60 +59,67 @@ protected:
void Unlock(void) { mMutex.Unlock(); }
virtual void Action(void);
- // Basic operations
- void DrawBackground(const POINT &Pos, const SIZE &Size, const tColor *Bg, const tColor *Fg, int Alpha, const string &Path);
- void DrawImage(const POINT &Pos, const SIZE &Size, const tColor *Bg, const tColor *Fg, int Alpha, const string &Path);
- void DrawText(const POINT &Pos, const SIZE &Size, const tColor *Fg, const string &Text, const cFont *Font, int Align);
- void DrawRectangle(const POINT &Pos, const SIZE &Size, const tColor *Fg);
- void DrawEllipse(const POINT &Pos, const SIZE &Size, const tColor *Fg, int Arc);
- void DrawSlope(const POINT &Pos, const SIZE &Size, const tColor *Fg, int Arc);
- void DrawProgressbar(const POINT &Pos, const SIZE &Size, int Current, int Total, const tColor *Fg, const tColor *Bg, const tColor *Selected, const tColor *Mark, const tColor *Cur, const cMarks *Marks = NULL);
- void DrawMark(const POINT &Pos, const SIZE &Size, bool Start, bool Current, bool Horizontal, const tColor *Mark, const tColor *Cur);
- void DrawScrolltext(const POINT &Pos, const SIZE &Size, const tColor *Fg, const string &Text, const cFont *Font, int Align);
- void DrawScrollbar(const POINT &Pos, const SIZE &Size, int Offset, int Shown, int Total, const tColor *Bg, const tColor *Fg);
-
- // displays a full item
- void DisplayItem(cText2SkinItem *Item, const tItemData *Data = NULL);
-
- // High-level operations
- void DisplayDateTime(cText2SkinItem *Item);
- void DisplayChannelNumberName(cText2SkinItem *Item);
- void DisplayPresentTime(cText2SkinItem *Item);
- void DisplayPresentIcon(cText2SkinItem *Item);
- void DisplayPresentText(cText2SkinItem *Item);
- void DisplayFollowingTime(cText2SkinItem *Item);
- void DisplayFollowingTitle(cText2SkinItem *Item);
- void DisplayFollowingShortText(cText2SkinItem *Item);
- void DisplayLanguage(cText2SkinItem *Item);
- void DisplayChannelIcon(cText2SkinItem *Item);
- void DisplayVolume(cText2SkinItem *Item);
- void DisplayMuteIcon(cText2SkinItem *Item);
- void DisplayReplayTime(cText2SkinItem *Item);
- void DisplayReplayTitle(cText2SkinItem *Item);
- void DisplayReplayPrompt(cText2SkinItem *Item);
- void DisplayReplaySymbol(cText2SkinItem *Item);
- void DisplayReplayMode(cText2SkinItem *Item);
- void DisplayMessage(cText2SkinItem *Item);
- void DisplayMenuTitle(cText2SkinItem *Item);
- void DisplayMenuButton(cText2SkinItem *Item);
- void DisplayMenuText(cText2SkinItem *Item);
- void DisplayMenuScrollIcon(cText2SkinItem *Item);
- void DisplayMenuItems(cText2SkinItem *Item);
-
- // Helpers
- string ItemText(cText2SkinItem *Item);
- string ItemText(cText2SkinItem *Item, const string &Content);
- int GetEditableWidth(MenuItem Item, bool Current);
+ // Drawing operations
+ void DrawObject(const cxObject *Object);
+ void DrawBackground(const txPoint &Pos, const txSize &Size, const tColor *Bg, const tColor *Fg,
+ int Alpha, const std::string &Path);
+ void DrawImage(const txPoint &Pos, const tColor *Bg, const tColor *Fg, int Alpha,
+ const std::string &Path);
+ void DrawText(const txPoint &Pos, const txSize &Size, const tColor *Fg,
+ const std::string &Text, const cFont *Font, int Align);
+ void DrawRectangle(const txPoint &Pos, const txSize &Size,
+ const tColor *Fg);
+ void DrawEllipse(const txPoint &Pos, const txSize &Size, const tColor *Fg,
+ int Arc);
+ void DrawSlope(const txPoint &Pos, const txSize &Size, const tColor *Fg,
+ int Arc);
+ void DrawProgressbar(const txPoint &Pos, const txSize &Size, int Current,
+ int Total, const tColor *Fg, const tColor *Bg,
+ const tColor *Selected, const tColor *Mark, const tColor *Cur,
+ const cMarks *Marks = NULL);
+ void DrawMark(const txPoint &Pos, const txSize &Size, bool Start,
+ bool Current, bool Horizontal, const tColor *Mark,
+ const tColor *Cur);
+ void DrawScrolltext(const txPoint &Pos, const txSize &Size,
+ const tColor *Fg, const std::string &Text, const cFont *Font, int Align);
+ void DrawScrollbar(const txPoint &Pos, const txSize &Size, const tColor *Bg, const tColor *Fg);
+
+ //int GetEditableWidth(MenuItem Item, bool Current);
void Update(void);
+ // all renderers shall return appropriate data for the tokens
+ virtual cxType GetTokenData(const txToken &Token);
+ // the replay renderer shall return its marks here
+ virtual const cMarks *GetMarks(void) const { return NULL; }
+ // the menu renderer shall return its tab information here
+ virtual int GetTab(int n) { return 0; }
+ virtual bool HasTabText(int Index, int n) { return false; }
+ virtual void SetEditableWidth(int Width) {}
+
+ // functions for display renderer to control behaviour
+ void Flush(bool Force = false);
+ void SetDirty(void) { mDirty = true; }
+ void Scroll(bool Up, bool Page) { if (mScroller) mScroller->Scroll(Up, Page); }
+
public:
- cText2SkinRender(cText2SkinLoader *Loader, eSkinSection Section);
+ cText2SkinRender(cText2SkinLoader *Loader, cxDisplay::eType Section, const std::string &BasePath = "",
+ bool OffScreen = false);
virtual ~cText2SkinRender();
- static POINT Transform(const POINT &Pos);
- static bool ItemColor(const string &Color, tColor &Result);
-
- void Flush(void) { Lock(); mDoUpdate.Broadcast(); Unlock(); }
+ // functions for object classes to obtain dynamic item information
+ static txPoint Transform(const txPoint &Pos);
+ static bool ItemColor(const std::string &Color, tColor &Result);
+ static std::string ImagePath(const std::string &Filename);
+ static cxType GetToken(const txToken &Token);
};
+inline void cText2SkinRender::Flush(bool Force) {
+ if (mDirty || Force) {
+ Lock();
+ mDoUpdate.Broadcast();
+ Unlock();
+ mDirty = false;
+ }
+}
+
#endif // VDR_TEXT2SKIN_RENDER_H
diff --git a/screen.c b/screen.c
index 3b85515..a45cb4a 100644
--- a/screen.c
+++ b/screen.c
@@ -1,66 +1,116 @@
/*
- * $Id: screen.c,v 1.2 2004/07/13 13:52:51 lordjaxom Exp $
+ * $Id: screen.c,v 1.2 2004/12/06 15:01:02 lordjaxom Exp $
*/
#include "screen.h"
-cText2SkinScreen::cText2SkinScreen(int x, int y) {
- mOsd = cOsdProvider::NewOsd(x, y);
- Dprintf("got osd -> %p\n", mOsd);
+cText2SkinScreen::cText2SkinScreen(bool OffScreen) {
+ mOsd = NULL;
+ mScreen = NULL;
+ mOffScreen = OffScreen;
+
+ if (mOffScreen)
+ mScreen = new cBitmap(720, 576, 8);
+ else
+ mOsd = cOsdProvider::NewOsd(0, 0);
}
cText2SkinScreen::~cText2SkinScreen() {
+ delete mScreen;
delete mOsd;
}
eOsdError cText2SkinScreen::SetAreas(const tArea *Areas, int NumAreas) {
- eOsdError result = mOsd->CanHandleAreas(Areas, NumAreas);
- if (result == oeOk) {
- mOsd->SetAreas(Areas, NumAreas);
- mNumRegions = NumAreas;
- for (int i = 0; i < mNumRegions; ++i)
- mRegions[i] = new cBitmap(Areas[i].Width(), Areas[i].Height(), Areas[i].bpp, Areas[i].x1, Areas[i].y1);
- Clear();
+ if (!mOffScreen) {
+ eOsdError result = mOsd->CanHandleAreas(Areas, NumAreas);
+ if (result == oeOk)
+ mOsd->SetAreas(Areas, NumAreas);
+ else
+ return result;
}
- return result;
+
+ mNumRegions = NumAreas;
+#ifndef DIRECTBLIT
+ for (int i = 0; i < mNumRegions; ++i)
+ mRegions[i] = new cBitmap(Areas[i].Width(), Areas[i].Height(), Areas[i].bpp, Areas[i].x1, Areas[i].y1);
+#endif
+ Clear();
+
+ return oeOk;
}
void cText2SkinScreen::Clear(void) {
for (int i = 0; i < mNumRegions; ++i) {
+#ifndef DIRECTBLIT
mRegions[i]->Reset();
mRegions[i]->Clean();
mRegions[i]->DrawRectangle(mRegions[i]->X0(), mRegions[i]->Y0(), mRegions[i]->X0() + mRegions[i]->Width() - 1, mRegions[i]->Y0() + mRegions[i]->Height() - 1, clrTransparent);
+#else
+ cBitmap *b = mOsd->GetBitmap(i);
+ if (b) {
+ b->Reset();
+ b->Clean();
+ b->DrawRectangle(b->X0(), b->Y0(), b->X0() + b->Width() - 1, b->Y0() + b->Height() - 1, clrTransparent);
+ }
+#endif
}
}
void cText2SkinScreen::DrawBitmap(int x, int y, const cBitmap &Bitmap, tColor ColorFg, tColor ColorBg) {
+#ifndef DIRECTBLIT
for (int i = 0; i < mNumRegions; ++i)
mRegions[i]->DrawBitmap(x, y, Bitmap, ColorFg, ColorBg);
+#else
+ mOsd->DrawBitmap(x, y, Bitmap, ColorFg, ColorBg);
+#endif
}
void cText2SkinScreen::DrawRectangle(int x1, int y1, int x2, int y2, tColor Color) {
+#ifndef DIRECTBLIT
for (int i = 0; i < mNumRegions; ++i)
mRegions[i]->DrawRectangle(x1, y1, x2, y2, Color);
+#else
+ mOsd->DrawRectangle(x1, y1, x2, y2, Color);
+#endif
}
void cText2SkinScreen::DrawText(int x, int y, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font, int Width, int Height, int Alignment) {
+#ifndef DIRECTBLIT
for (int i = 0; i < mNumRegions; ++i)
mRegions[i]->DrawText(x, y, s, ColorFg, ColorBg, Font, Width, Height, Alignment);
+#else
+ mOsd->DrawText(x, y, s, ColorFg, ColorBg, Font, Width, Height, Alignment);
+#endif
}
void cText2SkinScreen::DrawEllipse(int x1, int y1, int x2, int y2, tColor Color, int Quadrants) {
+#ifndef DIRECTBLIT
for (int i = 0; i < mNumRegions; ++i)
mRegions[i]->DrawEllipse(x1, y1, x2, y2, Color, Quadrants);
+#else
+ mOsd->DrawEllipse(x1, y1, x2, y2, Color, Quadrants);
+#endif
}
void cText2SkinScreen::DrawSlope(int x1, int y1, int x2, int y2, tColor Color, int Type) {
+#ifndef DIRECTBLIT
for (int i = 0; i < mNumRegions; ++i)
mRegions[i]->DrawSlope(x1, y1, x2, y2, Color, Type);
+#else
+ mOsd->DrawSlope(x1, y1, x2, y2, Color, Type);
+#endif
}
void cText2SkinScreen::Flush(void) {
- for (int i = 0; i < mNumRegions; ++i)
- mOsd->DrawBitmap(mRegions[i]->X0(), mRegions[i]->Y0(), *mRegions[i]);
- mOsd->Flush();
+ for (int i = 0; i < mNumRegions; ++i) {
+ if (mOffScreen)
+ mScreen->DrawBitmap(mRegions[i]->X0(), mRegions[i]->Y0(), *mRegions[i]);
+#ifndef DIRECTBLIT
+ else
+ mOsd->DrawBitmap(mRegions[i]->X0(), mRegions[i]->Y0(), *mRegions[i]);
+#endif
+ }
+ if (!mOffScreen)
+ mOsd->Flush();
}
diff --git a/screen.h b/screen.h
index 71572a0..b397785 100644
--- a/screen.h
+++ b/screen.h
@@ -1,5 +1,5 @@
/*
- * $Id: screen.h,v 1.2 2004/07/13 13:52:51 lordjaxom Exp $
+ * $Id: screen.h,v 1.2 2004/12/06 15:01:02 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_SCREEN_H
@@ -8,14 +8,21 @@
#include "common.h"
#include <vdr/osd.h>
+#undef DIRECTBLIT
+
class cText2SkinScreen {
+ /* Skin Editor */
+ friend class VSkinnerScreen;
+
private:
cOsd *mOsd;
+ cBitmap *mScreen;
cBitmap *mRegions[MAXOSDAREAS];
+ bool mOffScreen;
int mNumRegions;
public:
- cText2SkinScreen(int x, int y);
+ cText2SkinScreen(bool OffScreen = false);
~cText2SkinScreen();
eOsdError SetAreas(const tArea *Areas, int NumAreas);
diff --git a/scroller.c b/scroller.c
index 465dcde..9a057cc 100644
--- a/scroller.c
+++ b/scroller.c
@@ -1,5 +1,5 @@
/*
- * $Id: scroller.c,v 1.1 2004/07/05 17:55:34 lordjaxom Exp $
+ * $Id: scroller.c,v 1.3 2004/12/08 17:13:26 lordjaxom Exp $
*/
#include "scroller.h"
@@ -56,14 +56,12 @@ void cText2SkinScroller::Scroll(bool Up, bool Page)
mOffset -= Page ? mShown : 1;
if (mOffset < 0)
mOffset = 0;
- DrawText();
}
} else {
if (CanScrollDown()) {
mOffset += Page ? mShown : 1;
if (mOffset + mShown > Total())
mOffset = Total() - mShown;
- DrawText();
}
}
}
diff --git a/scroller.h b/scroller.h
index 9b338d9..dae6cf2 100644
--- a/scroller.h
+++ b/scroller.h
@@ -1,5 +1,5 @@
/*
- * $Id: scroller.h,v 1.1 2004/07/05 17:55:34 lordjaxom Exp $
+ * $Id: scroller.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_SCROLLER_H
diff --git a/setup.c b/setup.c
index 3a96131..7a8a9e8 100644
--- a/setup.c
+++ b/setup.c
@@ -1,9 +1,8 @@
/*
- * $Id: setup.c,v 1.4 2004/06/18 16:08:11 lordjaxom Exp $
+ * $Id: setup.c,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#include "setup.h"
-#include "bitmap.h"
cText2SkinSetup Text2SkinSetup;
@@ -19,30 +18,3 @@ bool cText2SkinSetup::SetupParse(const char *Name, const char *Value) {
return true;
}
-// --- cText2SkinSetupPage ----------------------------------------------------
-
-cText2SkinSetupPage::cText2SkinSetupPage(void) {
- mData = Text2SkinSetup;
- Add(new cOsdItem(tr("Flush image cache"), osUser1));
- Add(new cMenuEditIntItem(tr("Max. image cache size"), &mData.MaxCacheFill));
-}
-
-cText2SkinSetupPage::~cText2SkinSetupPage() {
-}
-
-void cText2SkinSetupPage::Store(void) {
- SetupStore("MaxCacheFill", mData.MaxCacheFill);
- Text2SkinSetup = mData;
-}
-
-eOSState cText2SkinSetupPage::ProcessKey(eKeys Key) {
- eOSState state = cMenuSetupPage::ProcessKey(Key);
- if (state == osUser1) {
- Skins.Message(mtInfo, tr("Flushing image cache..."));
- cText2SkinBitmap::FlushCache();
- Skins.Message(mtInfo, NULL);
- return osContinue;
- }
- return state;
-}
-
diff --git a/setup.h b/setup.h
index c726190..935873a 100644
--- a/setup.h
+++ b/setup.h
@@ -1,12 +1,11 @@
/*
- * $Id: setup.h,v 1.3 2004/06/18 16:08:11 lordjaxom Exp $
+ * $Id: setup.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_SETUP_H
#define VDR_TEXT2SKIN_SETUP_H
#include "common.h"
-#include <vdr/menuitems.h>
class cText2SkinSetup {
public:
@@ -17,18 +16,6 @@ public:
int MaxCacheFill;
};
-class cText2SkinSetupPage: public cMenuSetupPage {
-private:
- cText2SkinSetup mData;
-
-public:
- cText2SkinSetupPage(void);
- virtual ~cText2SkinSetupPage();
-
- virtual void Store(void);
- eOSState ProcessKey(eKeys Key);
-};
-
extern cText2SkinSetup Text2SkinSetup;
#endif // VDR_TEXT2SKIN_SETUP_H
diff --git a/status.c b/status.c
index fb2002d..7bbb749 100644
--- a/status.c
+++ b/status.c
@@ -1,16 +1,21 @@
/*
- * $Id: status.c,v 1.2 2004/06/12 19:17:06 lordjaxom Exp $
+ * $Id: status.c,v 1.3 2004/12/08 18:47:37 lordjaxom Exp $
*/
#include "status.h"
-cText2SkinStatus cText2SkinStatus::mStatus;
+cText2SkinStatus *cText2SkinStatus::mStatus = NULL;
+const std::string cText2SkinStatus::ReplayNames[__REPLAY_COUNT__] =
+ { "", "normal", "mp3", "mplayer", "dvd", "vcd", "image" };
+
+cText2SkinStatus Text2SkinStatus;
cText2SkinStatus::cText2SkinStatus(void) {
+ mStatus = this;
mReplayMode = replayNone;
}
-void cText2SkinStatus::Replaying(const cControl *Control, const char *Name) {
+void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name) {
if (Name != NULL) {
mReplayMode = replayNormal;
if (strlen(Name) > 6 && Name[0]=='[' && Name[3]==']' && Name[5]=='(') {
@@ -27,6 +32,8 @@ void cText2SkinStatus::Replaying(const cControl *Control, const char *Name) {
mReplayMode = replayVCD;
else if (access(Name, F_OK) == 0)
mReplayMode = replayMPlayer;
+ else if (strncmp(Name, "[image]", 7) == 0)
+ mReplayMode = replayImage;
else if (strlen(Name) > 7) {
int i, n;
for (i = 0, n = 0; Name[i]; ++i) {
diff --git a/status.h b/status.h
index a67e3e3..ccdbf85 100644
--- a/status.h
+++ b/status.h
@@ -1,5 +1,5 @@
/*
- * $Id: status.h,v 1.2 2004/06/12 19:17:06 lordjaxom Exp $
+ * $Id: status.h,v 1.2 2004/12/08 17:13:26 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_STATUS_H
@@ -9,18 +9,36 @@
#include <vdr/status.h>
class cText2SkinStatus: public cStatus {
+public:
+ enum eReplayMode {
+ replayNone,
+ replayNormal,
+ replayMP3,
+ replayMPlayer,
+ replayDVD,
+ replayVCD,
+ replayImage,
+
+#define __REPLAY_COUNT__ (replayImage+1)
+ };
+
private:
- static cText2SkinStatus mStatus;
+ static cText2SkinStatus *mStatus;
+ static const std::string ReplayNames[__REPLAY_COUNT__];
eReplayMode mReplayMode;
protected:
- cText2SkinStatus(void);
-
virtual void Replaying(const cControl *Control, const char *Name);
public:
- static eReplayMode ReplayMode(void) { return mStatus.mReplayMode; }
+ cText2SkinStatus(void);
+
+ static const std::string &ReplayMode(void);
};
+inline const std::string &cText2SkinStatus::ReplayMode(void) {
+ return ReplayNames[mStatus->mReplayMode];
+}
+
#endif // VDR_TEXT2SKIN_STATUS_H
diff --git a/text2skin.c b/text2skin.c
index f014c9e..f90c698 100644
--- a/text2skin.c
+++ b/text2skin.c
@@ -3,16 +3,17 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: text2skin.c,v 1.25 2004/07/14 16:01:38 lordjaxom Exp $
+ * $Id: text2skin.c,v 1.2 2004/12/08 17:13:26 lordjaxom Exp $
*/
#include "text2skin.h"
#include "setup.h"
+#include "menu.h"
#include "i18n.h"
#include "loader.h"
-const char *cText2SkinPlugin::VERSION = "0.0.8.1";
-const char *cText2SkinPlugin::THEMEVERSION = "0.0.3";
+const char *cText2SkinPlugin::VERSION = "1.0-pre1";
+const char *cText2SkinPlugin::SKINVERSION = "1.0";
const char *cText2SkinPlugin::DESCRIPTION = "Loader for text-based skins";
cText2SkinPlugin::cText2SkinPlugin(void) {
@@ -24,7 +25,7 @@ cText2SkinPlugin::~cText2SkinPlugin() {
bool cText2SkinPlugin::Start(void) {
RegisterI18n(Phrases);
cText2SkinLoader::Start();
- return true;
+ return true;
}
cMenuSetupPage *cText2SkinPlugin::SetupMenu(void) {
diff --git a/text2skin.h b/text2skin.h
index 8699c65..9391e5b 100644
--- a/text2skin.h
+++ b/text2skin.h
@@ -1,5 +1,5 @@
/*
- * $Id: text2skin.h,v 1.4 2004/06/11 15:01:58 lordjaxom Exp $
+ * $Id: text2skin.h,v 1.2 2004/12/08 17:13:26 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_H
@@ -11,11 +11,11 @@
class cText2SkinPlugin : public cPlugin {
private:
static const char *VERSION;
- static const char *THEMEVERSION;
+ static const char *SKINVERSION;
static const char *DESCRIPTION;
public:
- static const char *ThemeVersion(void) { return THEMEVERSION; }
+ static const char *SkinVersion(void) { return SKINVERSION; }
cText2SkinPlugin(void);
virtual ~cText2SkinPlugin();
diff --git a/theme.c b/theme.c
index 706a15d..376d468 100644
--- a/theme.c
+++ b/theme.c
@@ -1,5 +1,5 @@
/*
- * $Id: theme.c,v 1.2 2004/06/16 18:46:50 lordjaxom Exp $
+ * $Id: theme.c,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#include "theme.h"
#include <vdr/osd.h>
@@ -16,7 +16,7 @@ bool cText2SkinTheme::Parse(const char *Text) {
if (l) {
if (strncmp(Text, "Item=Color,", 11) == 0) {
Text += 11;
- string name;
+ std::string name;
tColor value;
if (ParseVar(Text, "name", name) && ParseVar(Text, "default", &value)) {
mMap[name] = mTheme.AddColor(name.c_str(), value);
diff --git a/theme.h b/theme.h
index 36ba3d1..0d6b167 100644
--- a/theme.h
+++ b/theme.h
@@ -1,5 +1,5 @@
/*
- * $Id: theme.h,v 1.1 2004/06/02 20:43:05 lordjaxom Exp $
+ * $Id: theme.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
*/
#ifndef VDR_TEXT2SKIN_THEME_H
@@ -7,12 +7,13 @@
#include "common.h"
#include "file.h"
+#include <map>
#include <vdr/themes.h>
class cText2SkinTheme: public cText2SkinFile {
private:
- cTheme mTheme;
- map<string,int> mMap;
+ cTheme mTheme;
+ std::map<std::string,int> mMap;
protected:
bool Parse(const char *Text);
@@ -22,10 +23,10 @@ public:
virtual ~cText2SkinTheme();
cTheme *Theme(void) { return &mTheme; }
- tColor Color(const string &Name);
+ tColor Color(const std::string &Name);
};
-inline tColor cText2SkinTheme::Color(const string &Name) {
+inline tColor cText2SkinTheme::Color(const std::string &Name) {
if (mMap.find(Name) != mMap.end())
return mTheme.Color(mMap[Name]);
else
diff --git a/xml/display.c b/xml/display.c
new file mode 100644
index 0000000..4790b2d
--- /dev/null
+++ b/xml/display.c
@@ -0,0 +1,42 @@
+/*
+ * $Id: display.c,v 1.3 2004/12/08 17:13:26 lordjaxom Exp $
+ */
+
+#include "xml/display.h"
+
+static const std::string DisplayNames[] =
+ { "channelInfo", "channelSmall", "volume", "message", "replayInfo", "replaySmall", "menu" };
+
+cxDisplay::cxDisplay(cxSkin *parent):
+ mType((eType)__COUNT_DISPLAY__),
+ mNumWindows(0),
+ mSkin(parent)
+{
+}
+
+bool cxDisplay::ParseType(const std::string &Text)
+{
+ for (int i = 0; i < (int)__COUNT_DISPLAY__; ++i) {
+ if (DisplayNames[i].length() > 0 && DisplayNames[i] == Text) {
+ mType = (eType)i;
+ return true;
+ }
+ }
+ return false;
+}
+
+const std::string &cxDisplay::GetType(void) const
+{
+ return DisplayNames[mType];
+}
+
+cxDisplays::cxDisplays(void)
+{
+}
+
+cxDisplays::~cxDisplays()
+{
+ iterator it = begin();
+ while (it != end())
+ (delete (*it).second, ++it);
+}
diff --git a/xml/display.h b/xml/display.h
new file mode 100644
index 0000000..6c233b2
--- /dev/null
+++ b/xml/display.h
@@ -0,0 +1,58 @@
+/*
+ * $Id: display.h,v 1.3 2004/12/08 17:13:26 lordjaxom Exp $
+ */
+
+#ifndef VDR_TEXT2SKIN_DISPLAY_H
+#define VDR_TEXT2SKIN_DISPLAY_H
+
+#include "xml/object.h"
+#include <string>
+#include <map>
+
+class cxSkin;
+
+class cxDisplay {
+ friend bool xStartElem(const std::string &name, std::map<std::string,std::string> &attrs);
+ friend bool xEndElem(const std::string &name);
+
+public:
+ enum eType {
+ channelInfo,
+ channelSmall,
+ volume,
+ message,
+ replayInfo,
+ replaySmall,
+ menu,
+#define __COUNT_DISPLAY__ (menu + 1)
+ };
+
+private:
+ eType mType;
+ txWindow mWindows[MAXOSDAREAS];
+ int mNumWindows;
+ cxObjects mObjects;
+ cxSkin *mSkin;
+
+public:
+ cxDisplay(cxSkin *parent);
+
+ bool ParseType(const std::string &Text);
+ const std::string &GetType(void) const;
+
+ eType Type(void) const { return mType; }
+ const txWindow *Windows(void) const { return mWindows; }
+ int NumWindows(void) const { return mNumWindows; }
+ cxSkin *Skin(void) const { return mSkin; }
+
+ uint Objects(void) const { return mObjects.size(); }
+ const cxObject *GetObject(int n) const { return mObjects[n]; }
+};
+
+class cxDisplays: public std::map<cxDisplay::eType,cxDisplay*> {
+public:
+ cxDisplays(void);
+ ~cxDisplays();
+};
+
+#endif // VDR_TEXT2SKIN_DISPLAY_H
diff --git a/xml/function.c b/xml/function.c
new file mode 100644
index 0000000..e6e321c
--- /dev/null
+++ b/xml/function.c
@@ -0,0 +1,212 @@
+/*
+ * $Id: function.c,v 1.4 2004/12/08 18:47:37 lordjaxom Exp $
+ */
+
+#include "xml/function.h"
+#include "render.h"
+#include "common.h"
+#include <vdr/tools.h>
+
+static const char *Internals[] = {
+ "not", "and", "or", "equal", "file", "trans", NULL
+};
+
+const std::string cxFunction::False = "";
+const std::string cxFunction::True = "1";
+
+cxFunction::cxFunction(void):
+ mType(string),
+ mString(),
+ mNumber(0),
+ mNumParams(0)
+{
+}
+
+cxFunction::cxFunction(const cxString &String):
+ mType(string),
+ mString(String),
+ mNumber(0),
+ mNumParams(0)
+{
+}
+
+cxFunction::cxFunction(const cxFunction &Src):
+ mType(Src.mType),
+ mString(Src.mString),
+ mNumber(Src.mNumber),
+ mNumParams(Src.mNumParams)
+{
+ for (uint i = 0; i < mNumParams; ++i)
+ mParams[i] = new cxFunction(*Src.mParams[i]);
+}
+
+cxFunction::~cxFunction()
+{
+ for (uint i = 0; i < mNumParams; ++i)
+ delete mParams[i];
+}
+
+bool cxFunction::Parse(const std::string &Text)
+{
+ const char *text = Text.c_str();
+ const char *ptr = text, *last = text;
+ eType type = undefined_function;
+ int inExpr = 0;
+ cxFunction *expr;
+
+ if (*ptr == '\'' || *ptr == '{') {
+ // must be string
+ if (strlen(ptr) < 2
+ || (*ptr == '\'' && *(ptr + strlen(ptr) - 1) != '\'')
+ || (*ptr == '{' && *(ptr + strlen(ptr) - 1) != '}')) {
+ esyslog("ERROR: Unmatched string end\n");
+ return false;
+ }
+
+ std::string temp;
+ if (*ptr == '\'')
+ temp.assign(ptr + 1, strlen(ptr) - 2);
+ else
+ temp.assign(ptr);
+
+ int pos = -1;
+ while ((pos = temp.find("\\'", pos + 1)) != -1)
+ temp.replace(pos, 1, "\'");
+
+ if (!mString.Parse(temp))
+ return false;
+
+ mType = string;
+ }
+ else {
+ // expression
+ for (; *ptr; ++ptr) {
+ if (*ptr == '(') {
+ if (inExpr++ == 0) {
+ int i;
+ for (i = 0; Internals[i] != NULL; ++i) {
+ if ((size_t)(ptr - last) == strlen(Internals[i])
+ && memcmp(last, Internals[i], ptr - last) == 0){
+ type = (eType)(INTERNAL + 1 + i);
+ break;
+ }
+ }
+
+ if (Internals[i] == NULL) {
+ esyslog("ERROR: Unknown function %.*s", (int)(ptr - last), last);
+ return false;
+ }
+ last = ptr + 1;
+ }
+ }
+ else if (*ptr == ',' || *ptr == ')') {
+ if (inExpr == 0) {
+ esyslog("ERROR: Unmatched '%c' in expression", *ptr);
+ return false;
+ }
+
+ if (inExpr == 1) {
+ expr = new cxFunction;
+ if (!expr->Parse(std::string(last, ptr - last))) {
+ delete expr;
+ return false;
+ }
+
+ mType = type;
+ mParams[mNumParams++] = expr;
+ last = ptr + 1;
+ }
+
+ if (*ptr == ')') {
+ if (inExpr == 1) {
+ int params = 0;
+
+ switch (mType) {
+ case fun_and:
+ case fun_or: params = -1; break;
+
+ case fun_eq: ++params;
+ case fun_not:
+ case fun_trans:
+ case fun_file: ++params;
+ default: break;
+ }
+
+ if (params != -1 && mNumParams != (uint)params) {
+ esyslog("ERROR: Text2Skin: Wrong number of parameters to %s, "
+ "expecting %d", Internals[mType - 1 - INTERNAL], params);
+ return false;
+ }
+ }
+
+ --inExpr;
+ }
+ }
+ }
+
+ if (inExpr > 0) {
+ esyslog("ERROR: Expecting ')' in expression");
+ return false;
+ }
+ }
+
+ return true;
+}
+
+const std::string &cxFunction::FunFile(const std::string &Param) const
+{
+ std::string path = cText2SkinRender::ImagePath(Param);
+ Dprintf("checking file(%s)\n", path.c_str());
+ if (access(path.c_str(), F_OK) == 0)
+ return Param;
+ return False;
+}
+
+std::string cxFunction::Evaluate(void) const
+{
+ switch (mType) {
+ case string:
+ return mString.Evaluate();
+
+ case fun_not:
+ return mParams[0]->EvaluateToBool() ? False : True;
+
+ case fun_and:
+ for (uint i = 0; i < mNumParams; ++i) {
+ if (!mParams[i]->EvaluateToBool())
+ return False;
+ }
+ return True;
+
+ case fun_or:
+ for (uint i = 0; i < mNumParams; ++i) {
+ if (mParams[i]->EvaluateToBool())
+ return True;
+ }
+ return False;
+
+ case fun_eq:
+ return mParams[0]->Evaluate() == mParams[1]->Evaluate() ? True : False;
+
+ case fun_file:
+ return FunFile(mParams[0]->Evaluate());
+
+ case fun_trans:
+ return tr(mParams[0]->Evaluate().c_str());
+
+ default:
+ Dprintf("unknown function code\n");
+ esyslog("ERROR: Unknown function code called (this shouldn't happen)");
+ break;
+ }
+ return False;
+}
+
+bool cxFunction::EvaluateToBool(void)
+{
+ std::string result = Evaluate();
+ if (result == False/* || result == "0"*/)
+ return false;
+ return true;
+}
+
diff --git a/xml/function.h b/xml/function.h
new file mode 100644
index 0000000..a7d8838
--- /dev/null
+++ b/xml/function.h
@@ -0,0 +1,66 @@
+/*
+ * $Id: function.h,v 1.4 2004/12/08 18:47:37 lordjaxom Exp $
+ */
+
+#ifndef VDR_TEXT2SKIN_XML_FUNCTION_H
+#define VDR_TEXT2SKIN_XML_FUNCTION_H
+
+#include "xml/string.h"
+#include <string>
+
+#define STRING 0x01000000
+#define NUMBER 0x02000000
+#define INTERNAL 0x04000000
+
+#define MAXPARAMETERS 16
+
+class cxFunction {
+public:
+ enum eType {
+ undefined_function,
+
+ string = STRING,
+ number = NUMBER,
+
+ fun_not = INTERNAL + 1,
+ fun_and = INTERNAL + 2,
+ fun_or = INTERNAL + 3,
+ fun_eq = INTERNAL + 4,
+ fun_file = INTERNAL + 5,
+ fun_trans = INTERNAL + 6
+ };
+
+ static const std::string False;
+ static const std::string True;
+
+private:
+ eType mType;
+ cxString mString;
+ int mNumber;
+ cxFunction *mParams[MAXPARAMETERS];
+ uint mNumParams;
+
+protected:
+ const std::string &FunFile(const std::string &Param) const;
+
+public:
+ cxFunction(void);
+ cxFunction(const cxString &String);
+ cxFunction(const cxFunction &Src);
+ ~cxFunction();
+
+ bool Parse(const std::string &Text);
+ std::string Evaluate(void) const;
+ bool EvaluateToBool(void);
+
+ void SetIndex(uint Index, int Tab);
+};
+
+inline void cxFunction::SetIndex(uint Index, int Tab)
+{
+ mString.SetIndex(Index, Tab);
+ for (uint i = 0; i < mNumParams; ++i)
+ mParams[i]->SetIndex(Index, Tab);
+}
+
+#endif // VDR_TEXT2SKIN_XML_FUNCTION_H
diff --git a/xml/object.c b/xml/object.c
new file mode 100644
index 0000000..6932106
--- /dev/null
+++ b/xml/object.c
@@ -0,0 +1,169 @@
+/*
+ * $Id: object.c,v 1.4 2004/12/08 17:13:26 lordjaxom Exp $
+ */
+
+#include "xml/object.h"
+#include "render.h"
+#include "font.h"
+
+static const std::string ObjectNames[] =
+ { "image", "text", "rectangle", "ellipse", "slope", "progress", "scrolltext", "scrollbar",
+ "block", "list", "item" };
+
+cxObject::cxObject(cxDisplay *parent):
+ mType((eType)__COUNT_OBJECT__),
+ mPos1(0, 0),
+ mPos2(-1, -1),
+ mAlpha(255),
+ mArc(0),
+ mAlign(taDefault),
+ mCondition(NULL),
+ mFont(cFont::GetFont(fontOsd)),
+ mObjects(NULL),
+ mDisplay(parent),
+ mSkin(parent->Skin())
+{
+}
+
+cxObject::cxObject(const cxObject &Src):
+ mType(Src.mType),
+ mPos1(Src.mPos1),
+ mPos2(Src.mPos2),
+ mAlpha(Src.mAlpha),
+ mArc(Src.mArc),
+ mFg(Src.mFg),
+ mBg(Src.mBg),
+ mMark(Src.mMark),
+ mActive(Src.mActive),
+ mKeep(Src.mKeep),
+ mPath(Src.mPath),
+ mText(Src.mText),
+ mAlign(Src.mAlign),
+ mCondition(NULL),
+ mCurrent(Src.mCurrent),
+ mTotal(Src.mTotal),
+ mFont(Src.mFont),
+ mObjects(NULL),
+ mDisplay(Src.mDisplay),
+ mSkin(Src.mSkin)
+{
+ if (Src.mCondition)
+ mCondition = new cxFunction(*Src.mCondition);
+ if (Src.mObjects)
+ mObjects = new cxObjects(*Src.mObjects);
+}
+
+cxObject::~cxObject()
+{
+ delete mCondition;
+ delete mObjects;
+}
+
+bool cxObject::ParseType(const std::string &Text) {
+ for (int i = 0; i < (int)__COUNT_OBJECT__; ++i) {
+ if (ObjectNames[i] == Text) {
+ mType = (eType)i;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool cxObject::ParseCondition(const std::string &Text) {
+ cxFunction *result = new cxFunction;
+ if (result->Parse(Text)) {
+ delete mCondition;
+ mCondition = result;
+ return true;
+ }
+ return false;
+}
+
+bool cxObject::ParseAlignment(const std::string &Text) {
+ if (Text == "center") mAlign = (eTextAlignment)(taTop | taCenter);
+ else if (Text == "right") mAlign = (eTextAlignment)(taTop | taRight);
+ else if (Text == "left") mAlign = (eTextAlignment)(taTop | taLeft);
+ else
+ return false;
+ return true;
+}
+
+bool cxObject::ParseFontFace(const std::string &Text) {
+ /*for (int i = 0; i < eDvbFontSize; ++i) {
+ if (FontNames[i] == Text) {
+ mFont = cFont::GetFont((eDvbFont)i);
+ return true;
+ }
+ }*/
+
+ int size = 0, pos;
+ std::string face = Text;
+ if ((pos = face.find(':')) != -1) {
+ size = atoi(face.substr(pos + 1).c_str());
+ face.erase(pos);
+ }
+ Dprintf("trying: %s %d\n", ((std::string)SkinPath() + "/fonts/" + face).c_str(), size);
+ if ((mFont = cText2SkinFont::Load(SkinPath() + "/fonts", face, size)) != NULL)
+ return true;
+ else if ((mFont = cText2SkinFont::Load(SkinPath() + "/" + mSkin->Name(), face, size)) != NULL)
+ return true;
+ return false;
+}
+
+const std::string &cxObject::TypeName(void) const {
+ return ObjectNames[mType];
+}
+
+txPoint cxObject::Pos(void) const {
+ return txPoint(mSkin->BaseOffset().x + (mPos1.x < 0 ? Skin()->BaseSize().w + mPos1.x : mPos1.x),
+ mSkin->BaseOffset().y + (mPos1.y < 0 ? Skin()->BaseSize().h + mPos1.y : mPos1.y));
+}
+
+txSize cxObject::Size(void) const {
+ txPoint p1(mSkin->BaseOffset().x + (mPos1.x < 0 ? Skin()->BaseSize().w + mPos1.x : mPos1.x),
+ mSkin->BaseOffset().y + (mPos1.y < 0 ? Skin()->BaseSize().h + mPos1.y : mPos1.y));
+ txPoint p2(mSkin->BaseOffset().x + (mPos2.x < 0 ? Skin()->BaseSize().w + mPos2.x : mPos2.x),
+ mSkin->BaseOffset().y + (mPos2.y < 0 ? Skin()->BaseSize().h + mPos2.y : mPos2.y));
+ return txSize(p2.x - p1.x + 1, p2.y - p1.y + 1);
+}
+
+const tColor *cxObject::Fg(void) const
+{
+ static tColor Fg;
+ return cText2SkinRender::ItemColor(mFg, Fg) ? &Fg : NULL;
+}
+
+const tColor *cxObject::Bg(void) const
+{
+ static tColor Bg;
+ return cText2SkinRender::ItemColor(mBg, Bg) ? &Bg : NULL;
+}
+
+const tColor *cxObject::Mark(void) const
+{
+ static tColor Mark;
+ return cText2SkinRender::ItemColor(mMark, Mark) ? &Mark : NULL;
+}
+
+const tColor *cxObject::Active(void) const
+{
+ static tColor Active;
+ return cText2SkinRender::ItemColor(mActive, Active) ? &Active : NULL;
+}
+
+const tColor *cxObject::Keep(void) const
+{
+ static tColor Keep;
+ return cText2SkinRender::ItemColor(mKeep, Keep) ? &Keep : NULL;
+}
+
+cxObjects::cxObjects(void)
+{
+}
+
+cxObjects::~cxObjects()
+{
+ for (uint i = 0; i < size(); ++i)
+ delete operator[](i);
+}
+
diff --git a/xml/object.h b/xml/object.h
new file mode 100644
index 0000000..8b134a9
--- /dev/null
+++ b/xml/object.h
@@ -0,0 +1,148 @@
+/*
+ * $Id: object.h,v 1.4 2004/12/08 17:13:26 lordjaxom Exp $
+ */
+
+#ifndef VDR_TEXT2SKIN_XML_OBJECT_H
+#define VDR_TEXT2SKIN_XML_OBJECT_H
+
+#include "xml/string.h"
+#include "xml/function.h"
+#include <vdr/osd.h>
+#include <vector>
+#include <string>
+#include <map>
+
+class cxDisplay;
+class cxSkin;
+
+struct txPoint {
+ int x, y;
+ txPoint(int _x = 0, int _y = 0) { x = _x; y = _y; }
+};
+
+struct txSize {
+ int w, h;
+ txSize(int _w = 0, int _h = 0) { w = _w; h = _h; }
+};
+
+struct txWindow {
+ txPoint pos1;
+ txPoint pos2;
+ int bpp;
+ txWindow(int _x1 = 0, int _y1 = 0, int _x2 = -1, int _y2 = -1, int _bpp=4):
+ pos1(_x1, _y2), pos2(_x2, _y2), bpp(_bpp) {}
+};
+
+class cxObjects;
+
+class cxObject {
+ friend class cText2SkinRender;
+ friend bool xStartElem(const std::string &name, std::map<std::string,std::string> &attrs);
+ friend bool xCharData(const std::string &text);
+ friend bool xEndElem(const std::string &name);
+
+ /* Skin Editor */
+ friend class VSkinnerItem;
+
+public:
+ enum eType {
+ image,
+ text,
+ rectangle,
+ ellipse,
+ slope,
+ progress,
+ scrolltext,
+ scrollbar,
+ block,
+ list,
+ item,
+#define __COUNT_OBJECT__ (item + 1)
+ };
+
+private:
+ eType mType;
+ txPoint mPos1;
+ txPoint mPos2;
+ int mAlpha;
+ int mArc;
+ std::string mFg;
+ std::string mBg;
+ std::string mMark;
+ std::string mActive;
+ std::string mKeep;
+ cxString mPath;
+ cxString mText;
+ eTextAlignment mAlign;
+ cxFunction *mCondition;
+ cxString mCurrent;
+ cxString mTotal;
+ const cFont *mFont;
+ cxObjects *mObjects; // used for block objects such as <list>
+ cxDisplay *mDisplay;
+ cxSkin *mSkin;
+
+public:
+ cxObject(cxDisplay *parent);
+ cxObject(const cxObject &Src);
+ ~cxObject();
+
+ bool ParseType (const std::string &Text);
+ bool ParseCondition(const std::string &Text);
+ bool ParseAlignment(const std::string &Text);
+ bool ParseFontFace (const std::string &Text);
+
+ void SetIndex(uint Index, int Tab);
+
+ eType Type(void) const { return mType; }
+ cxFunction *Condition(void) const { return mCondition; }
+ int Alpha(void) const { return mAlpha; }
+ eTextAlignment Align(void) const { return mAlign; }
+ int Arc(void) const { return mArc; }
+ std::string Path(void) const { return mPath.Evaluate(); }
+ std::string Text(void) const { return mText.Evaluate(); }
+ int Current(void) const { return mCurrent.Evaluate(); }
+ int Total(void) const { return mTotal.Evaluate(); }
+ const cFont *Font(void) const { return mFont; }
+ cxDisplay *Display(void) const { return mDisplay; }
+ cxSkin *Skin(void) const { return mSkin; }
+
+ const std::string &TypeName(void) const;
+ txPoint Pos(void) const;
+ txSize Size(void) const;
+ const tColor *Fg(void) const;
+ const tColor *Bg(void) const;
+ const tColor *Mark(void) const;
+ const tColor *Active(void) const;
+ const tColor *Keep(void) const;
+
+ uint Objects(void) const;
+ const cxObject *GetObject(uint Index) const;
+};
+
+inline void cxObject::SetIndex(uint Index, int Tab)
+{
+ mText.SetIndex(Index, Tab);
+ mPath.SetIndex(Index, Tab);
+ if (mCondition != NULL)
+ mCondition->SetIndex(Index, Tab);
+}
+
+class cxObjects: public std::vector<cxObject*> {
+public:
+ cxObjects(void);
+ ~cxObjects();
+};
+
+// recursive dependancy
+inline uint cxObject::Objects(void) const
+{
+ return mObjects ? mObjects->size() : 0;
+}
+
+inline const cxObject *cxObject::GetObject(uint Index) const
+{
+ return mObjects ? (*mObjects)[Index] : NULL;
+}
+
+#endif // VDR_TEXT2SKIN_XML_OBJECT_H
diff --git a/xml/parser.c b/xml/parser.c
new file mode 100644
index 0000000..1349769
--- /dev/null
+++ b/xml/parser.c
@@ -0,0 +1,310 @@
+/*
+ * $Id: parser.c,v 1.4 2004/12/08 17:13:26 lordjaxom Exp $
+ */
+
+#include "xml/parser.h"
+#include "xml/xml.h"
+#include "xml/skin.h"
+#include "common.h"
+#include <vdr/tools.h>
+#include <stdio.h>
+#include <vector>
+#include <string>
+
+#define STR_SKIN "skin"
+#define STR_DISPLAY "display"
+#define STR_ID "id"
+#define STR_WINDOW "window"
+#define STR_X1 "x1"
+#define STR_Y1 "y1"
+#define STR_X "x"
+#define STR_Y "y"
+#define STR_X2 "x2"
+#define STR_Y2 "y2"
+#define STR_BPP "bpp"
+#define STR_IMAGE "image"
+#define STR_PATH "path"
+#define STR_ALPHA "alpha"
+#define STR_TEXT "text"
+#define STR_CONDITION "condition"
+#define STR_NOT "not"
+#define STR_FILE "file"
+#define STR_COLOR "color"
+#define STR_ALIGN "align"
+#define STR_RECTANGLE "rectangle"
+#define STR_ELLIPSE "ellipse"
+#define STR_SLOPE "slope"
+#define STR_PROGRESS "progress"
+#define STR_BGCOLOR "bgcolor"
+#define STR_CURRENT "current"
+#define STR_TOTAL "total"
+#define STR_VERSION "version"
+#define STR_NAME "name"
+#define STR_SCREENBASE "screenBase"
+#define STR_FONT "font"
+#define STR_ARC "arc"
+
+#define MSG_BADTAG "ERROR: The tag %s was not expected in this context"
+#define MSG_BADENDTAG "ERROR: The tag %s was not expected in this context"
+#define MSG_BADATTR "ERROR: The attribute %s was not expected in tag %s"
+#define MSG_MISSATTR "ERROR: The tag %s lacks the attribute %s"
+#define MSG_BADVALUE "ERROR: %s is not allowed for attribute %s"
+#define MSG_PARSERR "ERROR: Parser error in %s:%d: %s"
+#define MSG_BADCDATA "ERROR: Bad character data"
+#define MSG_NOFILE "ERROR: Couldn't read %s: %m"
+#define MSG_MANYWINS "ERROR: Too many windows"
+
+#define TAG_ERR_REMAIN(_context) do { \
+ esyslog("ERROR: Text2Skin: Unexpected tag %s within %s", \
+ name.c_str(), _context); \
+ return false; \
+ } while (0)
+
+#define TAG_ERR_CHILD(_context) do { \
+ esyslog("ERROR: Text2Skin: No child tag %s expected within %s", \
+ name.c_str(), _context); \
+ return false; \
+ } while (0)
+
+#define TAG_ERR_END(_context) do { \
+ esyslog("ERROR: Text2Skin: Unexpected closing tag for %s within %s", \
+ name.c_str(), _context); \
+ return false; \
+ } while (0)
+
+#define ATTRIB_OPT_STRING(_attr,_target) \
+ if (attrs.find(_attr) != attrs.end()) { \
+ _target = attrs[_attr]; \
+ attrs.erase(_attr); \
+ }
+
+#define ATTRIB_MAN_STRING(_attr,_target) \
+ ATTRIB_OPT_STRING(_attr,_target) \
+ else { \
+ esyslog("ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \
+ _attr, name.c_str()); \
+ return false; \
+ }
+
+#define ATTRIB_OPT_NUMBER(_attr,_target) \
+ if (attrs.find(_attr) != attrs.end()) { \
+ char *_e; const char *_t = attrs[_attr].c_str(); \
+ long _l = strtol(_t, &_e, 10); \
+ if (_e ==_t || *_e != '\0') { \
+ esyslog("ERROR: Text2Skin: Invalid numeric value \"%s\" in attribute %s", \
+ _t, _attr); \
+ return false; \
+ } else \
+ _target = _l; \
+ attrs.erase(_attr); \
+ }
+
+#define ATTRIB_MAN_NUMBER(_attr,_target) \
+ ATTRIB_OPT_NUMBER(_attr,_target) \
+ else { \
+ esyslog("ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \
+ _attr, name.c_str()); \
+ return false; \
+ }
+
+#define ATTRIB_OPT_FUNC(_attr,_func) \
+ if (attrs.find(_attr) != attrs.end()) { \
+ if (!_func(attrs[_attr])) { \
+ esyslog("ERROR: Text2Skin: Unexpected value %s for attribute %s", \
+ attrs[_attr].c_str(), _attr); \
+ return false; \
+ } \
+ attrs.erase(_attr); \
+ }
+
+#define ATTRIB_MAN_FUNC(_attr,_func) \
+ ATTRIB_OPT_FUNC(_attr,_func) \
+ else { \
+ esyslog("ERROR: Text2Skin: Mandatory attribute %s missing in tag %s", \
+ _attr, name.c_str()); \
+ return false; \
+ }
+
+static std::vector<std::string> context;
+static cxSkin *skin = NULL;
+static cxDisplay *display = NULL;
+static cxObject *parent = NULL;
+static cxObject *object = NULL;
+
+bool xStartElem(const std::string &name, std::map<std::string,std::string> &attrs) {
+ Dprintf("start element: %s\n", name.c_str());
+
+ if (context.size() == 0) {
+ if (name == "skin") {
+ ATTRIB_MAN_STRING("version", skin->mVersion);
+ ATTRIB_MAN_STRING("name", skin->mTitle);
+ ATTRIB_MAN_FUNC ("screenBase", skin->ParseBase);
+ }
+ else
+ TAG_ERR_REMAIN("document");
+ }
+ else if (context[context.size() - 1] == "skin") {
+ if (name == "display") {
+ display = new cxDisplay(skin);
+ ATTRIB_MAN_FUNC ("id", display->ParseType);
+ }
+ else
+ TAG_ERR_REMAIN("skin");
+ }
+ else if (context[context.size() - 1] == "display"
+ || context[context.size() - 1] == "list"
+ || context[context.size() - 1] == "block") {
+ if (object != NULL) {
+ parent = object;
+ object = NULL;
+ }
+
+ if (name == "window") {
+ if (display->mNumWindows < MAXOSDAREAS) {
+ txWindow window;
+ ATTRIB_OPT_NUMBER("x1", window.pos1.x);
+ ATTRIB_OPT_NUMBER("y1", window.pos1.y);
+ ATTRIB_OPT_NUMBER("x2", window.pos2.x);
+ ATTRIB_OPT_NUMBER("y2", window.pos2.y);
+ ATTRIB_OPT_NUMBER("bpp", window.bpp);
+ display->mWindows[display->mNumWindows++] = window;
+ } else
+ esyslog("ERROR: Text2Skin: Too many windows in display");
+ }
+ else {
+ object = new cxObject(display);
+ if (object->ParseType(name)) {
+ ATTRIB_OPT_NUMBER("x1", object->mPos1.x);
+ ATTRIB_OPT_NUMBER("y1", object->mPos1.y);
+ ATTRIB_OPT_NUMBER("x2", object->mPos2.x);
+ ATTRIB_OPT_NUMBER("y2", object->mPos2.y);
+ ATTRIB_OPT_FUNC ("condition", object->ParseCondition);
+
+ if (name == "image") {
+ ATTRIB_OPT_NUMBER("x", object->mPos1.x);
+ ATTRIB_OPT_NUMBER("y", object->mPos1.y);
+ ATTRIB_OPT_NUMBER("alpha", object->mAlpha);
+ ATTRIB_OPT_STRING("color", object->mFg);
+ ATTRIB_OPT_STRING("bgColor", object->mBg);
+ ATTRIB_MAN_FUNC ("path", object->mPath.Parse);
+ }
+ else if (name == "text"
+ || name == "scrolltext") {
+ ATTRIB_OPT_STRING("color", object->mFg);
+ ATTRIB_OPT_FUNC ("align", object->ParseAlignment);
+ ATTRIB_OPT_FUNC ("font", object->ParseFontFace);
+ }
+ else if (name == "rectangle") {
+ ATTRIB_OPT_STRING("color", object->mFg);
+ }
+ else if (name == "ellipse" || name == "slope") {
+ ATTRIB_OPT_STRING("color", object->mFg);
+ ATTRIB_OPT_NUMBER("arc", object->mArc);
+ }
+ else if (name == "progress"
+ || name == "scrollbar") {
+ ATTRIB_OPT_STRING("color", object->mFg);
+ ATTRIB_OPT_STRING("bgColor", object->mBg);
+ ATTRIB_OPT_FUNC ("current", object->mCurrent.Parse);
+ ATTRIB_OPT_FUNC ("total", object->mTotal.Parse);
+ }
+ else if (name == "item") {
+ ATTRIB_MAN_NUMBER("height", object->mPos2.y);
+ --object->mPos2.y;
+ }
+ } else
+ TAG_ERR_REMAIN(context[context.size() - 1].c_str());
+ }
+ } else
+ TAG_ERR_CHILD(context[context.size() - 1].c_str());
+ context.push_back(name);
+ return true;
+}
+
+bool xCharData(const std::string &text) {
+ int start = 0, end = text.length() - 1;
+
+ Dprintf("char data before: %s\n", text.c_str());
+
+ while (text[start] == '\012' || text[start] == '\015' || text[start] == ' ' || text[start] == '\t')
+ ++start;
+
+ while (text[end] == '\012' || text[end] == '\015' || text[end] == ' ' || text[end] == '\t')
+ --end;
+
+ Dprintf("char data after: %s\n", text.substr(start, end - start + 1).c_str());
+
+ if (end - start + 1 > 0) {
+ Dprintf("context: %s\n", context[context.size() - 1].c_str());
+ if (context[context.size() - 1] == "text"
+ || context[context.size() - 1] == "scrolltext") {
+ if (!object->mText.Parse(text.substr(start, end - start + 1)))
+ return false;
+ } else
+ esyslog(MSG_BADCDATA);
+ }
+ return true;
+}
+
+bool xEndElem(const std::string &name) {
+ Dprintf("end element: %s\n", name.c_str());
+ if (context[context.size() - 1] == name) {
+ if (name == "display") {
+ skin->mDisplays[display->Type()] = display;
+ display = NULL;
+ }
+ else if (object != NULL || parent != NULL) {
+ if (object == NULL) {
+ Dprintf("rotating parent to object\n");
+ object = parent;
+ parent = NULL;
+ }
+
+ if (object->mCondition == NULL) {
+ switch (object->mType) {
+ case cxObject::text:
+ object->mCondition = new cxFunction(object->mText);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (parent != NULL) {
+ Dprintf("pushing to parent\n");
+ if (parent->mObjects == NULL)
+ parent->mObjects = new cxObjects();
+ parent->mObjects->push_back(object);
+ }
+ else
+ display->mObjects.push_back(object);
+ object = NULL;
+ }
+ context.pop_back();
+ } else
+ TAG_ERR_END(context[context.size() - 1].c_str());
+ return true;
+}
+
+cxSkin *xmlParse(const std::string &name, const std::string &fileName) {
+ skin = new cxSkin(name);
+ context.clear();
+
+ XML xml(fileName);
+ xml.nodeStartCB(xStartElem);
+ xml.nodeEndCB(xEndElem);
+ xml.cdataCB(xCharData);
+ if (xml.parse() != 0) {
+ esyslog("ERROR: Text2Skin: Parse error in %s, line %d", fileName.c_str(), xml.lineNr());
+ DELETENULL(skin);
+ DELETENULL(display);
+ DELETENULL(object);
+ return NULL;
+ }
+
+ cxSkin *result = skin;
+ skin = NULL;
+ return result;
+}
+
diff --git a/xml/parser.h b/xml/parser.h
new file mode 100644
index 0000000..60fe30c
--- /dev/null
+++ b/xml/parser.h
@@ -0,0 +1,14 @@
+/*
+ * $Id: parser.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
+ */
+
+#ifndef VDR_TEXT2SKIN_PARSER_H
+#define VDR_TEXT2SKIN_PARSER_H
+
+#include <string>
+
+class cxSkin;
+
+cxSkin *xmlParse(const std::string &name, const std::string &fileName);
+
+#endif // VDR_TEXT2SKIN_PARSER_H
diff --git a/xml/skin.c b/xml/skin.c
new file mode 100644
index 0000000..0cc753b
--- /dev/null
+++ b/xml/skin.c
@@ -0,0 +1,44 @@
+/*
+ * $Id: skin.c,v 1.2 2004/12/08 17:13:26 lordjaxom Exp $
+ */
+
+#include "xml/skin.h"
+#include <vdr/tools.h>
+#include <vdr/config.h>
+
+const std::string ScreenBases[] = { "relative", "absolute" };
+
+cxSkin::cxSkin(const std::string &Name):
+ mName(Name) {
+}
+
+void cxSkin::SetBase(eScreenBase Base) {
+ mBase = Base;
+ switch (mBase) {
+ case relative:
+ mBaseOffset = txPoint(Setup.OSDLeft, Setup.OSDTop);
+ mBaseSize = txSize(Setup.OSDWidth, Setup.OSDHeight);
+ break;
+
+ case absolute:
+ mBaseOffset = txPoint(0, 0);
+ mBaseSize = txSize(720, 576); //XXX
+ break;
+
+ default:
+ break;
+ }
+}
+
+bool cxSkin::ParseBase(const std::string &Text) {
+ int i;
+ for (i = 0; i < (int)__COUNT_BASE__; ++i) {
+ if (ScreenBases[i] == Text)
+ break;
+ }
+ if (i < (int)__COUNT_BASE__) {
+ SetBase((eScreenBase)i);
+ return true;
+ }
+ return false;
+}
diff --git a/xml/skin.h b/xml/skin.h
new file mode 100644
index 0000000..40e25e7
--- /dev/null
+++ b/xml/skin.h
@@ -0,0 +1,64 @@
+/*
+ * $Id: skin.h,v 1.3 2004/12/08 17:13:26 lordjaxom Exp $
+ */
+
+#ifndef VDR_TEXT2SKIN_XML_SKIN_H
+#define VDR_TEXT2SKIN_XML_SKIN_H
+
+#include "xml/display.h"
+#include <vdr/osd.h>
+#include <expat.h>
+#include <map>
+#include <string>
+
+// --- cxSkin -----------------------------------------------------------------
+
+class cxSkin {
+ friend bool xStartElem(const std::string &name, std::map<std::string,std::string> &attrs);
+ friend bool xEndElem(const std::string &name);
+
+ /* Skin Editor */
+ friend class VSkinnerView;
+
+public:
+ enum eScreenBase {
+ relative,
+ absolute,
+#define __COUNT_BASE__ (absolute + 1)
+ };
+
+private:
+ eScreenBase mBase;
+ txPoint mBaseOffset;
+ txSize mBaseSize;
+ std::string mName;
+ std::string mTitle;
+ std::string mVersion;
+
+ cxDisplays mDisplays;
+
+protected:
+ void SetBase(eScreenBase Base);
+
+public:
+ cxSkin(const std::string &Name);
+
+ cxDisplay *Get(cxDisplay::eType Type);
+
+ bool ParseBase(const std::string &Text);
+
+ eScreenBase Base(void) const { return mBase; }
+ const txPoint &BaseOffset(void) const { return mBaseOffset; }
+ const txSize &BaseSize(void) const { return mBaseSize; }
+ const std::string &Name(void) const { return mName; }
+ const std::string &Title(void) const { return mTitle; }
+ const std::string &Version(void) const { return mVersion; }
+};
+
+inline cxDisplay *cxSkin::Get(cxDisplay::eType Type) {
+ if (mDisplays.find(Type) != mDisplays.end())
+ return mDisplays[Type];
+ return NULL;
+}
+
+#endif // VDR_TEXT2SKIN_XML_SKIN_H
diff --git a/xml/string.c b/xml/string.c
new file mode 100644
index 0000000..051a003
--- /dev/null
+++ b/xml/string.c
@@ -0,0 +1,161 @@
+/*
+ * $Id: string.c,v 1.5 2004/12/08 17:22:28 lordjaxom Exp $
+ */
+
+#include "xml/string.h"
+#include "render.h"
+#include <vdr/tools.h>
+
+static const char *Tokens[__COUNT_TOKEN__] = {
+ "DateTime",
+
+ // Channel Display
+ "ChannelNumber", "ChannelName", "ChannelShortName", "ChannelBouquet", "PresentStartDateTime",
+ "PresentVPSDateTime", "PresentEndDateTime", "PresentDuration", "PresentProgress",
+ "PresentTitle", "PresentShortText", "PresentDescription", "FollowingStartDateTime",
+ "FollowingVPSDateTime", "FollowingEndDateTime", "FollowingDuration",
+ "FollowingTitle", "FollowingShortText", "FollowingDescription", "Language",
+ "HasTeletext", "HasMultilang", "HasDolby", "IsEncrypted", "IsRadio", "IsRecording", "HasVPS",
+ "HasTimer", "IsRunning",
+
+ // Volume Display
+ "VolumeCurrent", "VolumeTotal", "IsMute",
+
+ // Message Display
+ "Message", "MessageStatus", "MessageInfo", "MessageWarning",
+ "MessageError",
+
+ // Replay Display
+ "ReplayTitle", "ReplayPositionIndex", "ReplayDurationIndex", "ReplayPrompt", "IsPlaying",
+ "IsFastForward", "IsFastRewind", "IsSlowForward", "IsSlowRewind", "IsPausing",
+ "ReplayPosition", "ReplayDuration", "ReplayMode",
+
+ // Menu Page
+ "MenuTitle", "MenuGroup", "IsMenuGroup", "MenuItem", "IsMenuItem", "MenuCurrent", "IsMenuCurrent",
+ "MenuText", "ButtonRed", "ButtonGreen", "ButtonYellow", "ButtonBlue", "CanScrollUp",
+ "CanScrollDown"
+};
+
+std::string txToken::Token(const txToken &Token) {
+ std::string result = (std::string)"{" + Tokens[Token.Type];
+ if (Token.Attrib.length() > 0)
+ result += ":" + Token.Attrib;
+ result += "}";
+
+ return result;
+}
+
+cxString::cxString(void) {
+}
+
+bool cxString::Parse(const std::string &Text) {
+ const char *text = Text.c_str();
+ const char *ptr = text, *last = text;
+ bool inToken = false;
+ bool inAttrib = false;
+ int offset = 0;
+
+ Dprintf("parsing: %s\n", Text.c_str());
+
+ for (; *ptr; ++ptr) {
+ if (inToken && *ptr == '\\') {
+ if (*(ptr + 1) == '\0') {
+ esyslog("ERROR: Stray \\ in token attribute\n");
+ return false;
+ }
+
+ ++ptr;
+ continue;
+ }
+ else if (*ptr == '{') {
+ if (inToken) {
+ esyslog("ERROR: Unexpected '{' in token");
+ return false;
+ }
+
+ mText.append(last, ptr - last);
+ last = ptr + 1;
+ inToken = true;
+ }
+ else if (*ptr == '}' || (inToken && *ptr == ':')) {
+ if (!inToken) {
+ esyslog("ERROR: Unexpected '}' outside of token");
+ return false;
+ }
+
+ if (inAttrib) {
+ if (*ptr == ':') {
+ esyslog("ERROR: Unexpected ':' inside of token attribute");
+ return false;
+ }
+
+ int pos = -1;
+ txToken &lastToken = mTokens[mTokens.size() - 1];
+ lastToken.Attrib.assign(last, ptr - last);
+ while ((pos = lastToken.Attrib.find('\\', pos + 1)) != -1) {
+ switch (lastToken.Attrib[pos + 1]) {
+ case 'n':
+ lastToken.Attrib.replace(pos, 2, "\n");
+ break;
+
+ default:
+ lastToken.Attrib.erase(pos, 1);
+ }
+ }
+
+ inAttrib = false;
+ inToken = false;
+ } else {
+ int i;
+ for (i = 0; i < (int)__COUNT_TOKEN__; ++i) {
+ if ((size_t)(ptr - last) == strlen(Tokens[i])
+ && memcmp(last, Tokens[i], ptr - last) == 0) {
+ txToken token((exToken)i, offset, "");
+ mTokens.push_back(token);
+ break;
+ }
+ }
+
+ if (i == (int)__COUNT_TOKEN__) {
+ esyslog("ERROR: Unexpected token {%.*s}", (int)(ptr - last), last);
+ return false;
+ }
+
+ if (*ptr == ':')
+ inAttrib = true;
+ else
+ inToken = false;
+ }
+
+ last = ptr + 1;
+ }
+ else if (!inToken)
+ ++offset;
+ }
+
+ if (inToken) {
+ esyslog("ERROR: Expecting '}' in token");
+ return false;
+ }
+
+ mText.append(last, ptr - last);
+ return true;
+}
+
+cxType cxString::Evaluate(void) const
+{
+ std::string result;
+ int offset = 0;
+
+ if (mText.length() == 0 && mTokens.size() == 1)
+ return cText2SkinRender::GetToken(mTokens[0]);
+
+ for (uint i = 0; i < mTokens.size(); ++i) {
+ result.append(mText.c_str() + offset, mTokens[i].Offset - offset);
+ result.append(cText2SkinRender::GetToken(mTokens[i]));
+ offset = mTokens[i].Offset;
+ }
+ result.append(mText.c_str() + offset);
+ return result;
+}
+
diff --git a/xml/string.h b/xml/string.h
new file mode 100644
index 0000000..5c89d13
--- /dev/null
+++ b/xml/string.h
@@ -0,0 +1,128 @@
+/*
+ * $Id: string.h,v 1.5 2004/12/08 18:47:37 lordjaxom Exp $
+ */
+
+#ifndef VDR_TEXT2SKIN_XML_STRING_H
+#define VDR_TEXT2SKIN_XML_STRING_H
+
+#include "xml/type.h"
+#include <string>
+#include <vector>
+
+enum exToken {
+ tDateTime,
+
+ // Channel Display
+ tChannelNumber,
+ tChannelName,
+ tChannelShortName,
+ tChannelBouquet,
+ // next 8 also in Menu
+ tPresentStartDateTime,
+ tPresentVPSDateTime,
+ tPresentEndDateTime,
+ tPresentDuration,
+ tPresentProgress,
+ tPresentTitle,
+ tPresentShortText,
+ tPresentDescription,
+ tFollowingStartDateTime,
+ tFollowingVPSDateTime,
+ tFollowingEndDateTime,
+ tFollowingDuration,
+ tFollowingTitle,
+ tFollowingShortText,
+ tFollowingDescription,
+ tLanguage,
+ tHasTeletext,
+ tHasMultilang,
+ tHasDolby,
+ tIsEncrypted,
+ tIsRadio,
+ tIsRecording,
+ // next 3 also in Menu
+ tHasVPS,
+ tHasTimer,
+ tIsRunning,
+
+ // VolumeDisplay
+ tVolumeCurrent,
+ tVolumeTotal,
+ tIsMute,
+
+ // Message Display
+ tMessage,
+ tMessageStatus,
+ tMessageInfo,
+ tMessageWarning,
+ tMessageError,
+
+ // Replay Display
+ tReplayTitle,
+ tReplayPositionIndex,
+ tReplayDurationIndex,
+ tReplayPrompt,
+ tIsPlaying,
+ tIsFastForward,
+ tIsFastRewind,
+ tIsSlowForward,
+ tIsSlowRewind,
+ tIsPausing,
+ tReplayPosition,
+ tReplayDuration,
+ tReplayMode,
+
+ // Menu Page
+ tMenuTitle,
+ tMenuGroup,
+ tIsMenuGroup,
+ tMenuItem,
+ tIsMenuItem,
+ tMenuCurrent,
+ tIsMenuCurrent,
+ tMenuText,
+ tButtonRed,
+ tButtonGreen,
+ tButtonYellow,
+ tButtonBlue,
+ tCanScrollUp,
+ tCanScrollDown,
+
+#define __COUNT_TOKEN__ (tCanScrollDown + 1)
+};
+
+struct txToken {
+ exToken Type;
+ uint Offset;
+ std::string Attrib;
+ int Index;
+ int Tab;
+
+ txToken(void): Index(-1), Tab(-1) {}
+ txToken(exToken t, uint o, const std::string &a): Type(t), Offset(o), Attrib(a), Index(-1), Tab(-1) {}
+ static std::string Token(const txToken &Token);
+};
+
+class cxString {
+private:
+ std::string mText;
+ std::vector<txToken> mTokens;
+
+public:
+ cxString(void);
+
+ bool Parse(const std::string &Text);
+ cxType Evaluate(void) const;
+
+ void SetIndex(uint Index, int Tab);
+};
+
+inline void cxString::SetIndex(uint Index, int Tab)
+{
+ for (uint i = 0; i < mTokens.size(); ++i) {
+ mTokens[i].Index = Index;
+ mTokens[i].Tab = Tab;
+ }
+}
+
+#endif // VDR_TEXT2SKIN_XML_STRING_H
diff --git a/xml/type.c b/xml/type.c
new file mode 100644
index 0000000..d311b30
--- /dev/null
+++ b/xml/type.c
@@ -0,0 +1,20 @@
+/*
+ * $Id: type.c,v 1.2 2004/12/08 17:13:26 lordjaxom Exp $
+ */
+
+#include "xml/type.h"
+#include "xml/function.h"
+#include <stdio.h>
+
+const std::string &cxType::String(void) {
+ static char buffer[50];
+ if (mType == number) {
+ snprintf(buffer, sizeof(buffer), "%d", mNumber);
+ mString = buffer;
+ mType = string;
+ } else if (mType == boolean) {
+ mString = mNumber ? cxFunction::True : cxFunction::False;
+ mType = string;
+ }
+ return mString;
+}
diff --git a/xml/type.h b/xml/type.h
new file mode 100644
index 0000000..1b1113c
--- /dev/null
+++ b/xml/type.h
@@ -0,0 +1,42 @@
+/*
+ * $Id: type.h,v 1.3 2004/12/08 17:13:26 lordjaxom Exp $
+ */
+
+#ifndef VDR_TEXT2SKIN_XML_TYPE_H
+#define VDR_TEXT2SKIN_XML_TYPE_H
+
+#include <string>
+
+class cxType {
+public:
+ enum eType {
+ string,
+ number,
+ boolean
+ };
+
+private:
+ eType mType;
+ std::string mString;
+ int mNumber;
+
+public:
+ cxType(const char *String): mType(string), mString(String ?: "") {}
+ cxType(std::string String): mType(string), mString(String) {}
+ cxType(int Number): mType(number), mNumber(Number) {}
+ cxType(time_t Number): mType(number), mNumber(Number) {}
+ cxType(bool Value): mType(boolean), mNumber(Value ? 1 : 0) {}
+
+ const std::string &String(void);
+ int Number(void) const;
+
+ operator std::string () { return String(); }
+ operator int () { return Number(); }
+ operator bool () { return Number(); }
+};
+
+inline int cxType::Number(void) const {
+ return mType == number ? mNumber : 0;
+}
+
+#endif // VDR_TEXT2SKIN_XML_TYPE_H
diff --git a/xml/xml.c b/xml/xml.c
new file mode 100644
index 0000000..07dae8c
--- /dev/null
+++ b/xml/xml.c
@@ -0,0 +1,295 @@
+/*
+ * $Id: xml.c,v 1.2 2004/12/06 15:01:02 lordjaxom Exp $
+ * This module was kindly provided by Clemens Kirchgatterer
+ */
+
+#include <ctype.h>
+
+#include <iostream>
+#include <fstream>
+
+#include "xml.h"
+
+using namespace std;
+
+enum {
+ LOOK4START, // looking for first element start
+ LOOK4TAG, // looking for element tag
+ INTAG, // reading tag
+ LOOK4ATTRN, // looking for attr name, > or /
+ INATTRN, // reading attr name
+ LOOK4ATTRV, // looking for attr value
+ SAWSLASH, // saw / in element opening
+ INATTRV, // in attr value
+ LOOK4CLOSETAG, // looking for closing tag after <
+ INCLOSETAG, // reading closing tag
+};
+
+XML::XML(const string &file) {
+ char *buffer;
+ long size;
+
+ ifstream f(file.c_str(), ios::in|ios::binary|ios::ate);
+ size = f.tellg();
+ f.seekg(0, ios::beg);
+ buffer = new char [size];
+ f.read(buffer, size);
+ f.close();
+ data = buffer;
+ delete[] buffer;
+ nodestartcb = NULL;
+ nodeendcb = NULL;
+ cdatacb = NULL;
+ parseerrorcb = NULL;
+ progresscb = NULL;
+}
+
+XML::XML(const char *mem, unsigned int len) {
+ data.assign(mem, len);
+ nodestartcb = NULL;
+ nodeendcb = NULL;
+ cdatacb = NULL;
+ parseerrorcb = NULL;
+ progresscb = NULL;
+}
+
+void
+XML::nodeStartCB(XML_NODE_START_CB(cb)) {
+ nodestartcb = cb;
+}
+
+void
+XML::nodeEndCB(XML_NODE_END_CB(cb)) {
+ nodeendcb = cb;
+}
+
+void
+XML::cdataCB(XML_CDATA_CB(cb)) {
+ cdatacb = cb;
+}
+
+void
+XML::parseErrorCB(XML_PARSE_ERROR_CB(cb)) {
+ parseerrorcb = cb;
+}
+
+void
+XML::progressCB(XML_PROGRESS_CB(cb)) {
+ progresscb = cb;
+}
+
+int
+XML::parse(void) {
+ float percent = 0;
+ unsigned int len;
+ int last = 0;
+
+ state = LOOK4START;
+ linenr = 1;
+ skipping = false;
+ len = data.length();
+ for (unsigned int i=0; i<len; i++) {
+ if (readChar(data[i])) return (-1);
+ if (progresscb) {
+ percent = ((float)i/len)*100;
+ if ((int)percent>last) {
+ progresscb((int)percent);
+ last = ((int)percent);
+ }
+ }
+ }
+ return (0);
+}
+
+bool
+XML::isTokenChar(bool start, int c) {
+ return (isalpha(c) || c == '_' || (!start && isdigit(c)));
+}
+
+int
+XML::readChar(int c) {
+ // new line?
+ if (c == '\n') linenr++;
+
+ switch (state) {
+
+ // looking for element start
+ case LOOK4START:
+ if (c == '<') {
+ if (cdatacb) {
+ int pos = 0;
+ while ((pos = cdata.find('&', pos)) != -1) {
+ if (cdata.substr(pos, 4) == "&lt;")
+ cdata.replace(pos, 4, "<");
+ else if (cdata.substr(pos, 4) == "&gt;")
+ cdata.replace(pos, 4, ">");
+ else if (cdata.substr(pos, 5) == "&amp;")
+ cdata.replace(pos, 5, "&");
+ ++pos;
+ }
+ if (!cdatacb(cdata))
+ return (-1);
+ }
+ cdata = "";
+ attr.clear();
+ tag = "";
+ state = LOOK4TAG;
+ } else
+ cdata += c;
+ // silently ignore until resync
+ break;
+
+ // looking for element tag
+ case LOOK4TAG:
+ // skip comments and declarations.
+ if (skipping) {
+ if (c == '>') {
+ skipping = false;
+ state = LOOK4START;
+ }
+ break;
+ } else {
+ if (c == '?' || c == '!') {
+ skipping = true;
+ break;
+ }
+ }
+ if (isTokenChar(1, c)) {
+ tag += c;
+ state = INTAG;
+ } else if (c == '/') {
+ state = LOOK4CLOSETAG;
+ } else if (!isspace(c)) {
+ if (parseerrorcb) {
+ parseerrorcb(linenr, "Bogus tag char", c);
+ }
+ return (-1);
+ }
+ break;
+
+ // reading tag
+ case INTAG:
+ if (isTokenChar(0, c)) {
+ tag += c;
+ } else if (c == '>') {
+ if (nodestartcb)
+ if (!nodestartcb(tag, attr))
+ return (-1);
+ state = LOOK4START;
+ } else if (c == '/') {
+ state = SAWSLASH;
+ } else {
+ state = LOOK4ATTRN;
+ }
+ break;
+
+ // looking for attr name, > or /
+ case LOOK4ATTRN:
+ if (c == '>') {
+ if (nodestartcb)
+ if (!nodestartcb(tag, attr))
+ return (-1);
+ state = LOOK4START;
+ } else if (c == '/') {
+ state = SAWSLASH;
+ } else if (isTokenChar(1, c)) {
+ attrn = "";
+ attrn += c;
+ state = INATTRN;
+ } else if (!isspace(c)) {
+ if (parseerrorcb) {
+ parseerrorcb(linenr, "Bogus 1st attr name char", c);
+ }
+ return (-2);
+ }
+ break;
+
+ // saw / in element opening
+ case SAWSLASH:
+ if (c == '>') {
+ if (nodestartcb)
+ if (!nodestartcb(tag, attr))
+ return (-1);
+ if (nodeendcb)
+ if (!nodeendcb(tag))
+ return (-1);
+ state = LOOK4START;
+ } else {
+ if (parseerrorcb) {
+ parseerrorcb(linenr, "Bogus char before >", c);
+ }
+ return (-3);
+ }
+ break;
+
+ // reading attr name
+ case INATTRN:
+ if (isTokenChar(0, c)) {
+ attrn += c;
+ } else if (isspace(c) || c == '=') {
+ state = LOOK4ATTRV;
+ } else {
+ if (parseerrorcb) {
+ parseerrorcb(linenr, "Bogus attr name char", c);
+ }
+ return (-4);
+ }
+ break;
+
+ // looking for attr value
+ case LOOK4ATTRV:
+ if (c == '\'' || c == '"') {
+ delim = c;
+ attrv = "";
+ state = INATTRV;
+ } else if (!(isspace(c) || c == '=')) {
+ if (parseerrorcb) {
+ parseerrorcb(linenr, "No attribute value", c);
+ }
+ return (-5);
+ }
+ break;
+
+ // in attr value
+ case INATTRV:
+ if (c == delim) {
+ attr[attrn] = attrv;
+ state = LOOK4ATTRN;
+ } else if (!iscntrl(c)) {
+ attrv += c;
+ }
+ break;
+
+ // looking for closing tag after <
+ case LOOK4CLOSETAG:
+ if (isTokenChar(1, c)) {
+ tag += c;
+ state = INCLOSETAG;
+ } else if (!isspace(c)) {
+ if (parseerrorcb) {
+ parseerrorcb(linenr, "Bogus preend tag char", c);
+ }
+ return (-6);
+ }
+ break;
+
+ // reading closing tag
+ case INCLOSETAG:
+ if (isTokenChar(0, c)) {
+ tag += c;
+ } else if (c == '>') {
+ if (nodeendcb)
+ if (!nodeendcb(tag))
+ return false;
+ state = LOOK4START;
+ } else if (!isspace(c)) {
+ if (parseerrorcb) {
+ parseerrorcb(linenr, "Bogus end tag char", c);
+ }
+ return (-7);
+ }
+ break;
+ }
+
+ return (0);
+}
diff --git a/xml/xml.h b/xml/xml.h
new file mode 100644
index 0000000..9abc641
--- /dev/null
+++ b/xml/xml.h
@@ -0,0 +1,63 @@
+/*
+ * $Id: xml.h,v 1.1.1.1 2004/11/19 16:45:31 lordjaxom Exp $
+ * This module was kindly provided by Clemens Kirchgatterer
+ */
+
+#ifndef _XML_H_
+#define _XML_H_
+
+#include <string>
+#include <map>
+
+#define XML_NODE_START_CB(CB) \
+bool (*CB)(const std::string &tag, std::map<std::string, std::string> &attr)
+#define XML_NODE_END_CB(CB) \
+bool (*CB)(const std::string &tag)
+#define XML_CDATA_CB(CB) \
+bool (*CB)(const std::string &text)
+#define XML_PARSE_ERROR_CB(CB) \
+void (*CB)(int line, const char *txt, char c)
+#define XML_PROGRESS_CB(CB) \
+void (*CB)(int percent)
+
+class XML {
+
+public:
+
+ XML(const std::string &file);
+ XML(const char *mem, unsigned int len);
+
+ void nodeStartCB(XML_NODE_START_CB(cb));
+ void nodeEndCB(XML_NODE_END_CB(cb));
+ void cdataCB(XML_CDATA_CB(cb));
+ void parseErrorCB(XML_PARSE_ERROR_CB(cb));
+ void progressCB(XML_PROGRESS_CB(cb));
+
+ int parse(void);
+
+ int lineNr(void) const { return linenr; }
+
+protected:
+
+ bool isTokenChar(bool start, int c);
+ int readChar(int c);
+
+private:
+
+ bool skipping;
+ int state;
+ int linenr;
+ int delim;
+
+ std::string data, cdata, tag, attrn, attrv;
+ std::map<std::string, std::string> attr;
+
+ XML_NODE_START_CB(nodestartcb);
+ XML_NODE_END_CB(nodeendcb);
+ XML_CDATA_CB(cdatacb);
+ XML_PARSE_ERROR_CB(parseerrorcb);
+ XML_PROGRESS_CB(progresscb);
+
+};
+
+#endif // _XML_H_