1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Freetype font support; full UTF-8 support; dropped pixel fonts

This commit is contained in:
Klaus Schmidinger 2007-06-10 13:02:43 +02:00
parent 32dd727d05
commit c6f8a14957
54 changed files with 1601 additions and 130662 deletions

View File

@ -2083,3 +2083,7 @@ Oktay Yolge
Krzysztof Parma <krzycho@zoz.wodzislaw.pl> Krzysztof Parma <krzycho@zoz.wodzislaw.pl>
for suggesting to implement the SVDRP command REMO for suggesting to implement the SVDRP command REMO
Alexander Riedel <alexander-riedel@t-online.de>
for a patch that was used as a base to implement support for Freetype fonts and
UTF-8 handling

30
HISTORY
View File

@ -5180,7 +5180,7 @@ Video Disk Recorder Revision History
- Official release. - Official release.
2007-05-12: Version 1.5.3 2007-06-10: Version 1.5.3
- Fixed some spelling errors in 'newplugin' (thanks to Ville Skyttä). - Fixed some spelling errors in 'newplugin' (thanks to Ville Skyttä).
- Fixed a busy loop in fast forward if the next video data file is missing - Fixed a busy loop in fast forward if the next video data file is missing
@ -5198,3 +5198,31 @@ Video Disk Recorder Revision History
- Increased the maximum number of CA system ids to cope with the AlphaCrypt - Increased the maximum number of CA system ids to cope with the AlphaCrypt
CAM's version 3.11 firmware. CAM's version 3.11 firmware.
- Fixed getting the code setting from the locale (thanks to Matthias Schwarzott). - Fixed getting the code setting from the locale (thanks to Matthias Schwarzott).
- Implemented support for Freetype fonts (based on a patch from Alexander Riedel).
- If the OSD device in use has at least 8bpp bitmap depth and this is also
used by the current skin, Freetype fonts are displayed "anti-aliased".
The new setup parameter "OSD/Anti-alias" can be used to turn this off.
- The new function cOsd::SetAntiAliasGranularity() can be used to help the OSD
in managing the available color palette entries when doing anti-aliasing.
Skins that use 8bpp bitmaps can call this function with the maximum number
of colors used, and the maximum number of color combinations. The OSD will
then evenly split the available palette entries between the various colors
combinations, so that fonts can be "anti-aliased". By default a total of
10 colors and 10 combinations is assumed.
- The pixel fonts have been completely removed from the VDR source.
- VDR is now "UTF-8 aware". It handles strings according to the character
encoding used on the user's system. All internationalization strings and
incoming SI data are converted to the system encoding.
- Plugins that handle strings need to be aware that on systems with UTF-8
encoding a "character symbol" may consist of more than a single byte in
memory. The functions and macros named Utf8...() can be used to handle
strings without needing to care about the underlying character encoding
(see tools.h for details).
- Even though the weekdays of repeating timers are presented to the user as UTF-8
characters in the OSD, the timers.conf file and the SVDRP timer commands still
use single byte characters ("MTWTFSS") to make sure this information is handled
correctly between systems with different character encodings.
- Added a missing i18n string for "CAM" in the Turkish OSD texts.
- Improved editing strings that are too long to fit into the editable area.
- Changes to the OSD settings in the "Setup/OSD" menu now immediately take effect
when the "Ok" key is pressed.

17
INSTALL
View File

@ -35,11 +35,18 @@ Refer to http://linuxtv.org for more information about the Linux-DVB driver.
VDR requires the Linux-DVB driver version dated 2003-08-23 or higher VDR requires the Linux-DVB driver version dated 2003-08-23 or higher
to work properly. to work properly.
You will also need to install the "libjpeg" and "libcap" libraries, You will also need to install the following libraries, as well as their
as well as their "devel" packages to get the necessary header files "devel" packages to get the necessary header files for compiling VDR:
for compiling VDR. If the "capability" module is not compiled into
your kernel, you may need to do "modprobe capability" before running freetype2
VDR. libcap
libjpeg
If the "capability" module is not compiled into your kernel, you may
need to do "modprobe capability" before running VDR.
When running VDR, the Freetype fonts must be installed in the directory
/usr/share/fonts/truetype.
After extracting the package, change into the VDR directory After extracting the package, change into the VDR directory
and type 'make'. This should produce an executable file and type 'make'. This should produce an executable file

17
MANUAL
View File

@ -503,6 +503,23 @@ Version 1.4
current skin wants to, and 2 means always use the small current skin wants to, and 2 means always use the small
font. font.
Anti-alias = 1 Controls whether the OSD uses "anti-aliasing" to improve
font rendering. To make this work, the OSD must support
at least 256 colors, and the skin in use has to
utilize these. If either of these conditions is not met,
rendering will be done without anti-aliasing.
OSD font name = arialbd.ttf
Small font name = arial.ttf
Fixed font name = courbd.ttf
The file names of the various fonts to use.
OSD font size = 22
Small font size = 18
Fixed font size = 20
The sizes (in pixel) of the various fonts. Valid range is
10...64.
Channel info position = bottom Channel info position = bottom
The position of the channel info window in the OSD The position of the channel info window in the OSD
(either 'bottom' or 'top'). (either 'bottom' or 'top').

105
Makefile
View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Makefile 1.99 2007/03/11 10:22:18 kls Exp $ # $Id: Makefile 1.100 2007/05/28 11:22:42 kls Exp $
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
@ -17,8 +17,8 @@ CXXFLAGS ?= -g -O2 -Wall -Woverloaded-virtual
LSIDIR = ./libsi LSIDIR = ./libsi
MANDIR = /usr/local/man MANDIR = /usr/local/man
BINDIR = /usr/local/bin BINDIR = /usr/local/bin
LIBS = -ljpeg -lpthread -ldl -lcap LIBS = -ljpeg -lpthread -ldl -lcap -lfreetype
INCLUDES = INCLUDES = -I/usr/include/freetype2
PLUGINDIR= ./PLUGINS PLUGINDIR= ./PLUGINS
PLUGINLIBDIR= $(PLUGINDIR)/lib PLUGINLIBDIR= $(PLUGINDIR)/lib
@ -39,34 +39,6 @@ OBJS = audio.o channels.o ci.o config.o cutter.o device.o diseqc.o dvbdevice.o d
skinclassic.o skins.o skinsttng.o sources.o spu.o status.o svdrp.o themes.o thread.o\ skinclassic.o skins.o skinsttng.o sources.o spu.o status.o svdrp.o themes.o thread.o\
timers.o tools.o transfer.o vdr.o videodir.o timers.o tools.o transfer.o vdr.o videodir.o
FIXFONT_ISO8859_1 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-1
OSDFONT_ISO8859_1 = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1
SMLFONT_ISO8859_1 = -adobe-helvetica-medium-r-normal--18-*-100-100-p-*-iso8859-1
FIXFONT_ISO8859_2 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-2
OSDFONT_ISO8859_2 = -adobe-helvetica-medium-r-normal--24-*-75-75-p-*-iso8859-2
SMLFONT_ISO8859_2 = -adobe-helvetica-medium-r-normal--18-*-75-75-p-*-iso8859-2
FIXFONT_ISO8859_5 = -rfx-courier-bold-r-normal--24-*-75-75-m-*-iso8859-5
OSDFONT_ISO8859_5 = -rfx-helvetica-medium-r-normal--24-*-75-75-p-*-iso8859-5
SMLFONT_ISO8859_5 = -rfx-helvetica-medium-r-normal--18-*-75-75-p-*-iso8859-5
FIXFONT_ISO8859_7 = --user-medium-r-normal--26-171-110-110-m-140-iso8859-7
OSDFONT_ISO8859_7 = --user-medium-r-normal--23-179-85-85-m-120-iso8859-7
SMLFONT_ISO8859_7 = --user-medium-r-normal--19-160-72-72-m-110-iso8859-7
FIXFONT_ISO8859_9 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-9
OSDFONT_ISO8859_9 = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-9
SMLFONT_ISO8859_9 = -adobe-helvetica-medium-r-normal--18-*-100-100-p-*-iso8859-9
FIXFONT_ISO8859_13 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-13
OSDFONT_ISO8859_13 = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-13
SMLFONT_ISO8859_13 = -adobe-helvetica-medium-r-normal--18-*-100-100-p-*-iso8859-13
FIXFONT_ISO8859_15 = -adobe-courier-bold-r-normal--25-*-100-100-m-*-iso8859-15
OSDFONT_ISO8859_15 = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-15
SMLFONT_ISO8859_15 = -adobe-helvetica-medium-r-normal--18-*-100-100-p-*-iso8859-15
ifndef NO_KBD ifndef NO_KBD
DEFINES += -DREMOTE_KBD DEFINES += -DREMOTE_KBD
endif endif
@ -98,15 +70,6 @@ DEFINES += -DVFAT
endif endif
all: vdr all: vdr
font: genfontfile\
fontfix-iso8859-1.c fontosd-iso8859-1.c fontsml-iso8859-1.c\
fontfix-iso8859-2.c fontosd-iso8859-2.c fontsml-iso8859-2.c\
fontfix-iso8859-5.c fontosd-iso8859-5.c fontsml-iso8859-5.c\
fontfix-iso8859-7.c fontosd-iso8859-7.c fontsml-iso8859-7.c\
fontfix-iso8859-9.c fontosd-iso8859-9.c fontsml-iso8859-9.c\
fontfix-iso8859-13.c fontosd-iso8859-13.c fontsml-iso8859-13.c\
fontfix-iso8859-15.c fontosd-iso8859-15.c fontsml-iso8859-15.c
@echo "font files created."
# Implicit rules: # Implicit rules:
@ -127,62 +90,6 @@ $(DEPFILE): Makefile
vdr: $(OBJS) $(SILIB) vdr: $(OBJS) $(SILIB)
$(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(NCURSESLIB) $(LIBS) $(LIBDIRS) $(SILIB) -o vdr $(CXX) $(CXXFLAGS) -rdynamic $(OBJS) $(NCURSESLIB) $(LIBS) $(LIBDIRS) $(SILIB) -o vdr
# The font files:
fontfix-iso8859-1.c:
./genfontfile "cFont::tPixelData FontFix_iso8859_1" "$(FIXFONT_ISO8859_1)" > $@
fontosd-iso8859-1.c:
./genfontfile "cFont::tPixelData FontOsd_iso8859_1" "$(OSDFONT_ISO8859_1)" > $@
fontsml-iso8859-1.c:
./genfontfile "cFont::tPixelData FontSml_iso8859_1" "$(SMLFONT_ISO8859_1)" > $@
fontfix-iso8859-2.c:
./genfontfile "cFont::tPixelData FontFix_iso8859_2" "$(FIXFONT_ISO8859_2)" > $@
fontosd-iso8859-2.c:
./genfontfile "cFont::tPixelData FontOsd_iso8859_2" "$(OSDFONT_ISO8859_2)" > $@
fontsml-iso8859-2.c:
./genfontfile "cFont::tPixelData FontSml_iso8859_2" "$(SMLFONT_ISO8859_2)" > $@
fontfix-iso8859-5.c:
./genfontfile "cFont::tPixelData FontFix_iso8859_5" "$(FIXFONT_ISO8859_5)" > $@
fontosd-iso8859-5.c:
./genfontfile "cFont::tPixelData FontOsd_iso8859_5" "$(OSDFONT_ISO8859_5)" > $@
fontsml-iso8859-5.c:
./genfontfile "cFont::tPixelData FontSml_iso8859_5" "$(SMLFONT_ISO8859_5)" > $@
fontfix-iso8859-7.c:
./genfontfile "cFont::tPixelData FontFix_iso8859_7" "$(FIXFONT_ISO8859_7)" > $@
fontosd-iso8859-7.c:
./genfontfile "cFont::tPixelData FontOsd_iso8859_7" "$(OSDFONT_ISO8859_7)" > $@
fontsml-iso8859-7.c:
./genfontfile "cFont::tPixelData FontSml_iso8859_7" "$(SMLFONT_ISO8859_7)" > $@
fontfix-iso8859-9.c:
./genfontfile "cFont::tPixelData FontFix_iso8859_9" "$(FIXFONT_ISO8859_9)" > $@
fontosd-iso8859-9.c:
./genfontfile "cFont::tPixelData FontOsd_iso8859_9" "$(OSDFONT_ISO8859_9)" > $@
fontsml-iso8859-9.c:
./genfontfile "cFont::tPixelData FontSml_iso8859_9" "$(SMLFONT_ISO8859_9)" > $@
fontfix-iso8859-13.c:
./genfontfile "cFont::tPixelData FontFix_iso8859_13" "$(FIXFONT_ISO8859_13)" > $@
fontosd-iso8859-13.c:
./genfontfile "cFont::tPixelData FontOsd_iso8859_13" "$(OSDFONT_ISO8859_13)" > $@
fontsml-iso8859-13.c:
./genfontfile "cFont::tPixelData FontSml_iso8859_13" "$(SMLFONT_ISO8859_13)" > $@
fontfix-iso8859-15.c:
./genfontfile "cFont::tPixelData FontFix_iso8859_15" "$(FIXFONT_ISO8859_15)" > $@
fontosd-iso8859-15.c:
./genfontfile "cFont::tPixelData FontOsd_iso8859_15" "$(OSDFONT_ISO8859_15)" > $@
fontsml-iso8859-15.c:
./genfontfile "cFont::tPixelData FontSml_iso8859_15" "$(SMLFONT_ISO8859_15)" > $@
# The font file generator:
genfontfile: genfontfile.c
$(CC) $(CFLAGS) -o $@ -L/usr/X11R6/lib $< -lX11
# The libsi library: # The libsi library:
$(SILIB): $(SILIB):
@ -261,10 +168,8 @@ srcdoc:
clean: clean:
$(MAKE) -C $(LSIDIR) clean $(MAKE) -C $(LSIDIR) clean
-rm -f $(OBJS) $(DEPFILE) vdr genfontfile genfontfile.o core* *~ -rm -f $(OBJS) $(DEPFILE) vdr core* *~
-rm -rf include -rm -rf include
-rm -rf srcdoc -rm -rf srcdoc
fontclean: CLEAN: clean
-rm -f fontfix*.c fontosd*.c fontsml*.c
CLEAN: clean fontclean

View File

@ -6,7 +6,7 @@
<center><h1>The VDR Plugin System</h1></center> <center><h1>The VDR Plugin System</h1></center>
<center><b>Version 1.5.1</b></center> <center><b>Version 1.5.3</b></center>
<p> <p>
<center> <center>
Copyright &copy; 2006 Klaus Schmidinger<br> Copyright &copy; 2006 Klaus Schmidinger<br>
@ -14,12 +14,15 @@ Copyright &copy; 2006 Klaus Schmidinger<br>
<a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a> <a href="http://www.cadsoft.de/vdr">www.cadsoft.de/vdr</a>
</center> </center>
<p> <p>
<!--X1.5.0--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%> <!--X1.5.0--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.5.0 are marked like this. Important modifications introduced in version 1.5.0 are marked like this.
<!--X1.5.0--></td></tr></table> <!--X1.5.0--></td></tr></table>
<!--X1.5.1--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.5.1--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.5.1 are marked like this. Important modifications introduced in version 1.5.1 are marked like this.
<!--X1.5.1--></td></tr></table> <!--X1.5.1--></td></tr></table>
<!--X1.5.3--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
Important modifications introduced in version 1.5.3 are marked like this.
<!--X1.5.3--></td></tr></table>
<p> <p>
VDR provides an easy to use plugin interface that allows additional functionality VDR provides an easy to use plugin interface that allows additional functionality
to be added to the program by implementing a dynamically loadable library file. to be added to the program by implementing a dynamically loadable library file.
@ -58,7 +61,7 @@ structures and allows it to hook itself into specific areas to perform special a
<li><a href="#Housekeeping">Housekeeping</a> <li><a href="#Housekeeping">Housekeeping</a>
<li><a href="#Main thread hook">Main thread hook</a> <li><a href="#Main thread hook">Main thread hook</a>
<li><a href="#Activity">Activity</a> <li><a href="#Activity">Activity</a>
<!--X1.5.1--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.5.1--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
<li><a href="#Wakeup">Wakeup</a> <li><a href="#Wakeup">Wakeup</a>
<!--X1.5.1--></td></tr></table> <!--X1.5.1--></td></tr></table>
<li><a href="#Setup parameters">Setup parameters</a> <li><a href="#Setup parameters">Setup parameters</a>
@ -82,7 +85,7 @@ structures and allows it to hook itself into specific areas to perform special a
<li><a href="#Devices">Devices</a> <li><a href="#Devices">Devices</a>
<li><a href="#Audio">Audio</a> <li><a href="#Audio">Audio</a>
<li><a href="#Remote Control">Remote Control</a> <li><a href="#Remote Control">Remote Control</a>
<!--X1.5.0--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%> <!--X1.5.0--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
<li><a href="#Conditional Access">Conditional Access</a> <li><a href="#Conditional Access">Conditional Access</a>
<!--X1.5.0--></td></tr></table> <!--X1.5.0--></td></tr></table>
</ul> </ul>
@ -681,7 +684,7 @@ be queried, and further prompts may show up. If all prompts have been confirmed,
the shutdown will take place. As soon as one prompt is not confirmed, no the shutdown will take place. As soon as one prompt is not confirmed, no
further plugins will be queried and no shutdown will be done. further plugins will be queried and no shutdown will be done.
<!--X1.5.1--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%> <!--X1.5.1--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%>
<a name="Wakeup"><hr><h2>Wakeup</h2> <a name="Wakeup"><hr><h2>Wakeup</h2>
<center><i><b>Wake me up before you go-go</b></i></center><p> <center><i><b>Wake me up before you go-go</b></i></center><p>
@ -970,6 +973,19 @@ written to the log file, indicating that a translation is missing.
Texts are first searched for in the <i>Phrases</i> registered for this plugin (if any) Texts are first searched for in the <i>Phrases</i> registered for this plugin (if any)
and then in the global VDR texts. So a plugin can make use of texts defined by the and then in the global VDR texts. So a plugin can make use of texts defined by the
core VDR code. core VDR code.
<p>
<!--X1.5.3--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
The system VDR is running on may use a character encoding where a single character
(or <i>symbol</i>) consists of more than one byte (UTF-8, as opposed to, for instance,
ISO8859-1, where every character is represented by a single byte in memory).
In order to make sure a plugin works regardless of the character encoding the current
system uses, the VDR core code provides several functions and macros that allow accessing
text strings transparently without knowing whether this is a single or multi byte
character set. The names of these functions and macros are all of the form <tt>Utf8...()</tt>,
and are defined in <tt>VDR/tools.h</tt>.
Most of the time a plugin doesn't need to care about this, but when it comes to
handling individual characters these functions may come in handy.
<!--X1.5.3--></td></tr></table>
<a name="Custom services"><hr><h2>Custom services</h2> <a name="Custom services"><hr><h2>Custom services</h2>
@ -1618,7 +1634,22 @@ Note that a plugin should always at first request a single drawing area
with the full required resolution. Only if this fails shall it use alternate with the full required resolution. Only if this fails shall it use alternate
areas. Drawing areas are always rectangular and may not overlap (but do not need areas. Drawing areas are always rectangular and may not overlap (but do not need
to be adjacent). to be adjacent).
<p>
<!--X1.5.3--><table width=100%><tr><td bgcolor=#FF0000>&nbsp;</td><td width=100%>
Special consideration may have to be given to color usage if the OSD provides
8bpp (256 colors). In that case, fonts may be drawn using <i>anti-aliasing</i>,
which requires several blended color values between the foreground and background
color. In order to not use up the whole color palette for a single color
combination (and thus be unable to draw any other colors at all), it may be
useful to call
<p><table><tr><td bgcolor=#F0F0F0><pre>
osd-&gt;SetAntiAliasGranularity();
</pre></td></tr></table><p>
which allows the system to evenly distribute the palette entries to the various
color combinations (see <tt>VDR/osd.h</tt> for details).
<!--X1.5.3--></td></tr></table>
<p> <p>
Directly accessing the OSD is only allowed from the foreground thread, which Directly accessing the OSD is only allowed from the foreground thread, which
restricts this to a <tt>cOsdObject</tt> returned from the plugin's <tt>MainMenuAction()</tt> restricts this to a <tt>cOsdObject</tt> returned from the plugin's <tt>MainMenuAction()</tt>
@ -2087,7 +2118,7 @@ Put(uint64 Code, bool Repeat = false, bool Release = false);
The other parameters have the same meaning as in the first version of this function. The other parameters have the same meaning as in the first version of this function.
<!--X1.5.0--><table width=100%><tr><td bgcolor=#AA0000>&nbsp;</td><td width=100%> <!--X1.5.0--><table width=100%><tr><td bgcolor=#00AA00>&nbsp;</td><td width=100%>
<a name="Conditional Access"><hr><h2>Conditional Access</h2> <a name="Conditional Access"><hr><h2>Conditional Access</h2>
<center><i><b>Members only!</b></i></center><p> <center><i><b>Members only!</b></i></center><p>

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.c 1.150 2007/02/25 13:58:45 kls Exp $ * $Id: config.c 1.151 2007/06/02 11:21:40 kls Exp $
*/ */
#include "config.h" #include "config.h"
@ -264,6 +264,13 @@ cSetup::cSetup(void)
OSDHeight = 486; OSDHeight = 486;
OSDMessageTime = 1; OSDMessageTime = 1;
UseSmallFont = 1; UseSmallFont = 1;
AntiAlias = 1;
strcpy(FontOsd, "arialbd.ttf");
strcpy(FontSml, "arial.ttf");
strcpy(FontFix, "courbd.ttf");
FontOsdSize = 22;
FontSmlSize = 18;
FontFixSize = 20;
MaxVideoFileSize = MAXVIDEOFILESIZE; MaxVideoFileSize = MAXVIDEOFILESIZE;
SplitEditedFiles = 0; SplitEditedFiles = 0;
MinEventTimeout = 30; MinEventTimeout = 30;
@ -427,6 +434,13 @@ bool cSetup::Parse(const char *Name, const char *Value)
else if (!strcasecmp(Name, "OSDHeight")) { OSDHeight = atoi(Value); if (OSDHeight < 100) OSDHeight *= 27; } else if (!strcasecmp(Name, "OSDHeight")) { OSDHeight = atoi(Value); if (OSDHeight < 100) OSDHeight *= 27; }
else if (!strcasecmp(Name, "OSDMessageTime")) OSDMessageTime = atoi(Value); else if (!strcasecmp(Name, "OSDMessageTime")) OSDMessageTime = atoi(Value);
else if (!strcasecmp(Name, "UseSmallFont")) UseSmallFont = atoi(Value); else if (!strcasecmp(Name, "UseSmallFont")) UseSmallFont = atoi(Value);
else if (!strcasecmp(Name, "AntiAlias")) AntiAlias = atoi(Value);
else if (!strcasecmp(Name, "FontOsd")) strn0cpy(FontOsd, Value, MAXFONTNAME);
else if (!strcasecmp(Name, "FontSml")) strn0cpy(FontSml, Value, MAXFONTNAME);
else if (!strcasecmp(Name, "FontFix")) strn0cpy(FontFix, Value, MAXFONTNAME);
else if (!strcasecmp(Name, "FontOsdSize")) FontOsdSize = atoi(Value);
else if (!strcasecmp(Name, "FontSmlSize")) FontSmlSize = atoi(Value);
else if (!strcasecmp(Name, "FontFixSize")) FontFixSize = atoi(Value);
else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value); else if (!strcasecmp(Name, "MaxVideoFileSize")) MaxVideoFileSize = atoi(Value);
else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value); else if (!strcasecmp(Name, "SplitEditedFiles")) SplitEditedFiles = atoi(Value);
else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value); else if (!strcasecmp(Name, "MinEventTimeout")) MinEventTimeout = atoi(Value);
@ -497,6 +511,13 @@ bool cSetup::Save(void)
Store("OSDHeight", OSDHeight); Store("OSDHeight", OSDHeight);
Store("OSDMessageTime", OSDMessageTime); Store("OSDMessageTime", OSDMessageTime);
Store("UseSmallFont", UseSmallFont); Store("UseSmallFont", UseSmallFont);
Store("AntiAlias", AntiAlias);
Store("FontOsd", FontOsd);
Store("FontSml", FontSml);
Store("FontFix", FontFix);
Store("FontOsdSize", FontOsdSize);
Store("FontSmlSize", FontSmlSize);
Store("FontFixSize", FontFixSize);
Store("MaxVideoFileSize", MaxVideoFileSize); Store("MaxVideoFileSize", MaxVideoFileSize);
Store("SplitEditedFiles", SplitEditedFiles); Store("SplitEditedFiles", SplitEditedFiles);
Store("MinEventTimeout", MinEventTimeout); Store("MinEventTimeout", MinEventTimeout);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: config.h 1.289 2007/04/28 14:47:24 kls Exp $ * $Id: config.h 1.290 2007/06/02 11:22:17 kls Exp $
*/ */
#ifndef __CONFIG_H #ifndef __CONFIG_H
@ -17,6 +17,7 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "i18n.h" #include "i18n.h"
#include "font.h"
#include "tools.h" #include "tools.h"
// VDR's own version number: // VDR's own version number:
@ -242,6 +243,13 @@ public:
int OSDLeft, OSDTop, OSDWidth, OSDHeight; int OSDLeft, OSDTop, OSDWidth, OSDHeight;
int OSDMessageTime; int OSDMessageTime;
int UseSmallFont; int UseSmallFont;
int AntiAlias;
char FontOsd[MAXFONTNAME];
char FontSml[MAXFONTNAME];
char FontFix[MAXFONTNAME];
int FontOsdSize;
int FontSmlSize;
int FontFixSize;
int MaxVideoFileSize; int MaxVideoFileSize;
int SplitEditedFiles; int SplitEditedFiles;
int MinEventTimeout, MinUserInactivity; int MinEventTimeout, MinUserInactivity;

9
eit.c
View File

@ -8,7 +8,7 @@
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
* Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>. * Adapted to 'libsi' for VDR 1.3.0 by Marcel Wiesweg <marcel.wiesweg@gmx.de>.
* *
* $Id: eit.c 1.122 2006/10/09 16:14:36 kls Exp $ * $Id: eit.c 1.123 2007/06/10 12:51:05 kls Exp $
*/ */
#include "eit.h" #include "eit.h"
@ -188,6 +188,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo
if (hit) { if (hit) {
char linkName[ld->privateData.getLength() + 1]; char linkName[ld->privateData.getLength() + 1];
strn0cpy(linkName, (const char *)ld->privateData.getData(), sizeof(linkName)); strn0cpy(linkName, (const char *)ld->privateData.getData(), sizeof(linkName));
// TODO is there a standard way to determine the character set of this string?
cChannel *link = Channels.GetByChannelID(linkID); cChannel *link = Channels.GetByChannelID(linkID);
if (link != channel) { // only link to other channels, not the same one if (link != channel) { // only link to other channels, not the same one
//fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d %02X '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX //fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d %02X '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX
@ -218,7 +219,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo
if (1 <= Stream && Stream <= 2 && Type != 0) { if (1 <= Stream && Stream <= 2 && Type != 0) {
if (!Components) if (!Components)
Components = new cComponents; Components = new cComponents;
char buffer[256]; char buffer[Utf8BufSize(256)];
Components->SetComponent(Components->NumComponents(), cd->getStreamContent(), cd->getComponentType(), I18nNormalizeLanguageCode(cd->languageCode), cd->description.getText(buffer, sizeof(buffer))); Components->SetComponent(Components->NumComponents(), cd->getStreamContent(), cd->getComponentType(), I18nNormalizeLanguageCode(cd->languageCode), cd->description.getText(buffer, sizeof(buffer)));
} }
} }
@ -230,7 +231,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo
if (!rEvent) { if (!rEvent) {
if (ShortEventDescriptor) { if (ShortEventDescriptor) {
char buffer[256]; char buffer[Utf8BufSize(256)];
pEvent->SetTitle(ShortEventDescriptor->name.getText(buffer, sizeof(buffer))); pEvent->SetTitle(ShortEventDescriptor->name.getText(buffer, sizeof(buffer)));
pEvent->SetShortText(ShortEventDescriptor->text.getText(buffer, sizeof(buffer))); pEvent->SetShortText(ShortEventDescriptor->text.getText(buffer, sizeof(buffer)));
} }
@ -239,7 +240,7 @@ cEIT::cEIT(cSchedules *Schedules, int Source, u_char Tid, const u_char *Data, bo
pEvent->SetShortText(NULL); pEvent->SetShortText(NULL);
} }
if (ExtendedEventDescriptors) { if (ExtendedEventDescriptors) {
char buffer[ExtendedEventDescriptors->getMaximumTextLength(": ") + 1]; char buffer[Utf8BufSize(ExtendedEventDescriptors->getMaximumTextLength(": ")) + 1];
pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": ")); pEvent->SetDescription(ExtendedEventDescriptors->getText(buffer, sizeof(buffer), ": "));
} }
else if (!HasExternalData) else if (!HasExternalData)

4
epg.c
View File

@ -7,7 +7,7 @@
* Original version (as used in VDR before 1.3.0) written by * Original version (as used in VDR before 1.3.0) written by
* Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>. * Robert Schneider <Robert.Schneider@web.de> and Rolf Hakenes <hakenes@hippomi.de>.
* *
* $Id: epg.c 1.81 2006/10/28 09:12:42 kls Exp $ * $Id: epg.c 1.82 2007/06/10 12:52:19 kls Exp $
*/ */
#include "epg.h" #include "epg.h"
@ -634,6 +634,7 @@ Final:
// data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel): // data, so let's always convert them to blanks (independent of the setting of EPGBugfixLevel):
strreplace(title, '\n', ' '); strreplace(title, '\n', ' ');
strreplace(shortText, '\n', ' '); strreplace(shortText, '\n', ' ');
/* TODO adapt to UTF-8
// Same for control characters: // Same for control characters:
strreplace(title, '\x86', ' '); strreplace(title, '\x86', ' ');
strreplace(title, '\x87', ' '); strreplace(title, '\x87', ' ');
@ -641,6 +642,7 @@ Final:
strreplace(shortText, '\x87', ' '); strreplace(shortText, '\x87', ' ');
strreplace(description, '\x86', ' '); strreplace(description, '\x86', ' ');
strreplace(description, '\x87', ' '); strreplace(description, '\x87', ' ');
XXX*/
} }
// --- cSchedule ------------------------------------------------------------- // --- cSchedule -------------------------------------------------------------

362
font.c
View File

@ -4,125 +4,296 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: font.c 1.14 2007/03/11 09:51:44 kls Exp $ * $Id: font.c 1.15 2007/06/09 14:41:27 kls Exp $
*/ */
#include "config.h"
#include <ctype.h>
#include "font.h" #include "font.h"
#include <ctype.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "config.h"
#include "osd.h"
#include "tools.h" #include "tools.h"
#include "fontfix-iso8859-1.c" // --- cFreetypeFont ---------------------------------------------------------
#include "fontosd-iso8859-1.c"
#include "fontsml-iso8859-1.c"
#include "fontfix-iso8859-2.c" #define KERNING_UNKNOWN (-10000)
#include "fontosd-iso8859-2.c"
#include "fontsml-iso8859-2.c"
#include "fontfix-iso8859-5.c" struct tKerning {
#include "fontosd-iso8859-5.c" uint prevSym;
#include "fontsml-iso8859-5.c" int kerning;
tKerning(uint PrevSym, int Kerning) { prevSym = PrevSym; kerning = Kerning; }
#include "fontfix-iso8859-7.c"
#include "fontosd-iso8859-7.c"
#include "fontsml-iso8859-7.c"
#include "fontfix-iso8859-9.c"
#include "fontosd-iso8859-9.c"
#include "fontsml-iso8859-9.c"
#include "fontfix-iso8859-13.c"
#include "fontosd-iso8859-13.c"
#include "fontsml-iso8859-13.c"
#include "fontfix-iso8859-15.c"
#include "fontosd-iso8859-15.c"
#include "fontsml-iso8859-15.c"
// --- cFont -----------------------------------------------------------------
static const void *const FontData[eDvbCodeSize][eDvbFontSize] = {
{ FontOsd_iso8859_1, FontFix_iso8859_1, FontSml_iso8859_1 },
{ FontOsd_iso8859_2, FontFix_iso8859_2, FontSml_iso8859_2 },
{ FontOsd_iso8859_5, FontFix_iso8859_5, FontSml_iso8859_5 },
{ FontOsd_iso8859_7, FontFix_iso8859_7, FontSml_iso8859_7 },
{ FontOsd_iso8859_9, FontFix_iso8859_9, FontSml_iso8859_9 },
{ FontOsd_iso8859_13, FontFix_iso8859_13, FontSml_iso8859_13 },
{ FontOsd_iso8859_15, FontFix_iso8859_15, FontSml_iso8859_15 },
}; };
static const char *FontCode[eDvbCodeSize] = { class cGlyph : public cListObject {
"iso8859-1", private:
"iso8859-2", uint charCode;
"iso8859-5", uchar *bitmap;
"iso8859-7", int advanceX;
"iso8859-9", int advanceY;
"iso8859-13", int left; ///< The bitmap's left bearing expressed in integer pixels.
"iso8859-15", int top; ///< The bitmap's top bearing expressed in integer pixels.
int width; ///< The number of pixels per bitmap row.
int rows; ///< The number of bitmap rows.
int pitch; ///< The pitch's absolute value is the number of bytes taken by one bitmap row, including padding.
cVector<tKerning> kerningCache;
public:
cGlyph(uint CharCode, FT_GlyphSlotRec_ *GlyphData);
virtual ~cGlyph();
uint CharCode(void) const { return charCode; }
uchar *Bitmap(void) const { return bitmap; }
int AdvanceX(void) const { return advanceX; }
int AdvanceY(void) const { return advanceY; }
int Left(void) const { return left; }
int Top(void) const { return top; }
int Width(void) const { return width; }
int Rows(void) const { return rows; }
int Pitch(void) const { return pitch; }
int GetKerningCache(uint PrevSym) const;
void SetKerningCache(uint PrevSym, int Kerning);
}; };
eDvbCode cFont::code = code_iso8859_1; cGlyph::cGlyph(uint CharCode, FT_GlyphSlotRec_ *GlyphData)
cFont *cFont::fonts[eDvbFontSize] = { NULL };
cFont::cFont(const void *Data)
{ {
SetData(Data); charCode = CharCode;
advanceX = GlyphData->advance.x >> 6;
advanceY = GlyphData->advance.y >> 6;
left = GlyphData->bitmap_left;
top = GlyphData->bitmap_top;
width = GlyphData->bitmap.width;
rows = GlyphData->bitmap.rows;
pitch = GlyphData->bitmap.pitch;
bitmap = MALLOC(uchar, rows * pitch);
memcpy(bitmap, GlyphData->bitmap.buffer, rows * pitch);
} }
void cFont::SetData(const void *Data) cGlyph::~cGlyph()
{ {
if (Data) { free(bitmap);
height = ((tCharData *)Data)->height; }
for (int i = 0; i < NUMCHARS; i++)
data[i] = (tCharData *)&((tPixelData *)Data)[(i < 32 ? 0 : i - 32) * (height + 2)]; int cGlyph::GetKerningCache(uint PrevSym) const
{
for (int i = kerningCache.Size(); --i > 0; ) {
if (kerningCache[i].prevSym == PrevSym)
return kerningCache[i].kerning;
}
return KERNING_UNKNOWN;
}
void cGlyph::SetKerningCache(uint PrevSym, int Kerning)
{
kerningCache.Append(tKerning(PrevSym, Kerning));
}
class cFreetypeFont : public cFont {
private:
int height;
int bottom;
FT_Library library; ///< Handle to library
FT_Face face; ///< Handle to face object
mutable cList<cGlyph> glyphCacheMonochrome;
mutable cList<cGlyph> glyphCacheAntiAliased;
int Bottom(void) const { return bottom; }
int Kerning(cGlyph *Glyph, uint PrevSym) const;
cGlyph* Glyph(uint CharCode, bool AntiAliased = false) const;
public:
cFreetypeFont(const char *Name, int CharHeight);
virtual ~cFreetypeFont();
virtual int Width(uint c) const;
virtual int Width(const char *s) const;
virtual int Height(void) const { return height; }
virtual void DrawText(cBitmap *Bitmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const;
};
cFreetypeFont::cFreetypeFont(const char *Name, int CharHeight)
{
height = 0;
bottom = 0;
int error = FT_Init_FreeType(&library);
if (!error) {
error = FT_New_Face(library, Name, 0, &face);
if (!error) {
if (face->num_fixed_sizes && face->available_sizes) { // fixed font
// TODO what exactly does all this mean?
height = face->available_sizes->height;
for (uint sym ='A'; sym < 'z'; sym++) { // search for descender for fixed font FIXME
FT_UInt glyph_index = FT_Get_Char_Index(face, sym);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (!error) {
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
if (!error) {
if (face->glyph->bitmap.rows-face->glyph->bitmap_top > bottom)
bottom = face->glyph->bitmap.rows-face->glyph->bitmap_top;
} }
else else
height = 0; esyslog("ERROR: FreeType: error %d in FT_Render_Glyph", error);
}
else
esyslog("ERROR: FreeType: error %d in FT_Load_Glyph", error);
}
}
else {
error = FT_Set_Char_Size(face, // handle to face object
0, // char_width in 1/64th of points
CharHeight * 64, // CharHeight in 1/64th of points
0, // horizontal device resolution
0); // vertical device resolution
if (!error) {
height = ((face->size->metrics.ascender-face->size->metrics.descender) + 63) / 64;
bottom = abs((face->size->metrics.descender - 63) / 64);
}
else
esyslog("ERROR: FreeType: error %d during FT_Set_Char_Size (font = %s)\n", error, Name);
}
}
else
esyslog("ERROR: FreeType: load error %d (font = %s)", error, Name);
}
else
esyslog("ERROR: FreeType: initialization error %d (font = %s)", error, Name);
} }
int cFont::Width(const char *s) const cFreetypeFont::~cFreetypeFont()
{
FT_Done_Face(face);
FT_Done_FreeType(library);
}
int cFreetypeFont::Kerning(cGlyph *Glyph, uint PrevSym) const
{
int kerning = 0;
if (Glyph && PrevSym) {
kerning = Glyph->GetKerningCache(PrevSym);
if (kerning == KERNING_UNKNOWN) {
FT_Vector delta;
FT_UInt glyph_index = FT_Get_Char_Index(face, Glyph->CharCode());
FT_UInt glyph_index_prev = FT_Get_Char_Index(face, PrevSym);
FT_Get_Kerning(face, glyph_index_prev, glyph_index, FT_KERNING_DEFAULT, &delta);
kerning = delta.x / 64;
Glyph->SetKerningCache(PrevSym, kerning);
}
}
return kerning;
}
cGlyph* cFreetypeFont::Glyph(uint CharCode, bool AntiAliased) const
{
// Lookup in cache:
cList<cGlyph> *glyphCache = AntiAliased ? &glyphCacheAntiAliased : &glyphCacheMonochrome;
for (cGlyph *g = glyphCache->First(); g; g = glyphCache->Next(g)) {
if (g->CharCode() == CharCode)
return g;
}
FT_UInt glyph_index = FT_Get_Char_Index(face, CharCode);
// Load glyph image into the slot (erase previous one):
int error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error)
esyslog("ERROR: FreeType: error during FT_Load_Glyph");
else {
#if ((FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 7) || (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 2 && FREETYPE_PATCH <= 1))// TODO workaround for bug? which one?
if (AntiAliased || CharCode == 32)
#else
if (AntiAliased)
#endif
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL);
else
error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_MONO);
if (error)
esyslog("ERROR: FreeType: error during FT_Render_Glyph %d, %d\n", CharCode, glyph_index);
else { //new bitmap
cGlyph *Glyph = new cGlyph(CharCode, face->glyph);
glyphCache->Add(Glyph);
return Glyph;
}
}
return NULL;
}
int cFreetypeFont::Width(uint c) const
{
cGlyph *g = Glyph(c, Setup.AntiAlias);
return g ? g->AdvanceX() : 0;
}
int cFreetypeFont::Width(const char *s) const
{ {
int w = 0; int w = 0;
while (s && *s) if (s) {
w += Width(*s++); uint prevSym = 0;
while (*s) {
int sl = Utf8CharLen(s);
uint sym = Utf8CharGet(s, sl);
s += sl;
cGlyph *g = Glyph(sym, Setup.AntiAlias);
if (g)
w += g->AdvanceX() + Kerning(g, prevSym);
prevSym = sym;
}
}
return w; return w;
} }
int cFont::Height(const char *s) const void cFreetypeFont::DrawText(cBitmap *Bitmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const
{ {
int h = 0; if (s && height) { // checking height to make sure we actually have a valid font
if (s && *s) bool AntiAliased = Setup.AntiAlias && Bitmap->Bpp() >= 8;
h = height; // all characters have the same height! tIndex fg = Bitmap->Index(ColorFg);
return h; uint prevSym = 0;
} while (*s) {
int sl = Utf8CharLen(s);
bool cFont::SetCode(const char *Code) uint sym = Utf8CharGet(s, sl);
{ s += sl;
for (int i = 0; i < eDvbCodeSize; i++) { cGlyph *g = Glyph(sym, AntiAliased);
if (strcmp(Code, FontCode[i]) == 0) { int kerning = Kerning(g, prevSym);
SetCode(eDvbCode(i)); prevSym = sym;
return true; uchar *buffer = g->Bitmap();
int symWidth = g->Width();
if (Width && x + symWidth + g->Left() + kerning - 1 > Width)
break; // we don't draw partial characters
if (x + symWidth + g->Left() + kerning > 0) {
for (int row = 0; row < g->Rows(); row++) {
for (int pitch = 0; pitch < g->Pitch(); pitch++) {
uchar bt = *(buffer + (row * g->Pitch() + pitch));
if (AntiAliased) {
if (bt > 0x00) {
int px = x + pitch + g->Left() + kerning;
int py = y + row + (height - Bottom() - g->Top());
if (bt == 0xFF)
Bitmap->SetIndex(px, py, fg);
else {
tColor bg = (ColorBg != clrTransparent) ? ColorBg : Bitmap->GetColor(px, py);
Bitmap->SetIndex(px, py, Bitmap->Index(Bitmap->Blend(ColorFg, bg, bt)));
} }
} }
return false; }
} else { //monochrome rendering
for (int col = 0; col < 8 && col + pitch * 8 <= symWidth; col++) {
void cFont::SetCode(eDvbCode Code) if (bt & 0x80)
{ Bitmap->SetIndex(x + col + pitch * 8 + g->Left() + kerning, y + row + (height - Bottom() - g->Top()), fg);
if (code != Code) { bt <<= 1;
code = Code; }
for (int i = 0; i < eDvbFontSize; i++) { }
if (fonts[i]) }
fonts[i]->SetData(FontData[code][i]); }
}
x += g->AdvanceX() + kerning;
if (x > Bitmap->Width() - 1)
break;
} }
} }
} }
void cFont::SetFont(eDvbFont Font, const void *Data) // --- cFont -----------------------------------------------------------------
cFont *cFont::fonts[eDvbFontSize] = { NULL };
void cFont::SetFont(eDvbFont Font, const char *Name, int CharHeight)
{ {
delete fonts[Font]; delete fonts[Font];
fonts[Font] = new cFont(Data ? Data : FontData[code][Font]); fonts[Font] = new cFreetypeFont(*Name == '/' ? Name : *AddDirectory(FONTDIR, Name), CharHeight);
} }
const cFont *cFont::GetFont(eDvbFont Font) const cFont *cFont::GetFont(eDvbFont Font)
@ -131,8 +302,13 @@ const cFont *cFont::GetFont(eDvbFont Font)
Font = fontOsd; Font = fontOsd;
else if (Setup.UseSmallFont == 2) else if (Setup.UseSmallFont == 2)
Font = fontSml; Font = fontSml;
if (!fonts[Font]) if (!fonts[Font]) {
SetFont(Font); switch (Font) {
case fontOsd: SetFont(Font, AddDirectory(FONTDIR, Setup.FontOsd), Setup.FontOsdSize); break;
case fontSml: SetFont(Font, AddDirectory(FONTDIR, Setup.FontSml), Setup.FontSmlSize); break;
case fontFix: SetFont(Font, AddDirectory(FONTDIR, Setup.FontFix), Setup.FontFixSize); break;
}
}
return fonts[Font]; return fonts[Font];
} }
@ -176,16 +352,18 @@ void cTextWrapper::Set(const char *Text, const cFont *Font, int Width)
stripspace(text); // strips trailing newlines stripspace(text); // strips trailing newlines
for (char *p = text; *p; ) { for (char *p = text; *p; ) {
if (*p == '\n') { int sl = Utf8CharLen(p);
uint sym = Utf8CharGet(p, sl);
if (sym == '\n') {
lines++; lines++;
w = 0; w = 0;
Blank = Delim = NULL; Blank = Delim = NULL;
p++; p++;
continue; continue;
} }
else if (isspace(*p)) else if (sl == 1 && isspace(sym))
Blank = p; Blank = p;
int cw = Font->Width(*p); int cw = Font->Width(sym);
if (w + cw > Width) { if (w + cw > Width) {
if (Blank) { if (Blank) {
*Blank = '\n'; *Blank = '\n';
@ -214,7 +392,7 @@ void cTextWrapper::Set(const char *Text, const cFont *Font, int Width)
Delim = p; Delim = p;
Blank = NULL; Blank = NULL;
} }
p++; p += sl;
} }
} }

64
font.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: font.h 1.15 2007/03/11 09:50:42 kls Exp $ * $Id: font.h 1.16 2007/06/10 12:58:54 kls Exp $
*/ */
#ifndef __FONT_H #ifndef __FONT_H
@ -13,6 +13,10 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#define MAXFONTNAME 64
#define MAXFONTSIZE 64
#define FONTDIR "/usr/share/fonts/truetype"
enum eDvbFont { enum eDvbFont {
fontOsd, fontOsd,
fontFix, fontFix,
@ -20,49 +24,35 @@ enum eDvbFont {
#define eDvbFontSize (fontSml + 1) #define eDvbFontSize (fontSml + 1)
}; };
enum eDvbCode { class cBitmap;
code_iso8859_1, typedef uint32_t tColor; // see also osd.h
code_iso8859_2, typedef uint8_t tIndex;
code_iso8859_5,
code_iso8859_7,
code_iso8859_9,
code_iso8859_13,
code_iso8859_15,
#define eDvbCodeSize (code_iso8859_15 + 1)
};
class cFont { class cFont {
public:
enum { NUMCHARS = 256 };
typedef uint32_t tPixelData;
struct tCharData {
tPixelData width, height;
tPixelData lines[1];
};
private: private:
static eDvbCode code;
static cFont *fonts[]; static cFont *fonts[];
const tCharData *data[NUMCHARS];
int height;
public: public:
cFont(const void *Data);
virtual ~cFont() {} virtual ~cFont() {}
void SetData(const void *Data); virtual int Width(uint c) const = 0;
virtual int Width(unsigned char c) const { return data[c]->width; } ///< Returns the width of the given character in pixel.
///< Returns the width of the given character. virtual int Width(const char *s) const = 0;
virtual int Width(const char *s) const; ///< Returns the width of the given string in pixel.
///< Returns the width of the given string. virtual int Height(void) const = 0;
virtual int Height(unsigned char c) const { return data[c]->height; } ///< Returns the height of this font in pixel (all characters have the same height).
///< Returns the height of the given character. int Height(const char *s) const { return Height(); }
virtual int Height(const char *s) const; ///< Returns the height of this font in pixel (obsolete, just for backwards compatibilty).
///< Returns the height of the given string. virtual void DrawText(cBitmap *Bitmap, int x, int y, const char *s, tColor ColorFg, tColor ColorBg, int Width) const = 0;
virtual int Height(void) const { return height; } ///< Draws the given text into the Bitmap at position (x, y) with the given colors.
///< Returns the height of this font (all characters have the same height). ///< The text will not exceed the given Width (if > 0), and will end with a complete character.
const tCharData *CharData(unsigned char c) const { return data[c]; } static void SetFont(eDvbFont Font, const char *Name, int CharHeight);
static bool SetCode(const char *Code); ///< Sets the given Font to use the font data from the file Name and make its characters
static void SetCode(eDvbCode Code); ///< CharHeight pixels high.
static void SetFont(eDvbFont Font, const void *Data = NULL);
static const cFont *GetFont(eDvbFont Font); static const cFont *GetFont(eDvbFont Font);
///< Gets the given Font, which was previously set by a call to SetFont().
///< If no SetFont() call has been made, the font as defined in the setup is returned.
///< The caller must not use the returned font outside the scope in which
///< it was retrieved by the call to GetFont(), because a call to SetFont()
///< may delete an existing font.
}; };
class cTextWrapper { class cTextWrapper {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,381 +0,0 @@
/* Copyright (c) Mark J. Kilgard, 1997. */
/* This program is freely distributable without licensing fees and is
provided without guarantee or warrantee expressed or implied. This
program is -not- in the public domain. */
/* X compile line: cc -o gentexfont gentexfont.c -lX11 */
/* 2000-10-01: Stripped down the original code to get a simple bitmap C-code generator */
/* for use with the VDR project (see http://www.cadsoft.de/vdr) */
/* Renamed the file 'genfontfile.c' since it no longer generates 'tex' data */
/* Klaus Schmidinger (kls@cadsoft.de) */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <math.h>
typedef struct {
unsigned short c; /* Potentially support 16-bit glyphs. */
unsigned char width;
unsigned char height;
signed char xoffset;
signed char yoffset;
signed char advance;
char dummy; /* Space holder for alignment reasons. */
short x;
short y;
} TexGlyphInfo;
typedef struct {
short width;
short height;
short xoffset;
short yoffset;
short advance;
unsigned char *bitmap;
} PerGlyphInfo, *PerGlyphInfoPtr;
typedef struct {
int min_char;
int max_char;
int max_ascent;
int max_descent;
PerGlyphInfo glyph[1];
} FontInfo, *FontInfoPtr;
Display *dpy;
FontInfoPtr fontinfo;
/* #define REPORT_GLYPHS */
#ifdef REPORT_GLYPHS
#define DEBUG_GLYPH4(msg,a,b,c,d) printf(msg,a,b,c,d)
#define DEBUG_GLYPH(msg) printf(msg)
#else
#define DEBUG_GLYPH4(msg,a,b,c,d) { /* nothing */ }
#define DEBUG_GLYPH(msg) { /* nothing */ }
#endif
#define MAX_GLYPHS_PER_GRAB 512 /* this is big enough for 2^9 glyph
character sets */
FontInfoPtr
SuckGlyphsFromServer(Display * dpy, Font font)
{
Pixmap offscreen;
XFontStruct *fontinfo;
XImage *image;
GC xgc;
XGCValues values;
int numchars;
int width, height, pixwidth;
int i, j;
XCharStruct *charinfo;
XChar2b character;
unsigned char *bitmapData;
int x, y;
int spanLength;
int charWidth, charHeight, maxSpanLength;
int grabList[MAX_GLYPHS_PER_GRAB];
int glyphsPerGrab = MAX_GLYPHS_PER_GRAB;
int numToGrab, thisglyph;
FontInfoPtr myfontinfo;
fontinfo = XQueryFont(dpy, font);
if (!fontinfo)
return NULL;
numchars = fontinfo->max_char_or_byte2 - fontinfo->min_char_or_byte2 + 1;
if (numchars < 1)
return NULL;
myfontinfo = (FontInfoPtr) malloc(sizeof(FontInfo) + (numchars - 1) * sizeof(PerGlyphInfo));
if (!myfontinfo)
return NULL;
myfontinfo->min_char = fontinfo->min_char_or_byte2;
myfontinfo->max_char = fontinfo->max_char_or_byte2;
myfontinfo->max_ascent = fontinfo->max_bounds.ascent;
myfontinfo->max_descent = fontinfo->max_bounds.descent;
width = fontinfo->max_bounds.rbearing - fontinfo->min_bounds.lbearing;
height = fontinfo->max_bounds.ascent + fontinfo->max_bounds.descent;
maxSpanLength = (width + 7) / 8;
/* Be careful determining the width of the pixmap; the X protocol allows
pixmaps of width 2^16-1 (unsigned short size) but drawing coordinates
max out at 2^15-1 (signed short size). If the width is too large, we
need to limit the glyphs per grab. */
if ((glyphsPerGrab * 8 * maxSpanLength) >= (1 << 15)) {
glyphsPerGrab = (1 << 15) / (8 * maxSpanLength);
}
pixwidth = glyphsPerGrab * 8 * maxSpanLength;
offscreen = XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)),
pixwidth, height, 1);
values.font = font;
values.background = 0;
values.foreground = 0;
xgc = XCreateGC(dpy, offscreen, GCFont | GCBackground | GCForeground, &values);
XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height);
XSetForeground(dpy, xgc, 1);
numToGrab = 0;
if (fontinfo->per_char == NULL) {
charinfo = &(fontinfo->min_bounds);
charWidth = charinfo->rbearing - charinfo->lbearing;
charHeight = charinfo->ascent + charinfo->descent;
spanLength = (charWidth + 7) / 8;
}
for (i = 0; i < numchars; i++) {
if (fontinfo->per_char != NULL) {
charinfo = &(fontinfo->per_char[i]);
charWidth = charinfo->rbearing - charinfo->lbearing;
charHeight = charinfo->ascent + charinfo->descent;
if (charWidth == 0 || charHeight == 0) {
/* Still must move raster pos even if empty character */
myfontinfo->glyph[i].width = 0;
myfontinfo->glyph[i].height = 0;
myfontinfo->glyph[i].xoffset = 0;
myfontinfo->glyph[i].yoffset = 0;
myfontinfo->glyph[i].advance = charinfo->width;
myfontinfo->glyph[i].bitmap = NULL;
goto PossiblyDoGrab;
}
}
grabList[numToGrab] = i;
/* XXX is this right for large fonts? */
character.byte2 = (i + fontinfo->min_char_or_byte2) & 255;
character.byte1 = (i + fontinfo->min_char_or_byte2) >> 8;
/* XXX we could use XDrawImageString16 which would also paint the backing
rectangle but X server bugs in some scalable font rasterizers makes it
more effective to do XFillRectangles to clear the pixmap and
XDrawImage16 for the text. */
XDrawString16(dpy, offscreen, xgc,
-charinfo->lbearing + 8 * maxSpanLength * numToGrab,
charinfo->ascent, &character, 1);
numToGrab++;
PossiblyDoGrab:
if (numToGrab >= glyphsPerGrab || i == numchars - 1) {
image = XGetImage(dpy, offscreen,
0, 0, pixwidth, height, 1, XYPixmap);
for (j = 0; j < numToGrab; j++) {
thisglyph = grabList[j];
if (fontinfo->per_char != NULL) {
charinfo = &(fontinfo->per_char[thisglyph]);
charWidth = charinfo->rbearing - charinfo->lbearing;
charHeight = charinfo->ascent + charinfo->descent;
spanLength = (charWidth + 7) / 8;
}
bitmapData = (unsigned char *)calloc(height * spanLength, sizeof(char));
if (!bitmapData)
goto FreeFontAndReturn;
DEBUG_GLYPH4("index %d, glyph %d (%d by %d)\n",
j, thisglyph + fontinfo->min_char_or_byte2, charWidth, charHeight);
for (y = 0; y < charHeight; y++) {
for (x = 0; x < charWidth; x++) {
/* XXX The algorithm used to suck across the font ensures that
each glyph begins on a byte boundary. In theory this would
make it convienent to copy the glyph into a byte oriented
bitmap. We actually use the XGetPixel function to extract
each pixel from the image which is not that efficient. We
could either do tighter packing in the pixmap or more
efficient extraction from the image. Oh well. */
if (XGetPixel(image, j * maxSpanLength * 8 + x, charHeight - 1 - y)) {
DEBUG_GLYPH("x");
bitmapData[y * spanLength + x / 8] |= (1 << (x & 7));
} else {
DEBUG_GLYPH(" ");
}
}
DEBUG_GLYPH("\n");
}
myfontinfo->glyph[thisglyph].width = charWidth;
myfontinfo->glyph[thisglyph].height = charHeight;
myfontinfo->glyph[thisglyph].xoffset = charinfo->lbearing;
myfontinfo->glyph[thisglyph].yoffset = -charinfo->descent;
myfontinfo->glyph[thisglyph].advance = charinfo->width;
myfontinfo->glyph[thisglyph].bitmap = bitmapData;
}
XDestroyImage(image);
numToGrab = 0;
/* do we need to clear the offscreen pixmap to get more? */
if (i < numchars - 1) {
XSetForeground(dpy, xgc, 0);
XFillRectangle(dpy, offscreen, xgc, 0, 0, 8 * maxSpanLength * glyphsPerGrab, height);
XSetForeground(dpy, xgc, 1);
}
}
}
XFreeGC(dpy, xgc);
XFreePixmap(dpy, offscreen);
return myfontinfo;
FreeFontAndReturn:
XDestroyImage(image);
XFreeGC(dpy, xgc);
XFreePixmap(dpy, offscreen);
for (j = i - 1; j >= 0; j--) {
if (myfontinfo->glyph[j].bitmap)
free(myfontinfo->glyph[j].bitmap);
}
free(myfontinfo);
return NULL;
}
void
printGlyph(FontInfoPtr font, int c)
{
PerGlyphInfoPtr glyph;
unsigned char *bitmapData;
int width, height, spanLength, charWidth;
int x, y, l;
char buf[1000], *b;
if (c < font->min_char || c > font->max_char) {
fprintf(stderr, "out of range glyph\n");
exit(1);
}
glyph = &font->glyph[c - font->min_char];
bitmapData = glyph->bitmap;
width = glyph->width;
spanLength = (width + 7) / 8;
height = glyph->height;
charWidth = glyph->xoffset + width;
if (charWidth < glyph->advance)
charWidth = glyph->advance;
printf(" { // %d\n", c);
printf(" %d, %d,\n", charWidth, font->max_ascent + font->max_descent);
for (y = 0; y < font->max_ascent - glyph->yoffset - height; y++) {
printf(" 0x%08X, // ", 0);
for (x = 0; x < charWidth; x++)
putchar('.');
putchar('\n');
}
for (y = height; y-- > 0;) {
l = 0;
b = buf;
for (x = 0; x < glyph->xoffset; x++)
*b++ = '.';
if (bitmapData) {
for (x = 0; x < width; x++) {
l <<= 1;
if (bitmapData[y * spanLength + x / 8] & (1 << (x & 7))) {
*b++ = '*';
l |= 1;
}
else
*b++ = '.';
}
for (x = 0; x < glyph->advance - width - glyph->xoffset; x++) {
*b++ = '.';
l <<= 1;
}
}
*b = 0;
printf(" 0x%08X, // %s\n", l, buf);
}
for (y = 0; y < font->max_descent + glyph->yoffset; y++) {
printf(" 0x%08X, // ", 0);
for (x = 0; x < glyph->xoffset + width || x < glyph->advance; x++)
putchar('.');
putchar('\n');
}
printf(" },\n");
}
void
getMetric(FontInfoPtr font, int c, TexGlyphInfo * tgi)
{
PerGlyphInfoPtr glyph;
unsigned char *bitmapData;
tgi->c = c;
if (c < font->min_char || c > font->max_char) {
tgi->width = 0;
tgi->height = 0;
tgi->xoffset = 0;
tgi->yoffset = 0;
tgi->dummy = 0;
tgi->advance = 0;
return;
}
glyph = &font->glyph[c - font->min_char];
bitmapData = glyph->bitmap;
if (bitmapData) {
tgi->width = glyph->width;
tgi->height = glyph->height;
tgi->xoffset = glyph->xoffset;
tgi->yoffset = glyph->yoffset;
} else {
tgi->width = 0;
tgi->height = 0;
tgi->xoffset = 0;
tgi->yoffset = 0;
}
tgi->dummy = 0;
tgi->advance = glyph->advance;
}
int
main(int argc, char *argv[])
{
int c;
TexGlyphInfo tgi;
int usageError = 0;
char *varname, *fontname;
XFontStruct *xfont;
int i;
if (argc == 3) {
varname = argv[1];
fontname = argv[2];
}
else
usageError = 1;
if (usageError) {
fprintf(stderr, "\n");
fprintf(stderr, "usage: genfontfile variable_name X_font_name\n");
fprintf(stderr, "\n");
exit(1);
}
dpy = XOpenDisplay(NULL);
if (!dpy) {
fprintf(stderr, "could not open display\n");
exit(1);
}
/* find an OpenGL-capable RGB visual with depth buffer */
xfont = XLoadQueryFont(dpy, fontname);
if (!xfont) {
fprintf(stderr, "could not get load X font: %s\n", fontname);
exit(1);
}
fontinfo = SuckGlyphsFromServer(dpy, xfont->fid);
if (!fontinfo) {
fprintf(stderr, "could not get font glyphs\n");
exit(1);
}
printf("static const %s[][%d] = {\n", varname, fontinfo->max_ascent + fontinfo->max_descent + 2);
for (c = 32; c < 256; c++) {
getMetric(fontinfo, c, &tgi);
printGlyph(fontinfo, c);
}
printf(" };\n");
return 0;
}

215
i18n.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: i18n.c 1.293 2007/03/11 10:05:36 kls Exp $ * $Id: i18n.c 1.294 2007/06/09 08:44:54 kls Exp $
* *
* Translations provided by: * Translations provided by:
* *
@ -3138,6 +3138,7 @@ const tI18nPhrase Phrases[] = {
"CAM", "CAM",
"CAM", "CAM",
"CAM", "CAM",
"CAM",
}, },
{ "Recording", { "Recording",
"Aufnahme", "Aufnahme",
@ -3554,6 +3555,167 @@ const tI18nPhrase Phrases[] = {
"v¾dy", "v¾dy",
"hep", "hep",
}, },
{ "Setup.OSD$Anti-alias",
"Kantenglättung",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "Setup.OSD$OSD font name",
"OSD Schriftart",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "Setup.OSD$Small font name",
"Kleine Schriftart",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "Setup.OSD$Fixed font name",
"Festbreiten-Schriftart",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "Setup.OSD$OSD font size (pixel)",
"OSD Schriftgröße (pixel)",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "Setup.OSD$Small font size (pixel)",
"Kleine Schriftgröße (pixel)",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "Setup.OSD$Fixed font size (pixel)",
"Festbreiten-Schriftgröße (pixel)",
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
"",// TODO
},
{ "Setup.OSD$Channel info position", { "Setup.OSD$Channel info position",
"Kanalinfo-Position", "Kanalinfo-Position",
"Pozicija informacije o kanalu", "Pozicija informacije o kanalu",
@ -5021,7 +5183,7 @@ const tI18nPhrase Phrases[] = {
" 0\t-.#~,/_@1\taãâbc2\tdef3\tghiî4\tjkl5\tmno6\tpqrsº7\ttþuv8\twxyz9", " 0\t-.#~,/_@1\taãâbc2\tdef3\tghiî4\tjkl5\tmno6\tpqrsº7\ttþuv8\twxyz9",
" 0\t-.#~,/_@1\taábc2\tdeéf3\tghií4\tjkl5\tmnoóöõ6\tpqrs7\ttuúüûv8\twxyz9", " 0\t-.#~,/_@1\taábc2\tdeéf3\tghií4\tjkl5\tmnoóöõ6\tpqrs7\ttuúüûv8\twxyz9",
"",//TODO "",//TODO
"",//TODO " 0\t-.#~,/_@1\tabcÐÑÒÓ2\tdefÔÕñÖ×3\tghiØÙÚÛ4\tjklÜÝÞ5\tmnoßàá6\tpqrsâãäå7\ttuvæçèéê8\twxyzëìíîï9",
"",//TODO "",//TODO
" 0\t-.#~,/_@1\tabcäå2\tdef3\tghi4\tjkl5\tmnoõö6\tpqrsð7\ttuvü8\twxyzþ9", " 0\t-.#~,/_@1\tabcäå2\tdef3\tghi4\tjkl5\tmnoõö6\tpqrsð7\ttuvü8\twxyzþ9",
" 0\t-.#~,/_@1\tabcæå2\tdef3\tghi4\tjkl5\tmnoø6\tpqrs7\ttuv8\twxyz9", " 0\t-.#~,/_@1\tabcæå2\tdef3\tghi4\tjkl5\tmnoø6\tpqrs7\ttuv8\twxyz9",
@ -6603,25 +6765,33 @@ const tI18nPhrase Phrases[] = {
class cI18nEntry : public cListObject { class cI18nEntry : public cListObject {
private: private:
const tI18nPhrase *phrases; const tI18nPhrase *phrases;
tI18nPhrase *converted;
const char *plugin; const char *plugin;
public: public:
cI18nEntry(const tI18nPhrase * const Phrases, const char *Plugin); cI18nEntry(const tI18nPhrase * const Phrases, const char *Plugin);
virtual ~cI18nEntry();
const tI18nPhrase *Phrases(void) { return phrases; } const tI18nPhrase *Phrases(void) { return phrases; }
tI18nPhrase **Converted(void) { return &converted; }
const char *Plugin(void) { return plugin; } const char *Plugin(void) { return plugin; }
}; };
cI18nEntry::cI18nEntry(const tI18nPhrase * const Phrases, const char *Plugin) cI18nEntry::cI18nEntry(const tI18nPhrase * const Phrases, const char *Plugin)
{ {
phrases = Phrases; phrases = Phrases;
converted = NULL;
plugin = Plugin; plugin = Plugin;
} }
cI18nEntry::~cI18nEntry()
{
delete converted;
}
// --- cI18nList ------------------------------------------------------------- // --- cI18nList -------------------------------------------------------------
class cI18nList : public cList<cI18nEntry> { class cI18nList : public cList<cI18nEntry> {
public: public:
cI18nEntry *Get(const char *Plugin); cI18nEntry *Get(const char *Plugin);
const tI18nPhrase *GetPhrases(const char *Plugin);
}; };
cI18nEntry *cI18nList::Get(const char *Plugin) cI18nEntry *cI18nList::Get(const char *Plugin)
@ -6635,16 +6805,28 @@ cI18nEntry *cI18nList::Get(const char *Plugin)
return NULL; return NULL;
} }
const tI18nPhrase *cI18nList::GetPhrases(const char *Plugin)
{
cI18nEntry *p = Get(Plugin);
return p ? p->Phrases() : NULL;
}
cI18nList I18nList; cI18nList I18nList;
// --- // ---
static tI18nPhrase *Converted = NULL;
static const char *ConvertPhrase(const tI18nPhrase *Original, tI18nPhrase **Converted, int NrPhrase, int NrLanguage)
{
if (!*Converted) {
int NumPhrases = 0;
for (const tI18nPhrase *p = Original; **p; p++)
NumPhrases++;
*Converted = new tI18nPhrase[NumPhrases + 1];
memset(*Converted, 0, sizeof(tI18nPhrase) * (NumPhrases + 1));
}
if (!(*Converted)[NrPhrase][NrLanguage]) {
cCharSetConv csc(Phrases[1][NrLanguage], cCharSetConv::SystemCharacterTable());
(*Converted)[NrPhrase][NrLanguage] = strdup(csc.Convert(Original[NrPhrase][NrLanguage]));
}
return (*Converted)[NrPhrase][NrLanguage];
}
void I18nRegister(const tI18nPhrase * const Phrases, const char *Plugin) void I18nRegister(const tI18nPhrase * const Phrases, const char *Plugin)
{ {
cI18nEntry *p = I18nList.Get(Plugin); cI18nEntry *p = I18nList.Get(Plugin);
@ -6657,13 +6839,14 @@ void I18nRegister(const tI18nPhrase * const Phrases, const char *Plugin)
const char *I18nTranslate(const char *s, const char *Plugin) const char *I18nTranslate(const char *s, const char *Plugin)
{ {
if (Setup.OSDLanguage) { if (Setup.OSDLanguage) {
const tI18nPhrase *p = Plugin ? I18nList.GetPhrases(Plugin) : Phrases; cI18nEntry *e = Plugin ? I18nList.Get(Plugin) : NULL;
if (!p) const tI18nPhrase *OriginalPhrases = e ? e->Phrases() : Phrases;
p = Phrases; tI18nPhrase **ConvertedPhrases = e ? e->Converted() : &Converted;
const tI18nPhrase *p = OriginalPhrases;
for (int i = ((p == Phrases) ? 1 : 2); i--; ) { for (int i = ((p == Phrases) ? 1 : 2); i--; ) {
for (; **p; p++) { for (; **p; p++) {
if (strcmp(s, **p) == 0) { if (strcmp(s, **p) == 0) {
const char *t = (*p)[Setup.OSDLanguage]; const char *t = ConvertPhrase(OriginalPhrases, ConvertedPhrases, p - OriginalPhrases, Setup.OSDLanguage);
if (t && *t) if (t && *t)
return t; return t;
} }
@ -6678,7 +6861,11 @@ const char *I18nTranslate(const char *s, const char *Plugin)
const char * const * I18nLanguages(void) const char * const * I18nLanguages(void)
{ {
return &Phrases[0][0]; if (!Converted || !(Converted)[0][0]) {
for (int i = 0; i < I18nNumLanguages; i++)
ConvertPhrase(Phrases, &Converted, 0, i);
}
return &Converted[0][0];
} }
const char * const * I18nCharSets(void) const char * const * I18nCharSets(void)

3
i18n.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: i18n.h 1.19 2007/03/11 09:52:16 kls Exp $ * $Id: i18n.h 1.20 2007/05/28 11:43:14 kls Exp $
*/ */
#ifndef __I18N_H #ifndef __I18N_H
@ -21,7 +21,6 @@ void I18nRegister(const tI18nPhrase * const Phrases, const char *Plugin);
const char *I18nTranslate(const char *s, const char *Plugin = NULL) __attribute_format_arg__(1); const char *I18nTranslate(const char *s, const char *Plugin = NULL) __attribute_format_arg__(1);
const char * const * I18nLanguages(void); const char * const * I18nLanguages(void);
const char * const * I18nCharSets(void);
const char *I18nLanguageCode(int Index); const char *I18nLanguageCode(int Index);
int I18nLanguageIndex(const char *Code); int I18nLanguageIndex(const char *Code);
const char *I18nNormalizeLanguageCode(const char *Code); const char *I18nNormalizeLanguageCode(const char *Code);

View File

@ -6,7 +6,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: si.c 1.19 2007/05/28 10:22:42 kls Exp $ * $Id: si.c 1.20 2007/06/10 09:31:34 kls Exp $
* * * *
***************************************************************************/ ***************************************************************************/
@ -219,7 +219,9 @@ char *String::getText() {
int len=getLength(); int len=getLength();
if (len < 0 || len > 4095) if (len < 0 || len > 4095)
return strdup("text error"); // caller will delete it! return strdup("text error"); // caller will delete it!
char *data=new char(len+1); char *data=new char(len+1); // FIXME If this function is ever actually used, this buffer might
// need to be bigger in order to hold the string as UTF-8.
// Maybe decodeText should dynamically handle this? kls 2007-06-10
decodeText(data, len+1); decodeText(data, len+1);
return data; return data;
} }
@ -404,6 +406,9 @@ void String::decodeText(char *buffer, int size) {
} }
bool singleByte; bool singleByte;
const char *cs = getCharacterTable(from, len, &singleByte); const char *cs = getCharacterTable(from, len, &singleByte);
// FIXME Need to make this UTF-8 aware (different control codes).
// However, there's yet to be found a broadcaster that actually
// uses UTF-8 for the SI data... (kls 2007-06-10)
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
if (*from == 0) if (*from == 0)
break; break;
@ -440,6 +445,9 @@ void String::decodeText(char *buffer, char *shortVersion, int sizeBuffer, int si
} }
bool singleByte; bool singleByte;
const char *cs = getCharacterTable(from, len, &singleByte); const char *cs = getCharacterTable(from, len, &singleByte);
// FIXME Need to make this UTF-8 aware (different control codes).
// However, there's yet to be found a broadcaster that actually
// uses UTF-8 for the SI data... (kls 2007-06-10)
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
if ( ((' ' <= *from) && (*from <= '~')) if ( ((' ' <= *from) && (*from <= '~'))
|| (*from == '\n') || (*from == '\n')

64
menu.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menu.c 1.450 2007/02/25 14:04:33 kls Exp $ * $Id: menu.c 1.451 2007/06/09 14:36:46 kls Exp $
*/ */
#include "menu.h" #include "menu.h"
@ -761,7 +761,7 @@ void cMenuTimerItem::Set(void)
{ {
cString day, name(""); cString day, name("");
if (timer->WeekDays()) if (timer->WeekDays())
day = timer->PrintDay(0, timer->WeekDays()); day = timer->PrintDay(0, timer->WeekDays(), false);
else if (timer->Day() - time(NULL) < 28 * SECSINDAY) { else if (timer->Day() - time(NULL) < 28 * SECSINDAY) {
day = itoa(timer->GetMDay(timer->Day())); day = itoa(timer->GetMDay(timer->Day()));
name = WeekDayName(timer->Day()); name = WeekDayName(timer->Day());
@ -1052,10 +1052,11 @@ bool cMenuScheduleItem::Update(bool Force)
char t = TimerMatchChars[timerMatch]; char t = TimerMatchChars[timerMatch];
char v = event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' '; char v = event->Vps() && (event->Vps() - event->StartTime()) ? 'V' : ' ';
char r = event->SeenWithin(30) && event->IsRunning() ? '*' : ' '; char r = event->SeenWithin(30) && event->IsRunning() ? '*' : ' ';
const char *csn = channel ? channel->ShortName(true) : NULL;
if (channel && withDate) if (channel && withDate)
asprintf(&buffer, "%d\t%.*s\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), 6, channel->ShortName(true), 6, *event->GetDateString(), *event->GetTimeString(), t, v, r, event->Title()); asprintf(&buffer, "%d\t%.*s\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), Utf8SymChars(csn, 6), csn, 6, *event->GetDateString(), *event->GetTimeString(), t, v, r, event->Title());
else if (channel) else if (channel)
asprintf(&buffer, "%d\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), 6, channel->ShortName(true), *event->GetTimeString(), t, v, r, event->Title()); asprintf(&buffer, "%d\t%.*s\t%s\t%c%c%c\t%s", channel->Number(), Utf8SymChars(csn, 6), csn, *event->GetTimeString(), t, v, r, event->Title());
else else
asprintf(&buffer, "%.*s\t%s\t%c%c%c\t%s", 6, *event->GetDateString(), *event->GetTimeString(), t, v, r, event->Title()); asprintf(&buffer, "%.*s\t%s\t%c%c%c\t%s", 6, *event->GetDateString(), *event->GetTimeString(), t, v, r, event->Title());
SetText(buffer, false); SetText(buffer, false);
@ -2157,7 +2158,10 @@ private:
int skinIndex; int skinIndex;
const char **skinDescriptions; const char **skinDescriptions;
cThemes themes; cThemes themes;
int originalThemeIndex;
int themeIndex; int themeIndex;
cFileNameList fontNames;
int fontOsdIndex, fontSmlIndex, fontFixIndex;
virtual void Set(void); virtual void Set(void);
public: public:
cMenuSetupOSD(void); cMenuSetupOSD(void);
@ -2171,13 +2175,18 @@ cMenuSetupOSD::cMenuSetupOSD(void)
skinIndex = originalSkinIndex = Skins.Current()->Index(); skinIndex = originalSkinIndex = Skins.Current()->Index();
skinDescriptions = new const char*[numSkins]; skinDescriptions = new const char*[numSkins];
themes.Load(Skins.Current()->Name()); themes.Load(Skins.Current()->Name());
themeIndex = Skins.Current()->Theme() ? themes.GetThemeIndex(Skins.Current()->Theme()->Description()) : 0; themeIndex = originalThemeIndex = Skins.Current()->Theme() ? themes.GetThemeIndex(Skins.Current()->Theme()->Description()) : 0;
fontNames.Load(FONTDIR);
if (fontNames.Size()) {
fontOsdIndex = max(0, fontNames.Find(Setup.FontOsd));
fontSmlIndex = max(0, fontNames.Find(Setup.FontSml));
fontFixIndex = max(0, fontNames.Find(Setup.FontFix));
}
Set(); Set();
} }
cMenuSetupOSD::~cMenuSetupOSD() cMenuSetupOSD::~cMenuSetupOSD()
{ {
cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]);
delete[] skinDescriptions; delete[] skinDescriptions;
} }
@ -2201,6 +2210,15 @@ void cMenuSetupOSD::Set(void)
Add(new cMenuEditIntItem( tr("Setup.OSD$Height"), &data.OSDHeight, MINOSDHEIGHT, MAXOSDHEIGHT)); Add(new cMenuEditIntItem( tr("Setup.OSD$Height"), &data.OSDHeight, MINOSDHEIGHT, MAXOSDHEIGHT));
Add(new cMenuEditIntItem( tr("Setup.OSD$Message time (s)"), &data.OSDMessageTime, 1, 60)); Add(new cMenuEditIntItem( tr("Setup.OSD$Message time (s)"), &data.OSDMessageTime, 1, 60));
Add(new cMenuEditStraItem(tr("Setup.OSD$Use small font"), &data.UseSmallFont, 3, useSmallFontTexts)); Add(new cMenuEditStraItem(tr("Setup.OSD$Use small font"), &data.UseSmallFont, 3, useSmallFontTexts));
Add(new cMenuEditBoolItem(tr("Setup.OSD$Anti-alias"), &data.AntiAlias));
if (fontNames.Size()) {
Add(new cMenuEditStraItem(tr("Setup.OSD$OSD font name"), &fontOsdIndex, fontNames.Size(), &fontNames[0]));
Add(new cMenuEditStraItem(tr("Setup.OSD$Small font name"), &fontSmlIndex, fontNames.Size(), &fontNames[0]));
Add(new cMenuEditStraItem(tr("Setup.OSD$Fixed font name"), &fontFixIndex, fontNames.Size(), &fontNames[0]));
}
Add(new cMenuEditIntItem( tr("Setup.OSD$OSD font size (pixel)"), &data.FontOsdSize, 10, MAXFONTSIZE));
Add(new cMenuEditIntItem( tr("Setup.OSD$Small font size (pixel)"),&data.FontSmlSize, 10, MAXFONTSIZE));
Add(new cMenuEditIntItem( tr("Setup.OSD$Fixed font size (pixel)"),&data.FontFixSize, 10, MAXFONTSIZE));
Add(new cMenuEditBoolItem(tr("Setup.OSD$Channel info position"), &data.ChannelInfoPos, tr("bottom"), tr("top"))); Add(new cMenuEditBoolItem(tr("Setup.OSD$Channel info position"), &data.ChannelInfoPos, tr("bottom"), tr("top")));
Add(new cMenuEditIntItem( tr("Setup.OSD$Channel info time (s)"), &data.ChannelInfoTime, 1, 60)); Add(new cMenuEditIntItem( tr("Setup.OSD$Channel info time (s)"), &data.ChannelInfoTime, 1, 60));
Add(new cMenuEditBoolItem(tr("Setup.OSD$Info on channel switch"), &data.ShowInfoOnChSwitch)); Add(new cMenuEditBoolItem(tr("Setup.OSD$Info on channel switch"), &data.ShowInfoOnChSwitch));
@ -2215,29 +2233,57 @@ void cMenuSetupOSD::Set(void)
eOSState cMenuSetupOSD::ProcessKey(eKeys Key) eOSState cMenuSetupOSD::ProcessKey(eKeys Key)
{ {
bool ModifiedApperance = false;
if (Key == kOk) { if (Key == kOk) {
if (skinIndex != originalSkinIndex) { if (skinIndex != originalSkinIndex) {
cSkin *Skin = Skins.Get(skinIndex); cSkin *Skin = Skins.Get(skinIndex);
if (Skin) { if (Skin) {
strn0cpy(data.OSDSkin, Skin->Name(), sizeof(data.OSDSkin)); strn0cpy(data.OSDSkin, Skin->Name(), sizeof(data.OSDSkin));
Skins.SetCurrent(Skin->Name()); Skins.SetCurrent(Skin->Name());
ModifiedApperance = true;
} }
} }
if (themes.NumThemes() && Skins.Current()->Theme()) { if (themes.NumThemes() && Skins.Current()->Theme()) {
Skins.Current()->Theme()->Load(themes.FileName(themeIndex)); Skins.Current()->Theme()->Load(themes.FileName(themeIndex));
strn0cpy(data.OSDTheme, themes.Name(themeIndex), sizeof(data.OSDTheme)); strn0cpy(data.OSDTheme, themes.Name(themeIndex), sizeof(data.OSDTheme));
ModifiedApperance |= themeIndex != originalThemeIndex;
} }
if (data.OSDLeft != Setup.OSDLeft || data.OSDTop != Setup.OSDTop || data.OSDWidth != Setup.OSDWidth || data.OSDHeight != Setup.OSDHeight) {
data.OSDWidth &= ~0x07; // OSD width must be a multiple of 8 data.OSDWidth &= ~0x07; // OSD width must be a multiple of 8
ModifiedApperance = true;
}
if (data.UseSmallFont != Setup.UseSmallFont || data.AntiAlias != Setup.AntiAlias)
ModifiedApperance = true;
if (fontNames.Size()) {
strn0cpy(data.FontOsd, fontNames[fontOsdIndex], sizeof(data.FontOsd));
strn0cpy(data.FontSml, fontNames[fontSmlIndex], sizeof(data.FontSml));
strn0cpy(data.FontFix, fontNames[fontFixIndex], sizeof(data.FontFix));
}
if (strcmp(data.FontOsd, Setup.FontOsd) || data.FontOsdSize != Setup.FontOsdSize) {
cFont::SetFont(fontOsd, data.FontOsd, data.FontOsdSize);
ModifiedApperance = true;
}
if (strcmp(data.FontSml, Setup.FontSml) || data.FontSmlSize != Setup.FontSmlSize) {
cFont::SetFont(fontSml, data.FontSml, data.FontSmlSize);
ModifiedApperance = true;
}
if (strcmp(data.FontFix, Setup.FontFix) || data.FontFixSize != Setup.FontFixSize) {
cFont::SetFont(fontFix, data.FontFix, data.FontFixSize);
ModifiedApperance = true;
}
} }
int osdLanguage = data.OSDLanguage; int osdLanguage = data.OSDLanguage;
int oldSkinIndex = skinIndex; int oldSkinIndex = skinIndex;
eOSState state = cMenuSetupBase::ProcessKey(Key); eOSState state = cMenuSetupBase::ProcessKey(Key);
if (ModifiedApperance)
SetDisplayMenu();
if (data.OSDLanguage != osdLanguage || skinIndex != oldSkinIndex) { if (data.OSDLanguage != osdLanguage || skinIndex != oldSkinIndex) {
int OriginalOSDLanguage = Setup.OSDLanguage; int OriginalOSDLanguage = Setup.OSDLanguage;
Setup.OSDLanguage = data.OSDLanguage; Setup.OSDLanguage = data.OSDLanguage;
cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]);
cSkin *Skin = Skins.Get(skinIndex); cSkin *Skin = Skins.Get(skinIndex);
if (Skin) { if (Skin) {
@ -2910,10 +2956,8 @@ bool cMenuMain::Update(bool Force)
int Minutes = int(double(FreeMB) / MB_PER_MINUTE); int Minutes = int(double(FreeMB) / MB_PER_MINUTE);
int Hours = Minutes / 60; int Hours = Minutes / 60;
Minutes %= 60; Minutes %= 60;
char buffer[40];
snprintf(buffer, sizeof(buffer), "%s - %s %d%% - %2d:%02d %s", tr("VDR"), tr("Disk"), Percent, Hours, Minutes, tr("free"));
//XXX -> skin function!!! //XXX -> skin function!!!
SetTitle(buffer); SetTitle(cString::sprintf("%s - %s %d%% - %2d:%02d %s", tr("VDR"), tr("Disk"), Percent, Hours, Minutes, tr("free")));
result = true; result = true;
} }
lastDiskSpaceCheck = time(NULL); lastDiskSpaceCheck = time(NULL);

View File

@ -4,11 +4,12 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menuitems.c 1.48 2007/01/04 13:30:37 kls Exp $ * $Id: menuitems.c 1.49 2007/06/08 15:16:38 kls Exp $
*/ */
#include "menuitems.h" #include "menuitems.h"
#include <ctype.h> #include <ctype.h>
#include <wctype.h>
#include "i18n.h" #include "i18n.h"
#include "plugin.h" #include "plugin.h"
#include "remote.h" #include "remote.h"
@ -252,23 +253,64 @@ eOSState cMenuEditChrItem::ProcessKey(eKeys Key)
cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed) cMenuEditStrItem::cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed)
:cMenuEditItem(Name) :cMenuEditItem(Name)
{ {
orgValue = NULL;
value = Value; value = Value;
length = Length; length = Length;
allowed = strdup(Allowed ? Allowed : ""); allowed = Allowed;
pos = -1; pos = -1;
offset = 0;
insert = uppercase = false; insert = uppercase = false;
newchar = true; newchar = true;
charMap = tr(" 0\t-.#~,/_@1\tabc2\tdef3\tghi4\tjkl5\tmno6\tpqrs7\ttuv8\twxyz9"); lengthUtf8 = 0;
currentChar = NULL; valueUtf8 = NULL;
allowedUtf8 = NULL;
charMapUtf8 = NULL;
currentCharUtf8 = NULL;
lastKey = kNone; lastKey = kNone;
Set(); Set();
} }
cMenuEditStrItem::~cMenuEditStrItem() cMenuEditStrItem::~cMenuEditStrItem()
{ {
free(orgValue); delete valueUtf8;
free(allowed); delete allowedUtf8;
delete charMapUtf8;
}
void cMenuEditStrItem::EnterEditMode(void)
{
if (!valueUtf8) {
valueUtf8 = new uint[length];
lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
int l = strlen(allowed) + 1;
allowedUtf8 = new uint[l];
Utf8ToArray(allowed, allowedUtf8, l);
const char *charMap = tr(" 0\t-.#~,/_@1\tabc2\tdef3\tghi4\tjkl5\tmno6\tpqrs7\ttuv8\twxyz9");
l = strlen(charMap) + 1;
charMapUtf8 = new uint[l];
Utf8ToArray(charMap, charMapUtf8, l);
currentCharUtf8 = charMapUtf8;
AdvancePos();
}
}
void cMenuEditStrItem::LeaveEditMode(bool SaveValue)
{
if (valueUtf8) {
if (SaveValue) {
Utf8FromArray(valueUtf8, value, length);
stripspace(value);
}
lengthUtf8 = 0;
delete valueUtf8;
valueUtf8 = NULL;
delete allowedUtf8;
allowedUtf8 = NULL;
delete charMapUtf8;
charMapUtf8 = NULL;
pos = -1;
offset = 0;
newchar = true;
}
} }
void cMenuEditStrItem::SetHelpKeys(void) void cMenuEditStrItem::SetHelpKeys(void)
@ -279,84 +321,120 @@ void cMenuEditStrItem::SetHelpKeys(void)
cSkinDisplay::Current()->SetButtons(NULL); cSkinDisplay::Current()->SetButtons(NULL);
} }
uint *cMenuEditStrItem::IsAllowed(uint c)
{
if (allowedUtf8) {
for (uint *a = allowedUtf8; *a; a++) {
if (c == *a)
return a;
}
}
return NULL;
}
void cMenuEditStrItem::AdvancePos(void) void cMenuEditStrItem::AdvancePos(void)
{ {
if (pos < length - 2 && pos < int(strlen(value)) ) { if (pos < length - 2 && pos < lengthUtf8) {
if (++pos >= int(strlen(value))) { if (++pos >= lengthUtf8) {
if (pos >= 2 && value[pos - 1] == ' ' && value[pos - 2] == ' ') if (pos >= 2 && valueUtf8[pos - 1] == ' ' && valueUtf8[pos - 2] == ' ')
pos--; // allow only two blanks at the end pos--; // allow only two blanks at the end
else { else {
value[pos] = ' '; valueUtf8[pos] = ' ';
value[pos + 1] = 0; valueUtf8[pos + 1] = 0;
lengthUtf8++;
} }
} }
} }
newchar = true; newchar = true;
if (!insert && isalpha(value[pos])) if (!insert && Utf8is(alpha, valueUtf8[pos]))
uppercase = isupper(value[pos]); uppercase = Utf8is(upper, valueUtf8[pos]);
} }
void cMenuEditStrItem::Set(void) void cMenuEditStrItem::Set(void)
{ {
char buf[1000];
if (InEditMode()) { if (InEditMode()) {
// This is an ugly hack to make editing strings work with the 'skincurses' plugin. // This is an ugly hack to make editing strings work with the 'skincurses' plugin.
const cFont *font = dynamic_cast<cSkinDisplayMenu *>(cSkinDisplay::Current())->GetTextAreaFont(false); const cFont *font = dynamic_cast<cSkinDisplayMenu *>(cSkinDisplay::Current())->GetTextAreaFont(false);
if (!font || font->Width("W") != 1) // all characters have with == 1 in the font used by 'skincurses' if (!font || font->Width("W") != 1) // all characters have with == 1 in the font used by 'skincurses'
font = cFont::GetFont(fontOsd); font = cFont::GetFont(fontOsd);
strncpy(buf, value, pos);
snprintf(buf + pos, sizeof(buf) - pos - 2, insert && newchar ? "[]%c%s" : "[%c]%s", *(value + pos), value + pos + 1);
int width = cSkinDisplay::Current()->EditableWidth(); int width = cSkinDisplay::Current()->EditableWidth();
if (font->Width(buf) <= width) { width -= font->Width("[]");
// the whole buffer fits on the screen width -= font->Width("<>"); // reserving this anyway make the whole thing simpler
if (pos < offset)
offset = pos;
int WidthFromOffset = 0;
int EndPos = lengthUtf8;
for (int i = offset; i < lengthUtf8; i++) {
WidthFromOffset += font->Width(valueUtf8[i]);
if (WidthFromOffset > width) {
if (pos >= i) {
do {
WidthFromOffset -= font->Width(valueUtf8[offset]);
offset++;
} while (WidthFromOffset > width && offset < pos);
EndPos = pos + 1;
}
else {
EndPos = i;
break;
}
}
}
char buf[1000];
char *p = buf;
if (offset)
*p++ = '<';
p += Utf8FromArray(valueUtf8 + offset, p, sizeof(buf) - (p - buf), pos - offset);
*p++ = '[';
if (insert && newchar)
*p++ = ']';
p += Utf8FromArray(&valueUtf8[pos], p, sizeof(buf) - (p - buf), 1);
if (!(insert && newchar))
*p++ = ']';
p += Utf8FromArray(&valueUtf8[pos + 1], p, sizeof(buf) - (p - buf), EndPos - pos - 1);
if (EndPos != lengthUtf8)
*p++ = '>';
*p = 0;
SetValue(buf); SetValue(buf);
return;
}
width -= font->Width('>'); // assuming '<' and '>' have the same width
int w = 0;
int i = 0;
int l = strlen(buf);
while (i < l && w <= width)
w += font->Width(buf[i++]);
if (i >= pos + 4) {
// the cursor fits on the screen
buf[i - 1] = '>';
buf[i] = 0;
SetValue(buf);
return;
}
// the cursor doesn't fit on the screen
w = 0;
if (buf[i = pos + 3]) {
buf[i] = '>';
buf[i + 1] = 0;
}
else
i--;
while (i >= 0 && w <= width)
w += font->Width(buf[i--]);
buf[++i] = '<';
SetValue(buf + i);
} }
else else
SetValue(value); SetValue(value);
} }
char cMenuEditStrItem::Inc(char c, bool Up) uint cMenuEditStrItem::Inc(uint c, bool Up)
{ {
const char *p = strchr(allowed, c); uint *p = IsAllowed(c);
if (!p) if (!p)
p = allowed; p = allowedUtf8;
if (Up) { if (Up) {
if (!*++p) if (!*++p)
p = allowed; p = allowedUtf8;
}
else if (--p < allowedUtf8) {
p = allowedUtf8;
while (*p && *(p + 1))
p++;
} }
else if (--p < allowed)
p = allowed + strlen(allowed) - 1;
return *p; return *p;
} }
void cMenuEditStrItem::Insert(void)
{
memmove(valueUtf8 + pos + 1, valueUtf8 + pos, (lengthUtf8 - pos + 1) * sizeof(*valueUtf8));
lengthUtf8++;
valueUtf8[pos] = ' ';
}
void cMenuEditStrItem::Delete(void)
{
memmove(valueUtf8 + pos, valueUtf8 + pos + 1, (lengthUtf8 - pos) * sizeof(*valueUtf8));
lengthUtf8--;
}
eOSState cMenuEditStrItem::ProcessKey(eKeys Key) eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
{ {
bool SameKey = NORMALKEY(Key) == lastKey; bool SameKey = NORMALKEY(Key) == lastKey;
@ -365,7 +443,7 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
else if (!newchar && k0 <= lastKey && lastKey <= k9 && autoAdvanceTimeout.TimedOut()) { else if (!newchar && k0 <= lastKey && lastKey <= k9 && autoAdvanceTimeout.TimedOut()) {
AdvancePos(); AdvancePos();
newchar = true; newchar = true;
currentChar = NULL; currentCharUtf8 = NULL;
Set(); Set();
return osContinue; return osContinue;
} }
@ -374,7 +452,7 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
if (InEditMode()) { if (InEditMode()) {
if (!insert || !newchar) { if (!insert || !newchar) {
uppercase = !uppercase; uppercase = !uppercase;
value[pos] = uppercase ? toupper(value[pos]) : tolower(value[pos]); valueUtf8[pos] = uppercase ? Utf8to(upper, valueUtf8[pos]) : Utf8to(lower, valueUtf8[pos]);
} }
} }
else else
@ -390,21 +468,21 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
return osUnknown; return osUnknown;
break; break;
case kYellow|k_Repeat: case kYellow|k_Repeat:
case kYellow: // Remove the character at current position; in insert mode it is the character to the right of cursor case kYellow: // Remove the character at the current position; in insert mode it is the character to the right of the cursor
if (InEditMode()) { if (InEditMode()) {
if (strlen(value) > 1) { if (lengthUtf8 > 1) {
if (!insert || pos < int(strlen(value)) - 1) if (!insert || pos < lengthUtf8 - 1)
memmove(value + pos, value + pos + 1, strlen(value) - pos); Delete();
else if (insert && pos == int(strlen(value)) - 1) else if (insert && pos == lengthUtf8 - 1)
value[pos] = ' '; // in insert mode, deleting the last character replaces it with a blank to keep the cursor position valueUtf8[pos] = ' '; // in insert mode, deleting the last character replaces it with a blank to keep the cursor position
// reduce position, if we removed the last character // reduce position, if we removed the last character
if (pos == int(strlen(value))) if (pos == lengthUtf8)
pos--; pos--;
} }
else if (strlen(value) == 1) else if (lengthUtf8 == 1)
value[0] = ' '; // This is the last character in the string, replace it with a blank valueUtf8[0] = ' '; // This is the last character in the string, replace it with a blank
if (isalpha(value[pos])) if (Utf8is(alpha, valueUtf8[pos]))
uppercase = isupper(value[pos]); uppercase = Utf8is(upper, valueUtf8[pos]);
newchar = true; newchar = true;
} }
else else
@ -423,13 +501,14 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
pos--; pos--;
newchar = true; newchar = true;
} }
if (!insert && isalpha(value[pos])) if (!insert && Utf8is(alpha, valueUtf8[pos]))
uppercase = isupper(value[pos]); uppercase = Utf8is(upper, valueUtf8[pos]);
break; break;
case kRight|k_Repeat: case kRight|k_Repeat:
case kRight: AdvancePos(); case kRight: if (InEditMode())
if (pos == 0) { AdvancePos();
orgValue = strdup(value); else {
EnterEditMode();
SetHelpKeys(); SetHelpKeys();
} }
break; break;
@ -439,15 +518,13 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
case kDown: if (InEditMode()) { case kDown: if (InEditMode()) {
if (insert && newchar) { if (insert && newchar) {
// create a new character in insert mode // create a new character in insert mode
if (int(strlen(value)) < length - 1) { if (lengthUtf8 < length - 1)
memmove(value + pos + 1, value + pos, strlen(value) - pos + 1); Insert();
value[pos] = ' ';
}
} }
if (uppercase) if (uppercase)
value[pos] = toupper(Inc(tolower(value[pos]), NORMALKEY(Key) == kUp)); valueUtf8[pos] = Utf8to(upper, Inc(Utf8to(lower, valueUtf8[pos]), NORMALKEY(Key) == kUp));
else else
value[pos] = Inc( value[pos], NORMALKEY(Key) == kUp); valueUtf8[pos] = Inc( valueUtf8[pos], NORMALKEY(Key) == kUp);
newchar = false; newchar = false;
} }
else else
@ -459,35 +536,33 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
if (!SameKey) { if (!SameKey) {
if (!newchar) if (!newchar)
AdvancePos(); AdvancePos();
currentChar = NULL; currentCharUtf8 = NULL;
} }
if (!currentChar || !*currentChar || *currentChar == '\t') { if (!currentCharUtf8 || !*currentCharUtf8 || *currentCharUtf8 == '\t') {
// find the beginning of the character map entry for Key // find the beginning of the character map entry for Key
int n = NORMALKEY(Key) - k0; int n = NORMALKEY(Key) - k0;
currentChar = charMap; currentCharUtf8 = charMapUtf8;
while (n > 0 && *currentChar) { while (n > 0 && *currentCharUtf8) {
if (*currentChar++ == '\t') if (*currentCharUtf8++ == '\t')
n--; n--;
} }
// find first allowed character // find first allowed character
while (*currentChar && *currentChar != '\t' && !strchr(allowed, *currentChar)) while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8))
currentChar++; currentCharUtf8++;
} }
if (*currentChar && *currentChar != '\t') { if (*currentCharUtf8 && *currentCharUtf8 != '\t') {
if (insert && newchar) { if (insert && newchar) {
// create a new character in insert mode // create a new character in insert mode
if (int(strlen(value)) < length - 1) { if (lengthUtf8 < length - 1)
memmove(value + pos + 1, value + pos, strlen(value) - pos + 1); Insert();
value[pos] = ' ';
} }
} valueUtf8[pos] = *currentCharUtf8;
value[pos] = *currentChar;
if (uppercase) if (uppercase)
value[pos] = toupper(value[pos]); valueUtf8[pos] = Utf8to(upper, valueUtf8[pos]);
// find next allowed character // find next allowed character
do { do {
currentChar++; currentCharUtf8++;
} while (*currentChar && *currentChar != '\t' && !strchr(allowed, *currentChar)); } while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8));
newchar = false; newchar = false;
autoAdvanceTimeout.Set(AUTO_ADVANCE_TIMEOUT); autoAdvanceTimeout.Set(AUTO_ADVANCE_TIMEOUT);
} }
@ -498,32 +573,25 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
break; break;
case kBack: case kBack:
case kOk: if (InEditMode()) { case kOk: if (InEditMode()) {
if (Key == kBack && orgValue) { LeaveEditMode(Key == kOk);
strcpy(value, orgValue);
free(orgValue);
orgValue = NULL;
}
pos = -1;
newchar = true;
stripspace(value);
SetHelpKeys(); SetHelpKeys();
break; break;
} }
// run into default // run into default
default: if (InEditMode() && BASICKEY(Key) == kKbd) { default: if (InEditMode() && BASICKEY(Key) == kKbd) {
int c = KEYKBD(Key); int c = KEYKBD(Key);
if (c <= 0xFF) { if (c <= 0xFF) { // FIXME what about other UTF-8 characters?
const char *p = strchr(allowed, tolower(c)); uint *p = IsAllowed(Utf8to(lower, c));
if (p) { if (p) {
int l = strlen(value); if (insert && lengthUtf8 < length - 1)
if (insert && l < length - 1) Insert();
memmove(value + pos + 1, value + pos, l - pos + 1); valueUtf8[pos] = c;
value[pos] = c;
if (pos < length - 2) if (pos < length - 2)
pos++; pos++;
if (pos >= l) { if (pos >= lengthUtf8) {
value[pos] = ' '; valueUtf8[pos] = ' ';
value[pos + 1] = 0; valueUtf8[pos + 1] = 0;
lengthUtf8 = pos + 1;
} }
} }
else { else {
@ -540,7 +608,7 @@ eOSState cMenuEditStrItem::ProcessKey(eKeys Key)
else { else {
switch (c) { switch (c) {
case kfHome: pos = 0; break; case kfHome: pos = 0; break;
case kfEnd: pos = strlen(value) - 1; break; case kfEnd: pos = lengthUtf8 - 1; break;
case kfIns: return ProcessKey(kGreen); case kfIns: return ProcessKey(kGreen);
case kfDel: return ProcessKey(kYellow); case kfDel: return ProcessKey(kYellow);
} }
@ -690,7 +758,7 @@ void cMenuEditDateItem::Set(void)
#define DATEBUFFERSIZE 32 #define DATEBUFFERSIZE 32
char buf[DATEBUFFERSIZE]; char buf[DATEBUFFERSIZE];
if (weekdays && *weekdays) { if (weekdays && *weekdays) {
SetValue(cTimer::PrintDay(0, *weekdays)); SetValue(cTimer::PrintDay(0, *weekdays, false));
return; return;
} }
else if (*value) { else if (*value) {
@ -880,9 +948,7 @@ cMenuSetupPage::cMenuSetupPage(void)
void cMenuSetupPage::SetSection(const char *Section) void cMenuSetupPage::SetSection(const char *Section)
{ {
char buf[40]; SetTitle(cString::sprintf("%s - %s", tr("Setup"), Section));
snprintf(buf, sizeof(buf), "%s - %s", tr("Setup"), Section);
SetTitle(buf);
} }
eOSState cMenuSetupPage::ProcessKey(eKeys Key) eOSState cMenuSetupPage::ProcessKey(eKeys Key)
@ -903,9 +969,7 @@ eOSState cMenuSetupPage::ProcessKey(eKeys Key)
void cMenuSetupPage::SetPlugin(cPlugin *Plugin) void cMenuSetupPage::SetPlugin(cPlugin *Plugin)
{ {
plugin = Plugin; plugin = Plugin;
char buf[40]; SetSection(cString::sprintf("%s '%s'", tr("Plugin"), plugin->Name()));
snprintf(buf, sizeof(buf), "%s '%s'", tr("Plugin"), plugin->Name());
SetSection(buf);
} }
void cMenuSetupPage::SetupStore(const char *Name, const char *Value) void cMenuSetupPage::SetupStore(const char *Name, const char *Value)

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: menuitems.h 1.20 2006/04/14 10:01:47 kls Exp $ * $Id: menuitems.h 1.21 2007/06/08 11:53:37 kls Exp $
*/ */
#ifndef __MENUITEMS_H #ifndef __MENUITEMS_H
@ -77,22 +77,29 @@ public:
class cMenuEditStrItem : public cMenuEditItem { class cMenuEditStrItem : public cMenuEditItem {
private: private:
char *orgValue;
char *value; char *value;
int length; int length;
char *allowed; const char *allowed;
int pos; int pos, offset;
bool insert, newchar, uppercase; bool insert, newchar, uppercase;
const char *charMap; int lengthUtf8;
const char *currentChar; uint *valueUtf8;
uint *allowedUtf8;
uint *charMapUtf8;
uint *currentCharUtf8;
eKeys lastKey; eKeys lastKey;
cTimeMs autoAdvanceTimeout; cTimeMs autoAdvanceTimeout;
void SetHelpKeys(void); void SetHelpKeys(void);
uint *IsAllowed(uint c);
void AdvancePos(void); void AdvancePos(void);
virtual void Set(void); virtual void Set(void);
char Inc(char c, bool Up); uint Inc(uint c, bool Up);
void Insert(void);
void Delete(void);
protected: protected:
bool InEditMode(void) { return pos >= 0; } void EnterEditMode(void);
void LeaveEditMode(bool SaveValue = false);
bool InEditMode(void) { return valueUtf8 != NULL; }
public: public:
cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed); cMenuEditStrItem(const char *Name, char *Value, int Length, const char *Allowed);
~cMenuEditStrItem(); ~cMenuEditStrItem();

4
nit.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: nit.h 1.2 2004/01/18 16:31:08 kls Exp $ * $Id: nit.h 1.3 2007/06/10 08:50:21 kls Exp $
*/ */
#ifndef __NIT_H #ifndef __NIT_H
@ -13,7 +13,7 @@
#include "filter.h" #include "filter.h"
#define MAXNITS 16 #define MAXNITS 16
#define MAXNETWORKNAME 256 #define MAXNETWORKNAME Utf8BufSize(256)
class cNitFilter : public cFilter { class cNitFilter : public cFilter {
private: private:

95
osd.c
View File

@ -4,11 +4,12 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osd.c 1.68 2007/02/17 16:05:52 kls Exp $ * $Id: osd.c 1.69 2007/06/10 12:16:36 kls Exp $
*/ */
#include "osd.h" #include "osd.h"
#include <math.h> #include <math.h>
#include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -20,6 +21,18 @@
cPalette::cPalette(int Bpp) cPalette::cPalette(int Bpp)
{ {
SetBpp(Bpp); SetBpp(Bpp);
SetAntiAliasGranularity(10, 10);
}
void cPalette::SetAntiAliasGranularity(uint FixedColors, uint BlendColors)
{
if (FixedColors >= MAXNUMCOLORS || BlendColors == 0)
antiAliasGranularity = MAXNUMCOLORS - 1;
else {
int ColorsForBlending = MAXNUMCOLORS - FixedColors;
int ColorsPerBlend = ColorsForBlending / BlendColors + 2; // +2 = the full foreground and background colors, which are amoung the fixed colors
antiAliasGranularity = double(MAXNUMCOLORS - 1) / (ColorsPerBlend - 1);
}
} }
void cPalette::Reset(void) void cPalette::Reset(void)
@ -30,18 +43,23 @@ void cPalette::Reset(void)
int cPalette::Index(tColor Color) int cPalette::Index(tColor Color)
{ {
// Check if color is already defined:
for (int i = 0; i < numColors; i++) { for (int i = 0; i < numColors; i++) {
if (color[i] == Color) if (color[i] == Color)
return i; return i;
} }
// No exact color, try a close one:
int i = ClosestColor(Color, 4);
if (i >= 0)
return i;
// No close one, try to define a new one:
if (numColors < maxColors) { if (numColors < maxColors) {
color[numColors++] = Color; color[numColors++] = Color;
modified = true; modified = true;
return numColors - 1; return numColors - 1;
} }
dsyslog("too many different colors used in palette"); // Out of colors, so any close color must do:
//TODO: return the index of the "closest" color? return ClosestColor(Color);
return 0;
} }
void cPalette::SetBpp(int Bpp) void cPalette::SetBpp(int Bpp)
@ -91,6 +109,48 @@ void cPalette::Replace(const cPalette &Palette)
for (int i = 0; i < Palette.numColors; i++) for (int i = 0; i < Palette.numColors; i++)
SetColor(i, Palette.color[i]); SetColor(i, Palette.color[i]);
numColors = Palette.numColors; numColors = Palette.numColors;
antiAliasGranularity = Palette.antiAliasGranularity;
}
tColor cPalette::Blend(tColor ColorFg, tColor ColorBg, uint8_t Level)
{
if (antiAliasGranularity > 0)
Level = uint8_t(int(Level / antiAliasGranularity + 0.5) * antiAliasGranularity);
int Af = (ColorFg & 0xFF000000) >> 24;
int Rf = (ColorFg & 0x00FF0000) >> 16;
int Gf = (ColorFg & 0x0000FF00) >> 8;
int Bf = (ColorFg & 0x000000FF);
int Ab = (ColorBg & 0xFF000000) >> 24;
int Rb = (ColorBg & 0x00FF0000) >> 16;
int Gb = (ColorBg & 0x0000FF00) >> 8;
int Bb = (ColorBg & 0x000000FF);
int A = (Ab + (Af - Ab) * Level / 0xFF) & 0xFF;
int R = (Rb + (Rf - Rb) * Level / 0xFF) & 0xFF;
int G = (Gb + (Gf - Gb) * Level / 0xFF) & 0xFF;
int B = (Bb + (Bf - Bb) * Level / 0xFF) & 0xFF;
return (A << 24) | (R << 16) | (G << 8) | B;
}
int cPalette::ClosestColor(tColor Color, int MaxDiff)
{
int n = 0;
int d = INT_MAX;
int A1 = (Color & 0xFF000000) >> 24;
int R1 = (Color & 0x00FF0000) >> 16;
int G1 = (Color & 0x0000FF00) >> 8;
int B1 = (Color & 0x000000FF);
for (int i = 0; i < numColors; i++) {
int A2 = (color[i] & 0xFF000000) >> 24;
int R2 = (color[i] & 0x00FF0000) >> 16;
int G2 = (color[i] & 0x0000FF00) >> 8;
int B2 = (color[i] & 0x000000FF);
int diff = (abs(A1 - A2) << 1) + (abs(R1 - R2) << 1) + (abs(G1 - G2) << 1) + (abs(B1 - B2) << 1);
if (diff < d) {
d = diff;
n = i;
}
}
return d <= MaxDiff ? n : -1;
} }
// --- cBitmap --------------------------------------------------------------- // --- cBitmap ---------------------------------------------------------------
@ -424,26 +484,7 @@ void cBitmap::DrawText(int x, int y, const char *s, tColor ColorFg, tColor Color
return; return;
x -= x0; x -= x0;
y -= y0; y -= y0;
tIndex fg = Index(ColorFg); Font->DrawText(this, x, y, s, ColorFg, ColorBg, limit);
tIndex bg = (ColorBg != clrTransparent) ? Index(ColorBg) : 0;
while (s && *s) {
const cFont::tCharData *CharData = Font->CharData(*s++);
if (limit && int(x + CharData->width) > limit)
break; // we don't draw partial characters
if (int(x + CharData->width) > 0) {
for (int row = 0; row < h; row++) {
cFont::tPixelData PixelData = CharData->lines[row];
for (int col = CharData->width; col-- > 0; ) {
if (ColorBg != clrTransparent || (PixelData & 1))
SetIndex(x + col, y + row, (PixelData & 1) ? fg : bg);
PixelData >>= 1;
}
}
}
x += CharData->width;
if (x > width - 1)
break;
}
} }
} }
@ -623,6 +664,12 @@ cOsd::~cOsd()
isOpen--; isOpen--;
} }
void cOsd::SetAntiAliasGranularity(uint FixedColors, uint BlendColors)
{
for (int i = 0; i < numBitmaps; i++)
bitmaps[i]->SetAntiAliasGranularity(FixedColors, BlendColors);
}
cBitmap *cOsd::GetBitmap(int Area) cBitmap *cOsd::GetBitmap(int Area)
{ {
return Area < numBitmaps ? bitmaps[Area] : NULL; return Area < numBitmaps ? bitmaps[Area] : NULL;

44
osd.h
View File

@ -4,12 +4,13 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osd.h 1.53 2006/02/26 14:45:05 kls Exp $ * $Id: osd.h 1.54 2007/06/10 12:15:52 kls Exp $
*/ */
#ifndef __OSD_H #ifndef __OSD_H
#define __OSD_H #define __OSD_H
#include <limits.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include "font.h" #include "font.h"
@ -41,7 +42,7 @@ enum eOsdError { oeOk,
oeUnknown, oeUnknown,
}; };
typedef uint32_t tColor; typedef uint32_t tColor; // see also font.h
typedef uint8_t tIndex; typedef uint8_t tIndex;
class cPalette { class cPalette {
@ -50,11 +51,22 @@ private:
int bpp; int bpp;
int maxColors, numColors; int maxColors, numColors;
bool modified; bool modified;
double antiAliasGranularity;
protected: protected:
typedef tIndex tIndexes[MAXNUMCOLORS]; typedef tIndex tIndexes[MAXNUMCOLORS];
public: public:
cPalette(int Bpp = 8); cPalette(int Bpp = 8);
///< Initializes the palette with the given color depth. ///< Initializes the palette with the given color depth.
void SetAntiAliasGranularity(uint FixedColors, uint BlendColors);
///< Allows the system to optimize utilization of the limited color
///< palette entries when generating blended colors for anti-aliasing.
///< FixedColors is the maximum number of colors used, and BlendColors
///< is the maximum number of foreground/background color combinations
///< used with anti-aliasing. If this function is not called with
///< useful values, the palette may be filled up with many shades of
///< a single color combination, and may not be able to serve all
///< requested colors. By default the palette assumes there will be
///< 10 fixed colors and 10 color combinations.
int Bpp(void) { return bpp; } int Bpp(void) { return bpp; }
void Reset(void); void Reset(void);
///< Resets the palette, making it contain no colors. ///< Resets the palette, making it contain no colors.
@ -62,7 +74,7 @@ public:
///< Returns the index of the given Color (the first color has index 0). ///< Returns the index of the given Color (the first color has index 0).
///< If Color is not yet contained in this palette, it will be added if ///< If Color is not yet contained in this palette, it will be added if
///< there is a free slot. If the color can't be added to this palette, ///< there is a free slot. If the color can't be added to this palette,
///< 0 will be returned. ///< the closest existing color will be returned.
tColor Color(int Index) { return Index < maxColors ? color[Index] : 0; } tColor Color(int Index) { return Index < maxColors ? color[Index] : 0; }
///< Returns the color at the given Index. If Index is outside the valid ///< Returns the color at the given Index. If Index is outside the valid
///< range, 0 will be returned. ///< range, 0 will be returned.
@ -88,6 +100,18 @@ public:
void Replace(const cPalette &Palette); void Replace(const cPalette &Palette);
///< Replaces the colors of this palette with the colors from the given ///< Replaces the colors of this palette with the colors from the given
///< palette. ///< palette.
tColor Blend(tColor ColorFg, tColor ColorBg, uint8_t Level);
///< Determines a color that consists of a linear blend between ColorFg
///< and ColorBg. If Level is 0, the result is ColorBg, if it is 255,
///< the result is ColorFg. If SetAntiAliasGranularity() has been called previously,
///< Level will be mapped to a limited range of levels that allow to make best
///< use of the palette entries.
int ClosestColor(tColor Color, int MaxDiff = INT_MAX);
///< Returns the index of a color in this paltte that is closest to the given
///< Color. MaxDiff can be used to control the maximum allowed color difference.
///< If no color with a maximum difference of MaxDiff can be found, -1 will
///< be returned. With the default value of INT_MAX, there will always be
///< a valid color index returned, but the color may be completely different.
}; };
enum eTextAlignment { taCenter = 0x00, enum eTextAlignment { taCenter = 0x00,
@ -98,6 +122,8 @@ enum eTextAlignment { taCenter = 0x00,
taDefault = taTop | taLeft taDefault = taTop | taLeft
}; };
class cFont;
class cBitmap : public cPalette { class cBitmap : public cPalette {
private: private:
tIndex *bitmap; tIndex *bitmap;
@ -202,6 +228,8 @@ public:
///< 7: vertical, falling, upper ///< 7: vertical, falling, upper
const tIndex *Data(int x, int y); const tIndex *Data(int x, int y);
///< Returns the address of the index byte at the given coordinates. ///< Returns the address of the index byte at the given coordinates.
tColor GetColor(int x, int y) { return Color(*Data(x, y)); }
///< Returns the color at the given coordinates.
}; };
struct tArea { struct tArea {
@ -247,6 +275,16 @@ public:
int Top(void) { return top; } int Top(void) { return top; }
int Width(void) { return width; } int Width(void) { return width; }
int Height(void) { return height; } int Height(void) { return height; }
void SetAntiAliasGranularity(uint FixedColors, uint BlendColors);
///< Allows the system to optimize utilization of the limited color
///< palette entries when generating blended colors for anti-aliasing.
///< FixedColors is the maximum number of colors used, and BlendColors
///< is the maximum number of foreground/background color combinations
///< used with anti-aliasing. If this function is not called with
///< useful values, the palette may be filled up with many shades of
///< a single color combination, and may not be able to serve all
///< requested colors. By default the palette assumes there will be
///< 10 fixed colors and 10 color combinations.
cBitmap *GetBitmap(int Area); cBitmap *GetBitmap(int Area);
///< Returns a pointer to the bitmap for the given Area, or NULL if no ///< Returns a pointer to the bitmap for the given Area, or NULL if no
///< such bitmap exists. ///< such bitmap exists.

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osdbase.c 1.30 2007/01/07 14:41:16 kls Exp $ * $Id: osdbase.c 1.31 2007/06/09 10:07:46 kls Exp $
*/ */
#include "osdbase.h" #include "osdbase.h"
@ -86,10 +86,8 @@ cOsdMenu::cOsdMenu(const char *Title, int c0, int c1, int c2, int c3, int c4)
subMenu = NULL; subMenu = NULL;
helpRed = helpGreen = helpYellow = helpBlue = NULL; helpRed = helpGreen = helpYellow = helpBlue = NULL;
status = NULL; status = NULL;
if (!displayMenuCount++) { if (!displayMenuCount++)
displayMenu = Skins.Current()->DisplayMenu(); SetDisplayMenu();
displayMenuItems = displayMenu->MaxItems();
}
} }
cOsdMenu::~cOsdMenu() cOsdMenu::~cOsdMenu()
@ -103,15 +101,25 @@ cOsdMenu::~cOsdMenu()
DELETENULL(displayMenu); DELETENULL(displayMenu);
} }
void cOsdMenu::SetDisplayMenu(void)
{
if (displayMenu) {
displayMenu->Clear();
delete displayMenu;
}
displayMenu = Skins.Current()->DisplayMenu();
displayMenuItems = displayMenu->MaxItems();
}
const char *cOsdMenu::hk(const char *s) const char *cOsdMenu::hk(const char *s)
{ {
static char buffer[64]; static cString buffer;
if (s && hasHotkeys) { if (s && hasHotkeys) {
if (digit == 0 && '1' <= *s && *s <= '9' && *(s + 1) == ' ') if (digit == 0 && '1' <= *s && *s <= '9' && *(s + 1) == ' ')
digit = -1; // prevents automatic hotkeys - input already has them digit = -1; // prevents automatic hotkeys - input already has them
if (digit >= 0) { if (digit >= 0) {
digit++; digit++;
snprintf(buffer, sizeof(buffer), " %c %s", (digit < 10) ? '0' + digit : ' ' , s); buffer = cString::sprintf(" %c %s", (digit < 10) ? '0' + digit : ' ' , s);
s = buffer; s = buffer;
} }
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osdbase.h 1.15 2007/01/07 14:41:32 kls Exp $ * $Id: osdbase.h 1.16 2007/06/09 11:49:00 kls Exp $
*/ */
#ifndef __OSDBASE_H #ifndef __OSDBASE_H
@ -96,6 +96,7 @@ private:
int digit; int digit;
bool hasHotkeys; bool hasHotkeys;
protected: protected:
void SetDisplayMenu(void);
cSkinDisplayMenu *DisplayMenu(void) { return displayMenu; } cSkinDisplayMenu *DisplayMenu(void) { return displayMenu; }
const char *hk(const char *s); const char *hk(const char *s);
void SetCols(int c0, int c1 = 0, int c2 = 0, int c3 = 0, int c4 = 0); void SetCols(int c0, int c1 = 0, int c2 = 0, int c3 = 0, int c4 = 0);

8
sdt.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: sdt.c 1.16 2006/04/15 14:12:21 kls Exp $ * $Id: sdt.c 1.17 2007/06/10 08:50:49 kls Exp $
*/ */
#include "sdt.h" #include "sdt.h"
@ -56,9 +56,9 @@ void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length
case 0x04: // NVOD reference service case 0x04: // NVOD reference service
case 0x05: // NVOD time-shifted service case 0x05: // NVOD time-shifted service
{ {
char NameBuf[1024]; char NameBuf[Utf8BufSize(1024)];
char ShortNameBuf[1024]; char ShortNameBuf[Utf8BufSize(1024)];
char ProviderNameBuf[1024]; char ProviderNameBuf[Utf8BufSize(1024)];
sd->serviceName.getText(NameBuf, ShortNameBuf, sizeof(NameBuf), sizeof(ShortNameBuf)); sd->serviceName.getText(NameBuf, ShortNameBuf, sizeof(NameBuf), sizeof(ShortNameBuf));
char *pn = compactspace(NameBuf); char *pn = compactspace(NameBuf);
char *ps = compactspace(ShortNameBuf); char *ps = compactspace(ShortNameBuf);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: skinclassic.c 1.15 2006/03/31 13:59:50 kls Exp $ * $Id: skinclassic.c 1.16 2007/06/10 12:42:02 kls Exp $
*/ */
#include "skinclassic.h" #include "skinclassic.h"
@ -94,8 +94,13 @@ cSkinClassicDisplayChannel::cSkinClassicDisplayChannel(bool WithInfo)
message = false; message = false;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - Lines * lineHeight)); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - Lines * lineHeight));
timeWidth = font->Width("00:00") + 4; timeWidth = font->Width("00:00") + 4;
tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, Lines * lineHeight - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, Lines * lineHeight - 1, 4 } }; tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, Lines * lineHeight - 1, 4 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrBackground)); osd->DrawRectangle(0, 0, osd->Width() - 1, osd->Height() - 1, Theme.Color(clrBackground));
} }
@ -142,7 +147,9 @@ void cSkinClassicDisplayChannel::Flush(void)
{ {
if (!message) { if (!message) {
cString date = DayDateTime(); cString date = DayDateTime();
osd->DrawText(osd->Width() - cFont::GetFont(fontSml)->Width(date) - 2, 0, date, Theme.Color(clrChannelDate), Theme.Color(clrBackground), cFont::GetFont(fontSml)); const cFont *font = cFont::GetFont(fontSml);
int w = font->Width(date);
osd->DrawText(osd->Width() - w - 2, 0, date, Theme.Color(clrChannelDate), Theme.Color(clrBackground), cFont::GetFont(fontSml), w);
} }
osd->Flush(); osd->Flush();
} }
@ -155,6 +162,7 @@ private:
int x0, x1; int x0, x1;
int y0, y1, y2, y3, y4, y5; int y0, y1, y2, y3, y4, y5;
int lineHeight; int lineHeight;
cString lastDate;
void SetScrollbar(void); void SetScrollbar(void);
public: public:
cSkinClassicDisplayMenu(void); cSkinClassicDisplayMenu(void);
@ -187,6 +195,10 @@ cSkinClassicDisplayMenu::cSkinClassicDisplayMenu(void)
y4 = y5 - lineHeight; y4 = y5 - lineHeight;
y3 = y4 - lineHeight; y3 = y4 - lineHeight;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop);
tArea Areas[] = { { x0, y0, x1 - 1, y5 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { x0, y0, x1 - 1, y5 - 1, 4 } }; tArea Areas[] = { { x0, y0, x1 - 1, y5 - 1, 4 } };
if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
@ -197,6 +209,7 @@ cSkinClassicDisplayMenu::cSkinClassicDisplayMenu(void)
}; };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
} }
}
osd->DrawRectangle(x0, y0, x1 - 1, y5 - 1, Theme.Color(clrBackground)); osd->DrawRectangle(x0, y0, x1 - 1, y5 - 1, Theme.Color(clrBackground));
} }
@ -305,9 +318,10 @@ void cSkinClassicDisplayMenu::SetEvent(const cEvent *Event)
ts.Set(osd, xl, y, x1 - xl, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground)); ts.Set(osd, xl, y, x1 - xl, y3 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
if (Event->Vps() && Event->Vps() != Event->StartTime()) { if (Event->Vps() && Event->Vps() != Event->StartTime()) {
char *buffer; char *buffer;
asprintf(&buffer, " VPS: %s", *Event->GetVpsString()); asprintf(&buffer, " VPS: %s ", *Event->GetVpsString());
const cFont *font = cFont::GetFont(fontSml); const cFont *font = cFont::GetFont(fontSml);
osd->DrawText(x1 - font->Width(buffer), y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font); int w = font->Width(buffer);
osd->DrawText(x1 - w, y, buffer, Theme.Color(clrMenuEventVpsFg), Theme.Color(clrMenuEventVpsBg), font, w);
free(buffer); free(buffer);
} }
y += ts.Height(); y += ts.Height();
@ -376,8 +390,12 @@ const cFont *cSkinClassicDisplayMenu::GetTextAreaFont(bool FixedFont) const
void cSkinClassicDisplayMenu::Flush(void) void cSkinClassicDisplayMenu::Flush(void)
{ {
cString date = DayDateTime(); cString date = DayDateTime();
if (!lastDate || strcmp(date, lastDate)) {
const cFont *font = cFont::GetFont(fontOsd); const cFont *font = cFont::GetFont(fontOsd);
osd->DrawText(x1 - font->Width(date) - 2, y0, date, Theme.Color(clrMenuDate), Theme.Color(clrMenuTitleBg), font); int w = font->Width(date);
osd->DrawText(x1 - w - 2, y0, date, Theme.Color(clrMenuDate), Theme.Color(clrMenuTitleBg), font, w);
lastDate = date;
}
osd->Flush(); osd->Flush();
} }
@ -414,8 +432,13 @@ cSkinClassicDisplayReplay::cSkinClassicDisplayReplay(bool ModeOnly)
y2 = 2 * lineHeight; y2 = 2 * lineHeight;
y3 = 3 * lineHeight; y3 = 3 * lineHeight;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y3); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y3);
tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 4 } }; tArea Areas[] = { { x0, y0, x1 - 1, y3 - 1, 4 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
osd->DrawRectangle(x0, y0, x1 - 1, y3 - 1, ModeOnly ? clrTransparent : Theme.Color(clrBackground)); osd->DrawRectangle(x0, y0, x1 - 1, y3 - 1, ModeOnly ? clrTransparent : Theme.Color(clrBackground));
} }
@ -455,14 +478,15 @@ void cSkinClassicDisplayReplay::SetCurrent(const char *Current)
{ {
const cFont *font = cFont::GetFont(fontOsd); const cFont *font = cFont::GetFont(fontOsd);
int w = font->Width(Current); int w = font->Width(Current);
osd->DrawText(x0, y2, Current, Theme.Color(clrReplayCurrent), Theme.Color(clrBackground), font, lastCurrentWidth > w ? lastCurrentWidth : 0); osd->DrawText(x0, y2, Current, Theme.Color(clrReplayCurrent), Theme.Color(clrBackground), font, lastCurrentWidth > w ? lastCurrentWidth : w);
lastCurrentWidth = w; lastCurrentWidth = w;
} }
void cSkinClassicDisplayReplay::SetTotal(const char *Total) void cSkinClassicDisplayReplay::SetTotal(const char *Total)
{ {
const cFont *font = cFont::GetFont(fontOsd); const cFont *font = cFont::GetFont(fontOsd);
osd->DrawText(x1 - font->Width(Total), y2, Total, Theme.Color(clrReplayTotal), Theme.Color(clrBackground), font); int w = font->Width(Total);
osd->DrawText(x1 - font->Width(Total), y2, Total, Theme.Color(clrReplayTotal), Theme.Color(clrBackground), font, w);
} }
void cSkinClassicDisplayReplay::SetJump(const char *Jump) void cSkinClassicDisplayReplay::SetJump(const char *Jump)
@ -503,8 +527,13 @@ cSkinClassicDisplayVolume::cSkinClassicDisplayVolume(void)
const cFont *font = cFont::GetFont(fontOsd); const cFont *font = cFont::GetFont(fontOsd);
int lineHeight = font->Height(); int lineHeight = font->Height();
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - lineHeight); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - lineHeight);
tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, lineHeight - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, lineHeight - 1, 4 } }; tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, lineHeight - 1, 4 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
} }
cSkinClassicDisplayVolume::~cSkinClassicDisplayVolume() cSkinClassicDisplayVolume::~cSkinClassicDisplayVolume()
@ -572,8 +601,13 @@ cSkinClassicDisplayTracks::cSkinClassicDisplayTracks(const char *Title, int NumT
y1 = lineHeight; y1 = lineHeight;
y2 = y1 + NumTracks * lineHeight; y2 = y1 + NumTracks * lineHeight;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y2); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y2);
tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 4 } }; tArea Areas[] = { { x0, y0, x1 - 1, y2 - 1, 4 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x1 - x0); osd->DrawText(x0, y0, Title, Theme.Color(clrMenuTitleFg), Theme.Color(clrMenuTitleBg), font, x1 - x0);
for (int i = 0; i < NumTracks; i++) for (int i = 0; i < NumTracks; i++)
SetItem(Tracks[i], i, false); SetItem(Tracks[i], i, false);
@ -630,8 +664,13 @@ cSkinClassicDisplayMessage::cSkinClassicDisplayMessage(void)
const cFont *font = cFont::GetFont(fontOsd); const cFont *font = cFont::GetFont(fontOsd);
int lineHeight = font->Height(); int lineHeight = font->Height();
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - lineHeight); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - lineHeight);
tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, lineHeight - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, lineHeight - 1, 2 } }; tArea Areas[] = { { 0, 0, Setup.OSDWidth - 1, lineHeight - 1, 2 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
} }
cSkinClassicDisplayMessage::~cSkinClassicDisplayMessage() cSkinClassicDisplayMessage::~cSkinClassicDisplayMessage()

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: skinsttng.c 1.19 2006/02/17 15:57:37 kls Exp $ * $Id: skinsttng.c 1.20 2007/06/10 12:40:43 kls Exp $
*/ */
// Star Trek: The Next Generation® is a registered trademark of Paramount Pictures // Star Trek: The Next Generation® is a registered trademark of Paramount Pictures
@ -178,8 +178,13 @@ cSkinSTTNGDisplayChannel::cSkinSTTNGDisplayChannel(bool WithInfo)
int yt = (y0 + y1) / 2; int yt = (y0 + y1) / 2;
int yb = (y6 + y7) / 2; int yb = (y6 + y7) / 2;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - y7)); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - y7));
tArea Areas[] = { { 0, 0, x7 - 1, y7 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { 0, 0, x7 - 1, y7 - 1, 4 } }; tArea Areas[] = { { 0, 0, x7 - 1, y7 - 1, 4 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, Theme.Color(clrBackground)); osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, Theme.Color(clrBackground));
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent); osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent); osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent);
@ -211,8 +216,13 @@ cSkinSTTNGDisplayChannel::cSkinSTTNGDisplayChannel(bool WithInfo)
y0 = 0; y0 = 0;
y1 = lineHeight; y1 = lineHeight;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - y1)); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + (Setup.ChannelInfoPos ? 0 : Setup.OSDHeight - y1));
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 4 } }; tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 4 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, clrTransparent); osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, clrTransparent);
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7); osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor); osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
@ -297,7 +307,7 @@ void cSkinSTTNGDisplayChannel::Flush(void)
const cFont *font = cFont::GetFont(fontSml); const cFont *font = cFont::GetFont(fontSml);
cString date = DayDateTime(); cString date = DayDateTime();
int w = font->Width(date); int w = font->Width(date);
osd->DrawText(x4 - w - 2, y7 - font->Height(date), date, Theme.Color(clrChannelDate), frameColor, font); osd->DrawText(x4 - w - 2, y7 - font->Height(), date, Theme.Color(clrChannelDate), frameColor, font, w);
cDevice *Device = cDevice::PrimaryDevice(); cDevice *Device = cDevice::PrimaryDevice();
const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack()); const tTrackId *Track = Device->GetTrack(Device->GetCurrentAudioTrack());
if (!Track && *lastTrackId.description || Track && strcmp(lastTrackId.description, Track->description)) { if (!Track && *lastTrackId.description || Track && strcmp(lastTrackId.description, Track->description)) {
@ -333,6 +343,7 @@ private:
tColor frameColor; tColor frameColor;
int currentIndex; int currentIndex;
bool message; bool message;
cString lastDate;
void SetScrollbar(void); void SetScrollbar(void);
public: public:
cSkinSTTNGDisplayMenu(void); cSkinSTTNGDisplayMenu(void);
@ -378,6 +389,10 @@ cSkinSTTNGDisplayMenu::cSkinSTTNGDisplayMenu(void)
int yt = (y0 + y1) / 2; int yt = (y0 + y1) / 2;
int yb = (y6 + y7) / 2; int yb = (y6 + y7) / 2;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop);
tArea Areas[] = { { x0, y0, x7 - 1, y7 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { x0, y0, x7 - 1, y7 - 1, 4 } }; tArea Areas[] = { { x0, y0, x7 - 1, y7 - 1, 4 } };
if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
@ -390,6 +405,7 @@ cSkinSTTNGDisplayMenu::cSkinSTTNGDisplayMenu(void)
}; };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
} }
}
osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, Theme.Color(clrBackground)); osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, Theme.Color(clrBackground));
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent); osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent); osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent);
@ -465,7 +481,7 @@ void cSkinSTTNGDisplayMenu::SetTitle(const char *Title)
const char *VDR = " VDR"; const char *VDR = " VDR";
int w = font->Width(VDR); int w = font->Width(VDR);
osd->DrawText(x3 + 5, y0, Title, Theme.Color(clrMenuTitle), frameColor, font, x4 - w - x3 - 5); osd->DrawText(x3 + 5, y0, Title, Theme.Color(clrMenuTitle), frameColor, font, x4 - w - x3 - 5);
osd->DrawText(x4 - w, y0, VDR, frameColor, clrBlack, font); osd->DrawText(x4 - w, y0, VDR, frameColor, clrBlack, font, w, lineHeight);
} }
void cSkinSTTNGDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue) void cSkinSTTNGDisplayMenu::SetButtons(const char *Red, const char *Green, const char *Yellow, const char *Blue)
@ -551,9 +567,10 @@ void cSkinSTTNGDisplayMenu::SetEvent(const cEvent *Event)
ts.Set(osd, xl, y, x4 - xl, y4 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground)); ts.Set(osd, xl, y, x4 - xl, y4 - y, t, font, Theme.Color(clrMenuEventTime), Theme.Color(clrBackground));
if (Event->Vps() && Event->Vps() != Event->StartTime()) { if (Event->Vps() && Event->Vps() != Event->StartTime()) {
char *buffer; char *buffer;
asprintf(&buffer, " VPS: %s", *Event->GetVpsString()); asprintf(&buffer, " VPS: %s ", *Event->GetVpsString());
const cFont *font = cFont::GetFont(fontSml); const cFont *font = cFont::GetFont(fontSml);
osd->DrawText(x4 - font->Width(buffer), y, buffer, Theme.Color(clrMenuEventVps), frameColor, font); int w = font->Width(buffer);
osd->DrawText(x4 - w, y, buffer, Theme.Color(clrMenuEventVps), frameColor, font, w);
int yb = y + font->Height(); int yb = y + font->Height();
osd->DrawRectangle(x5, y, x6 - 1, yb - 1, frameColor); osd->DrawRectangle(x5, y, x6 - 1, yb - 1, frameColor);
osd->DrawEllipse (x6, y, x7 - 1, yb - 1, frameColor, 5); osd->DrawEllipse (x6, y, x7 - 1, yb - 1, frameColor, 5);
@ -640,8 +657,12 @@ void cSkinSTTNGDisplayMenu::Flush(void)
{ {
if (!message) { if (!message) {
cString date = DayDateTime(); cString date = DayDateTime();
if (!lastDate || strcmp(date, lastDate)) {
const cFont *font = cFont::GetFont(fontSml); const cFont *font = cFont::GetFont(fontSml);
osd->DrawText(x4 - font->Width(date) - 2, y7 - font->Height(date), date, Theme.Color(clrMenuDate), frameColor, font); int w = font->Width(date);
osd->DrawText(x4 - w - 2, y7 - font->Height(), date, Theme.Color(clrMenuDate), frameColor, font, w);
lastDate = date;
}
} }
osd->Flush(); osd->Flush();
} }
@ -697,8 +718,13 @@ cSkinSTTNGDisplayReplay::cSkinSTTNGDisplayReplay(bool ModeOnly)
int yt = (y0 + y1) / 2; int yt = (y0 + y1) / 2;
int yb = (y6 + y7) / 2; int yb = (y6 + y7) / 2;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y7); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y7);
tArea Areas[] = { { 0, 0, x7 - 1, y7 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { 0, 0, x7 - 1, y7 - 1, 4 } }; tArea Areas[] = { { 0, 0, x7 - 1, y7 - 1, 4 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, ModeOnly ? clrTransparent : Theme.Color(clrBackground)); osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, ModeOnly ? clrTransparent : Theme.Color(clrBackground));
if (!ModeOnly) { if (!ModeOnly) {
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent); osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
@ -760,14 +786,15 @@ void cSkinSTTNGDisplayReplay::SetCurrent(const char *Current)
{ {
const cFont *font = cFont::GetFont(fontSml); const cFont *font = cFont::GetFont(fontSml);
int w = font->Width(Current); int w = font->Width(Current);
osd->DrawText(x3, y6, Current, Theme.Color(clrReplayCurrent), frameColor, font, lastCurrentWidth > w ? lastCurrentWidth : 0); osd->DrawText(x3, y6, Current, Theme.Color(clrReplayCurrent), frameColor, font, lastCurrentWidth > w ? lastCurrentWidth : w);
lastCurrentWidth = w; lastCurrentWidth = w;
} }
void cSkinSTTNGDisplayReplay::SetTotal(const char *Total) void cSkinSTTNGDisplayReplay::SetTotal(const char *Total)
{ {
const cFont *font = cFont::GetFont(fontSml); const cFont *font = cFont::GetFont(fontSml);
osd->DrawText(x4 - font->Width(Total) - 5, y6, Total, Theme.Color(clrReplayTotal), frameColor, font); int w = font->Width(Total);
osd->DrawText(x4 - w - 5, y6, Total, Theme.Color(clrReplayTotal), frameColor, font, w);
} }
void cSkinSTTNGDisplayReplay::SetJump(const char *Jump) void cSkinSTTNGDisplayReplay::SetJump(const char *Jump)
@ -825,8 +852,13 @@ cSkinSTTNGDisplayVolume::cSkinSTTNGDisplayVolume(void)
y0 = 0; y0 = 0;
y1 = lineHeight; y1 = lineHeight;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y1); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y1);
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 4 } }; tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 4 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, clrTransparent); osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, clrTransparent);
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7); osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor); osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);
@ -935,6 +967,10 @@ cSkinSTTNGDisplayTracks::cSkinSTTNGDisplayTracks(const char *Title, int NumTrack
int yt = (y0 + y1) / 2; int yt = (y0 + y1) / 2;
int yb = (y6 + y7) / 2; int yb = (y6 + y7) / 2;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y7); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y7);
tArea Areas[] = { { x0, y0, x7 - 1, y7 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { x0, y0, x7 - 1, y7 - 1, 4 } }; tArea Areas[] = { { x0, y0, x7 - 1, y7 - 1, 4 } };
if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk) if (osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
@ -947,6 +983,7 @@ cSkinSTTNGDisplayTracks::cSkinSTTNGDisplayTracks(const char *Title, int NumTrack
}; };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
} }
}
osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, Theme.Color(clrBackground)); osd->DrawRectangle(x0, y0, x7 - 1, y7 - 1, Theme.Color(clrBackground));
osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent); osd->DrawRectangle(x0, y0, x1 - 1, y1 - 1, clrTransparent);
osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent); osd->DrawRectangle(x0, y6, x1 - 1, y7 - 1, clrTransparent);
@ -1057,8 +1094,13 @@ cSkinSTTNGDisplayMessage::cSkinSTTNGDisplayMessage(void)
y0 = 0; y0 = 0;
y1 = lineHeight; y1 = lineHeight;
osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y1); osd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop + Setup.OSDHeight - y1);
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 8 } };
if (Setup.AntiAlias && osd->CanHandleAreas(Areas, sizeof(Areas) / sizeof(tArea)) == oeOk)
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
else {
tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 2 } }; tArea Areas[] = { { x0, y0, x7 - 1, y1 - 1, 2 } };
osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea)); osd->SetAreas(Areas, sizeof(Areas) / sizeof(tArea));
}
osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, clrTransparent); osd->DrawRectangle(x0, y0, x7 - 1, y1 - 1, clrTransparent);
osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7); osd->DrawEllipse (x0, y0, x1 - 1, y1 - 1, frameColor, 7);
osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor); osd->DrawRectangle(x1, y0, x2 - 1, y1 - 1, frameColor);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: timers.c 1.65 2006/09/15 14:15:53 kls Exp $ * $Id: timers.c 1.66 2007/06/03 13:48:57 kls Exp $
*/ */
#include "timers.h" #include "timers.h"
@ -136,7 +136,7 @@ cString cTimer::ToText(bool UseChannelID)
{ {
char *buffer; char *buffer;
strreplace(file, ':', '|'); strreplace(file, ':', '|');
asprintf(&buffer, "%u:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays), start, stop, priority, lifetime, file, aux ? aux : ""); asprintf(&buffer, "%u:%s:%s:%04d:%04d:%d:%d:%s:%s\n", flags, UseChannelID ? *Channel()->GetChannelID().ToString() : *itoa(Channel()->Number()), *PrintDay(day, weekdays, true), start, stop, priority, lifetime, file, aux ? aux : "");
strreplace(file, '|', ':'); strreplace(file, '|', ':');
return cString(buffer, true); return cString(buffer, true);
} }
@ -212,17 +212,26 @@ bool cTimer::ParseDay(const char *s, time_t &Day, int &WeekDays)
return true; return true;
} }
cString cTimer::PrintDay(time_t Day, int WeekDays) cString cTimer::PrintDay(time_t Day, int WeekDays, bool SingleByteChars)
{ {
#define DAYBUFFERSIZE 32 #define DAYBUFFERSIZE 64
char buffer[DAYBUFFERSIZE]; char buffer[DAYBUFFERSIZE];
char *b = buffer; char *b = buffer;
if (WeekDays) { if (WeekDays) {
const char *w = tr("MTWTFSS"); const char *w = "MTWTFSS";
if (!SingleByteChars)
w = tr(w);
while (*w) { while (*w) {
*b++ = (WeekDays & 1) ? *w : '-'; int sl = Utf8CharLen(w);
if (WeekDays & 1) {
for (int i = 0; i < sl; i++)
b[i] = w[i];
b += sl;
}
else
*b++ = '-';
WeekDays >>= 1; WeekDays >>= 1;
w++; w += sl;
} }
if (Day) if (Day)
*b++ = '@'; *b++ = '@';
@ -239,7 +248,7 @@ cString cTimer::PrintDay(time_t Day, int WeekDays)
cString cTimer::PrintFirstDay(void) const cString cTimer::PrintFirstDay(void) const
{ {
if (weekdays) { if (weekdays) {
cString s = PrintDay(day, weekdays); cString s = PrintDay(day, weekdays, true);
if (strlen(s) == 18) if (strlen(s) == 18)
return *s + 8; return *s + 8;
} }

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: timers.h 1.29 2006/09/04 17:07:39 kls Exp $ * $Id: timers.h 1.30 2007/06/03 13:24:58 kls Exp $
*/ */
#ifndef __TIMERS_H #ifndef __TIMERS_H
@ -94,7 +94,7 @@ public:
cString PrintFirstDay(void) const; cString PrintFirstDay(void) const;
static int TimeToInt(int t); static int TimeToInt(int t);
static bool ParseDay(const char *s, time_t &Day, int &WeekDays); static bool ParseDay(const char *s, time_t &Day, int &WeekDays);
static cString PrintDay(time_t Day, int WeekDays); static cString PrintDay(time_t Day, int WeekDays, bool SingleByteChars);
}; };
class cTimers : public cConfig<cTimer> { class cTimers : public cConfig<cTimer> {

264
tools.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.c 1.122 2007/01/07 14:44:57 kls Exp $ * $Id: tools.c 1.123 2007/06/09 14:21:21 kls Exp $
*/ */
#include "tools.h" #include "tools.h"
@ -570,6 +570,221 @@ uint64_t cTimeMs::Elapsed(void)
return Now() - begin; return Now() - begin;
} }
// --- UTF-8 support ---------------------------------------------------------
static uint SystemToUtf8[128] = { 0 };
int Utf8CharLen(const char *s)
{
if (cCharSetConv::SystemCharacterTable())
return 1;
#define MT(s, m, v) ((*(s) & (m)) == (v)) // Mask Test
if (MT(s, 0xE0, 0xC0) && MT(s + 1, 0xC0, 0x80))
return 2;
if (MT(s, 0xF0, 0xE0) && MT(s + 1, 0xC0, 0x80) && MT(s + 2, 0xC0, 0x80))
return 3;
if (MT(s, 0xF8, 0xF0) && MT(s + 1, 0xC0, 0x80) && MT(s + 2, 0xC0, 0x80) && MT(s + 3, 0xC0, 0x80))
return 4;
return 1;
}
uint Utf8CharGet(const char *s, int Length)
{
if (cCharSetConv::SystemCharacterTable())
return (uchar)*s < 128 ? *s : SystemToUtf8[(uchar)*s - 128];
if (!Length)
Length = Utf8CharLen(s);
switch (Length) {
case 2: return ((*s & 0x1F) << 6) | (*(s + 1) & 0x3F);
case 3: return ((*s & 0x0F) << 4) | ((*(s + 1) & 0x3F) << 6) | (*(s + 2) & 0x3F);
case 4: return ((*s & 0x07) << 2) | ((*(s + 1) & 0x3F) << 4) | ((*(s + 2) & 0x3F) << 6) | (*(s + 3) & 0x3F);
}
return *s;
}
int Utf8CharSet(uint c, char *s)
{
if (c < 0x80 || cCharSetConv::SystemCharacterTable()) {
if (s)
*s = c;
return 1;
}
if (c < 0x800) {
if (s) {
*s++ = ((c >> 6) & 0x1F) | 0xC0;
*s = (c & 0x3F) | 0x80;
}
return 2;
}
if (c < 0x10000) {
if (s) {
*s++ = ((c >> 12) & 0x0F) | 0xE0;
*s++ = ((c >> 6) & 0x3F) | 0x80;
*s = (c & 0x3F) | 0x80;
}
return 3;
}
if (c < 0x110000) {
if (s) {
*s++ = ((c >> 18) & 0x07) | 0xF0;
*s++ = ((c >> 12) & 0x3F) | 0x80;
*s++ = ((c >> 6) & 0x3F) | 0x80;
*s = (c & 0x3F) | 0x80;
}
return 4;
}
return 0; // can't convert to UTF-8
}
int Utf8SymChars(const char *s, int Symbols)
{
if (cCharSetConv::SystemCharacterTable())
return Symbols;
int n = 0;
while (*s && Symbols--) {
int sl = Utf8CharLen(s);
s += sl;
n += sl;
}
return n;
}
int Utf8ToArray(const char *s, uint *a, int Size)
{
int n = 0;
while (*s && --Size > 0) {
if (cCharSetConv::SystemCharacterTable())
*a++ = *s++;
else {
int sl = Utf8CharLen(s);
*a++ = Utf8CharGet(s, sl);
s += sl;
}
n++;
}
if (Size > 0)
*a = 0;
return n;
}
int Utf8FromArray(const uint *a, char *s, int Size, int Max)
{
int NumChars = 0;
int NumSyms = 0;
while (*a && NumChars < Size) {
if (Max >= 0 && NumSyms++ >= Max)
break;
if (cCharSetConv::SystemCharacterTable()) {
*s++ = *a++;
NumChars++;
}
else {
int sl = Utf8CharSet(*a);
if (NumChars + sl <= Size) {
Utf8CharSet(*a, s);
a++;
s += sl;
NumChars += sl;
}
else
break;
}
}
if (NumChars < Size)
*s = 0;
return NumChars;
}
// --- cCharSetConv ----------------------------------------------------------
char *cCharSetConv::systemCharacterTable = NULL;
cCharSetConv::cCharSetConv(const char *FromCode, const char *ToCode)
{
if (!FromCode)
FromCode = systemCharacterTable;
if (!ToCode)
ToCode = "UTF-8";
cd = (FromCode && ToCode) ? iconv_open(ToCode, FromCode) : (iconv_t)-1;
result = NULL;
length = 0;
}
cCharSetConv::~cCharSetConv()
{
free(result);
iconv_close(cd);
}
void cCharSetConv::SetSystemCharacterTable(const char *CharacterTable)
{
free(systemCharacterTable);
systemCharacterTable = NULL;
if (!strcasestr(CharacterTable, "UTF")) {
// Set up a map for the character values 128...255:
char buf[129];
for (int i = 0; i < 128; i++)
buf[i] = i + 128;
buf[129] = 0;
cCharSetConv csc(CharacterTable);
const char *s = csc.Convert(buf);
int i = 0;
while (*s) {
int sl = Utf8CharLen(s);
SystemToUtf8[i] = Utf8CharGet(s, sl);
s += sl;
i++;
}
systemCharacterTable = strdup(CharacterTable);
}
}
const char *cCharSetConv::Convert(const char *From, char *To, size_t ToLength)
{
if (cd != (iconv_t)-1) {
char *FromPtr = (char *)From;
size_t FromLength = strlen(From);
char *ToPtr = To;
if (!ToPtr) {
length = max(length, FromLength * 2); // some reserve to avoid later reallocations
result = (char *)realloc(result, length);
ToPtr = result;
ToLength = length;
}
else if (!ToLength)
return From; // can't convert into a zero sized buffer
ToLength--; // save space for terminating 0
char *Converted = ToPtr;
while (FromLength > 0) {
if (iconv(cd, &FromPtr, &FromLength, &ToPtr, &ToLength) == size_t(-1)) {
if (errno == E2BIG || errno == EILSEQ && ToLength < 1) {
if (To)
break; // caller provided a fixed size buffer, but it was too small
// The result buffer is too small, so increase it:
size_t d = ToPtr - result;
size_t r = length / 2;
length += r;
result = (char *)realloc(result, length);
ToLength += r;
ToPtr = result + d;
}
if (errno == EILSEQ) {
// A character can't be converted, so mark it with '?' and proceed:
FromPtr++;
FromLength--;
*ToPtr++ = '?';
ToLength--;
}
else if (errno != E2BIG)
return From; // unknown error, return original string
}
}
*ToPtr = 0;
return Converted;
}
return From;
}
// --- cString --------------------------------------------------------------- // --- cString ---------------------------------------------------------------
cString::cString(const char *S, bool TakePointer) cString::cString(const char *S, bool TakePointer)
@ -607,12 +822,12 @@ cString cString::sprintf(const char *fmt, ...)
cString WeekDayName(int WeekDay) cString WeekDayName(int WeekDay)
{ {
char buffer[4]; char buffer[16];
WeekDay = WeekDay == 0 ? 6 : WeekDay - 1; // we start with Monday==0! WeekDay = WeekDay == 0 ? 6 : WeekDay - 1; // we start with Monday==0!
if (0 <= WeekDay && WeekDay <= 6) { if (0 <= WeekDay && WeekDay <= 6) {
const char *day = tr("MonTueWedThuFriSatSun"); const char *day = tr("MonTueWedThuFriSatSun");
day += WeekDay * 3; day += Utf8SymChars(day, WeekDay * 3);
strn0cpy(buffer, day, sizeof(buffer)); strn0cpy(buffer, day, min(Utf8SymChars(day, 3) + 1, int(sizeof(buffer))));
return buffer; return buffer;
} }
else else
@ -890,6 +1105,47 @@ struct dirent *cReadDir::Next(void)
return directory && readdir_r(directory, &u.d, &result) == 0 ? result : NULL; return directory && readdir_r(directory, &u.d, &result) == 0 ? result : NULL;
} }
// --- cFileNameList ---------------------------------------------------------
cFileNameList::cFileNameList(const char *Directory)
{
Load(Directory);
}
cFileNameList::~cFileNameList()
{
for (int i = 0; i < Size(); i++)
free(At(i));
}
bool cFileNameList::Load(const char *Directory)
{
if (Directory) {
cReadDir d(Directory);
struct dirent *e;
if (d.Ok()) {
while ((e = d.Next()) != NULL) {
if (strcmp(e->d_name, ".") && strcmp(e->d_name, ".."))
Append(strdup(e->d_name));
}
Sort(CompareStrings);
return true;
}
else
LOG_ERROR_STR(Directory);
}
return false;
}
int cFileNameList::Find(const char *FileName)
{
for (int i = 0; i < Size(); i++) {
if (!strcmp(FileName, At(i)))
return i;
}
return -1;
}
// --- cFile ----------------------------------------------------------------- // --- cFile -----------------------------------------------------------------
bool cFile::files[FD_SETSIZE] = { false }; bool cFile::files[FD_SETSIZE] = { false };

126
tools.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: tools.h 1.97 2007/01/07 14:45:11 kls Exp $ * $Id: tools.h 1.98 2007/06/10 08:46:23 kls Exp $
*/ */
#ifndef __TOOLS_H #ifndef __TOOLS_H
@ -13,10 +13,12 @@
#include <dirent.h> #include <dirent.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <iconv.h>
#include <poll.h> #include <poll.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <syslog.h> #include <syslog.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -72,6 +74,73 @@ template<class T> inline void put_unaligned(unsigned int v, T* p)
((s *)p)->v = v; ((s *)p)->v = v;
} }
// When handling strings that might contain UTF-8 characters, it may be necessary
// to process a "symbol" that consists of several actual character bytes. The
// following functions allow transparently accessing a "char *" string without
// having to worry about what character set is actually used.
int Utf8CharLen(const char *s);
///< Returns the number of character bytes at the beginning of the given
///< string that form a UTF-8 symbol.
uint Utf8CharGet(const char *s, int Length = 0);
///< Returns the UTF-8 symbol at the beginning of the given string.
///< Length can be given from a previous call to Utf8CharLen() to avoid calculating
///< it again. If no Length is given, Utf8CharLen() will be called.
int Utf8CharSet(uint c, char *s = NULL);
///< Converts the given UTF-8 symbol to a sequence of character bytes and copies
///< them to the given string. Returns the number of bytes written. If no string
///< is given, only the number of bytes is returned and nothing is copied.
int Utf8SymChars(const char *s, int Symbols);
///< Returns the number of character bytes at the beginning of the given
///< string that form at most the given number of UTF-8 Symbols.
int Utf8ToArray(const char *s, uint *a, int Size);
///< Converts the given character bytes (including the terminating 0) into an
///< array of UTF-8 symbols of the given Size. Returns the number of symbols
///< in the array (without the terminating 0).
int Utf8FromArray(const uint *a, char *s, int Size, int Max = -1);
///< Converts the given array of UTF-8 symbols (including the terminating 0)
///< into a sequence of character bytes of at most Size length. Returns the
///< number of character bytes written (without the terminating 0).
///< If Max is given, only that many symbols will be converted.
///< The resulting string is always zero-terminated if Size is big enough.
// When allocating buffer space, make sure we reserve enough space to hold
// a string in UTF-8 representation:
#define Utf8BufSize(s) ((s) * 4)
// The following macros automatically use the correct versions of the character
// class functions:
#define Utf8to(conv, c) (cCharSetConv::SystemCharacterTable() ? to##conv(c) : tow##conv(c))
#define Utf8is(ccls, c) (cCharSetConv::SystemCharacterTable() ? is##ccls(c) : isw##ccls(c))
class cCharSetConv {
private:
iconv_t cd;
char *result;
size_t length;
static char *systemCharacterTable;
public:
cCharSetConv(const char *FromCode = NULL, const char *ToCode = NULL);
///< Sets up a character set converter to convert from FromCode to ToCode.
///< If FromCode is NULL, the previously set systemCharacterTable is used.
///< If ToCode is NULL, "UTF-8" is used.
~cCharSetConv();
const char *Convert(const char *From, char *To = NULL, size_t ToLength = 0);
///< Converts the given Text from FromCode to ToCode (as set in the cosntructor).
///< If To is given, it is used to copy at most ToLength bytes of the result
///< (including the terminating 0) into that buffer. If To is not given,
///< the result is copied into a dynamically allocated buffer and is valid as
///< long as this object lives, or until the next call to Convert(). The
///< return value always points to the result if the conversion was successful
///< (even if a fixed size To buffer was given and the result didn't fit into
///< it). If the string could not be converted, the result points to the
///< original From string.
static const char *SystemCharacterTable(void) { return systemCharacterTable; }
static void SetSystemCharacterTable(const char *CharacterTable);
};
class cString { class cString {
private: private:
char *s; char *s;
@ -320,6 +389,61 @@ public:
T *Next(const T *object) const { return (T *)object->cListObject::Next(); } // avoid ambiguities in case of a "list of lists" T *Next(const T *object) const { return (T *)object->cListObject::Next(); } // avoid ambiguities in case of a "list of lists"
}; };
template<class T> class cVector {
private:
mutable int allocated;
mutable int size;
mutable T *data;
void Realloc(int NewAllocated) const { data = (T *)realloc(data, (allocated = NewAllocated) * sizeof(T)); }
public:
cVector(int Allocated = 10)
{
allocated = 0;
size = 0;
data = NULL;
Realloc(Allocated);
}
virtual ~cVector() { free(data); }
T& At(int Index) const
{
if (Index >= size)
Realloc(size = Index + 1);
return data[Index];
}
const T& operator[](int Index) const
{
return At(Index);
}
T& operator[](int Index)
{
return At(Index);
}
int Size(void) const { return size; }
virtual void Append(T Data)
{
if (size >= allocated)
Realloc(allocated * 4 / 2); // increase size by 50%
data[size++] = Data;
}
void Sort(__compar_fn_t Compare)
{
qsort(data, size, sizeof(T), Compare);
}
};
inline int CompareStrings(const void *a, const void *b)
{
return strcmp(*(const char **)a, *(const char **)b);
}
class cFileNameList : public cVector<char *> {
public:
cFileNameList(const char *Directory = NULL);
virtual ~cFileNameList();
bool Load(const char *Directory);
int Find(const char *FileName);
};
class cHashObject : public cListObject { class cHashObject : public cListObject {
friend class cHashBase; friend class cHashBase;
private: private:

11
vdr.5
View File

@ -8,7 +8,7 @@
.\" License as specified in the file COPYING that comes with the .\" License as specified in the file COPYING that comes with the
.\" vdr distribution. .\" vdr distribution.
.\" .\"
.\" $Id: vdr.5 1.61 2007/01/07 14:04:12 kls Exp $ .\" $Id: vdr.5 1.62 2007/06/03 13:21:34 kls Exp $
.\" .\"
.TH vdr 5 "07 Jan 2007" "1.4.5" "Video Disk Recorder Files" .TH vdr 5 "07 Jan 2007" "1.4.5" "Video Disk Recorder Files"
.SH NAME .SH NAME
@ -249,9 +249,14 @@ cause the timer to record on that day. Example:
.B MTWTF\-\- .B MTWTF\-\-
will define a timer that records on Monday through Friday and does not record will define a timer that records on Monday through Friday and does not record
on weekends. The same result could be achieved with \fBABCDE\-\-\fR (this is on weekends.
used to allow setting the days with language specific characters).
Note that only letters may be used here, no digits. Note that only letters may be used here, no digits.
For compatibility with timers created with earlier versions of VDR,
the same result could be achieved with \fBABCDE\-\-\fR (which was
used to allow setting the days with language specific characters).
Since version 1.5.3 VDR can use UTF-8 characters to present data to
the user, but the weekday encoding in the \fItimers.conf\fR file
always uses single byte characters.
The day definition of a `repeating' timer may be followed by the date when that The day definition of a `repeating' timer may be followed by the date when that
timer shall hit for the first time. The format for this is \fB@YYYY\-MM\-DD\fR, timer shall hit for the first time. The format for this is \fB@YYYY\-MM\-DD\fR,

5
vdr.c
View File

@ -22,7 +22,7 @@
* *
* The project's page is at http://www.cadsoft.de/vdr * The project's page is at http://www.cadsoft.de/vdr
* *
* $Id: vdr.c 1.290 2007/05/12 09:35:07 kls Exp $ * $Id: vdr.c 1.291 2007/06/09 12:33:53 kls Exp $
*/ */
#include <getopt.h> #include <getopt.h>
@ -502,6 +502,7 @@ int main(int argc, char *argv[])
CodeSet++; // skip the dot CodeSet++; // skip the dot
bool known = SI::SetSystemCharacterTable(CodeSet); bool known = SI::SetSystemCharacterTable(CodeSet);
isyslog("codeset is '%s' - %s", CodeSet, known ? "known" : "unknown"); isyslog("codeset is '%s' - %s", CodeSet, known ? "known" : "unknown");
cCharSetConv::SetSystemCharacterTable(CodeSet);
} }
} }
@ -544,8 +545,6 @@ int main(int argc, char *argv[])
)) ))
EXIT(2); EXIT(2);
cFont::SetCode(I18nCharSets()[Setup.OSDLanguage]);
// Recordings: // Recordings:
Recordings.Update(); Recordings.Update();