summaryrefslogtreecommitdiff
path: root/setup_native/source
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@suse.cz>2011-05-27 20:39:30 +0200
committerJan Holesovsky <kendy@suse.cz>2011-05-27 20:39:30 +0200
commit88c1a56d1127376284095465cf85f5b4e71a08e5 (patch)
tree4b7ae852d8a8b86f9125b9218d36faf574b9a1a7 /setup_native/source
parent779b389116e7112c7ca29cb08e56cfcb043ecc4d (diff)
parent84d9f0ceb2048550acf763879993348fb1cfb473 (diff)
Merge remote-tracking branch 'origin/integration/dev300_m106'
Conflicts: extensions/source/svg/svgaction.cxx extensions/source/svg/svguno.cxx package/source/xstor/owriteablestream.cxx package/source/xstor/xstorage.cxx package/source/zippackage/ZipPackageStream.cxx setup_native/source/win32/customactions/shellextensions/registerextensions.cxx wizards/com/sun/star/wizards/letter/LetterWizardDialogImpl.java
Diffstat (limited to 'setup_native/source')
-rwxr-xr-xsetup_native/source/packinfo/shellscripts_extensions.txt24
-rw-r--r--setup_native/source/win32/customactions/rebase/rebase.cxx85
-rw-r--r--setup_native/source/win32/customactions/relnotes/exports.dxp3
-rw-r--r--setup_native/source/win32/customactions/relnotes/makefile.mk76
-rw-r--r--setup_native/source/win32/customactions/relnotes/relnotes.cxx188
-rw-r--r--setup_native/source/win32/customactions/shellextensions/registerextensions.cxx23
-rw-r--r--setup_native/source/win32/msi-encodinglist.txt2
7 files changed, 114 insertions, 287 deletions
diff --git a/setup_native/source/packinfo/shellscripts_extensions.txt b/setup_native/source/packinfo/shellscripts_extensions.txt
index 0be870990b71..3ab47f925802 100755
--- a/setup_native/source/packinfo/shellscripts_extensions.txt
+++ b/setup_native/source/packinfo/shellscripts_extensions.txt
@@ -76,6 +76,12 @@ END
if [ -x "$$RPM_INSTALL_PREFIX/PRODUCTDIRECTORYNAME/program/unopkg" ]; then
"$$RPM_INSTALL_PREFIX/PRODUCTDIRECTORYNAME/program/unopkg" sync
+ if [ "$$?" != "0" ]; then
+ echo "ERROR: Registration of extensions failed!"
+ exit 1
+ else
+ echo "SUCCESS: unopkg returns successful!"
+ fi
find "$$RPM_INSTALL_PREFIX/PRODUCTDIRECTORYNAME/share/prereg/bundled" -type f -exec chmod 644 {} \;
fi
@@ -87,6 +93,12 @@ END
if [ -x "$$RPM_INSTALL_PREFIX/PRODUCTDIRECTORYNAME/program/unopkg" ]; then
"$$RPM_INSTALL_PREFIX/PRODUCTDIRECTORYNAME/program/unopkg" sync
+ if [ "$$?" != "0" ]; then
+ echo "ERROR: Registration of extensions failed!"
+ exit 1
+ else
+ echo "SUCCESS: unopkg returns successful!"
+ fi
find "$$RPM_INSTALL_PREFIX/PRODUCTDIRECTORYNAME/share/prereg/bundled" -type f -exec chmod 644 {} \;
fi
@@ -99,6 +111,12 @@ END
if [ -x "PRODUCTDIRECTORYNAME/program/unopkg" ]; then
"PRODUCTDIRECTORYNAME/program/unopkg" sync
+ if [ "$$?" != "0" ]; then
+ echo "ERROR: Registration of extensions failed!"
+ exit 1
+ else
+ echo "SUCCESS: unopkg returns successful!"
+ fi
find "PRODUCTDIRECTORYNAME/share/prereg/bundled" -type f -exec chmod 644 {} \;
fi
@@ -111,6 +129,12 @@ END
if [ -x "PRODUCTDIRECTORYNAME/program/unopkg" ]
then
"PRODUCTDIRECTORYNAME/program/unopkg" sync
+ if [ "$$?" != "0" ]; then
+ echo "ERROR: Registration of extensions failed!"
+ exit 1
+ else
+ echo "SUCCESS: unopkg returns successful!"
+ fi
find "PRODUCTDIRECTORYNAME/share/prereg/bundled" -type f -exec chmod 644 {} \;
fi
diff --git a/setup_native/source/win32/customactions/rebase/rebase.cxx b/setup_native/source/win32/customactions/rebase/rebase.cxx
index 1eb3fedbf2f0..601af93dd20a 100644
--- a/setup_native/source/win32/customactions/rebase/rebase.cxx
+++ b/setup_native/source/win32/customactions/rebase/rebase.cxx
@@ -20,11 +20,14 @@
#include <malloc.h>
#include <time.h>
#include <string>
+#include <hash_map>
const DWORD PE_Signature = 0x00004550;
+typedef std::pair< std::string, bool > StringPair;
+typedef std::hash_map< std::string, bool > ExcludeLibsMap;
#ifdef DEBUG
-inline void OutputDebugStringFormat( LPCSTR pFormat, ... )
+static void OutputDebugStringFormat( LPCSTR pFormat, ... )
{
CHAR buffer[1024];
va_list args;
@@ -34,7 +37,7 @@ inline void OutputDebugStringFormat( LPCSTR pFormat, ... )
OutputDebugStringA( buffer );
}
#else
-static inline void OutputDebugStringFormat( LPCSTR, ... )
+static void OutputDebugStringFormat( LPCSTR, ... )
{
}
#endif
@@ -99,22 +102,31 @@ static BOOL rebaseImage( MSIHANDLE /*handle*/, const std::string& sFilePath, LPV
return bResult;
}
-static BOOL rebaseImagesInFolder( MSIHANDLE handle, const std::string& sPath, LPVOID address )
+static BOOL rebaseImagesInFolder( MSIHANDLE handle, const std::string& sPath, LPVOID address, ExcludeLibsMap& rExcludeMap )
{
- std::string sDir = sPath;
- std::string sPattern = sPath + TEXT("*.dll");
-
+ std::string sDir = sPath;
+ std::string sPattern = sPath + TEXT("*.dll");
WIN32_FIND_DATA aFindFileData;
- HANDLE hFind = FindFirstFile( sPattern.c_str(), &aFindFileData );
+ HANDLE hFind = FindFirstFile( sPattern.c_str(), &aFindFileData );
if ( IsValidHandle(hFind) )
{
BOOL fSuccess = false;
do
{
- std::string sLibFile = sDir + aFindFileData.cFileName;
- rebaseImage( handle, sLibFile, address );
+ std::string sFileName = aFindFileData.cFileName;
+ if ( rExcludeMap.find( sFileName ) == rExcludeMap.end() )
+ {
+ OutputDebugStringFormat( "Rebase library: %s", sFileName.c_str() );
+ std::string sLibFile = sDir + sFileName;
+ rebaseImage( handle, sLibFile, address );
+ }
+ else
+ {
+ OutputDebugStringFormat( "Exclude library %s from rebase", sFileName.c_str() );
+ }
+
fSuccess = FindNextFile( hFind, &aFindFileData );
}
while ( fSuccess );
@@ -125,7 +137,7 @@ static BOOL rebaseImagesInFolder( MSIHANDLE handle, const std::string& sPath, LP
return ERROR_SUCCESS;
}
-static BOOL rebaseImages( MSIHANDLE handle, LPVOID pAddress )
+static BOOL rebaseImages( MSIHANDLE handle, LPVOID pAddress, ExcludeLibsMap& rMap )
{
std::string sInstallPath = GetMsiProperty(handle, TEXT("INSTALLLOCATION"));
@@ -133,9 +145,9 @@ static BOOL rebaseImages( MSIHANDLE handle, LPVOID pAddress )
std::string sOfficeDir = sInstallPath + TEXT("program\\");
std::string sUreDir = sInstallPath + TEXT("URE\\bin\\");
- BOOL bResult = rebaseImagesInFolder( handle, sBasisDir, pAddress );
- bResult &= rebaseImagesInFolder( handle, sOfficeDir, pAddress );
- bResult &= rebaseImagesInFolder( handle, sUreDir, pAddress );
+ BOOL bResult = rebaseImagesInFolder( handle, sBasisDir, pAddress, rMap );
+ bResult &= rebaseImagesInFolder( handle, sOfficeDir, pAddress, rMap );
+ bResult &= rebaseImagesInFolder( handle, sUreDir, pAddress, rMap );
return bResult;
}
@@ -147,21 +159,66 @@ static BOOL IsServerSystem( MSIHANDLE /*handle*/ )
GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&osVersionInfoEx));
if ( osVersionInfoEx.wProductType != VER_NT_WORKSTATION )
+ {
+ OutputDebugStringFormat( "Server system detected. No rebase necessary!" );
return TRUE;
+ }
else
+ {
+ OutputDebugStringFormat( "Client system detected. Rebase necessary!" );
return FALSE;
+ }
+}
+
+static void InitExcludeFromRebaseList( MSIHANDLE handle, ExcludeLibsMap& rMap )
+{
+ size_t nPos( 0 );
+ const TCHAR cDelim = ',';
+ std::string sLibsExcluded = GetMsiProperty(handle, TEXT("EXCLUDE_FROM_REBASE"));
+
+ while ( nPos < sLibsExcluded.size() )
+ {
+ size_t nDelPos = sLibsExcluded.find_first_of( cDelim, nPos );
+
+ std::string sExcludedLibName;
+ if ( nDelPos != std::string::npos )
+ {
+ sExcludedLibName = sLibsExcluded.substr( nPos, nDelPos - nPos );
+ nPos = nDelPos+1;
+ }
+ else
+ {
+ sExcludedLibName = sLibsExcluded.substr( nPos );
+ nPos = sLibsExcluded.size();
+ }
+
+ if ( sExcludedLibName.size() > 0 )
+ {
+ OutputDebugStringFormat( "Insert library %s into exclude from rebase list", sExcludedLibName.c_str() );
+ rMap.insert( StringPair( sExcludedLibName, true ));
+ }
+ }
}
extern "C" BOOL __stdcall RebaseLibrariesOnProperties( MSIHANDLE handle )
{
static LPVOID pDefault = reinterpret_cast<LPVOID>(0x10000000);
+ OutputDebugStringFormat( "RebaseLibrariesOnProperties has been called" );
std::string sDontOptimizeLibs = GetMsiProperty(handle, TEXT("DONTOPTIMIZELIBS"));
if ( sDontOptimizeLibs.length() > 0 && sDontOptimizeLibs == "1" )
+ {
+ OutputDebugStringFormat( "Don't optimize libraries set. No rebase necessary!" );
return TRUE;
+ }
if ( !IsServerSystem( handle ))
- return rebaseImages( handle, pDefault );
+ {
+ ExcludeLibsMap aExcludeLibsMap;
+ InitExcludeFromRebaseList( handle, aExcludeLibsMap );
+
+ return rebaseImages( handle, pDefault, aExcludeLibsMap );
+ }
return TRUE;
}
diff --git a/setup_native/source/win32/customactions/relnotes/exports.dxp b/setup_native/source/win32/customactions/relnotes/exports.dxp
deleted file mode 100644
index 55a454d3d58f..000000000000
--- a/setup_native/source/win32/customactions/relnotes/exports.dxp
+++ /dev/null
@@ -1,3 +0,0 @@
-ShowReleaseNotesBefore
-ShowReleaseNotesAfter
-ShowSurveyAfter
diff --git a/setup_native/source/win32/customactions/relnotes/makefile.mk b/setup_native/source/win32/customactions/relnotes/makefile.mk
deleted file mode 100644
index 526d45e71393..000000000000
--- a/setup_native/source/win32/customactions/relnotes/makefile.mk
+++ /dev/null
@@ -1,76 +0,0 @@
-#*************************************************************************
-#
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# Copyright 2000, 2010 Oracle and/or its affiliates.
-#
-# OpenOffice.org - a multi-platform office productivity suite
-#
-# This file is part of OpenOffice.org.
-#
-# OpenOffice.org is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Lesser General Public License version 3
-# only, as published by the Free Software Foundation.
-#
-# OpenOffice.org is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License version 3 for more details
-# (a copy is included in the LICENSE file that accompanied this code).
-#
-# You should have received a copy of the GNU Lesser General Public License
-# version 3 along with OpenOffice.org. If not, see
-# <http://www.openoffice.org/license.html>
-# for a copy of the LGPLv3 License.
-#
-#*************************************************************************
-
-PRJ=..$/..$/..$/..
-PRJNAME=setup_native
-TARGET=relnotes
-
-
-# --- Settings -----------------------------------------------------
-
-ENABLE_EXCEPTIONS=TRUE
-NO_DEFAULT_STL=TRUE
-DYNAMIC_CRT=
-USE_DEFFILE=TRUE
-
-.INCLUDE : settings.mk
-
-CDEFS+=-DUNICODE
-
-UWINAPILIB=
-
-# --- Files --------------------------------------------------------
-
-.IF "$(GUI)"=="WNT"
-
-SLOFILES = $(SLO)$/relnotes.obj
-
-STDSHL+= \
- $(ADVAPI32LIB)\
- $(SHELL32LIB)\
- $(MSILIB)
-
-SHL1LIBS = $(SLB)$/$(TARGET).lib
-
-SHL1TARGET = $(TARGET)
-SHL1IMPLIB = i$(TARGET)
-
-SHL1DEF = $(MISC)$/$(SHL1TARGET).def
-SHL1DEPN = $(SLB)$/$(TARGET).lib
-SHL1BASE = 0x1c000000
-DEF1NAME=$(SHL1TARGET)
-DEF1EXPORTFILE=exports.dxp
-
-.ENDIF
-
-# --- Targets --------------------------------------------------------------
-
-.INCLUDE : target.mk
-
-# -------------------------------------------------------------------------
-
-
diff --git a/setup_native/source/win32/customactions/relnotes/relnotes.cxx b/setup_native/source/win32/customactions/relnotes/relnotes.cxx
deleted file mode 100644
index 48aaf9b417bd..000000000000
--- a/setup_native/source/win32/customactions/relnotes/relnotes.cxx
+++ /dev/null
@@ -1,188 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-
-#ifdef _MSC_VER
-#pragma warning(push,1) // disable warnings within system headers
-#pragma warning(disable: 4917)
-#endif
-#include <windows.h>
-#include <msiquery.h>
-#include <shlobj.h>
-#ifdef _MSC_VER
-#pragma warning(pop)
-#endif
-
-#include <string.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <strsafe.h>
-#include <string>
-
-//----------------------------------------------------------
-#ifdef DEBUG
-inline void OutputDebugStringFormat( LPCTSTR pFormat, ... )
-{
- TCHAR buffer[1024];
- va_list args;
-
- va_start( args, pFormat );
- StringCchVPrintf( buffer, sizeof(buffer), pFormat, args );
- OutputDebugString( buffer );
-}
-#else
-static inline void OutputDebugStringFormat( LPCTSTR, ... )
-{
-}
-#endif
-
-//----------------------------------------------------------
-inline bool IsValidHandle( HANDLE handle )
-{
- return (NULL != handle) && (INVALID_HANDLE_VALUE != handle);
-}
-
-//----------------------------------------------------------
-static bool GetMsiProp(MSIHANDLE handle, LPCTSTR name, /*out*/std::wstring& value)
-{
- DWORD sz = 0;
- LPTSTR dummy = TEXT("");
- if (MsiGetProperty(handle, name, dummy, &sz) == ERROR_MORE_DATA)
- {
- sz++;
- DWORD nbytes = sz * sizeof(TCHAR);
- LPTSTR buff = reinterpret_cast<LPTSTR>(_alloca(nbytes));
- ZeroMemory(buff, nbytes);
- MsiGetProperty(handle, name, buff, &sz);
- value = buff;
- return true;
- }
- return false;
-}
-
-//----------------------------------------------------------
-//----------------------------------------------------------
-//----------------------------------------------------------
-UINT ShowReleaseNotes( TCHAR* pFileName, TCHAR* pFilePath )
-{
- TCHAR sFullPath[ MAX_PATH ];
-
- if ( FAILED( StringCchCopy( sFullPath, MAX_PATH, pFilePath ) ) )
- {
- OutputDebugStringFormat( TEXT("DEBUG: ShowReleaseNotes: Could not copy path [%s]"), pFilePath );
- return ERROR_SUCCESS;
- }
-
- if ( FAILED( StringCchCat( sFullPath, MAX_PATH, pFileName ) ) )
- {
- OutputDebugStringFormat( TEXT("DEBUG: ShowReleaseNotes: Could not append filename [%s]"), pFileName );
- return ERROR_SUCCESS;
- }
-
- HANDLE hFile = CreateFile( sFullPath, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if ( IsValidHandle(hFile) )
- {
- CloseHandle( hFile );
- OutputDebugStringFormat( TEXT("DEBUG: ShowReleaseNotes: Found file [%s]"), sFullPath );
-
- SHELLEXECUTEINFOW aExecInf;
- ZeroMemory( &aExecInf, sizeof( aExecInf ) );
-
- aExecInf.cbSize = sizeof( aExecInf );
- aExecInf.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
- aExecInf.lpVerb = TEXT("open");
- aExecInf.lpFile = sFullPath;
- aExecInf.lpDirectory = NULL;
- aExecInf.nShow = SW_SHOWNORMAL;
-
- SetLastError( 0 );
- ShellExecuteEx( &aExecInf );
- }
- else
- {
- OutputDebugStringFormat( TEXT("DEBUG: ShowReleaseNotes: File not found [%s]"), sFullPath );
- }
-
- return ERROR_SUCCESS;
-}
-
-//----------------------------------------------------------
-extern "C" UINT __stdcall ShowReleaseNotesBefore( MSIHANDLE )
-{
- TCHAR szPath[MAX_PATH];
-
- if( FAILED( SHGetSpecialFolderPath( NULL, szPath, CSIDL_COMMON_DOCUMENTS, true ) ) )
- return ERROR_SUCCESS;
-
- OutputDebugString( TEXT("DEBUG: ShowReleaseNotesBefore called") );
-
- return ShowReleaseNotes( TEXT("\\sun\\releasenote1.url"), szPath );
-}
-
-//----------------------------------------------------------
-extern "C" UINT __stdcall ShowReleaseNotesAfter( MSIHANDLE )
-{
- TCHAR szPath[MAX_PATH];
-
- if( FAILED( SHGetSpecialFolderPath( NULL, szPath, CSIDL_COMMON_DOCUMENTS, true ) ) )
- return ERROR_SUCCESS;
-
- OutputDebugString( TEXT("DEBUG: ShowReleaseNotesAfter called") );
-
- return ShowReleaseNotes( TEXT("\\sun\\releasenote2.url"), szPath );
-}
-
-//----------------------------------------------------------
-extern "C" UINT __stdcall ShowSurveyAfter( MSIHANDLE handle )
-{
- std::wstring prodname;
-
- GetMsiProp( handle, TEXT("ProductName"), prodname );
- std::wstring::size_type nIndex = prodname.find( TEXT( "OpenOffice.org" ) );
- if( std::wstring::npos == nIndex )
- return ERROR_SUCCESS;
-
- OutputDebugString( TEXT("DEBUG: ShowSurveyAfter called") );
-
- SHELLEXECUTEINFOW aExecInf;
- ZeroMemory( &aExecInf, sizeof( aExecInf ) );
-
- aExecInf.cbSize = sizeof( aExecInf );
- aExecInf.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
- aExecInf.lpVerb = TEXT("open");
- aExecInf.lpFile = TEXT("http://surveys.libreoffice.org/deinstall");
- aExecInf.lpDirectory = NULL;
- aExecInf.nShow = SW_SHOWNORMAL;
-
- SetLastError( 0 );
- ShellExecuteEx( &aExecInf );
-
- return ERROR_SUCCESS;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/setup_native/source/win32/customactions/shellextensions/registerextensions.cxx b/setup_native/source/win32/customactions/shellextensions/registerextensions.cxx
index 53066682e397..8139bb664e9e 100644
--- a/setup_native/source/win32/customactions/shellextensions/registerextensions.cxx
+++ b/setup_native/source/win32/customactions/shellextensions/registerextensions.cxx
@@ -198,13 +198,13 @@ static BOOL RemoveCompleteDirectory( std::_tstring sPath )
extern "C" UINT __stdcall RegisterExtensions(MSIHANDLE handle)
{
- std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") );
+ // std::_tstring sInstDir = GetMsiProperty( handle, TEXT("INSTALLLOCATION") );
+ std::_tstring sInstDir = GetMsiProperty( handle, TEXT("CustomActionData") );
std::_tstring sUnoPkgFile = sInstDir + TEXT("program\\unopkg.exe");
std::_tstring mystr;
WIN32_FIND_DATA aFindFileData;
-
- mystr = "unopkg file: " + sUnoPkgFile;
+ bool registrationError = false;
// Find unopkg.exe
HANDLE hFindUnopkg = FindFirstFile( sUnoPkgFile.c_str(), &aFindFileData );
@@ -213,14 +213,27 @@ extern "C" UINT __stdcall RegisterExtensions(MSIHANDLE handle)
{
// unopkg.exe exists in program directory
std::_tstring sCommand = sUnoPkgFile + " sync";
- mystr = "Command: " + sCommand;
DWORD exitCode = 0;
ExecuteCommand( sCommand.c_str(), & exitCode);
+ if ( ! fSuccess )
+ {
+ mystr = "ERROR: An error occured during registration of extensions!";
+ MessageBox(NULL, mystr.c_str(), "ERROR", MB_OK);
+ registrationError = true;
+ }
+
FindClose( hFindUnopkg );
}
- return ERROR_SUCCESS;
+ if ( registrationError )
+ {
+ return 1;
+ }
+ else
+ {
+ return ERROR_SUCCESS;
+ }
}
diff --git a/setup_native/source/win32/msi-encodinglist.txt b/setup_native/source/win32/msi-encodinglist.txt
index 123339c3d9c5..fa99da814fe6 100644
--- a/setup_native/source/win32/msi-encodinglist.txt
+++ b/setup_native/source/win32/msi-encodinglist.txt
@@ -87,7 +87,6 @@ nl 1252 1043
nn 1252 2068
no 1252 1044
nr 0 1580 # Ndebele South
-ns 0 1132 # Northern Sotho (Sepedi)
nso 0 1132
ny 0 1598
oc 1252 1154 # Occitan-lengadocian
@@ -134,6 +133,7 @@ ti-ER 0 1139 # Tigrinya
tn 0 1074 # Setsuana
tr 1254 1055 # Turkish
ts 0 1073 # Tsonga
+tk 0 1090
tt 1251 1092 # Tatar
ug 0 2200
uk 1251 1058 # Ukrainian