Ticket #8695: translation-infrastructure.patch

File translation-infrastructure.patch, 19.4 KB (added by jvprat, 17 years ago)

Translation core

  • configure

     
    6868_nasm=auto
    6969_build_hq_scalers=yes
    7070_build_scalers=yes
     71_translation=yes
    7172# more defaults
    7273_backend=sdl
    7374_ranlib=ranlib
     
    345346  --disable-mt32emu        don't enable the integrated MT-32 emulator
    346347  --disable-hq-scalers     exclude HQ2x and HQ3x scalers
    347348  --disable-scalers        exclude scalers
     349  --disable-translation    don't build support for translated messages
    348350
    349351Optional Libraries:
    350352  --with-alsa-prefix=DIR   Prefix where alsa is installed (optional)
     
    432434      --enable-plugins)         _build_plugins=yes ;;
    433435      --enable-mt32emu)         _mt32emu=yes    ;;
    434436      --disable-mt32emu)        _mt32emu=no     ;;
     437      --enable-translation)     _translation=yes ;;
     438      --disable-translation)    _translation=no ;;
    435439      --with-fluidsynth-prefix=*)
    436440        arg=`echo $ac_option | cut -d '=' -f 2`
    437441        FLUIDSYNTH_CFLAGS="-I$arg/include"
     
    12491253        add_flag_to_config_mk_if_no yes 'USE_MPEG2'
    12501254fi
    12511255echo "$_mpeg2"
    1252 rm -f $TMPC $TMPO$EXEEXT
    12531256
    12541257#
    12551258# Check for libfluidsynth
     
    12711274        _def_fluidsynth='#undef USE_FLUIDSYNTH'
    12721275fi
    12731276echo "$_fluidsynth"
    1274 rm -f $TMPC $TMPO$EXEEXT
    12751277
    12761278#
    12771279# Check for nasm
     
    12891291fi
    12901292
    12911293#
     1294# Check whether to build translation support
     1295#
     1296echo_n "Building translation support... "
     1297_def_detectlang='#undef DETECTLANG'
     1298_def_termconv='#undef TERMCONV'
     1299if test "$_translation" = no ; then
     1300        echo "no"
     1301        _def_translation='#undef TRANSLATION'
     1302        add_flag_to_config_mk_if_no yes 'ENABLE_TRANSLATION'
     1303else
     1304        echo_n "yes ("
     1305        _def_translation='#define TRANSLATION'
     1306        add_flag_to_config_mk_if_no no 'ENABLE_TRANSLATION'
     1307
     1308        _detectlang=no
     1309        cat > $TMPC << EOF
     1310#include <locale.h>
     1311int main(void) { setlocale(LC_ALL, ""); return 0; }
     1312EOF
     1313        cc_check $LDFLAGS $CXXFLAGS && _detectlang=yes
     1314
     1315        if test "$_detectlang" = yes ; then
     1316                echo_n "with runtime language detection, "
     1317                _def_detectlang='#define DETECTLANG'
     1318
     1319                _termconv=no
     1320                cat > $TMPC << EOF
     1321#include <langinfo.h>
     1322#include <iconv.h>
     1323int main(void) { nl_langinfo(CODESET); iconv_open(0, 0); return 0; }
     1324EOF
     1325                cc_check $LDFLAGS $CXXFLAGS && _termconv=yes
     1326
     1327                if test "$_termconv" = yes ; then
     1328                        echo "with terminal conversion)"
     1329                        _def_termconv='#define TERMCONV'
     1330                else
     1331                        echo "without terminal conversion)"
     1332                fi
     1333        else
     1334                echo "without runtime language detection)"
     1335        fi
     1336fi
     1337rm -f $TMPC $TMPO$EXEEXT
     1338
     1339#
    12921340# figure out installation directories
    12931341#
    12941342test -z "$_bindir" && _bindir="$_prefix/bin"
     
    14561504$_def_fluidsynth
    14571505$_def_mt32emu
    14581506
     1507/* Whether we should use messages translation */
     1508$_def_translation
     1509$_def_detectlang
     1510$_def_termconv
     1511
    14591512/* Whether we should use i386 assembly routines */
    14601513$_def_nasm
    14611514
  • common/module.mk

     
    1313        stream.o \
    1414        util.o \
    1515        system.o \
     16        translation.o \
    1617        unzip.o
    1718
     19ifdef ENABLE_TRANSLATION
     20common/translation.cpp: common/messages.cpp
     21
     22common/messages.cpp: $(wildcard po/*.po)
     23        tools/po2c $^ > common/messages.cpp
     24endif
     25
    1826# Include common rules
    1927include $(srcdir)/rules.mk
  • Makefile.common

     
    3939        graphics \
    4040        sound \
    4141        common \
    42         backends
     42        backends \
     43        po
    4344
    4445ifdef USE_MT32EMU
    4546MODULES += sound/softsynth/mt32
  • common/translation.h

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 */
     24
     25#ifndef COMMON_TRANSLATION_H
     26#define COMMON_TRANSLATION_H
     27
     28#include "common/stdafx.h"
     29#include "common/singleton.h"
     30#include "common/str.h"
     31
     32#ifdef TERMCONV
     33#include <iconv.h>
     34#endif // TERMCONV
     35
     36namespace Common {
     37
     38/**
     39 * Message translation manager.
     40 */
     41class TranslationManager : public Singleton<TranslationManager> {
     42private:
     43        char _syslang[6];
     44
     45#ifdef TERMCONV
     46        iconv_t _conversion;
     47        char* _convmsg;
     48        int _sizeconv;
     49#endif // TERMCONV
     50
     51public:
     52        /**
     53         * The constructor selects the translation language and determines
     54         * whether there's need for character set conversions.
     55         */
     56        TranslationManager();
     57
     58        ~TranslationManager();
     59
     60        /**
     61         * Sets the current translation language to the one specified in the
     62         * parameter. If the parameter is an empty string, it sets the default
     63         * system language.
     64         */
     65        void setLanguage(const char* lang);
     66
     67        /**
     68         * Returns the translation into the current language of the parameter
     69         * message. In case the message isn't found in the translation catalog,
     70         * it returns the original untranslated message.
     71         */
     72        const char* getTranslation(const char* message);
     73
     74        /**
     75         * Converts the message into the terminal character set (which may be
     76         * different than the GUI's "native" one.
     77         */
     78        const char* convertTerm(const char* message);
     79};
     80
     81}       // End of namespace Common
     82
     83#ifdef TRANSLATION
     84#define _(str) Common::TranslationManager::instance().getTranslation(str)
     85#define _t(str) Common::TranslationManager::instance().convertTerm(_(str))
     86#else
     87#define _(str) str
     88#define _t(str) str
     89#endif
     90
     91#endif
  • common/translation.cpp

     
     1/* ScummVM - Graphic Adventure Engine
     2 *
     3 * ScummVM is the legal property of its developers, whose names
     4 * are too numerous to list here. Please refer to the COPYRIGHT
     5 * file distributed with this source distribution.
     6 *
     7 * This program is free software; you can redistribute it and/or
     8 * modify it under the terms of the GNU General Public License
     9 * as published by the Free Software Foundation; either version 2
     10 * of the License, or (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 *
     17 * You should have received a copy of the GNU General Public License
     18 * along with this program; if not, write to the Free Software
     19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
     20 *
     21 * $URL$
     22 * $Id$
     23 */
     24
     25#include "translation.h"
     26
     27DECLARE_SINGLETON(Common::TranslationManager);
     28
     29#ifdef TRANSLATION
     30#include "messages.cpp"
     31#endif
     32
     33#ifdef DETECTLANG
     34#include <langinfo.h>
     35#endif
     36
     37#ifdef TERMCONV
     38#include <locale.h>
     39#endif
     40
     41namespace Common {
     42
     43
     44#ifdef TRANSLATION
     45
     46
     47// Translation enabled
     48
     49TranslationManager::TranslationManager()
     50{
     51#ifdef DETECTLANG
     52        // Activating current locale settings
     53        const char* locale = setlocale(LC_ALL, "");
     54
     55        // Detect the language from the locale
     56        if (!locale) {
     57                strcpy(_syslang, "C");
     58        } else {
     59                int len = strlen(locale);
     60                if (len > 5)
     61                        len = 5;
     62                strncpy(_syslang, locale, len);
     63                _syslang[len] = 0;
     64        }
     65#else // DETECTLANG
     66        strcpy(_syslang, "C");
     67#endif // DETECTLANG
     68
     69#ifdef TERMCONV
     70        _convmsg = NULL;
     71        _conversion = NULL;
     72#endif // TERMCONV
     73
     74        //TODO: Get the language from the config
     75        /*printf("domini actiu: %s\n", ConfMan.getActiveDomainName().c_str());
     76        Common::ConfigManager::Domain* dom = ConfMan.getDomain(ConfMan.kApplicationDomain);
     77        printf("domini d'aplicacio: %s\n", dom->getDomainComment().c_str());
     78        printf("domini actiu: %s\n", ConfMan.get("savepath").c_str());
     79        ConfMan.set("scummvm_language", "ca");*/
     80
     81        setLanguage("");
     82
     83}
     84
     85TranslationManager::~TranslationManager()
     86{
     87#ifdef TERMCONV
     88        iconv_close(_conversion);
     89        if (_convmsg)
     90                delete [] _convmsg;
     91#endif // TERMCONV
     92}
     93
     94void
     95TranslationManager::setLanguage(const char* lang)
     96{
     97        if (*lang == '\0')
     98                po2c_setlang(_syslang);
     99        else
     100                po2c_setlang(lang);
     101
     102#ifdef TERMCONV
     103        // Get the locale character set (for terminal output)
     104        const char* charset_term = nl_langinfo(CODESET);
     105
     106        // Get the messages character set
     107        const char* charset_po = po2c_getcharset();
     108
     109        // Delete previoyus conversion
     110        if (_conversion)
     111                iconv_close(_conversion);
     112
     113        // Initialize the conversion
     114        _conversion = iconv_open(charset_term, charset_po);
     115#endif // TERMCONV
     116}
     117
     118const char*
     119TranslationManager::getTranslation(const char* message)
     120{
     121        return po2c_gettext(message);
     122}
     123
     124const char*
     125TranslationManager::convertTerm(const char* message)
     126{
     127#ifdef TERMCONV
     128        // Preparing conversion origin
     129        size_t len = strlen(message);
     130        char* msgcpy = new char[len + 1];
     131        strcpy(msgcpy, message);
     132        char* msg = msgcpy;
     133        char** pmsg = &msg;
     134
     135        // Preparing conversion destination
     136        if (!_convmsg) {
     137                _sizeconv = len * 2;
     138                _convmsg = new char[_sizeconv];
     139        }
     140        size_t len2 = _sizeconv;
     141        char *conv = _convmsg;
     142        char** pconv = &conv;
     143
     144        // Clean previous conversions
     145        iconv(_conversion, NULL, NULL, pconv, &len2);
     146
     147        // Do the real conversion
     148        size_t size = iconv(_conversion, pmsg, &len, pconv, &len2);
     149        if (size == (size_t)-1) {
     150                printf("error while converting\n");
     151                //TODO: test whether the buffer is smaller than needed and resize
     152        }
     153
     154        delete [] msgcpy;
     155        return _convmsg;
     156#else // TERMCONV
     157        return message;
     158#endif // TERMCONV
     159}
     160
     161
     162#else // TRANSLATION
     163
     164
     165// Translation disabled
     166
     167TranslationManager::TranslationManager() {}
     168
     169TranslationManager::~TranslationManager() {}
     170
     171void
     172TranslationManager::setLanguage(const char* lang) {}
     173
     174const char*
     175TranslationManager::getTranslation(const char* message)
     176{
     177        return message;
     178}
     179
     180const char*
     181TranslationManager::convertTerm(const char* message)
     182{
     183        return message;
     184}
     185
     186#endif // TRANSLATION
     187
     188
     189}       // End of namespace Common
  • tools/README

     
    5151    Used to convert scumm-md5.txt into a SCUMM header file, or alternatively
    5252    PHP code for our website.
    5353
     54
     55po2c
     56----
     57    This perl script allows to convert all the translated messages in the .po
     58    files into a C++ file so it can be included inside ScummVM without runtime
     59    dependencies.
     60
  • tools/po2c

     
     1#!/usr/bin/perl
     2
     3#
     4# po2c - Converts .po files to C code
     5#
     6# Copyright (C) 2004      Angel Ortega <angel@triptico.com>
     7#
     8# This program is free software; you can redistribute it and/or modify
     9# it under the terms of the GNU General Public License as published by
     10# the Free Software Foundation; either version 2 of the License, or
     11# (at your option) any later version.
     12#
     13# This program is distributed in the hope that it will be useful,
     14# but WITHOUT ANY WARRANTY; without even the implied warranty of
     15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16# GNU General Public License for more details.
     17#
     18# You should have received a copy of the GNU General Public License
     19# along with this program; if not, write to the Free Software
     20# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     21#
     22# http://www.triptico.com
     23#
     24
     25$VERSION = "1.0.2";
     26
     27if(scalar(@ARGV) == 0)
     28{
     29        print "Usage: po2c {po file[s]}\n";
     30        exit 1;
     31}
     32
     33%msgs = ();
     34%msgids = ();
     35
     36# stage 1: loading
     37
     38# arguments are .po files
     39foreach my $f (@ARGV)
     40{
     41        my ($lang);
     42
     43        next unless(($lang) = ($f =~ /([^\/]+)\.po$/));
     44
     45        if(open F, $f)
     46        {
     47                my ($msgid, $val, %a);
     48
     49                while(<F>)
     50                {
     51                        chomp;
     52
     53                        # ignore blank lines or comments
     54                        next if /^$/ or /^#/;
     55
     56                        if(/^msgid\s+\"(.*)\"\s*$/)
     57                        {
     58                                # store previous msgid
     59                                if(defined($msgid))
     60                                {
     61                                        $a{$msgid} = $val;
     62                                        $msgids{$msgid} ++;
     63                                }
     64
     65                                # start of msgid
     66                                $val = $1;
     67                        }
     68                        elsif(/^msgstr\s+\"(.*)\"\s*$/)
     69                        {
     70                                # store previous msgid
     71                                $msgid = $val;
     72
     73                                # start of msgstr
     74                                $val = $1;
     75                        }
     76                        elsif(/^\"(.*)\"\s*$/)
     77                        {
     78                                # add to current value
     79                                $val .= $1;
     80                        }
     81                }
     82
     83                # store previous msgid
     84                if(defined($msgid))
     85                {
     86                        $a{$msgid} = $val;
     87                        $msgids{$msgid} ++;
     88                }
     89
     90                close F;
     91
     92                # add to the global message pool
     93                $msgs{$lang} = \%a;
     94        }
     95}
     96
     97# stage 2: convert the data
     98
     99# stores all sorted msgids into @msgids
     100@msgids = sort(keys(%msgids));
     101
     102# travels again, storing indexes into %msgids
     103for(my $n = 0;$n < scalar(@msgids);$n++)
     104{
     105        $msgids{$msgids[$n]} = $n;
     106}
     107
     108# stage 3: dump as C code
     109
     110print "/* generated by po2c $VERSION - Do not modify */\n\n";
     111print "#include <stdio.h>\n";
     112print "#include <string.h>\n\n";
     113
     114# dump first the msgid array
     115print "static const char * _po2c_msgids[] = {\n";
     116
     117for(my $n = 0;$n < scalar(@msgids);$n++)
     118{
     119        print "\t/* $n */ \"" . $msgids[$n] . "\",\n";
     120}
     121
     122print "\tNULL\n};\n\n";
     123
     124# dump the lang structure
     125print "struct _po2c_msg {\n";
     126print "\tint msgid;\n";
     127print "\tconst char * msgstr;\n";
     128print "};\n\n";
     129
     130# dump now each language
     131
     132foreach my $l (keys(%msgs))
     133{
     134        print "static struct _po2c_msg _po2c_lang_${l}[] = {\n";
     135
     136        # get the translation table for the language $l
     137        my ($m) = $msgs{$l};
     138
     139#       while (my ($msgstr, $msgid) = each (%$m))
     140        foreach my $msgid (sort(keys(%$m)))
     141        {
     142                my ($msgstr) = $m->{$msgid};
     143
     144                print "\t{ " . $msgids{$msgid} . ", \"" . $msgstr . "\" },\n"
     145                        if $msgstr;
     146        }
     147
     148        print "\t{ -1, NULL }\n};\n\n";
     149}
     150
     151# finally, dump the languages
     152
     153print "static struct {\n";
     154print "\tconst char * lang;\n";
     155print "\tconst char * charset;\n";
     156print "\tstruct _po2c_msg * msgs;\n";
     157print "} _po2c_langs[] = {\n";
     158
     159foreach my $l (keys(%msgs))
     160{
     161        $header = $msgs{$l}->{""};
     162        $header =~ /charset=([^\\]+)/;
     163        $charset = $1;
     164        print "\t{ \"" . $l . "\", \"" . $charset . "\", _po2c_lang_${l} },\n";
     165}
     166
     167print "\t{ NULL, NULL, NULL }\n};\n\n";
     168
     169print "/* code */\n";
     170print << 'EOF';
     171
     172static struct _po2c_msg * _po2c_lang=NULL;
     173static int _po2c_lang_size=0;
     174static const char * _po2c_charset=NULL;
     175
     176void po2c_setlang(const char * lang)
     177{
     178        int n;
     179
     180        _po2c_lang=NULL;
     181        _po2c_lang_size=0;
     182        _po2c_charset=NULL;
     183
     184        /* if lang is NULL or "", deactivate it */
     185        if(lang == NULL || *lang == '\0')
     186                return;
     187
     188        /* searches for a valid language array */
     189        for(n=0;_po2c_lang == NULL && _po2c_langs[n].lang != NULL;n++)
     190        {
     191                if(strcmp(lang, _po2c_langs[n].lang) == 0) {
     192                        _po2c_lang=_po2c_langs[n].msgs;
     193                        _po2c_charset=_po2c_langs[n].charset;
     194                }
     195        }
     196
     197        /* try partial searches */
     198        for(n=0;_po2c_lang == NULL && _po2c_langs[n].lang != NULL;n++)
     199        {
     200                if(strncmp(lang, _po2c_langs[n].lang, 2) == 0) {
     201                        _po2c_lang=_po2c_langs[n].msgs;
     202                        _po2c_charset=_po2c_langs[n].charset;
     203                }
     204        }
     205
     206        /* if found, count entries */
     207        if(_po2c_lang != NULL)
     208        {
     209                struct _po2c_msg * m;
     210
     211                for(m=_po2c_lang;m->msgid != -1;m++)
     212                        _po2c_lang_size++;
     213        }
     214}
     215
     216const char * po2c_gettext(const char * msgid)
     217{
     218        struct _po2c_msg * m;
     219        int b, t, n, c;
     220
     221        /* if no language is set or msgid is empty, return msgid as is */
     222        if(_po2c_lang == NULL || *msgid == '\0')
     223                return(msgid);
     224
     225        /* binary-search for the msgid */
     226        b=0; t=_po2c_lang_size - 1;
     227
     228        while(t >= b)
     229        {
     230                n=(b + t) / 2;
     231                m=&_po2c_lang[n];
     232
     233                c=strcmp(msgid, _po2c_msgids[m->msgid]);
     234
     235                if(c == 0)
     236                        return(m->msgstr);
     237                else
     238                if(c < 0)
     239                        t=n - 1;
     240                else
     241                        b=n + 1;
     242        }
     243
     244        return(msgid);
     245}
     246
     247const char * po2c_getcharset(void)
     248{
     249        if (_po2c_charset)
     250                return _po2c_charset;
     251        else
     252                return "ASCII";
     253}
     254EOF
     255
     256exit 0;
  • po/module.mk

    Property changes on: tools/po2c
    ___________________________________________________________________
    Name: svn:executable
       + *
    
     
     1POTFILE := po/scummvm.pot
     2POFILES := $(wildcard po/*.po)
     3
     4updatepot:
     5        xgettext -f po/POTFILES -k_ -k_t --copyright-holder="ScummVM" \
     6                --msgid-bugs-address=scummvm-devel@lists.sourceforge.net \
     7                -o $(POTFILE)_ --from-code utf-8
     8        sed -e 's/SOME DESCRIPTIVE TITLE/LANGUAGE translation for ScummVM/' \
     9                -e 's/UTF-8/CHARSET/' -e 's/PACKAGE/ScummVM/' $(POTFILE)_ > $(POTFILE).new
     10       
     11        rm $(POTFILE)_
     12        if test -f $(POTFILE); then \
     13                sed -f po/remove-potcdate.sed < $(POTFILE) > $(POTFILE).1 && \
     14                sed -f po/remove-potcdate.sed < $(POTFILE).new > $(POTFILE).2 && \
     15                if cmp $(POTFILE).1 $(POTFILE).2 >/dev/null 2>&1; then \
     16                        rm -f $(POTFILE).new; \
     17                else \
     18                        rm -f $(POTFILE) && \
     19                        mv -f $(POTFILE).new $(POTFILE); \
     20                fi; \
     21                rm -f $(POTFILE).1 $(POTFILE).2; \
     22        else \
     23                mv -f $(POTFILE).new $(POTFILE); \
     24        fi;
     25
     26po/%.po: $(POTFILE)
     27        msgmerge $@ $(POTFILE) -o $@.new
     28        if cmp $@ $@.new >/dev/null 2>&1; then \
     29                rm -f $@.new; \
     30        else \
     31                mv -f $@.new $@; \
     32        fi;
     33
     34update-translations: updatepot $(POFILES)
     35        @$(foreach file, $(POFILES), echo -n $(notdir $(basename $(file)))": ";msgfmt --statistic $(file);)
     36        @rm -f messages.mo
     37
     38.PHONY: updatepot update-translations
  • po/remove-potcdate.sed

     
     1# Sed script that remove the POT-Creation-Date line in the header entry
     2# from a POT file.
     3#
     4# The distinction between the first and the following occurrences of the
     5# pattern is achieved by looking at the hold space.
     6/^"POT-Creation-Date: .*"$/{
     7x
     8# Test if the hold space is empty.
     9s/P/P/
     10ta
     11# Yes it was empty. First occurrence. Remove the line.
     12g
     13d
     14bb
     15:a
     16# The hold space was nonempty. Following occurrences. Do nothing.
     17x
     18:b
     19}
  • po/POTFILES

     
     1#TODO: help_string & usage_string:
     2base/commandLine.cpp
     3base/main.cpp
     4common/advancedDetector.cpp
     5common/config-file.cpp
     6common/config-manager.cpp
     7common/file.cpp
     8common/hashmap.h
     9common/iff_container.h
     10common/md5.cpp
     11common/mutex.cpp
     12common/util.cpp
     13graphics/dxa_player.cpp
     14graphics/font.cpp
     15graphics/iff.cpp
     16graphics/mpeg_player.cpp
     17graphics/surface.cpp
     18#gui/about.cpp
     19gui/browser.cpp
     20gui/chooser.cpp
     21#gui/credits.h
     22gui/debugger.cpp
     23gui/dialog.cpp
     24gui/eval.cpp
     25gui/KeysDialog.h
     26gui/KeysDialog.cpp
     27gui/launcher.cpp
     28gui/massadd.cpp
     29gui/message.h
     30gui/newgui.cpp
     31gui/options.cpp
     32gui/themebrowser.cpp
     33gui/ThemeClassic.cpp
     34gui/theme-config.cpp
     35gui/theme.cpp
     36gui/ThemeModern.cpp
     37
     38#TODO: backends engines sound tools?