diff --git a/configure b/configure index d0aa090d938..4225ee481ca 100755 --- a/configure +++ b/configure @@ -363,12 +363,9 @@ macSDKify() val=$(echo $sdk_val $(echo $val | cut -s -d ' ' -f 2-)) echo "$var=$val" ;; - QMAKE_CFLAGS=*|QMAKE_CXXFLAGS=*) + QMAKE_CFLAGS=*|QMAKE_CXXFLAGS=*|QMAKE_LFLAGS=*) echo "$line -isysroot $sysroot $version_min_flag" ;; - QMAKE_LFLAGS=*) - echo "$line -Wl,-syslibroot,$sysroot $version_min_flag" - ;; *) echo "$line" ;; diff --git a/dist/changes-5.14.2 b/dist/changes-5.14.2 new file mode 100644 index 00000000000..df3cabe3bf5 --- /dev/null +++ b/dist/changes-5.14.2 @@ -0,0 +1,117 @@ +Qt 5.14.2 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.14.0 through 5.14.1. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + +https://doc.qt.io/qt-5/index.html + +The Qt version 5.14 series is binary compatible with the 5.13.x series. +Applications compiled for 5.13 will continue to run with 5.14. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* QtCore * +**************************************************************************** + + - QCollator: + * QTBUG-81673: Fixed a regression introduced in 5.14.0 that caused + QCollator not to operate with default-constructed QStrings and print a + warning on Windows. + + - QString, codecs: + * QTBUG-62011: ZWNBS is no longer discarded (mistaken for a BOM despite + not being at the start) when converting UCS4 to QString's UCS2. + + - QLocale: + * QTBUG-80459: Skip digit-grouping if the system locale is configured to + use an empty group separator. + * QTBUG-81530: Use "+" if MS reports empty for the system locale's plus + sign, as documented in MS's API for the relevant query. + + - QLockFile: + * Suppressed the warning on QNX that said 'setNativeLocks failed: + "Function not implemented"'. There is no difference in behavior: Qt + will continue not to be able to apply an OS- level file lock, which + means the lock could be accidentally stolen by buggy software. Correct + software using QLockFile should not be affected. + + - QObject: + * For the purposes of QT_NO_NARROWING_CONVERSIONS_IN_CONNECT, pointer + (incl. pointer-to-member) to bool conversions are now considered + narrowing. This matches the resolution of a defect report in C++ + itself. + + - QStorageInfo: + * Improved discovery of device nodes on Linux if the /dev entry was + renamed after the filesystem was mounted and udev is in use. + +**************************************************************************** +* QtGui * +**************************************************************************** + + - QTextMarkdownImporter: + * Text in Markdown format is assumed to be UTF-8. + * The "title" in a Markdown hyperlink is now used as the tooltip, + not the anchor name. + * Fixed vulnerability oss-fuzz-20450 (invalid input resulted in an + attempt to insert items into a list that no longer exists). + +**************************************************************************** +* QtWidgets * +**************************************************************************** + + - QLineEdit: + * the inputMask property has allowed any Letter or Number category + character for the respective mask characters, not just ASCII. The + documentation has been updated accordingly. + +**************************************************************************** +* qmake * +**************************************************************************** + + - To remove the NDEBUG define that is added by default in MSVC mkspecs, + write DEFINES_RELEASE -= NDEBUG in your .pro file. + - Install/uninstall rules are now generated for target.targets on Windows. + This mirrors the behavior on Unix. + +**************************************************************************** +* Third-Party Code * +**************************************************************************** + + - md4c was updated to 0.4.3. This fixes vulnerability oss-fuzz-20580. + + - QtSQL, sqlite: + * Updated to v3.31.1 + * [QTBUG-82533] Fixed CVE-2020-9327 + +**************************************************************************** +* CMake * +**************************************************************************** + + - Windows: + * Fixed linking with Qt static build + +**************************************************************************** +* MSVC * +**************************************************************************** + + - Fixed a compatibility issue found when linking code compiled with + version 16.6 to a Qt compiled with 16.5. + +**************************************************************************** +* MinGW * +**************************************************************************** + + - Fixed build regressions. + - The -debug-and-release configuration has been fixed. In this + configuration, Qt libraries again have a 'd' suffix. + - In the -debug configuration, libraries do not have a 'd' suffix, similar + to Unix platforms. diff --git a/doc/global/qt-html-templates-offline-simple.qdocconf b/doc/global/qt-html-templates-offline-simple.qdocconf index c3c2d3cca06..02a32285198 100644 --- a/doc/global/qt-html-templates-offline-simple.qdocconf +++ b/doc/global/qt-html-templates-offline-simple.qdocconf @@ -19,27 +19,11 @@ HTML.headerstyles = \ " }, 0);\n" \ " \n" -HTML.postheader = \ - "\n" \ - "
\n"\ - "
\n" \ - "
\n" \ - "
\n" \ - " \n" - -HTML.postpostheader = \ - "
\n"\ - "
\n" \ - "
\n" \ - "
\n" \ - "
\n" \ - "
\n" - HTML.navigationseparator = \ "\n" # Add some padding around code snippets, as we cannot # currectly style them for QTextBrowser using only CSS. -codeindent = 2 -codeprefix = "\n\n" -codesuffix = "\n\n" +codeindent = 1 +codeprefix = "\n" +codesuffix = "\n" diff --git a/doc/global/template/style/offline.css b/doc/global/template/style/offline.css index 13c942707a0..f99369a096e 100644 --- a/doc/global/template/style/offline.css +++ b/doc/global/template/style/offline.css @@ -297,11 +297,14 @@ table.buildversion { #buildversion { font-style: italic; - font-size: small; float: right; margin-right: 5px; } +#buildversion a { + background: none; +} + /* /* table of content diff --git a/examples/network/multistreamclient/client.cpp b/examples/network/multistreamclient/client.cpp index db6e3ba3048..ce84f3df9a2 100644 --- a/examples/network/multistreamclient/client.cpp +++ b/examples/network/multistreamclient/client.cpp @@ -126,8 +126,7 @@ Client::Client(QWidget *parent) connect(sctpSocket, &QSctpSocket::connected, this, &Client::connected); connect(sctpSocket, &QSctpSocket::disconnected, this, &Client::disconnected); connect(sctpSocket, &QSctpSocket::channelReadyRead, this, &Client::readDatagram); - connect(sctpSocket, QOverload::of(&QSctpSocket::error), - this, &Client::displayError); + connect(sctpSocket, &QSctpSocket::errorOccurred, this, &Client::displayError); connect(consumers[SctpChannels::Time], &Consumer::writeDatagram, this, &Client::writeDatagram); connect(consumers[SctpChannels::Chat], &Consumer::writeDatagram, this, &Client::writeDatagram); diff --git a/examples/network/securesocketclient/sslclient.cpp b/examples/network/securesocketclient/sslclient.cpp index 6eb10759966..d6c52a1c660 100644 --- a/examples/network/securesocketclient/sslclient.cpp +++ b/examples/network/securesocketclient/sslclient.cpp @@ -226,7 +226,7 @@ void SslClient::setupSecureSocket() this, &SslClient::socketStateChanged); connect(socket, &QSslSocket::encrypted, this, &SslClient::socketEncrypted); - connect(socket, QOverload::of(&QSslSocket::error), + connect(socket, &QSslSocket::errorOccurred, this, &SslClient::socketError); connect(socket, QOverload &>::of(&QSslSocket::sslErrors), this, &SslClient::sslErrors); diff --git a/examples/network/torrent/mainwindow.cpp b/examples/network/torrent/mainwindow.cpp index 331fa129440..c343ee81b94 100644 --- a/examples/network/torrent/mainwindow.cpp +++ b/examples/network/torrent/mainwindow.cpp @@ -183,7 +183,7 @@ MainWindow::MainWindow(QWidget *parent) bottomBar->addWidget((uploadLimitLabel = new QLabel(tr("0 KB/s")))); uploadLimitLabel->setFixedSize(QSize(fm.horizontalAdvance(tr("99999 KB/s")), fm.lineSpacing())); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS setUnifiedTitleAndToolBarOnMac(true); #endif diff --git a/examples/opengl/doc/src/cube.qdoc b/examples/opengl/doc/src/cube.qdoc index 4f5b6bda906..05014173c5e 100644 --- a/examples/opengl/doc/src/cube.qdoc +++ b/examples/opengl/doc/src/cube.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. diff --git a/examples/widgets/desktop/systray/window.cpp b/examples/widgets/desktop/systray/window.cpp index 3238e3bf314..e62b5fc0d0c 100644 --- a/examples/widgets/desktop/systray/window.cpp +++ b/examples/widgets/desktop/systray/window.cpp @@ -111,7 +111,7 @@ void Window::setVisible(bool visible) //! [2] void Window::closeEvent(QCloseEvent *event) { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS if (!event->spontaneous() || !isVisible()) { return; } diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp index a43adfceac6..d5a7d6ae079 100644 --- a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp +++ b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp @@ -120,7 +120,7 @@ void MainWindow::actionTriggered(QAction *action) void MainWindow::setupToolBar() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS setUnifiedTitleAndToolBarOnMac(true); #endif @@ -178,7 +178,7 @@ void MainWindow::setupMenuBar() for (int i = 0; i < toolBars.count(); ++i) toolBarMenu->addMenu(toolBars.at(i)->toolbarMenu()); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS toolBarMenu->addSeparator(); action = toolBarMenu->addAction(tr("Unified")); diff --git a/examples/widgets/richtext/textedit/textedit.cpp b/examples/widgets/richtext/textedit/textedit.cpp index eccc29d26d7..9b5425240d0 100644 --- a/examples/widgets/richtext/textedit/textedit.cpp +++ b/examples/widgets/richtext/textedit/textedit.cpp @@ -96,7 +96,7 @@ const QString rsrcPath = ":/images/win"; TextEdit::TextEdit(QWidget *parent) : QMainWindow(parent) { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS setUnifiedTitleAndToolBarOnMac(true); #endif setWindowTitle(QCoreApplication::applicationName()); diff --git a/examples/widgets/tools/settingseditor/mainwindow.cpp b/examples/widgets/tools/settingseditor/mainwindow.cpp index ccca16ffcd7..225a396f91f 100644 --- a/examples/widgets/tools/settingseditor/mainwindow.cpp +++ b/examples/widgets/tools/settingseditor/mainwindow.cpp @@ -157,10 +157,10 @@ void MainWindow::createActions() QAction *openIniFileAct = fileMenu->addAction(tr("Open I&NI File..."), this, &MainWindow::openIniFile); openIniFileAct->setShortcut(tr("Ctrl+N")); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QAction *openPropertyListAct = fileMenu->addAction(tr("Open Apple &Property List..."), this, &MainWindow::openPropertyList); openPropertyListAct->setShortcut(tr("Ctrl+P")); -#endif // Q_OS_OSX +#endif // Q_OS_MACOS #ifdef Q_OS_WIN QAction *openRegistryPathAct = fileMenu->addAction(tr("Open Windows &Registry Path..."), this, &MainWindow::openRegistryPath); diff --git a/mkspecs/common/msvc-based-version.conf b/mkspecs/common/msvc-based-version.conf index 38aecbaf59a..b53e3b61aab 100644 --- a/mkspecs/common/msvc-based-version.conf +++ b/mkspecs/common/msvc-based-version.conf @@ -29,4 +29,9 @@ greaterThan(QMAKE_MSC_VER, 1910) { COMPAT_MKSPEC = } +greaterThan(QMAKE_MSC_VER, 1919) { + # Visual Studio 2019 (16.0) / Visual C++ 19.20 and up + MSVC_VER = 16.0 +} + !isEmpty(COMPAT_MKSPEC):!$$COMPAT_MKSPEC: CONFIG += $$COMPAT_MKSPEC diff --git a/mkspecs/common/winrt_winphone/manifests/10.0/AppxManifest.xml.in b/mkspecs/common/winrt_winphone/manifests/10.0/AppxManifest.xml.in index 18683e01e33..fe9ddaf8f18 100644 --- a/mkspecs/common/winrt_winphone/manifests/10.0/AppxManifest.xml.in +++ b/mkspecs/common/winrt_winphone/manifests/10.0/AppxManifest.xml.in @@ -6,7 +6,8 @@ xmlns:uap=\"http://schemas.microsoft.com/appx/manifest/uap/windows10\" xmlns:uap3=\"http://schemas.microsoft.com/appx/manifest/uap/windows10/3\" xmlns:mobile=\"http://schemas.microsoft.com/appx/manifest/mobile/windows10\" - IgnorableNamespaces=\"uap uap3 mp mobile\"> + xmlns:iot=\"http://schemas.microsoft.com/appx/manifest/iot/windows10\" + IgnorableNamespaces=\"uap uap3 mp mobile iot\"> " else:contains(UAP3_CAPABILITIES, $$CAPABILITY): \ MANIFEST_CAPABILITIES += " " + else:contains(IOT_CAPABILITIES, $$CAPABILITY): \ + MANIFEST_CAPABILITIES += " " else: \ MANIFEST_CAPABILITIES += " " } diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf index e6a97734822..18562621ac6 100644 --- a/mkspecs/wasm-emscripten/qmake.conf +++ b/mkspecs/wasm-emscripten/qmake.conf @@ -8,17 +8,20 @@ include(../common/clang.conf) load(device_config) load(emcc_ver) -# Support setting WASM_OBJECT_FILES with -device-option WASM_OBJECT_FILES=1 -!isEmpty(WASM_OBJECT_FILES): { - !equals(WASM_OBJECT_FILES, 1):!equals(WASM_OBJECT_FILES, 0): \ - message(Error: The value for WASM_OBJECT_FILES must be 0 or 1) - QMAKE_CFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES - QMAKE_CXXFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES - QMAKE_LFLAGS += -s WASM_OBJECT_FILES=$$WASM_OBJECT_FILES -} else { - EMSCRIPTEN_VERSION=$$qtSystemEmccVersion() - lessThan(EMSCRIPTEN_VERSION, 1.39) { - EMCC_COMMON_LFLAGS += -s \"BINARYEN_TRAP_MODE=\'clamp\'\" +# Support enabling asyncify by configuring with "-device-option EMSCRIPTEN_ASYNCIFY=1" +!isEmpty(EMSCRIPTEN_ASYNCIFY): { + !equals(EMSCRIPTEN_ASYNCIFY, 1):!equals(EMSCRIPTEN_ASYNCIFY, 0): \ + message(Error: The value for EMSCRIPTEN_ASYNCIFY must be 0 or 1) + equals(EMSCRIPTEN_ASYNCIFY, 1): { + QMAKE_CFLAGS += -DQT_HAVE_EMSCRIPTEN_ASYNCIFY + QMAKE_CXXFLAGS += -DQT_HAVE_EMSCRIPTEN_ASYNCIFY + QMAKE_LFLAGS += -s ASYNCIFY + + # Emscripten recommends building with optimizations when using asyncify + # in order to reduce wasm file size, and may also generate broken wasm + # (with "wasm validation error: too many locals" type errors) if optimizations + # are omitted. Enable optimizations also for debug builds. + QMAKE_LFLAGS_DEBUG += -Os } } @@ -37,7 +40,8 @@ EMCC_COMMON_LFLAGS += \ -s NO_EXIT_RUNTIME=0 \ -s ERROR_ON_UNDEFINED_SYMBOLS=1 \ -s EXTRA_EXPORTED_RUNTIME_METHODS=[\"UTF16ToString\",\"stringToUTF16\"] \ - --bind + --bind \ + -s FETCH=1 # The -s arguments can also be used with release builds, # but are here in debug for clarity. diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index f1e03eb4079..c90092059f9 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -2608,6 +2608,14 @@ Specifies the module name to be used for automatically generated QML type registrations. For more information, see \l {Defining QML Types from C++}. + \section1 QML_FOREIGN_METATYPES + + Specifies further JSON files with metatypes to be considered when generating + qmltypes files. Use this when external libraries provide types that are + exposed to QML, either directly or as base types or properties of other + types. Qt types will automatically be considered and don't have to be added + here. + \section1 QT Specifies the \l{All Modules}{Qt modules} that are used by your project. For diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h index ddbeeb90d25..f92a68454b1 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h @@ -31,7 +31,6 @@ struct TranslatedAttribute; // The order of this enum governs priority of 'getLatestBufferStorage'. enum BufferUsage { - BUFFER_USAGE_SYSTEM_MEMORY, BUFFER_USAGE_STAGING, BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, BUFFER_USAGE_INDEX, @@ -40,6 +39,7 @@ enum BufferUsage BUFFER_USAGE_PIXEL_UNPACK, BUFFER_USAGE_PIXEL_PACK, BUFFER_USAGE_UNIFORM, + BUFFER_USAGE_SYSTEM_MEMORY, BUFFER_USAGE_EMULATED_INDEXED_VERTEX, BUFFER_USAGE_COUNT, diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp index e8f13b388fc..9ece77ecbca 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp @@ -845,7 +845,7 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(const gl::Context *context, stateManager->setRenderTarget(mBackBufferRTView.get(), nullptr); // Set the viewport - stateManager->setSimpleViewport(mWidth, mHeight); + stateManager->setSimpleViewport(width, height); // Apply textures stateManager->setSimplePixelTextureAndSampler(mOffscreenSRView, mPassThroughSampler); diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp index 5394e3d3e76..f5e6c938131 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp @@ -168,7 +168,7 @@ HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device, nullptr, nullptr, &swapChain1); if (SUCCEEDED(result)) { - factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); + factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_WINDOW_CHANGES); *swapChain = static_cast(swapChain1); } SafeRelease(factory2); @@ -196,7 +196,7 @@ HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device, HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain); if (SUCCEEDED(result)) { - factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); + factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_WINDOW_CHANGES); } return result; } diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index 31189fa2cd2..50784deaa5f 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 Intel Corporation. +** Copyright (C) 2020 Intel Corporation. ** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com ** ** Permission is hereby granted, free of charge, to any person obtaining a copy @@ -29,6 +29,11 @@ #include "forkfd.h" +/* Macros fine-tuning the build: */ +//#define FORKFD_NO_FORKFD 1 /* disable the forkfd() function */ +//#define FORKFD_NO_SPAWNFD 1 /* disable the spawnfd() function */ +//#define FORKFD_DISABLE_FORK_FALLBACK 1 /* disable falling back to fork() from system_forkfd() */ + #include #if defined(__OpenBSD__) || defined(__NetBSD__) # include @@ -94,7 +99,17 @@ static int system_has_forkfd(void); static int system_forkfd(int flags, pid_t *ppid, int *system); -static int system_forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage); +static int system_forkfd_wait(int ffd, struct forkfd_info *info, int ffdwoptions, struct rusage *rusage); + +static int disable_fork_fallback(void) +{ +#ifdef FORKFD_DISABLE_FORK_FALLBACK + /* if there's no system forkfd, we have to use the fallback */ + return system_has_forkfd(); +#else + return false; +#endif +} #define CHILDREN_IN_SMALL_ARRAY 16 #define CHILDREN_IN_BIG_ARRAY 256 @@ -225,6 +240,16 @@ static void convertStatusToForkfdInfo(int status, struct forkfd_info *info) } } +static int convertForkfdWaitFlagsToWaitFlags(int ffdoptions) +{ + int woptions = WEXITED; + if (ffdoptions & FFDW_NOWAIT) + woptions |= WNOWAIT; + if (ffdoptions & FFDW_NOHANG) + woptions |= WNOHANG; + return woptions; +} + static int tryReaping(pid_t pid, struct pipe_payload *payload) { /* reap the child */ @@ -586,12 +611,18 @@ static int create_pipe(int filedes[], int flags) * descriptor. You probably want to set this flag, since forkfd() does not work * if the original parent process dies. * - * @li @C FFD_USE_FORK Tell forkfd() to actually call fork() instead of a + * @li @c FFD_USE_FORK Tell forkfd() to actually call fork() instead of a * different system implementation that may be available. On systems where a * different implementation is available, its behavior may differ from that of * fork(), such as not calling the functions registered with pthread_atfork(). * If that's necessary, pass this flag. * + * @li @c FFD_VFORK_SEMANTICS Tell forkfd() to use semantics similar to + * vfork(), if that's available. For example, on Linux with pidfd support + * available, this will add the CLONE_VFORK option. On most other systems, + * including Linux without pidfd support, this option does nothing, as using + * the actual vfork() system call would cause a race condition. + * * The file descriptor returned by forkfd() supports the following operations: * * @li read(2) When the child process exits, then the buffer supplied to @@ -619,9 +650,12 @@ int forkfd(int flags, pid_t *ppid) int efd; #endif + if (disable_fork_fallback()) + flags &= ~FFD_USE_FORK; + if ((flags & FFD_USE_FORK) == 0) { fd = system_forkfd(flags, ppid, &ret); - if (ret) + if (ret || disable_fork_fallback()) return fd; } @@ -800,14 +834,17 @@ out: } #endif // _POSIX_SPAWN && !FORKFD_NO_SPAWNFD - -int forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage) +int forkfd_wait4(int ffd, struct forkfd_info *info, int options, struct rusage *rusage) { struct pipe_payload payload; int ret; - if (system_has_forkfd()) - return system_forkfd_wait(ffd, info, rusage); + if (system_has_forkfd()) { + /* if this is one of our pipes, not a procdesc/pidfd, we'll get an EBADF */ + ret = system_forkfd_wait(ffd, info, options, rusage); + if (disable_fork_fallback() || ret != -1 || errno != EBADF) + return ret; + } ret = read(ffd, &payload, sizeof(payload)); if (ret == -1) @@ -846,10 +883,11 @@ int system_forkfd(int flags, pid_t *ppid, int *system) return -1; } -int system_forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage) +int system_forkfd_wait(int ffd, struct forkfd_info *info, int options, struct rusage *rusage) { (void)ffd; (void)info; + (void)options; (void)rusage; return -1; } diff --git a/src/3rdparty/forkfd/forkfd.h b/src/3rdparty/forkfd/forkfd.h index fe70371719e..a864b598611 100644 --- a/src/3rdparty/forkfd/forkfd.h +++ b/src/3rdparty/forkfd/forkfd.h @@ -38,19 +38,27 @@ extern "C" { #endif -#define FFD_CLOEXEC 1 -#define FFD_NONBLOCK 2 -#define FFD_USE_FORK 4 +#define FFD_CLOEXEC 1 +#define FFD_NONBLOCK 2 +#define FFD_USE_FORK 4 +#define FFD_VFORK_SEMANTICS 8 #define FFD_CHILD_PROCESS (-2) +#define FFDW_NOHANG 1 /* WNOHANG */ +#define FFDW_NOWAIT 2 /* WNOWAIT */ + struct forkfd_info { int32_t code; int32_t status; }; int forkfd(int flags, pid_t *ppid); -int forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage); +int forkfd_wait4(int ffd, struct forkfd_info *info, int options, struct rusage *rusage); +static inline int forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage) +{ + return forkfd_wait4(ffd, info, 0, rusage); +} int forkfd_close(int ffd); #if _POSIX_SPAWN > 0 diff --git a/src/3rdparty/forkfd/forkfd_freebsd.c b/src/3rdparty/forkfd/forkfd_freebsd.c index 77ce3fcfada..c4ca796ccd4 100644 --- a/src/3rdparty/forkfd/forkfd_freebsd.c +++ b/src/3rdparty/forkfd/forkfd_freebsd.c @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 Intel Corporation. +** Copyright (C) 2020 Intel Corporation. ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and associated documentation files (the "Software"), to deal @@ -29,6 +29,10 @@ #include "forkfd_atomic.h" +// in forkfd.c +static int convertForkfdWaitFlagsToWaitFlags(int ffdoptions); +static void convertStatusToForkfdInfo(int status, struct forkfd_info *info); + #if __FreeBSD__ >= 10 /* On FreeBSD 10, PROCDESC was enabled by default. On v11, it's not an option * anymore and can't be disabled. */ @@ -81,19 +85,23 @@ int system_forkfd(int flags, pid_t *ppid, int *system) return ret; } -int system_forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage) +int system_forkfd_wait(int ffd, struct forkfd_info *info, int ffdoptions, struct rusage *rusage) { pid_t pid; int status; - int options = WEXITED; + int options = convertForkfdWaitFlagsToWaitFlags(ffdoptions); int ret = pdgetpid(ffd, &pid); if (ret == -1) return ret; - ret = fcntl(ffd, F_GETFL); - if (ret == -1) - return ret; - options |= (ret & O_NONBLOCK) ? WNOHANG : 0; + + if ((options & WNOHANG) == 0) { + /* check if the file descriptor is non-blocking */ + ret = fcntl(ffd, F_GETFL); + if (ret == -1) + return ret; + options |= (ret & O_NONBLOCK) ? WNOHANG : 0; + } ret = wait4(pid, &status, options, rusage); if (ret != -1 && info) convertStatusToForkfdInfo(status, info); diff --git a/src/3rdparty/forkfd/forkfd_linux.c b/src/3rdparty/forkfd/forkfd_linux.c index 27ab09f7480..c4f723343f4 100644 --- a/src/3rdparty/forkfd/forkfd_linux.c +++ b/src/3rdparty/forkfd/forkfd_linux.c @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 Intel Corporation. +** Copyright (C) 2020 Intel Corporation. ** ** Permission is hereby granted, free of charge, to any person obtaining a copy ** of this software and associated documentation files (the "Software"), to deal @@ -51,6 +51,10 @@ # define P_PIDFD 3 #endif +// in forkfd.c +static int convertForkfdWaitFlagsToWaitFlags(int ffdoptions); +static void convertStatusToForkfdInfo(int status, struct forkfd_info *info); + static ffd_atomic_int system_forkfd_state = FFD_ATOMIC_INIT(0); static int sys_waitid(int which, int pid_or_pidfd, siginfo_t *infop, int options, @@ -143,7 +147,10 @@ int system_forkfd(int flags, pid_t *ppid, int *system) } *system = 1; - pid = sys_clone(CLONE_PIDFD, &pidfd); + unsigned long cloneflags = CLONE_PIDFD; + if (flags & FFD_VFORK_SEMANTICS) + cloneflags |= CLONE_VFORK; + pid = sys_clone(cloneflags, &pidfd); if (ppid) *ppid = pid; @@ -162,15 +169,20 @@ int system_forkfd(int flags, pid_t *ppid, int *system) return pidfd; } -int system_forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage) +int system_forkfd_wait(int ffd, struct forkfd_info *info, int ffdoptions, struct rusage *rusage) { siginfo_t si; - int options = WEXITED | __WALL; - int ret = fcntl(ffd, F_GETFL); - if (ret == -1) - return ret; - if (ret & O_NONBLOCK) - options |= WNOHANG; + int ret; + int options = __WALL | convertForkfdWaitFlagsToWaitFlags(ffdoptions); + + if ((options & WNOHANG) == 0) { + /* check if the file descriptor is non-blocking */ + ret = fcntl(ffd, F_GETFL); + if (ret == -1) + return ret; + if (ret & O_NONBLOCK) + options |= WNOHANG; + } ret = sys_waitid(P_PIDFD, ffd, &si, options, rusage); if (ret == -1 && errno == ECHILD) { diff --git a/src/3rdparty/libjpeg/jconfig.h b/src/3rdparty/libjpeg/jconfig.h index fb1e88ae291..8ed5620ca35 100644 --- a/src/3rdparty/libjpeg/jconfig.h +++ b/src/3rdparty/libjpeg/jconfig.h @@ -2,7 +2,7 @@ #define JPEG_LIB_VERSION 80 -#define LIBJPEG_TURBO_VERSION 2.0.3 +#define LIBJPEG_TURBO_VERSION 2.0.4 #define LIBJPEG_TURBO_VERSION_NUMBER 2000002 diff --git a/src/3rdparty/libjpeg/jconfigint.h b/src/3rdparty/libjpeg/jconfigint.h index 66169185091..d945be285b5 100644 --- a/src/3rdparty/libjpeg/jconfigint.h +++ b/src/3rdparty/libjpeg/jconfigint.h @@ -8,7 +8,7 @@ #define PACKAGE_NAME "libjpeg-turbo" -#define VERSION "2.0.3" +#define VERSION "2.0.4" #if SIZE_MAX == 0xffffffff #define SIZEOF_SIZE_T 4 diff --git a/src/3rdparty/libjpeg/qt_attribution.json b/src/3rdparty/libjpeg/qt_attribution.json index fa815299686..1eb095128a1 100644 --- a/src/3rdparty/libjpeg/qt_attribution.json +++ b/src/3rdparty/libjpeg/qt_attribution.json @@ -6,7 +6,7 @@ "Description": "The Independent JPEG Group's JPEG software", "Homepage": "http://libjpeg-turbo.virtualgl.org/", - "Version": "2.0.3", + "Version": "2.0.4", "License": "Independent JPEG Group License", "LicenseId": "IJG", "LicenseFile": "LICENSE", diff --git a/src/3rdparty/libjpeg/src/ChangeLog.md b/src/3rdparty/libjpeg/src/ChangeLog.md index 3667d120b1c..4d1219e555d 100644 --- a/src/3rdparty/libjpeg/src/ChangeLog.md +++ b/src/3rdparty/libjpeg/src/ChangeLog.md @@ -1,3 +1,44 @@ +2.0.4 +===== + +### Significant changes relative to 2.0.3: + +1. Fixed a regression in the Windows packaging system (introduced by +2.0 beta1[2]) whereby, if both the 64-bit libjpeg-turbo SDK for GCC and the +64-bit libjpeg-turbo SDK for Visual C++ were installed on the same system, only +one of them could be uninstalled. + +2. Fixed a signed integer overflow and subsequent segfault that occurred when +attempting to decompress images with more than 715827882 pixels using the +64-bit C version of TJBench. + +3. Fixed out-of-bounds write in `tjDecompressToYUV2()` and +`tjDecompressToYUVPlanes()` (sometimes manifesting as a double free) that +occurred when attempting to decompress grayscale JPEG images that were +compressed with a sampling factor other than 1 (for instance, with +`cjpeg -grayscale -sample 2x2`). + +4. Fixed a regression introduced by 2.0.2[5] that caused the TurboJPEG API to +incorrectly identify some JPEG images with unusual sampling factors as 4:4:4 +JPEG images. This was known to cause a buffer overflow when attempting to +decompress some such images using `tjDecompressToYUV2()` or +`tjDecompressToYUVPlanes()`. + +5. Fixed an issue, detected by ASan, whereby attempting to losslessly transform +a specially-crafted malformed JPEG image containing an extremely-high-frequency +coefficient block (junk image data that could never be generated by a +legitimate JPEG compressor) could cause the Huffman encoder's local buffer to +be overrun. (Refer to 1.4.0[9] and 1.4beta1[15].) Given that the buffer +overrun was fully contained within the stack and did not cause a segfault or +other user-visible errant behavior, and given that the lossless transformer +(unlike the decompressor) is not generally exposed to arbitrary data exploits, +this issue did not likely pose a security risk. + +6. The ARM 64-bit (ARMv8) NEON SIMD assembly code now stores constants in a +separate read-only data section rather than in the text section, to support +execute-only memory layouts. + + 2.0.3 ===== @@ -138,10 +179,11 @@ would produce a "Bogus message code" error message if the underlying bitmap and PPM readers/writers threw an error that was specific to the readers/writers (as opposed to a general libjpeg API error.) -4. Fixed an issue whereby a specially-crafted malformed BMP file, one in which -the header specified an image width of 1073741824 pixels, would trigger a -floating point exception (division by zero) in the `tjLoadImage()` function -when attempting to load the BMP file into a 4-component image buffer. +4. Fixed an issue (CVE-2018-1152) whereby a specially-crafted malformed BMP +file, one in which the header specified an image width of 1073741824 pixels, +would trigger a floating point exception (division by zero) in the +`tjLoadImage()` function when attempting to load the BMP file into a +4-component image buffer. 5. Fixed an issue whereby certain combinations of calls to `jpeg_skip_scanlines()` and `jpeg_read_scanlines()` could trigger an infinite @@ -155,10 +197,10 @@ a 4:2:2 or 4:2:0 JPEG image using the merged (non-fancy) upsampling algorithms 7. The new CMake-based build system will now disable the MIPS DSPr2 SIMD extensions if it detects that the compiler does not support DSPr2 instructions. -8. Fixed out-of-bounds read in cjpeg that occurred when attempting to compress -a specially-crafted malformed color-index (8-bit-per-sample) BMP file in which -some of the samples (color indices) exceeded the bounds of the BMP file's color -table. +8. Fixed out-of-bounds read in cjpeg (CVE-2018-14498) that occurred when +attempting to compress a specially-crafted malformed color-index +(8-bit-per-sample) BMP file in which some of the samples (color indices) +exceeded the bounds of the BMP file's color table. 9. Fixed a signed integer overflow in the progressive Huffman decoder, detected by the Clang and GCC undefined behavior sanitizers, that could be triggered by @@ -318,8 +360,8 @@ write scanlines in bottom-up order.) djpeg will now exit gracefully if an output format other than PPM/PGM, GIF, or Targa is selected along with the `-crop` option. -4. Fixed an issue whereby `jpeg_skip_scanlines()` would segfault if color -quantization was enabled. +4. Fixed an issue (CVE-2017-15232) whereby `jpeg_skip_scanlines()` would +segfault if color quantization was enabled. 5. TJBench (both C and Java versions) will now display usage information if any command-line argument is unrecognized. This prevents the program from silently @@ -946,13 +988,13 @@ and IDCT algorithms (both are used during JPEG decompression.) For unknown reasons (probably related to clang), this code cannot currently be compiled for iOS. -15. Fixed an extremely rare bug that could cause the Huffman encoder's local -buffer to overrun when a very high-frequency MCU is compressed using quality -100 and no subsampling, and when the JPEG output buffer is being dynamically -resized by the destination manager. This issue was so rare that, even with a -test program specifically designed to make the bug occur (by injecting random -high-frequency YUV data into the compressor), it was reproducible only once in -about every 25 million iterations. +15. Fixed an extremely rare bug (CVE-2014-9092) that could cause the Huffman +encoder's local buffer to overrun when a very high-frequency MCU is compressed +using quality 100 and no subsampling, and when the JPEG output buffer is being +dynamically resized by the destination manager. This issue was so rare that, +even with a test program specifically designed to make the bug occur (by +injecting random high-frequency YUV data into the compressor), it was +reproducible only once in about every 25 million iterations. 16. Fixed an oversight in the TurboJPEG C wrapper: if any of the JPEG compression functions was called repeatedly with the same @@ -987,8 +1029,9 @@ entropy coding (by passing arguments of `-progressive -arithmetic` to cjpeg or jpegtran, for instance) would result in an error, `Requested feature was omitted at compile time`. -4. Fixed a couple of issues whereby malformed JPEG images would cause -libjpeg-turbo to use uninitialized memory during decompression. +4. Fixed a couple of issues (CVE-2013-6629 and CVE-2013-6630) whereby malformed +JPEG images would cause libjpeg-turbo to use uninitialized memory during +decompression. 5. Fixed an error (`Buffer passed to JPEG library is too small`) that occurred when calling the TurboJPEG YUV encoding function with a very small (< 5x5) @@ -1127,9 +1170,9 @@ correct behavior of the colorspace extensions when merged upsampling is used. upper 64 bits of xmm6 and xmm7 on Win64 platforms, which violated the Win64 calling conventions. -4. Fixed a regression caused by 1.2.0[6] whereby decompressing corrupt JPEG -images (specifically, images in which the component count was erroneously set -to a large value) would cause libjpeg-turbo to segfault. +4. Fixed a regression (CVE-2012-2806) caused by 1.2.0[6] whereby decompressing +corrupt JPEG images (specifically, images in which the component count was +erroneously set to a large value) would cause libjpeg-turbo to segfault. 5. Worked around a severe performance issue with "Bobcat" (AMD Embedded APU) processors. The `MASKMOVDQU` instruction, which was used by the libjpeg-turbo diff --git a/src/3rdparty/libjpeg/src/README.md b/src/3rdparty/libjpeg/src/README.md index c61b8556440..e7ff743a471 100644 --- a/src/3rdparty/libjpeg/src/README.md +++ b/src/3rdparty/libjpeg/src/README.md @@ -1,14 +1,14 @@ Background ========== -libjpeg-turbo is a JPEG image codec that uses SIMD instructions (MMX, SSE2, -AVX2, NEON, AltiVec) to accelerate baseline JPEG compression and decompression -on x86, x86-64, ARM, and PowerPC systems, as well as progressive JPEG -compression on x86 and x86-64 systems. On such systems, libjpeg-turbo is -generally 2-6x as fast as libjpeg, all else being equal. On other types of -systems, libjpeg-turbo can still outperform libjpeg by a significant amount, by -virtue of its highly-optimized Huffman coding routines. In many cases, the -performance of libjpeg-turbo rivals that of proprietary high-speed JPEG codecs. +libjpeg-turbo is a JPEG image codec that uses SIMD instructions to accelerate +baseline JPEG compression and decompression on x86, x86-64, ARM, PowerPC, and +MIPS systems, as well as progressive JPEG compression on x86 and x86-64 +systems. On such systems, libjpeg-turbo is generally 2-6x as fast as libjpeg, +all else being equal. On other types of systems, libjpeg-turbo can still +outperform libjpeg by a significant amount, by virtue of its highly-optimized +Huffman coding routines. In many cases, the performance of libjpeg-turbo +rivals that of proprietary high-speed JPEG codecs. libjpeg-turbo implements both the traditional libjpeg API as well as the less powerful but more straightforward TurboJPEG API. libjpeg-turbo also features @@ -145,14 +145,14 @@ supported and which aren't. #### Fully supported -- **libjpeg: IDCT scaling extensions in decompressor**
+- **libjpeg API: IDCT scaling extensions in decompressor**
libjpeg-turbo supports IDCT scaling with scaling factors of 1/8, 1/4, 3/8, 1/2, 5/8, 3/4, 7/8, 9/8, 5/4, 11/8, 3/2, 13/8, 7/4, 15/8, and 2/1 (only 1/4 and 1/2 are SIMD-accelerated.) -- **libjpeg: Arithmetic coding** +- **libjpeg API: Arithmetic coding** -- **libjpeg: In-memory source and destination managers**
+- **libjpeg API: In-memory source and destination managers**
See notes below. - **cjpeg: Separate quality settings for luminance and chrominance**
@@ -184,14 +184,14 @@ means of quality improvement. The reader is invited to peruse the research at but it is the general belief of our project that these features have not demonstrated sufficient usefulness to justify inclusion in libjpeg-turbo. -- **libjpeg: DCT scaling in compressor**
+- **libjpeg API: DCT scaling in compressor**
`cinfo.scale_num` and `cinfo.scale_denom` are silently ignored. There is no technical reason why DCT scaling could not be supported when emulating the libjpeg v7+ API/ABI, but without the SmartScale extension (see below), only scaling factors of 1/2, 8/15, 4/7, 8/13, 2/3, 8/11, 4/5, and 8/9 would be available, which is of limited usefulness. -- **libjpeg: SmartScale**
+- **libjpeg API: SmartScale**
`cinfo.block_size` is silently ignored. SmartScale is an extension to the JPEG format that allows for DCT block sizes other than 8x8. Providing support for this new format would be @@ -204,7 +204,7 @@ demonstrated sufficient usefulness to justify inclusion in libjpeg-turbo. interest in providing this feature would be as a means of supporting additional DCT scaling factors. -- **libjpeg: Fancy downsampling in compressor**
+- **libjpeg API: Fancy downsampling in compressor**
`cinfo.do_fancy_downsampling` is silently ignored. This requires the DCT scaling feature, which is not supported. @@ -252,8 +252,8 @@ building libjpeg-turbo. This will restore the pre-1.3 behavior, in which libjpeg v8 API/ABI. On Un*x systems, including the in-memory source/destination managers changes -the dynamic library version from 62.1.0 to 62.2.0 if using libjpeg v6b API/ABI -emulation and from 7.1.0 to 7.2.0 if using libjpeg v7 API/ABI emulation. +the dynamic library version from 62.2.0 to 62.3.0 if using libjpeg v6b API/ABI +emulation and from 7.2.0 to 7.3.0 if using libjpeg v7 API/ABI emulation. Note that, on most Un*x systems, the dynamic linker will not look for a function in a library until that function is actually used. Thus, if a program @@ -329,7 +329,7 @@ in a way that makes the rest of the libjpeg infrastructure happy, so it is necessary to use the slow Huffman decoder when decompressing a JPEG image that has restart markers. This can cause the decompression performance to drop by as much as 20%, but the performance will still be much greater than that of -libjpeg. Many consumer packages, such as PhotoShop, use restart markers when +libjpeg. Many consumer packages, such as Photoshop, use restart markers when generating JPEG images, so images generated by those programs will experience this issue. diff --git a/src/3rdparty/libjpeg/src/jchuff.c b/src/3rdparty/libjpeg/src/jchuff.c index 526203e3db7..cb05055d992 100644 --- a/src/3rdparty/libjpeg/src/jchuff.c +++ b/src/3rdparty/libjpeg/src/jchuff.c @@ -43,8 +43,8 @@ */ /* NOTE: Both GCC and Clang define __GNUC__ */ -#if defined __GNUC__ && (defined __arm__ || defined __aarch64__) -#if !defined __thumb__ || defined __thumb2__ +#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) +#if !defined(__thumb__) || defined(__thumb2__) #define USE_CLZ_INTRINSIC #endif #endif @@ -432,7 +432,7 @@ dump_buffer(working_state *state) * scanning order-- 1, 8, 16, etc.), then this will produce an encoded block * larger than 200 bytes. */ -#define BUFSIZE (DCTSIZE2 * 4) +#define BUFSIZE (DCTSIZE2 * 8) #define LOAD_BUFFER() { \ if (state->free_in_buffer < BUFSIZE) { \ diff --git a/src/3rdparty/libjpeg/src/jcphuff.c b/src/3rdparty/libjpeg/src/jcphuff.c index 024d3af0fb1..8c4efaf16cb 100644 --- a/src/3rdparty/libjpeg/src/jcphuff.c +++ b/src/3rdparty/libjpeg/src/jcphuff.c @@ -52,8 +52,8 @@ */ /* NOTE: Both GCC and Clang define __GNUC__ */ -#if defined __GNUC__ && (defined __arm__ || defined __aarch64__) -#if !defined __thumb__ || defined __thumb2__ +#if defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__)) +#if !defined(__thumb__) || defined(__thumb2__) #define USE_CLZ_INTRINSIC #endif #endif diff --git a/src/3rdparty/libjpeg/src/jfdctint.c b/src/3rdparty/libjpeg/src/jfdctint.c index c0391a92bee..b47c3061ac5 100644 --- a/src/3rdparty/libjpeg/src/jfdctint.c +++ b/src/3rdparty/libjpeg/src/jfdctint.c @@ -1,7 +1,7 @@ /* * jfdctint.c * - * This file was part of the Independent JPEG Group's software. + * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1996, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright (C) 2015, D. R. Commander. diff --git a/src/3rdparty/libjpeg/src/jidctint.c b/src/3rdparty/libjpeg/src/jidctint.c index 55573429f1a..98425d5fd08 100644 --- a/src/3rdparty/libjpeg/src/jidctint.c +++ b/src/3rdparty/libjpeg/src/jidctint.c @@ -1,7 +1,7 @@ /* * jidctint.c * - * This file was part of the Independent JPEG Group's software. + * This file was part of the Independent JPEG Group's software: * Copyright (C) 1991-1998, Thomas G. Lane. * Modification developed 2002-2009 by Guido Vollbeding. * libjpeg-turbo Modifications: diff --git a/src/3rdparty/libjpeg/src/jidctred.c b/src/3rdparty/libjpeg/src/jidctred.c index 1ff352f875f..1dd65a94d97 100644 --- a/src/3rdparty/libjpeg/src/jidctred.c +++ b/src/3rdparty/libjpeg/src/jidctred.c @@ -1,7 +1,7 @@ /* * jidctred.c * - * This file was part of the Independent JPEG Group's software. + * This file was part of the Independent JPEG Group's software: * Copyright (C) 1994-1998, Thomas G. Lane. * libjpeg-turbo Modifications: * Copyright (C) 2015, D. R. Commander. diff --git a/src/3rdparty/sqlite/patches/0001-Fix-CVE-2020-9327-in-SQLite.patch b/src/3rdparty/sqlite/patches/0001-Fix-CVE-2020-9327-in-SQLite.patch new file mode 100644 index 00000000000..4fbb2ee3397 --- /dev/null +++ b/src/3rdparty/sqlite/patches/0001-Fix-CVE-2020-9327-in-SQLite.patch @@ -0,0 +1,203 @@ +From 63566d1fff2665b777650594eec6eefd3587e177 Mon Sep 17 00:00:00 2001 +From: Andy Shaw +Date: Wed, 4 Mar 2020 07:44:22 +0100 +Subject: [PATCH] Fix CVE-2020-9327 in SQLite + +This was taken from abc473fb8fb99900 in SQLite, ref: +https://www.sqlite.org/cgi/src/info/abc473fb8fb99900 + +Fixes: QTBUG-82533 +Change-Id: I9840e29f19a0b861229987f5b59d8585ba2e55dc +--- + .../0001-Fix-CVE-2020-9327-in-SQLite.patch | 96 +++++++++++++++++++ + src/3rdparty/sqlite/sqlite3.c | 31 ++++-- + 2 files changed, 118 insertions(+), 9 deletions(-) + create mode 100644 src/3rdparty/sqlite/patches/0001-Fix-CVE-2020-9327-in-SQLite.patch + +diff --git a/src/3rdparty/sqlite/patches/0001-Fix-CVE-2020-9327-in-SQLite.patch b/src/3rdparty/sqlite/patches/0001-Fix-CVE-2020-9327-in-SQLite.patch +new file mode 100644 +index 0000000000..e0e8206db5 +--- /dev/null ++++ b/src/3rdparty/sqlite/patches/0001-Fix-CVE-2020-9327-in-SQLite.patch +@@ -0,0 +1,96 @@ ++From f79860e0fe251e3267a3cd5558dce98f918e0caa Mon Sep 17 00:00:00 2001 ++From: Andy Shaw ++Date: Wed, 4 Mar 2020 07:44:22 +0100 ++Subject: [PATCH] Fix CVE-2020-9327 in SQLite ++ ++Fixes: QTBUG-82533 ++Change-Id: I9840e29f19a0b861229987f5b59d8585ba2e55dc ++--- ++ src/3rdparty/sqlite/sqlite3.c | 31 ++++++++++++++++++++++--------- ++ 1 file changed, 22 insertions(+), 9 deletions(-) ++ ++diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c ++index 55dc686ee0..dfe5323a59 100644 ++--- a/src/3rdparty/sqlite/sqlite3.c +++++ b/src/3rdparty/sqlite/sqlite3.c ++@@ -17428,8 +17428,11 @@ struct Table { ++ */ ++ #ifndef SQLITE_OMIT_VIRTUALTABLE ++ # define IsVirtual(X) ((X)->nModuleArg) +++# define ExprIsVtab(X) \ +++ ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg) ++ #else ++ # define IsVirtual(X) 0 +++# define ExprIsVtab(X) 0 ++ #endif ++ ++ /* ++@@ -104133,19 +104136,25 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ ++ case TK_LT: ++ case TK_LE: ++ case TK_GT: ++- case TK_GE: +++ case TK_GE: { +++ Expr *pLeft = pExpr->pLeft; +++ Expr *pRight = pExpr->pRight; ++ testcase( pExpr->op==TK_EQ ); ++ testcase( pExpr->op==TK_NE ); ++ testcase( pExpr->op==TK_LT ); ++ testcase( pExpr->op==TK_LE ); ++ testcase( pExpr->op==TK_GT ); ++ testcase( pExpr->op==TK_GE ); ++- if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab)) ++- || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab)) +++ /* The y.pTab=0 assignment in wherecode.c always happens after the +++ ** impliesNotNullRow() test */ +++ if( (pLeft->op==TK_COLUMN && ALWAYS(pLeft->y.pTab!=0) +++ && IsVirtual(pLeft->y.pTab)) +++ || (pRight->op==TK_COLUMN && ALWAYS(pRight->y.pTab!=0) +++ && IsVirtual(pRight->y.pTab)) ++ ){ ++- return WRC_Prune; +++ return WRC_Prune; ++ } ++- +++ } ++ default: ++ return WRC_Continue; ++ } ++@@ -142591,7 +142600,8 @@ static int isAuxiliaryVtabOperator( ++ ** MATCH(expression,vtab_column) ++ */ ++ pCol = pList->a[1].pExpr; ++- if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ +++ testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 ); +++ if( ExprIsVtab(pCol) ){ ++ for(i=0; iu.zToken, aOp[i].zOp)==0 ){ ++ *peOp2 = aOp[i].eOp2; ++@@ -142613,7 +142623,8 @@ static int isAuxiliaryVtabOperator( ++ ** with function names in an arbitrary case. ++ */ ++ pCol = pList->a[0].pExpr; ++- if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ +++ testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 ); +++ if( ExprIsVtab(pCol) ){ ++ sqlite3_vtab *pVtab; ++ sqlite3_module *pMod; ++ void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); ++@@ -142636,10 +142647,12 @@ static int isAuxiliaryVtabOperator( ++ int res = 0; ++ Expr *pLeft = pExpr->pLeft; ++ Expr *pRight = pExpr->pRight; ++- if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){ +++ testcase( pLeft->op==TK_COLUMN && pLeft->y.pTab==0 ); +++ if( ExprIsVtab(pLeft) ){ ++ res++; ++ } ++- if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){ +++ testcase( pRight && pRight->op==TK_COLUMN && pRight->y.pTab==0 ); +++ if( pRight && ExprIsVtab(pRight) ){ ++ res++; ++ SWAP(Expr*, pLeft, pRight); ++ } ++-- ++2.21.0 (Apple Git-122.2) ++ +diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c +index 55dc686ee0..dfe5323a59 100644 +--- a/src/3rdparty/sqlite/sqlite3.c ++++ b/src/3rdparty/sqlite/sqlite3.c +@@ -17428,8 +17428,11 @@ struct Table { + */ + #ifndef SQLITE_OMIT_VIRTUALTABLE + # define IsVirtual(X) ((X)->nModuleArg) ++# define ExprIsVtab(X) \ ++ ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg) + #else + # define IsVirtual(X) 0 ++# define ExprIsVtab(X) 0 + #endif + + /* +@@ -104133,19 +104136,25 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ + case TK_LT: + case TK_LE: + case TK_GT: +- case TK_GE: ++ case TK_GE: { ++ Expr *pLeft = pExpr->pLeft; ++ Expr *pRight = pExpr->pRight; + testcase( pExpr->op==TK_EQ ); + testcase( pExpr->op==TK_NE ); + testcase( pExpr->op==TK_LT ); + testcase( pExpr->op==TK_LE ); + testcase( pExpr->op==TK_GT ); + testcase( pExpr->op==TK_GE ); +- if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab)) +- || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab)) ++ /* The y.pTab=0 assignment in wherecode.c always happens after the ++ ** impliesNotNullRow() test */ ++ if( (pLeft->op==TK_COLUMN && ALWAYS(pLeft->y.pTab!=0) ++ && IsVirtual(pLeft->y.pTab)) ++ || (pRight->op==TK_COLUMN && ALWAYS(pRight->y.pTab!=0) ++ && IsVirtual(pRight->y.pTab)) + ){ +- return WRC_Prune; ++ return WRC_Prune; + } +- ++ } + default: + return WRC_Continue; + } +@@ -142591,7 +142600,8 @@ static int isAuxiliaryVtabOperator( + ** MATCH(expression,vtab_column) + */ + pCol = pList->a[1].pExpr; +- if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ ++ testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 ); ++ if( ExprIsVtab(pCol) ){ + for(i=0; iu.zToken, aOp[i].zOp)==0 ){ + *peOp2 = aOp[i].eOp2; +@@ -142613,7 +142623,8 @@ static int isAuxiliaryVtabOperator( + ** with function names in an arbitrary case. + */ + pCol = pList->a[0].pExpr; +- if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ ++ testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 ); ++ if( ExprIsVtab(pCol) ){ + sqlite3_vtab *pVtab; + sqlite3_module *pMod; + void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); +@@ -142636,10 +142647,12 @@ static int isAuxiliaryVtabOperator( + int res = 0; + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pRight; +- if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){ ++ testcase( pLeft->op==TK_COLUMN && pLeft->y.pTab==0 ); ++ if( ExprIsVtab(pLeft) ){ + res++; + } +- if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){ ++ testcase( pRight && pRight->op==TK_COLUMN && pRight->y.pTab==0 ); ++ if( pRight && ExprIsVtab(pRight) ){ + res++; + SWAP(Expr*, pLeft, pRight); + } +-- +2.21.0 (Apple Git-122.2) + diff --git a/src/3rdparty/sqlite/sqlite3.c b/src/3rdparty/sqlite/sqlite3.c index 55dc686ee06..dfe5323a594 100644 --- a/src/3rdparty/sqlite/sqlite3.c +++ b/src/3rdparty/sqlite/sqlite3.c @@ -17428,8 +17428,11 @@ struct Table { */ #ifndef SQLITE_OMIT_VIRTUALTABLE # define IsVirtual(X) ((X)->nModuleArg) +# define ExprIsVtab(X) \ + ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg) #else # define IsVirtual(X) 0 +# define ExprIsVtab(X) 0 #endif /* @@ -104133,19 +104136,25 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){ case TK_LT: case TK_LE: case TK_GT: - case TK_GE: + case TK_GE: { + Expr *pLeft = pExpr->pLeft; + Expr *pRight = pExpr->pRight; testcase( pExpr->op==TK_EQ ); testcase( pExpr->op==TK_NE ); testcase( pExpr->op==TK_LT ); testcase( pExpr->op==TK_LE ); testcase( pExpr->op==TK_GT ); testcase( pExpr->op==TK_GE ); - if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab)) - || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab)) + /* The y.pTab=0 assignment in wherecode.c always happens after the + ** impliesNotNullRow() test */ + if( (pLeft->op==TK_COLUMN && ALWAYS(pLeft->y.pTab!=0) + && IsVirtual(pLeft->y.pTab)) + || (pRight->op==TK_COLUMN && ALWAYS(pRight->y.pTab!=0) + && IsVirtual(pRight->y.pTab)) ){ - return WRC_Prune; + return WRC_Prune; } - + } default: return WRC_Continue; } @@ -142591,7 +142600,8 @@ static int isAuxiliaryVtabOperator( ** MATCH(expression,vtab_column) */ pCol = pList->a[1].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ + testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 ); + if( ExprIsVtab(pCol) ){ for(i=0; iu.zToken, aOp[i].zOp)==0 ){ *peOp2 = aOp[i].eOp2; @@ -142613,7 +142623,8 @@ static int isAuxiliaryVtabOperator( ** with function names in an arbitrary case. */ pCol = pList->a[0].pExpr; - if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){ + testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 ); + if( ExprIsVtab(pCol) ){ sqlite3_vtab *pVtab; sqlite3_module *pMod; void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**); @@ -142636,10 +142647,12 @@ static int isAuxiliaryVtabOperator( int res = 0; Expr *pLeft = pExpr->pLeft; Expr *pRight = pExpr->pRight; - if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){ + testcase( pLeft->op==TK_COLUMN && pLeft->y.pTab==0 ); + if( ExprIsVtab(pLeft) ){ res++; } - if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){ + testcase( pRight && pRight->op==TK_COLUMN && pRight->y.pTab==0 ); + if( pRight && ExprIsVtab(pRight) ){ res++; SWAP(Expr*, pLeft, pRight); } diff --git a/src/3rdparty/tinycbor/tests/parser/data.cpp b/src/3rdparty/tinycbor/tests/parser/data.cpp index 0ab0e47be4c..3523c32167b 100644 --- a/src/3rdparty/tinycbor/tests/parser/data.cpp +++ b/src/3rdparty/tinycbor/tests/parser/data.cpp @@ -338,7 +338,7 @@ void addValidationColumns() QTest::addColumn("expectedError"); } -void addValidationData() +void addValidationData(size_t minInvalid = ~size_t(0)) { // illegal numbers are future extension points QTest::newRow("illegal-number-in-unsigned-1") << raw("\x81\x1c") << 0 << CborErrorIllegalNumber; @@ -488,26 +488,35 @@ void addValidationData() QTest::newRow("map-break-after-value-tag2") << raw("\x81\xbf\0\xd8\x20\xff") << 0 << CborErrorUnexpectedBreak; // check for pointer additions wrapping over the limit of the address space - CborError tooLargeOn32bit = (sizeof(void *) == 4) ? CborErrorDataTooLarge : CborErrorUnexpectedEOF; + auto wraparoundError = [minInvalid](uint64_t encodedSize) { + if (encodedSize > minInvalid) + return CborErrorDataTooLarge; + return CborErrorUnexpectedEOF; + }; + constexpr uint64_t FourGB = UINT32_MAX + UINT64_C(1); // on 32-bit systems, this is a -1 - QTest::newRow("bytearray-wraparound1") << raw("\x81\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-wraparound1") << raw("\x81\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF; + QTest::newRow("bytearray-wraparound1") << raw("\x81\x5a\xff\xff\xff\xff") << 0 << wraparoundError(UINT32_MAX); + QTest::newRow("string-wraparound1") << raw("\x81\x7a\xff\xff\xff\xff") << 0 << wraparoundError(UINT32_MAX); // on 32-bit systems, a 4GB addition could be dropped - QTest::newRow("bytearray-wraparound2") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit; - QTest::newRow("string-wraparound2") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit; + QTest::newRow("bytearray-wraparound2") << raw("\x81\x5b\0\0\0\1\0\0\0\0") << 0 << wraparoundError(FourGB); + QTest::newRow("string-wraparound2") << raw("\x81\x7b\0\0\0\1\0\0\0\0") << 0 << wraparoundError(FourGB); // on 64-bit systems, this could be a -1 - QTest::newRow("bytearray-wraparound3") << raw("\x81\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit; - QTest::newRow("string-wraparound3") << raw("\x81\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit; + QTest::newRow("bytearray-wraparound3") << raw("\x81\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 + << wraparoundError(UINT64_MAX); + QTest::newRow("string-wraparound3") << raw("\x81\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 + << wraparoundError(UINT64_MAX); // ditto on chunks - QTest::newRow("bytearray-chunk-wraparound1") << raw("\x81\x5f\x5a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF; - QTest::newRow("string-chunk-wraparound1") << raw("\x81\x7f\x7a\xff\xff\xff\xff") << 0 << CborErrorUnexpectedEOF; + QTest::newRow("bytearray-chunk-wraparound1") << raw("\x81\x5f\x5a\xff\xff\xff\xff") << 0 << wraparoundError(UINT32_MAX); + QTest::newRow("string-chunk-wraparound1") << raw("\x81\x7f\x7a\xff\xff\xff\xff") << 0 << wraparoundError(UINT32_MAX); // on 32-bit systems, a 4GB addition could be dropped - QTest::newRow("bytearray-chunk-wraparound2") << raw("\x81\x5f\x5b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit; - QTest::newRow("string-chunk-wraparound2") << raw("\x81\x7f\x7b\0\0\0\1\0\0\0\0") << 0 << tooLargeOn32bit; + QTest::newRow("bytearray-chunk-wraparound2") << raw("\x81\x5f\x5b\0\0\0\1\0\0\0\0") << 0 << wraparoundError(FourGB); + QTest::newRow("string-chunk-wraparound2") << raw("\x81\x7f\x7b\0\0\0\1\0\0\0\0") << 0 << wraparoundError(FourGB); // on 64-bit systems, this could be a -1 - QTest::newRow("bytearray-chunk-wraparound3") << raw("\x81\x5f\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit; - QTest::newRow("string-chunk-wraparound3") << raw("\x81\x7f\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 << tooLargeOn32bit; + QTest::newRow("bytearray-chunk-wraparound3") << raw("\x81\x5f\x5b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 + << wraparoundError(UINT64_MAX); + QTest::newRow("string-chunk-wraparound3") << raw("\x81\x7f\x7b\xff\xff\xff\xff\xff\xff\xff\xff") << 0 + << wraparoundError(UINT64_MAX); QTest::newRow("eof-after-array") << raw("\x81") << 0 << CborErrorUnexpectedEOF; QTest::newRow("eof-after-array2") << raw("\x81\x78\x20") << 0 << CborErrorUnexpectedEOF; diff --git a/src/angle/patches/0016-ANGLE-Fix-severe-performance-regression.patch b/src/angle/patches/0016-ANGLE-Fix-severe-performance-regression.patch new file mode 100644 index 00000000000..e9cda1337f8 --- /dev/null +++ b/src/angle/patches/0016-ANGLE-Fix-severe-performance-regression.patch @@ -0,0 +1,37 @@ +From b215999d63d6e6b087e53e24a47b8b60520ec9e4 Mon Sep 17 00:00:00 2001 +From: Oliver Wolff +Date: Wed, 11 Mar 2020 13:59:39 +0100 +Subject: [PATCH] ANGLE: Fix severe performance regression + +The changed buffer usage priority that was introduced in our ANGLE +update caused severe performance regressions for Qt applications. + +Fixes: QTBUG-73835 +Change-Id: I49839bb272cdeec0027264f2751b88bc149665ad +--- + src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h +index ddbeeb90d2..f92a68454b 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h +@@ -31,7 +31,6 @@ struct TranslatedAttribute; + // The order of this enum governs priority of 'getLatestBufferStorage'. + enum BufferUsage + { +- BUFFER_USAGE_SYSTEM_MEMORY, + BUFFER_USAGE_STAGING, + BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, + BUFFER_USAGE_INDEX, +@@ -40,6 +39,7 @@ enum BufferUsage + BUFFER_USAGE_PIXEL_UNPACK, + BUFFER_USAGE_PIXEL_PACK, + BUFFER_USAGE_UNIFORM, ++ BUFFER_USAGE_SYSTEM_MEMORY, + BUFFER_USAGE_EMULATED_INDEXED_VERTEX, + + BUFFER_USAGE_COUNT, +-- +2.20.1.windows.1 + diff --git a/src/angle/patches/0017-ANGLE-Fix-resizing-of-windows-Take-2.patch b/src/angle/patches/0017-ANGLE-Fix-resizing-of-windows-Take-2.patch new file mode 100644 index 00000000000..abab74b1923 --- /dev/null +++ b/src/angle/patches/0017-ANGLE-Fix-resizing-of-windows-Take-2.patch @@ -0,0 +1,27 @@ +From 029d42d1049dcde7950c11fb9adf07c07a8c4c02 Mon Sep 17 00:00:00 2001 +From: Oliver Wolff +Date: Wed, 18 Mar 2020 10:56:53 +0100 +Subject: [PATCH] ANGLE: Fix resizing of windows (Take 2) + +Task-number: QTBUG-62475 +Change-Id: I0ea17e7875906508941ae64bb396a4236928b0f9 +--- + .../angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +index e8f13b388f..9ece77ecbc 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp +@@ -845,7 +845,7 @@ EGLint SwapChain11::copyOffscreenToBackbuffer(const gl::Context *context, + stateManager->setRenderTarget(mBackBufferRTView.get(), nullptr); + + // Set the viewport +- stateManager->setSimpleViewport(mWidth, mHeight); ++ stateManager->setSimpleViewport(width, height); + + // Apply textures + stateManager->setSimplePixelTextureAndSampler(mOffscreenSRView, mPassThroughSampler); +-- +2.20.1.windows.1 + diff --git a/src/angle/patches/0018-ANGLE-d3d11-Do-not-register-windows-message-hooks-fo.patch b/src/angle/patches/0018-ANGLE-d3d11-Do-not-register-windows-message-hooks-fo.patch new file mode 100644 index 00000000000..03529c6531d --- /dev/null +++ b/src/angle/patches/0018-ANGLE-d3d11-Do-not-register-windows-message-hooks-fo.patch @@ -0,0 +1,45 @@ +From 3d23de2ad72968d0bf43dac4a9a0f237cc9e03e2 Mon Sep 17 00:00:00 2001 +From: Oliver Wolff +Date: Wed, 1 Apr 2020 14:48:48 +0200 +Subject: [PATCH] ANGLE: d3d11: Do not register windows message hooks for d3d11 + windows + +These message hooks are used to handle ALT+ENTER to enter/exit fullscreen +mode and PRINTSCREEN to take screenshots. Qt is implementing these +functionalities itself so we do not have to register these hooks. + +If too many of these hooks are registered, callbacks are no longer called +and Qt's message queue is no longer handling messages. By saving these +hooks we can make sure that more Qt windows at the same time are possible +without getting unresponsive due to too many hooks being registered. + +Change-Id: I5354f91f08cbfeda5e8dc3ad7f824fbd5b3b2932 +--- + .../src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp +index 5394e3d..f5e6c93 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow11Win32.cpp +@@ -168,7 +168,7 @@ HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device, + nullptr, nullptr, &swapChain1); + if (SUCCEEDED(result)) + { +- factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); ++ factory2->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_WINDOW_CHANGES); + *swapChain = static_cast(swapChain1); + } + SafeRelease(factory2); +@@ -196,7 +196,7 @@ HRESULT NativeWindow11Win32::createSwapChain(ID3D11Device *device, + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, swapChain); + if (SUCCEEDED(result)) + { +- factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_ALT_ENTER); ++ factory->MakeWindowAssociation(getNativeWindow(), DXGI_MWA_NO_WINDOW_CHANGES); + } + return result; + } +-- +2.7.4.windows.1 + diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake new file mode 100644 index 00000000000..88350cb68b7 --- /dev/null +++ b/src/corelib/Qt5CoreMacros.cmake @@ -0,0 +1,507 @@ +#============================================================================= +# Copyright 2005-2011 Kitware, Inc. +# Copyright (C) 2020 The Qt Company Ltd. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Kitware, Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +###################################### +# +# Macros for building Qt files +# +###################################### + +include(CMakeParseArguments) + +function(_qt5_warn_deprecated command_name) + if(NOT DEFINED _QT5_INTERNAL_SCOPE) + message(AUTHOR_WARNING + "${command_name} is not part of the official API, and might be removed in Qt 6.") + endif() +endfunction() + +# macro used to create the names of output files preserving relative dirs +macro(qt5_make_output_file infile prefix ext outfile ) + _qt5_warn_deprecated("qt5_make_output_file") + + string(LENGTH ${CMAKE_CURRENT_BINARY_DIR} _binlength) + string(LENGTH ${infile} _infileLength) + set(_checkinfile ${CMAKE_CURRENT_SOURCE_DIR}) + if(_infileLength GREATER _binlength) + string(SUBSTRING "${infile}" 0 ${_binlength} _checkinfile) + if(_checkinfile STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") + file(RELATIVE_PATH rel ${CMAKE_CURRENT_BINARY_DIR} ${infile}) + else() + file(RELATIVE_PATH rel ${CMAKE_CURRENT_SOURCE_DIR} ${infile}) + endif() + else() + file(RELATIVE_PATH rel ${CMAKE_CURRENT_SOURCE_DIR} ${infile}) + endif() + if(WIN32 AND rel MATCHES "^([a-zA-Z]):(.*)$") # absolute path + set(rel "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}") + endif() + set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${rel}") + string(REPLACE ".." "__" _outfile ${_outfile}) + get_filename_component(outpath ${_outfile} PATH) + if(CMAKE_VERSION VERSION_LESS "3.14") + get_filename_component(_outfile_ext ${_outfile} EXT) + get_filename_component(_outfile_ext ${_outfile_ext} NAME_WE) + get_filename_component(_outfile ${_outfile} NAME_WE) + string(APPEND _outfile ${_outfile_ext}) + else() + get_filename_component(_outfile ${_outfile} NAME_WLE) + endif() + file(MAKE_DIRECTORY ${outpath}) + set(${outfile} ${outpath}/${prefix}${_outfile}.${ext}) +endmacro() + + +macro(qt5_get_moc_flags _moc_flags) + _qt5_warn_deprecated("qt5_get_moc_flags") + + set(${_moc_flags}) + get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES) + + if(CMAKE_INCLUDE_CURRENT_DIR) + list(APPEND _inc_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + endif() + + foreach(_current ${_inc_DIRS}) + if("${_current}" MATCHES "\\.framework/?$") + string(REGEX REPLACE "/[^/]+\\.framework" "" framework_path "${_current}") + set(${_moc_flags} ${${_moc_flags}} "-F${framework_path}") + else() + set(${_moc_flags} ${${_moc_flags}} "-I${_current}") + endif() + endforeach() + + get_directory_property(_defines COMPILE_DEFINITIONS) + foreach(_current ${_defines}) + set(${_moc_flags} ${${_moc_flags}} "-D${_current}") + endforeach() + + if(WIN32) + set(${_moc_flags} ${${_moc_flags}} -DWIN32) + endif() + if (MSVC) + set(${_moc_flags} ${${_moc_flags}} --compiler-flavor=msvc) + endif() +endmacro() + + +# helper macro to set up a moc rule +function(qt5_create_moc_command infile outfile moc_flags moc_options moc_target moc_depends) + _qt5_warn_deprecated("qt5_create_moc_command") + + # Pass the parameters in a file. Set the working directory to + # be that containing the parameters file and reference it by + # just the file name. This is necessary because the moc tool on + # MinGW builds does not seem to handle spaces in the path to the + # file given with the @ syntax. + get_filename_component(_moc_outfile_name "${outfile}" NAME) + get_filename_component(_moc_outfile_dir "${outfile}" PATH) + if(_moc_outfile_dir) + set(_moc_working_dir WORKING_DIRECTORY ${_moc_outfile_dir}) + endif() + set (_moc_parameters_file ${outfile}_parameters) + set (_moc_parameters ${moc_flags} ${moc_options} -o "${outfile}" "${infile}") + string (REPLACE ";" "\n" _moc_parameters "${_moc_parameters}") + + if(moc_target) + set(_moc_parameters_file ${_moc_parameters_file}$<$>:_$>) + set(targetincludes "$") + set(targetdefines "$") + + set(targetincludes "$<$:-I$\n>") + set(targetdefines "$<$:-D$\n>") + + file (GENERATE + OUTPUT ${_moc_parameters_file} + CONTENT "${targetdefines}${targetincludes}${_moc_parameters}\n" + ) + + set(targetincludes) + set(targetdefines) + else() + file(WRITE ${_moc_parameters_file} "${_moc_parameters}\n") + endif() + + set(_moc_extra_parameters_file @${_moc_parameters_file}) + add_custom_command(OUTPUT ${outfile} + COMMAND ${Qt5Core_MOC_EXECUTABLE} ${_moc_extra_parameters_file} + DEPENDS ${infile} ${moc_depends} + ${_moc_working_dir} + VERBATIM) + set_source_files_properties(${infile} PROPERTIES SKIP_AUTOMOC ON) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON) +endfunction() + + +function(qt5_generate_moc infile outfile ) + set(_QT5_INTERNAL_SCOPE ON) + + # get include dirs and flags + qt5_get_moc_flags(moc_flags) + get_filename_component(abs_infile ${infile} ABSOLUTE) + set(_outfile "${outfile}") + if(NOT IS_ABSOLUTE "${outfile}") + set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}") + endif() + if ("x${ARGV2}" STREQUAL "xTARGET") + set(moc_target ${ARGV3}) + endif() + qt5_create_moc_command(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}" "") +endfunction() + +if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) + function(qt_generate_moc) + if(QT_DEFAULT_MAJOR_VERSION EQUAL 5) + qt5_generate_moc(${ARGV}) + elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6) + qt6_generate_moc(${ARGV}) + endif() + endfunction() +endif() + + +# qt5_wrap_cpp(outfiles inputfile ... ) + +function(qt5_wrap_cpp outfiles) + set(_QT5_INTERNAL_SCOPE ON) + + # get include dirs + qt5_get_moc_flags(moc_flags) + + set(options) + set(oneValueArgs TARGET) + set(multiValueArgs OPTIONS DEPENDS) + + cmake_parse_arguments(_WRAP_CPP "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(moc_files ${_WRAP_CPP_UNPARSED_ARGUMENTS}) + set(moc_options ${_WRAP_CPP_OPTIONS}) + set(moc_target ${_WRAP_CPP_TARGET}) + set(moc_depends ${_WRAP_CPP_DEPENDS}) + + foreach(it ${moc_files}) + get_filename_component(it ${it} ABSOLUTE) + qt5_make_output_file(${it} moc_ cpp outfile) + qt5_create_moc_command(${it} ${outfile} "${moc_flags}" "${moc_options}" "${moc_target}" "${moc_depends}") + list(APPEND ${outfiles} ${outfile}) + endforeach() + set(${outfiles} ${${outfiles}} PARENT_SCOPE) +endfunction() + +# This will override the CMake upstream command, because that one is for Qt 3. +if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) + function(qt_wrap_cpp outfiles) + if(QT_DEFAULT_MAJOR_VERSION EQUAL 5) + qt5_wrap_cpp("${outfiles}" ${ARGN}) + elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6) + qt6_wrap_cpp("${outfiles}" ${ARGN}) + endif() + set("${outfiles}" "${${outfiles}}" PARENT_SCOPE) + endfunction() +endif() + + +# _qt5_parse_qrc_file(infile _out_depends _rc_depends) +# internal + +function(_qt5_parse_qrc_file infile _out_depends _rc_depends) + get_filename_component(rc_path ${infile} PATH) + + if(EXISTS "${infile}") + # parse file for dependencies + # all files are absolute paths or relative to the location of the qrc file + file(READ "${infile}" RC_FILE_CONTENTS) + string(REGEX MATCHALL "]*>" "" RC_FILE "${RC_FILE}") + if(NOT IS_ABSOLUTE "${RC_FILE}") + set(RC_FILE "${rc_path}/${RC_FILE}") + endif() + set(RC_DEPENDS ${RC_DEPENDS} "${RC_FILE}") + endforeach() + # Since this cmake macro is doing the dependency scanning for these files, + # let's make a configured file and add it as a dependency so cmake is run + # again when dependencies need to be recomputed. + qt5_make_output_file("${infile}" "" "qrc.depends" out_depends) + configure_file("${infile}" "${out_depends}" COPYONLY) + else() + # The .qrc file does not exist (yet). Let's add a dependency and hope + # that it will be generated later + set(out_depends) + endif() + + set(${_out_depends} ${out_depends} PARENT_SCOPE) + set(${_rc_depends} ${RC_DEPENDS} PARENT_SCOPE) +endfunction() + + +# qt5_add_binary_resources(target inputfiles ... ) + +function(qt5_add_binary_resources target) + set(_QT5_INTERNAL_SCOPE ON) + + set(options) + set(oneValueArgs DESTINATION) + set(multiValueArgs OPTIONS) + + cmake_parse_arguments(_RCC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(rcc_files ${_RCC_UNPARSED_ARGUMENTS}) + set(rcc_options ${_RCC_OPTIONS}) + set(rcc_destination ${_RCC_DESTINATION}) + + if(NOT rcc_destination) + set(rcc_destination ${CMAKE_CURRENT_BINARY_DIR}/${target}.rcc) + endif() + + foreach(it ${rcc_files}) + get_filename_component(infile ${it} ABSOLUTE) + + _qt5_parse_qrc_file(${infile} _out_depends _rc_depends) + set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) + set(infiles ${infiles} ${infile}) + set(out_depends ${out_depends} ${_out_depends}) + set(rc_depends ${rc_depends} ${_rc_depends}) + endforeach() + + add_custom_command(OUTPUT ${rcc_destination} + COMMAND ${Qt5Core_RCC_EXECUTABLE} + ARGS ${rcc_options} --binary --name ${target} --output ${rcc_destination} ${infiles} + DEPENDS ${rc_depends} ${out_depends} ${infiles} VERBATIM) + add_custom_target(${target} ALL DEPENDS ${rcc_destination}) +endfunction() + +if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) + function(qt_add_binary_resources) + if(QT_DEFAULT_MAJOR_VERSION EQUAL 5) + qt5_add_binary_resources(${ARGV}) + elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6) + qt6_add_binary_resources(${ARGV}) + endif() + endfunction() +endif() + + +# qt5_add_resources(outfiles inputfile ... ) + +function(qt5_add_resources outfiles) + set(_QT5_INTERNAL_SCOPE ON) + + set(options) + set(oneValueArgs) + set(multiValueArgs OPTIONS) + + cmake_parse_arguments(_RCC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(rcc_files ${_RCC_UNPARSED_ARGUMENTS}) + set(rcc_options ${_RCC_OPTIONS}) + + if("${rcc_options}" MATCHES "-binary") + message(WARNING "Use qt5_add_binary_resources for binary option") + endif() + + foreach(it ${rcc_files}) + get_filename_component(outfilename ${it} NAME_WE) + get_filename_component(infile ${it} ABSOLUTE) + set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cpp) + + _qt5_parse_qrc_file(${infile} _out_depends _rc_depends) + set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) + + add_custom_command(OUTPUT ${outfile} + COMMAND ${Qt5Core_RCC_EXECUTABLE} + ARGS ${rcc_options} --name ${outfilename} --output ${outfile} ${infile} + MAIN_DEPENDENCY ${infile} + DEPENDS ${_rc_depends} "${_out_depends}" VERBATIM) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOMOC ON) + set_source_files_properties(${outfile} PROPERTIES SKIP_AUTOUIC ON) + list(APPEND ${outfiles} ${outfile}) + endforeach() + set(${outfiles} ${${outfiles}} PARENT_SCOPE) +endfunction() + +if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) + function(qt_add_resources outfiles) + if(QT_DEFAULT_MAJOR_VERSION EQUAL 5) + qt5_add_resources("${outfiles}" ${ARGN}) + elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6) + qt6_add_resources("${outfiles}" ${ARGN}) + endif() + set("${outfiles}" "${${outfiles}}" PARENT_SCOPE) + endfunction() +endif() + + +# qt5_add_big_resources(outfiles inputfile ... ) + +function(qt5_add_big_resources outfiles) + set(_QT5_INTERNAL_SCOPE ON) + + if (CMAKE_VERSION VERSION_LESS 3.9) + message(FATAL_ERROR, "qt5_add_big_resources requires CMake 3.9 or newer") + endif() + + set(options) + set(oneValueArgs) + set(multiValueArgs OPTIONS) + + cmake_parse_arguments(_RCC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + set(rcc_files ${_RCC_UNPARSED_ARGUMENTS}) + set(rcc_options ${_RCC_OPTIONS}) + + if("${rcc_options}" MATCHES "-binary") + message(WARNING "Use qt5_add_binary_resources for binary option") + endif() + + foreach(it ${rcc_files}) + get_filename_component(outfilename ${it} NAME_WE) + get_filename_component(infile ${it} ABSOLUTE) + set(tmpoutfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}tmp.cpp) + set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.o) + + _qt5_parse_qrc_file(${infile} _out_depends _rc_depends) + set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) + add_custom_command(OUTPUT ${tmpoutfile} + COMMAND ${Qt5Core_RCC_EXECUTABLE} ${rcc_options} --name ${outfilename} --pass 1 --output ${tmpoutfile} ${infile} + DEPENDS ${infile} ${_rc_depends} "${out_depends}" VERBATIM) + add_custom_target(big_resources_${outfilename} ALL DEPENDS ${tmpoutfile}) + add_library(rcc_object_${outfilename} OBJECT ${tmpoutfile}) + set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOMOC OFF) + set_target_properties(rcc_object_${outfilename} PROPERTIES AUTOUIC OFF) + add_dependencies(rcc_object_${outfilename} big_resources_${outfilename}) + # The modification of TARGET_OBJECTS needs the following change in cmake + # https://gitlab.kitware.com/cmake/cmake/commit/93c89bc75ceee599ba7c08b8fe1ac5104942054f + add_custom_command(OUTPUT ${outfile} + COMMAND ${Qt5Core_RCC_EXECUTABLE} + ARGS ${rcc_options} --name ${outfilename} --pass 2 --temp $ --output ${outfile} ${infile} + DEPENDS rcc_object_${outfilename} + VERBATIM) + list(APPEND ${outfiles} ${outfile}) + endforeach() + set(${outfiles} ${${outfiles}} PARENT_SCOPE) +endfunction() + +if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) + function(qt_add_big_resources outfiles) + if(QT_DEFAULT_MAJOR_VERSION EQUAL 5) + qt5_add_big_resources(${outfiles} ${ARGN}) + elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6) + qt6_add_big_resources(${outfiles} ${ARGN}) + endif() + set("${outfiles}" "${${outfiles}}" PARENT_SCOPE) + endfunction() +endif() + + +set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..") + +macro(qt5_use_modules _target _link_type) + _qt5_warn_deprecated("qt5_use_modules") + + if (NOT TARGET ${_target}) + message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.") + endif() + if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" ) + set(_qt5_modules ${ARGN}) + set(_qt5_link_type ${_link_type}) + else() + set(_qt5_modules ${_link_type} ${ARGN}) + endif() + + if ("${_qt5_modules}" STREQUAL "") + message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.") + endif() + + foreach(_module ${_qt5_modules}) + if (NOT Qt5${_module}_FOUND) + find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH) + if (NOT Qt5${_module}_FOUND) + message(FATAL_ERROR "Cannot use \"${_module}\" module which has not yet been found.") + endif() + endif() + target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES}) + set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS}) + set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS}) + set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG) + set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG) + set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG) + if (Qt5_POSITION_INDEPENDENT_CODE + AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" + OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)) + set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE}) + endif() + endforeach() +endmacro() + +function(qt5_import_plugins TARGET_NAME) + set(_doing "") + foreach(_arg ${ARGN}) + if(_arg STREQUAL "INCLUDE") + set(_doing "INCLUDE") + elseif(_arg STREQUAL "EXCLUDE") + set(_doing "EXCLUDE") + elseif(_arg STREQUAL "INCLUDE_BY_TYPE") + set(_doing "INCLUDE_BY_TYPE") + elseif(_arg STREQUAL "EXCLUDE_BY_TYPE") + set(_doing "EXCLUDE_BY_TYPE") + else() + if(_doing STREQUAL "INCLUDE") + set_property(TARGET ${TARGET_NAME} APPEND PROPERTY QT_PLUGINS "${_arg}") + elseif(_doing STREQUAL "EXCLUDE") + set_property(TARGET ${TARGET_NAME} APPEND PROPERTY QT_NO_PLUGINS "${_arg}") + elseif(_doing STREQUAL "INCLUDE_BY_TYPE") + string(REGEX REPLACE "[-/]" "_" _plugin_type "${_arg}") + set(_doing "INCLUDE_BY_TYPE_PLUGINS") + elseif(_doing STREQUAL "INCLUDE_BY_TYPE_PLUGINS") + set_property(TARGET ${TARGET_NAME} APPEND PROPERTY "QT_PLUGINS_${_plugin_type}" "${_arg}") + elseif(_doing STREQUAL "EXCLUDE_BY_TYPE") + string(REGEX REPLACE "[-/]" "_" _plugin_type "${_arg}") + set_property(TARGET ${TARGET_NAME} PROPERTY "QT_PLUGINS_${_plugin_type}" -) + else() + message(FATAL_ERROR "Unexpected extra argument: \"${_arg}\"") + endif() + endif() + endforeach() +endfunction() + +if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS) + function(qt_import_plugins) + if(QT_DEFAULT_MAJOR_VERSION EQUAL 5) + qt5_import_plugins(${ARGV}) + elseif(QT_DEFAULT_MAJOR_VERSION EQUAL 6) + qt6_import_plugins(${ARGV}) + endif() + endfunction() +endif() diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 42255747612..4d340892955 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -402,7 +402,8 @@ "# Block futimens() on Apple platforms unless it's available on ALL", "# deployment targets. This simplifies the logic at the call site", "# dramatically, as it isn't strictly needed compared to futimes().", - "darwin: QMAKE_CXXFLAGS += -Werror=unguarded-availability" + "darwin: QMAKE_CXXFLAGS += -Werror=unguarded-availability -Werror=unguarded-availability-new", + "CONFIG += warn_on" ] } }, diff --git a/src/corelib/doc/src/containers.qdoc b/src/corelib/doc/src/containers.qdoc index 61bce214be9..537bd8c8841 100644 --- a/src/corelib/doc/src/containers.qdoc +++ b/src/corelib/doc/src/containers.qdoc @@ -102,6 +102,10 @@ a vector can be quite slow, because it can lead to large numbers of items having to be moved by one position in memory. + \row \li \l{QVarLengthArray} + \li This provides a low-level variable-length array. It can be used + instead of QVector in places where speed is particularly important. + \row \li \l{QStack} \li This is a convenience subclass of QVector that provides "last in, first out" (LIFO) semantics. It adds the following @@ -594,15 +598,11 @@ \section1 Other Container-Like Classes - Qt includes three template classes that resemble containers in + Qt includes other template classes that resemble containers in some respects. These classes don't provide iterators and cannot be used with the \c foreach keyword. \list - \li QVarLengthArray provides a low-level - variable-length array. It can be used instead of QVector in - places where speed is particularly important. - \li QCache provides a cache to store objects of a certain type T associated with keys of type Key. diff --git a/src/corelib/doc/src/dontdocument.qdoc b/src/corelib/doc/src/dontdocument.qdoc index c84b789c46c..9ed53457775 100644 --- a/src/corelib/doc/src/dontdocument.qdoc +++ b/src/corelib/doc/src/dontdocument.qdoc @@ -39,3 +39,8 @@ QJsonValueRefPtr QAbstractConcatenable QStringBuilderCommon QTextCodec::ConverterState QThreadStorageData QTextStreamManipulator) */ + +/*! + \internal + \namespace QTextStreamFunctions +*/ diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index c9e155555c9..2b2a03cc76b 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2117,7 +2117,7 @@ QT_WARNING_DISABLE_DEPRECATED QSysInfo::MacVersion QSysInfo::macVersion() { const auto version = QOperatingSystemVersion::current(); -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) return QSysInfo::MacVersion(Q_MV_OSX(version.majorVersion(), version.minorVersion())); #elif defined(Q_OS_IOS) return QSysInfo::MacVersion(Q_MV_IOS(version.majorVersion(), version.minorVersion())); diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index c8c7c0bf9b6..82c255348f1 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2016 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -660,7 +660,7 @@ static QString getHostPrefixFromHostBinDir() #endif #ifndef QT_BUILD_QMAKE_BOOTSTRAP -static const char *getPrefix( +static QString getPrefix( #ifdef QT_BUILD_QMAKE QLibraryInfo::PathGroup group #endif @@ -669,17 +669,15 @@ static const char *getPrefix( #if defined(QT_BUILD_QMAKE) # if QT_CONFIGURE_CROSSBUILD if (group == QLibraryInfo::DevicePaths) - return QT_CONFIGURE_PREFIX_PATH; + return QString::fromLocal8Bit(QT_CONFIGURE_PREFIX_PATH); # else Q_UNUSED(group); # endif - static QByteArray extPrefixPath = getExtPrefixFromHostBinDir().toLatin1(); - return extPrefixPath.constData(); + return getExtPrefixFromHostBinDir(); #elif QT_CONFIG(relocatable) - static QByteArray prefixPath = getRelocatablePrefix().toLatin1(); - return prefixPath.constData(); + return getRelocatablePrefix(); #else - return QT_CONFIGURE_PREFIX_PATH; + return QString::fromLocal8Bit(QT_CONFIGURE_PREFIX_PATH); #endif } #endif // QT_BUILD_QMAKE_BOOTSTRAP @@ -800,7 +798,7 @@ QLibraryInfo::rawLocation(LibraryLocation loc, PathGroup group) // strlen is meaningless. const char * volatile path = nullptr; if (loc == PrefixPath) { - path = getPrefix( + ret = getPrefix( #ifdef QT_BUILD_QMAKE group #endif diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 479532fc36d..824215d1d97 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -272,7 +272,7 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) info objects, just append one to the file name given to the constructors or setFile(). - The file's dates are returned by created(), lastModified(), lastRead() and + The file's dates are returned by birthTime(), lastModified(), lastRead() and fileTime(). Information about the file's access permissions is obtained with isReadable(), isWritable() and isExecutable(). The file's ownership is available from owner(), ownerId(), group() and diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index eaf4e2d9afe..67cff7c68c2 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -69,7 +69,7 @@ # include #endif -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include #endif diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 86c8963cb60..96d9210c1c9 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -58,7 +58,7 @@ # include "qfilesystemwatcher_inotify_p.h" #elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(QT_PLATFORM_UIKIT) # include "qfilesystemwatcher_kqueue_p.h" -#elif defined(Q_OS_OSX) +#elif defined(Q_OS_MACOS) # include "qfilesystemwatcher_fsevents_p.h" #endif @@ -79,7 +79,7 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject return QInotifyFileSystemWatcherEngine::create(parent); #elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(QT_PLATFORM_UIKIT) return QKqueueFileSystemWatcherEngine::create(parent); -#elif defined(Q_OS_OSX) +#elif defined(Q_OS_MACOS) return QFseventsFileSystemWatcherEngine::create(parent); #else Q_UNUSED(parent); diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.mm b/src/corelib/io/qfilesystemwatcher_fsevents.mm index 6194bf7c713..e039559ea3f 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents.mm +++ b/src/corelib/io/qfilesystemwatcher_fsevents.mm @@ -199,7 +199,7 @@ void QFseventsFileSystemWatcherEngine::processEvent(ConstFSEventStreamRef stream const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) { -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) Q_UNUSED(streamRef); bool needsRestart = false; diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index ce2b7e8faa8..b5311404373 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -68,7 +68,7 @@ #include // kill #include // gethostname -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) # include #elif defined(Q_OS_LINUX) # include @@ -222,7 +222,7 @@ bool QLockFilePrivate::isProcessRunning(qint64 pid, const QString &appname) QString QLockFilePrivate::processNameByPid(qint64 pid) { -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) char name[1024]; proc_name(pid, name, sizeof(name) / sizeof(char)); return QFile::decodeName(name); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 2186f23ab69..930007ff04f 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -450,12 +450,19 @@ void QProcessPrivate::startProcess() workingDirPtr = encodedWorkingDirectory.constData(); } - // Start the process manager, and fork off the child process. - // ### Qt6: revisit whether the change in behavior due to not using fork() - // is acceptable for derived classes. + // Select FFD_USE_FORK and FFD_VFORK_SEMANTICS based on whether there's + // user code running in the child process: if there is, we don't know what + // the user will want to do, so we err on the safe side and request an + // actual fork() (for example, the user could attempt to do some + // synchronization with the parent process). But if there isn't, then our + // code in execChild() is just a handful of dup2() and a chdir(), so it's + // safe with vfork semantics: suspend the parent execution until the child + // either execve()s or _exit()s. int ffdflags = FFD_CLOEXEC; if (typeid(*q) != typeid(QProcess)) ffdflags |= FFD_USE_FORK; + else + ffdflags |= FFD_VFORK_SEMANTICS; pid_t childPid; forkfd = ::forkfd(ffdflags , &childPid); int lastForkErrno = errno; diff --git a/src/corelib/itemmodels/qitemselectionmodel.cpp b/src/corelib/itemmodels/qitemselectionmodel.cpp index e4ac5da2990..27442fb2fad 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.cpp +++ b/src/corelib/itemmodels/qitemselectionmodel.cpp @@ -1473,6 +1473,9 @@ bool QItemSelectionModel::isSelected(const QModelIndex &index) const Note that this function is usually faster than calling isSelected() on all items in the same row and that unselectable items are ignored. + + \note Since Qt 5.15, the default argument for \a parent is an empty + model index. */ bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) const { @@ -1545,6 +1548,9 @@ bool QItemSelectionModel::isRowSelected(int row, const QModelIndex &parent) cons Note that this function is usually faster than calling isSelected() on all items in the same column and that unselectable items are ignored. + + \note Since Qt 5.15, the default argument for \a parent is an empty + model index. */ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent) const { @@ -1616,6 +1622,9 @@ bool QItemSelectionModel::isColumnSelected(int column, const QModelIndex &parent /*! Returns \c true if there are any items selected in the \a row with the given \a parent. + + \note Since Qt 5.15, the default argument for \a parent is an empty + model index. */ bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &parent) const { @@ -1649,6 +1658,9 @@ bool QItemSelectionModel::rowIntersectsSelection(int row, const QModelIndex &par /*! Returns \c true if there are any items selected in the \a column with the given \a parent. + + \note Since Qt 5.15, the default argument for \a parent is an empty + model index. */ bool QItemSelectionModel::columnIntersectsSelection(int column, const QModelIndex &parent) const { diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 6ed4c942d86..58505513617 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -2678,12 +2678,19 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column) \property QSortFilterProxyModel::filterCaseSensitivity \brief the case sensitivity of the QRegExp pattern used to filter the - contents of the source model + contents of the source model. By default, the filter is case sensitive. \sa filterRegExp, sortCaseSensitivity */ + +/*! + \since 5.15 + \fn void QSortFilterProxyModel::filterCaseSensitivityChanged(Qt::CaseSensitivity filterCaseSensitivity) + \brief This signal is emitted when the case sensitivity of the filter + changes to \a filterCaseSensitivity. + */ Qt::CaseSensitivity QSortFilterProxyModel::filterCaseSensitivity() const { Q_D(const QSortFilterProxyModel); @@ -2710,6 +2717,13 @@ void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs) \sa filterCaseSensitivity, lessThan() */ + +/*! + \since 5.15 + \fn void QSortFilterProxyModel::sortCaseSensitivityChanged(Qt::CaseSensitivity sortCaseSensitivity) + \brief This signal is emitted when the case sensitivity for sorting + changes to \a sortCaseSensitivity. +*/ Qt::CaseSensitivity QSortFilterProxyModel::sortCaseSensitivity() const { Q_D(const QSortFilterProxyModel); @@ -2736,6 +2750,13 @@ void QSortFilterProxyModel::setSortCaseSensitivity(Qt::CaseSensitivity cs) \sa sortCaseSensitivity, lessThan() */ + +/*! + \since 5.15 + \fn void QSortFilterProxyModel::sortLocaleAwareChanged(bool sortLocaleAware) + \brief This signal is emitted when the locale aware setting + changes to \a sortLocaleAware. +*/ bool QSortFilterProxyModel::isSortLocaleAware() const { Q_D(const QSortFilterProxyModel); @@ -2856,12 +2877,19 @@ void QSortFilterProxyModel::setDynamicSortFilter(bool enable) /*! \since 4.2 \property QSortFilterProxyModel::sortRole - \brief the item role that is used to query the source model's data when sorting items + \brief the item role that is used to query the source model's data when + sorting items. The default value is Qt::DisplayRole. \sa lessThan() */ + +/*! + \since 5.15 + \fn void QSortFilterProxyModel::sortRoleChanged(int sortRole) + \brief This signal is emitted when the sort role changes to \a sortRole. +*/ int QSortFilterProxyModel::sortRole() const { Q_D(const QSortFilterProxyModel); @@ -2881,12 +2909,19 @@ void QSortFilterProxyModel::setSortRole(int role) /*! \since 4.2 \property QSortFilterProxyModel::filterRole - \brief the item role that is used to query the source model's data when filtering items + \brief the item role that is used to query the source model's data when + filtering items. The default value is Qt::DisplayRole. \sa filterAcceptsRow() */ + +/*! + \since 5.15 + \fn void QSortFilterProxyModel::filterRoleChanged(int filterRole) + \brief This signal is emitted when the filter role changes to \a filterRole. +*/ int QSortFilterProxyModel::filterRole() const { Q_D(const QSortFilterProxyModel); @@ -2914,6 +2949,13 @@ void QSortFilterProxyModel::setFilterRole(int role) \sa filterAcceptsRow() */ + +/*! + \since 5.15 + \fn void QSortFilterProxyModel::recursiveFilteringEnabledChanged(int recursiveFilteringEnabled) + \brief This signal is emitted when the recursive filter setting is changed + to \a recursiveFilteringEnabled. +*/ bool QSortFilterProxyModel::isRecursiveFilteringEnabled() const { Q_D(const QSortFilterProxyModel); diff --git a/src/corelib/kernel/qcore_mac.mm b/src/corelib/kernel/qcore_mac.mm index 0d334e73003..a8aa1dad1fc 100644 --- a/src/corelib/kernel/qcore_mac.mm +++ b/src/corelib/kernel/qcore_mac.mm @@ -458,7 +458,7 @@ QMacRootLevelAutoReleasePool::~QMacRootLevelAutoReleasePool() // ------------------------------------------------------------------------- -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // Use this method to keep all the information in the TextSegment. As long as it is ordered // we are in OK shape, and we can influence that ourselves. @@ -598,7 +598,7 @@ Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode) return i->qtKey; } -#endif // Q_OS_OSX +#endif // Q_OS_MACOS void qt_apple_check_os_version() { diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index 177551467ce..b482269df2b 100644 --- a/src/corelib/kernel/qeventdispatcher_cf.mm +++ b/src/corelib/kernel/qeventdispatcher_cf.mm @@ -48,7 +48,7 @@ #include -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS # include #elif defined(Q_OS_WATCHOS) # include diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index f2216d4113d..e841919600b 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -84,10 +84,8 @@ enum { WM_QT_ACTIVATENOTIFIERS = WM_USER + 2 }; -// WM_QT_SENDPOSTEDEVENTS message parameter enum { - WMWP_QT_TOFOREIGNLOOP = 0, - WMWP_QT_FROMWAKEUP + SendPostedEventsTimerId = ~1u }; class QEventDispatcherWin32Private; @@ -100,8 +98,8 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA QEventDispatcherWin32Private::QEventDispatcherWin32Private() : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), - getMessageHook(0), wakeUps(0), activateNotifiersPosted(false), - winEventNotifierActivatedEvent(NULL) + getMessageHook(0), sendPostedEventsTimerId(0), wakeUps(0), + activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL) { } @@ -129,6 +127,18 @@ void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/, QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId)); } +static inline UINT inputQueueMask() +{ + UINT result = QS_ALLEVENTS; + // QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of + // QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8. +#if WINVER > 0x0601 + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) + result &= ~(QS_TOUCH | QS_POINTER); +#endif // WINVER > 0x0601 + return result; +} + LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) { if (message == WM_NCCREATE) @@ -240,47 +250,39 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA case WM_TIMER: Q_ASSERT(d != 0); - d->sendTimerEvent(wp); + if (wp == d->sendPostedEventsTimerId) + q->sendPostedEvents(); + else + d->sendTimerEvent(wp); return 0; case WM_QT_SENDPOSTEDEVENTS: Q_ASSERT(d != 0); // We send posted events manually, if the window procedure was invoked // by the foreign event loop (e.g. from the native modal dialog). - q->sendPostedEvents(); + // Skip sending, if the message queue is not empty. + // sendPostedEventsTimer will deliver posted events later. + static const UINT mask = inputQueueMask(); + if (HIWORD(GetQueueStatus(mask)) == 0) + q->sendPostedEvents(); return 0; } // switch (message) return DefWindowProc(hwnd, message, wp, lp); } -static inline UINT inputQueueMask() -{ - UINT result = QS_ALLEVENTS; - // QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of - // QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8. -#if WINVER > 0x0601 - if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) - result &= ~(QS_TOUCH | QS_POINTER); -#endif // WINVER > 0x0601 - return result; -} - LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) { QEventDispatcherWin32 *q = qobject_cast(QAbstractEventDispatcher::instance()); Q_ASSERT(q != 0); QEventDispatcherWin32Private *d = q->d_func(); MSG *msg = reinterpret_cast(lp); - static const UINT mask = inputQueueMask(); - if (HIWORD(GetQueueStatus(mask)) == 0 && wp == PM_REMOVE) { - // Allow posting WM_QT_SENDPOSTEDEVENTS message. - d->wakeUps.storeRelaxed(0); - if (!(msg->hwnd == d->internalHwnd && msg->message == WM_QT_SENDPOSTEDEVENTS)) { - PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, - WMWP_QT_TOFOREIGNLOOP, 0); - } + if (msg->hwnd == d->internalHwnd && msg->message == WM_QT_SENDPOSTEDEVENTS + && wp == PM_REMOVE && d->sendPostedEventsTimerId == 0) { + // Start a timer to deliver posted events when the message queue is emptied. + d->sendPostedEventsTimerId = SetTimer(d->internalHwnd, SendPostedEventsTimerId, + USER_TIMER_MINIMUM, NULL); } return d->getMessageHook ? CallNextHookEx(0, code, wp, lp) : 0; } @@ -571,12 +573,15 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) } if (haveMessage) { if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) { - // Set result to 'true', if the message was sent by wakeUp(). - if (msg.wParam == WMWP_QT_FROMWAKEUP) - retVal = true; + // Set result to 'true' because the message was sent by wakeUp(). + retVal = true; continue; } if (msg.message == WM_TIMER) { + // Skip timer event intended for use inside foreign loop. + if (d->internalHwnd == msg.hwnd && msg.wParam == d->sendPostedEventsTimerId) + continue; + // avoid live-lock by keeping track of the timers we've already sent bool found = false; for (int i = 0; !found && i < processedTimers.count(); ++i) { @@ -968,8 +973,7 @@ void QEventDispatcherWin32::wakeUp() Q_D(QEventDispatcherWin32); if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) { // post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending - if (!PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, - WMWP_QT_FROMWAKEUP, 0)) + if (!PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0)) qErrnoWarning("QEventDispatcherWin32::wakeUp: Failed to post a message"); } } @@ -1015,6 +1019,10 @@ void QEventDispatcherWin32::closingDown() if (d->getMessageHook) UnhookWindowsHookEx(d->getMessageHook); d->getMessageHook = 0; + + if (d->sendPostedEventsTimerId != 0) + KillTimer(d->internalHwnd, d->sendPostedEventsTimerId); + d->sendPostedEventsTimerId = 0; } bool QEventDispatcherWin32::event(QEvent *e) @@ -1056,6 +1064,14 @@ bool QEventDispatcherWin32::event(QEvent *e) void QEventDispatcherWin32::sendPostedEvents() { Q_D(QEventDispatcherWin32); + + if (d->sendPostedEventsTimerId != 0) + KillTimer(d->internalHwnd, d->sendPostedEventsTimerId); + d->sendPostedEventsTimerId = 0; + + // Allow posting WM_QT_SENDPOSTEDEVENTS message. + d->wakeUps.storeRelaxed(0); + QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData.loadRelaxed()); } diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index a482c8b7dba..dbb30ab5681 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -171,6 +171,7 @@ public: HHOOK getMessageHook; // for controlling when to send posted events + UINT_PTR sendPostedEventsTimerId; QAtomicInt wakeUps; // timers diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index e7150931279..7429f5a3239 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -3532,6 +3532,7 @@ bool QMetaProperty::isQProperty() const \sa isDesignable(), isScriptable(), isStored() */ +#if QT_DEPRECATED_SINCE(5, 15) bool QMetaProperty::isEditable(const QObject *object) const { if (!mobj) @@ -3545,6 +3546,7 @@ bool QMetaProperty::isEditable(const QObject *object) const } return b; } +#endif /*! \class QMetaClassInfo diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 96f851a0e11..bb83080f62a 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -260,7 +260,9 @@ public: bool isDesignable(const QObject *obj = nullptr) const; bool isScriptable(const QObject *obj = nullptr) const; bool isStored(const QObject *obj = nullptr) const; - bool isEditable(const QObject *obj = nullptr) const; +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED bool isEditable(const QObject *obj = nullptr) const; +#endif bool isUser(const QObject *obj = nullptr) const; bool isConstant() const; bool isFinal() const; diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 192d4616b19..e956d497e99 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -936,6 +936,24 @@ struct ContainerCapabilitiesImpl().p { static_cast(const_cast(container))->push_back(*static_cast(value)); } }; +namespace QtPrivate { +namespace ContainerCapabilitiesMetaProgrammingHelper { + template + using void_t = void; +} +} + +template +struct ContainerCapabilitiesImpl().insert(std::declval())), decltype(std::declval() == std::declval())>> +{ + enum {ContainerCapabilities = ContainerIsAppendable}; + + // The code below invokes undefined behavior if and only if the pointer passed into QSequentialIterableImpl + // pointed to a const object to begin with + static void appendImpl(const void *container, const void *value) + { static_cast(const_cast(container))->insert(*static_cast(value)); } +}; + template::iterator_category> struct CapabilitiesImpl; diff --git a/src/corelib/kernel/qtestsupport_core.cpp b/src/corelib/kernel/qtestsupport_core.cpp index 8498f7f0258..428ebbd652c 100644 --- a/src/corelib/kernel/qtestsupport_core.cpp +++ b/src/corelib/kernel/qtestsupport_core.cpp @@ -67,7 +67,7 @@ Q_CORE_EXPORT void QTestPrivate::qSleep(int ms) Example: - \snippet code/src_corelib_kernel_qtestsupport_core.cpp 0 + \snippet code/src_corelib_kernel_qtestsupport_core_snippet.cpp 0 The code above will wait for the object to become ready, for a maximum of three seconds. diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 47f09e58a27..e512ff2c324 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -576,9 +576,7 @@ bool QLibraryPrivate::load() Q_TRACE(QLibraryPrivate_load_entry, fileName); - mutex.lock(); bool ret = load_sys(); - mutex.unlock(); if (qt_debug_component()) { if (ret) { qDebug() << "loaded library" << fileName; diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 29813e5863b..a5c72f81d96 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -123,6 +123,7 @@ QStringList QLibraryPrivate::prefixes_sys() bool QLibraryPrivate::load_sys() { + QMutexLocker locker(&mutex); QString attempt; QFileSystemEntry fsEntry(fileName); @@ -213,6 +214,7 @@ bool QLibraryPrivate::load_sys() } #endif + locker.unlock(); bool retry = true; Handle hnd = nullptr; for (int prefix = 0; retry && !hnd && prefix < prefixes.size(); prefix++) { @@ -235,15 +237,15 @@ bool QLibraryPrivate::load_sys() hnd = dlopen(QFile::encodeName(attempt), dlFlags); #ifdef Q_OS_ANDROID - if (!pHnd) { + if (!hnd) { auto attemptFromBundle = attempt; - pHnd = dlopen(QFile::encodeName(attemptFromBundle.replace(QLatin1Char('/'), QLatin1Char('_'))), dlFlags); + hnd = dlopen(QFile::encodeName(attemptFromBundle.replace(QLatin1Char('/'), QLatin1Char('_'))), dlFlags); } - if (pHnd) { + if (hnd) { using JniOnLoadPtr = jint (*)(JavaVM *vm, void *reserved); JniOnLoadPtr jniOnLoad = reinterpret_cast(dlsym(pHnd, "JNI_OnLoad")); if (jniOnLoad && jniOnLoad(QtAndroidPrivate::javaVM(), nullptr) == JNI_ERR) { - dlclose(pHnd); + dlclose(hnd); pHnd = nullptr; } } @@ -273,6 +275,8 @@ bool QLibraryPrivate::load_sys() } } #endif + + locker.relock(); if (!hnd) { errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName, qdlerror()); } diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp index 000bf762763..ef58724be8e 100644 --- a/src/corelib/plugin/qlibrary_win.cpp +++ b/src/corelib/plugin/qlibrary_win.cpp @@ -78,6 +78,7 @@ bool QLibraryPrivate::load_sys() // fileName // // NB If it's a plugin we do not ever try the ".dll" extension + QMutexLocker locker(&mutex); QStringList attempts; if (pluginState != IsAPlugin) @@ -95,6 +96,7 @@ bool QLibraryPrivate::load_sys() attempts.prepend(QDir::rootPath() + fileName); #endif + locker.unlock(); Handle hnd = nullptr; for (const QString &attempt : qAsConst(attempts)) { #ifndef Q_OS_WINRT @@ -115,6 +117,7 @@ bool QLibraryPrivate::load_sys() #ifndef Q_OS_WINRT SetErrorMode(oldmode); #endif + locker.relock(); if (!hnd) { errorString = QLibrary::tr("Cannot load library %1: %2").arg( QDir::toNativeSeparators(fileName), qt_error_string()); diff --git a/src/corelib/serialization/qcborstreamreader.cpp b/src/corelib/serialization/qcborstreamreader.cpp index c9834366065..ec385e06298 100644 --- a/src/corelib/serialization/qcborstreamreader.cpp +++ b/src/corelib/serialization/qcborstreamreader.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 Intel Corporation. +** Copyright (C) 2020 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -42,6 +42,7 @@ #define CBOR_NO_ENCODER_API #include +#include #include #include #include @@ -1055,6 +1056,10 @@ bool QCborStreamReader::next(int maxRecursion) } else if (isString() || isByteArray()) { auto r = _readByteArray_helper(); while (r.status == Ok) { + if (isString() && r.data.size() > MaxStringSize) { + d->handleError(CborErrorDataTooLarge); + break; + } if (isString() && !QUtf8::isValidUtf8(r.data, r.data.size()).isValidUtf8) { d->handleError(CborErrorInvalidUtf8TextString); break; @@ -1337,15 +1342,23 @@ QCborStreamReader::StringResult QCborStreamReader::_readString_helper() result.status = r.status; if (r.status == Ok) { - QTextCodec::ConverterState cs; - result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs); - if (cs.invalidChars == 0 && cs.remainingChars == 0) - return result; + // See QUtf8::convertToUnicode() a detailed explanation of why this + // conversion uses the same number of words or less. + CborError err = CborNoError; + if (r.data.size() > MaxStringSize) { + err = CborErrorDataTooLarge; + } else { + QTextCodec::ConverterState cs; + result.data = QUtf8::convertToUnicode(r.data, r.data.size(), &cs); + if (cs.invalidChars != 0 || cs.remainingChars != 0) + err = CborErrorInvalidUtf8TextString; + } - d->handleError(CborErrorInvalidUtf8TextString); - result.data.clear(); - result.status = Error; - return result; + if (err) { + d->handleError(err); + result.data.clear(); + result.status = Error; + } } return result; } @@ -1373,6 +1386,10 @@ QCborStreamReader::StringResult QCborStreamReader::_readByteArray_he qsizetype len = _currentStringChunkSize(); if (len < 0) return result; + if (len > MaxByteArraySize) { + d->handleError(CborErrorDataTooLarge); + return result; + } result.data.resize(len); auto r = readStringChunk(result.data.data(), len); diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 5a59646233d..ddc303e15dc 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 Intel Corporation. +** Copyright (C) 2020 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -53,6 +53,7 @@ #include #include +#include #include #include @@ -844,11 +845,6 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d) return QCborValue::Tag; } -#if QT_CONFIG(cborstreamreader) -// in qcborstream.cpp -extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error); -#endif - #if QT_CONFIG(cborstreamwriter) static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::EncodingOptions opt) { @@ -1462,23 +1458,59 @@ static Element decodeBasicValueFromCbor(QCborStreamReader &reader) return e; } -static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader) +static inline QCborContainerPrivate *createContainerFromCbor(QCborStreamReader &reader, int remainingRecursionDepth) { - auto d = new QCborContainerPrivate; - d->ref.storeRelaxed(1); - d->decodeFromCbor(reader); + if (Q_UNLIKELY(remainingRecursionDepth == 0)) { + QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep }); + return nullptr; + } + + QCborContainerPrivate *d = nullptr; + int mapShift = reader.isMap() ? 1 : 0; + if (reader.isLengthKnown()) { + quint64 len = reader.length(); + + // Clamp allocation to 1M elements (avoids crashing due to corrupt + // stream or loss of precision when converting from quint64 to + // QVector::size_type). + len = qMin(len, quint64(1024 * 1024 - 1)); + if (len) { + d = new QCborContainerPrivate; + d->ref.storeRelaxed(1); + d->elements.reserve(qsizetype(len) << mapShift); + } + } else { + d = new QCborContainerPrivate; + d->ref.storeRelaxed(1); + } + + reader.enterContainer(); + if (reader.lastError() != QCborError::NoError) + return d; + + while (reader.hasNext() && reader.lastError() == QCborError::NoError) + d->decodeValueFromCbor(reader, remainingRecursionDepth - 1); + + if (reader.lastError() == QCborError::NoError) + reader.leaveContainer(); + return d; } -static QCborValue taggedValueFromCbor(QCborStreamReader &reader) +static QCborValue taggedValueFromCbor(QCborStreamReader &reader, int remainingRecursionDepth) { + if (Q_UNLIKELY(remainingRecursionDepth == 0)) { + QCborContainerPrivate::setErrorInReader(reader, { QCborError::NestingTooDeep }); + return QCborValue::Invalid; + } + auto d = new QCborContainerPrivate; d->append(reader.toTag()); reader.next(); if (reader.lastError() == QCborError::NoError) { // decode tagged value - d->decodeValueFromCbor(reader); + d->decodeValueFromCbor(reader, remainingRecursionDepth - 1); } QCborValue::Type type; @@ -1494,6 +1526,13 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader) return QCborContainerPrivate::makeValue(type, -1, d); } +// in qcborstream.cpp +extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error); +inline void QCborContainerPrivate::setErrorInReader(QCborStreamReader &reader, QCborError error) +{ + qt_cbor_stream_set_error(reader.d.data(), error); +} + void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader) { auto addByteData_local = [this](QByteArray::size_type len) -> qint64 { @@ -1515,6 +1554,8 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader) // and calculate the final size if (add_overflow(offset, increment, &newSize)) return -1; + if (newSize > MaxByteArraySize) + return -1; // since usedData <= data.size(), this can't overflow usedData += increment; @@ -1538,7 +1579,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader) return; // error if (len != rawlen) { // truncation - qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge }); + setErrorInReader(reader, { QCborError::DataTooLarge }); return; } @@ -1548,7 +1589,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader) e.value = addByteData_local(len); if (e.value < 0) { // overflow - qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge }); + setErrorInReader(reader, { QCborError::DataTooLarge }); return; } } @@ -1562,7 +1603,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader) auto utf8result = QUtf8::isValidUtf8(dataPtr() + data.size() - len, len); if (!utf8result.isValidUtf8) { r.status = QCborStreamReader::Error; - qt_cbor_stream_set_error(reader.d.data(), { QCborError::InvalidUtf8String }); + setErrorInReader(reader, { QCborError::InvalidUtf8String }); break; } isAscii = isAscii && utf8result.isValidAscii; @@ -1586,14 +1627,7 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader) // error r.status = QCborStreamReader::Error; - qt_cbor_stream_set_error(reader.d.data(), { QCborError::DataTooLarge }); - } - - if (r.status == QCborStreamReader::Error) { - // There can only be errors if there was data to be read. - Q_ASSERT(e.flags & Element::HasByteData); - data.truncate(e.value); - return; + setErrorInReader(reader, { QCborError::DataTooLarge }); } // update size @@ -1607,14 +1641,30 @@ void QCborContainerPrivate::decodeStringFromCbor(QCborStreamReader &reader) Q_ASSERT(e.type == QCborValue::String); e.flags |= Element::StringIsAscii; } + + // check that this UTF-8 text string can be loaded onto a QString + if (e.type == QCborValue::String) { + if (Q_UNLIKELY(b->len > MaxStringSize)) { + setErrorInReader(reader, { QCborError::DataTooLarge }); + r.status = QCborStreamReader::Error; + } + } + } + + if (r.status == QCborStreamReader::Error) { + // There can only be errors if there was data to be read. + Q_ASSERT(e.flags & Element::HasByteData); + data.truncate(e.value); + return; } elements.append(e); } -void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader) +void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader, int remainingRecursionDepth) { - switch (reader.type()) { + QCborStreamReader::Type t = reader.type(); + switch (t) { case QCborStreamReader::UnsignedInteger: case QCborStreamReader::NegativeInteger: case QCborStreamReader::SimpleType: @@ -1631,37 +1681,17 @@ void QCborContainerPrivate::decodeValueFromCbor(QCborStreamReader &reader) case QCborStreamReader::Array: case QCborStreamReader::Map: + return append(makeValue(t == QCborStreamReader::Array ? QCborValue::Array : QCborValue::Map, -1, + createContainerFromCbor(reader, remainingRecursionDepth), + MoveContainer)); + case QCborStreamReader::Tag: - return append(QCborValue::fromCbor(reader)); + return append(taggedValueFromCbor(reader, remainingRecursionDepth)); case QCborStreamReader::Invalid: return; // probably a decode error } } - -void QCborContainerPrivate::decodeFromCbor(QCborStreamReader &reader) -{ - int mapShift = reader.isMap() ? 1 : 0; - if (reader.isLengthKnown()) { - quint64 len = reader.length(); - - // Clamp allocation to 1M elements (avoids crashing due to corrupt - // stream or loss of precision when converting from quint64 to - // QVector::size_type). - len = qMin(len, quint64(1024 * 1024 - 1)); - elements.reserve(qsizetype(len) << mapShift); - } - - reader.enterContainer(); - if (reader.lastError() != QCborError::NoError) - return; - - while (reader.hasNext() && reader.lastError() == QCborError::NoError) - decodeValueFromCbor(reader); - - if (reader.lastError() == QCborError::NoError) - reader.leaveContainer(); -} #endif // QT_CONFIG(cborstreamreader) /*! @@ -2363,6 +2393,8 @@ QCborValueRef QCborValue::operator[](qint64 key) } #if QT_CONFIG(cborstreamreader) +enum { MaximumRecursionDepth = 1024 }; + /*! Decodes one item from the CBOR stream found in \a reader and returns the equivalent representation. This function is recursive: if the item is a map @@ -2423,12 +2455,12 @@ QCborValue QCborValue::fromCbor(QCborStreamReader &reader) case QCborStreamReader::Map: result.n = -1; result.t = reader.isArray() ? Array : Map; - result.container = createContainerFromCbor(reader); + result.container = createContainerFromCbor(reader, MaximumRecursionDepth); break; // tag case QCborStreamReader::Tag: - result = taggedValueFromCbor(reader); + result = taggedValueFromCbor(reader, MaximumRecursionDepth); break; } diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h index f6d9c158417..1d686f118be 100644 --- a/src/corelib/serialization/qcborvalue_p.h +++ b/src/corelib/serialization/qcborvalue_p.h @@ -414,9 +414,9 @@ public: elements.remove(idx); } - void decodeValueFromCbor(QCborStreamReader &reader); - void decodeFromCbor(QCborStreamReader &reader); + void decodeValueFromCbor(QCborStreamReader &reader, int remainiingStackDepth); void decodeStringFromCbor(QCborStreamReader &reader); + static inline void setErrorInReader(QCborStreamReader &reader, QCborError error); }; QT_END_NAMESPACE diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp index 08702771a8e..05138ad6103 100644 --- a/src/corelib/serialization/qjsonarray.cpp +++ b/src/corelib/serialization/qjsonarray.cpp @@ -167,7 +167,11 @@ QJsonArray::QJsonArray(QCborContainerPrivate *array) */ void QJsonArray::initialize() { - a = nullptr; + // Because we're being called with uninitialized state, we can't do: + // a = nullptr; + // QExplicitlyDataSharedPointer::operator= will read the current value + void *ptr = &a; + memset(ptr, 0, sizeof(a)); } /*! @@ -177,7 +181,6 @@ QJsonArray::~QJsonArray() = default; QJsonArray::QJsonArray(std::initializer_list args) { - initialize(); for (const auto & arg : args) append(arg); } diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index a6987279d3e..b76e50e2d25 100644 --- a/src/corelib/serialization/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp @@ -150,7 +150,11 @@ QJsonObject::QJsonObject(QCborContainerPrivate *object) void QJsonObject::initialize() { - o = nullptr; + // Because we're being called with uninitialized state, we can't do: + // o = nullptr; + // QExplicitlyDataSharedPointer::operator= will read the current value + void *ptr = &o; + memset(ptr, 0, sizeof(o)); } /*! @@ -160,7 +164,6 @@ QJsonObject::~QJsonObject() = default; QJsonObject::QJsonObject(std::initializer_list > args) { - initialize(); for (const auto &arg : args) insert(arg.first, arg.second); } @@ -401,7 +404,9 @@ QJsonValue QJsonObject::operator [](const QString &key) const #if QT_STRINGVIEW_LEVEL < 2 /*! - Returns a reference to the value for \a key. + Returns a reference to the value for \a key. If there is no value with key + \a key in the object, one is created with a QJsonValue::Null value and then + returned. The return value is of type QJsonValueRef, a helper class for QJsonArray and QJsonObject. When you get an object of type QJsonValueRef, you can diff --git a/src/corelib/serialization/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp index b8137e0abd4..9325cd91639 100644 --- a/src/corelib/serialization/qtextstream.cpp +++ b/src/corelib/serialization/qtextstream.cpp @@ -135,30 +135,30 @@ static const int QTEXTSTREAM_BUFFERSIZE = 16384; \table \header \li Manipulator \li Description - \row \li \c Qt::bin \li Same as setIntegerBase(2). - \row \li \c Qt::oct \li Same as setIntegerBase(8). - \row \li \c Qt::dec \li Same as setIntegerBase(10). - \row \li \c Qt::hex \li Same as setIntegerBase(16). - \row \li \c Qt::showbase \li Same as setNumberFlags(numberFlags() | ShowBase). - \row \li \c Qt::forcesign \li Same as setNumberFlags(numberFlags() | ForceSign). - \row \li \c Qt::forcepoint \li Same as setNumberFlags(numberFlags() | ForcePoint). - \row \li \c Qt::noshowbase \li Same as setNumberFlags(numberFlags() & ~ShowBase). - \row \li \c Qt::noforcesign \li Same as setNumberFlags(numberFlags() & ~ForceSign). - \row \li \c Qt::noforcepoint \li Same as setNumberFlags(numberFlags() & ~ForcePoint). - \row \li \c Qt::uppercasebase \li Same as setNumberFlags(numberFlags() | UppercaseBase). - \row \li \c Qt::uppercasedigits \li Same as setNumberFlags(numberFlags() | UppercaseDigits). - \row \li \c Qt::lowercasebase \li Same as setNumberFlags(numberFlags() & ~UppercaseBase). - \row \li \c Qt::lowercasedigits \li Same as setNumberFlags(numberFlags() & ~UppercaseDigits). - \row \li \c Qt::fixed \li Same as setRealNumberNotation(FixedNotation). - \row \li \c Qt::scientific \li Same as setRealNumberNotation(ScientificNotation). - \row \li \c Qt::left \li Same as setFieldAlignment(AlignLeft). - \row \li \c Qt::right \li Same as setFieldAlignment(AlignRight). - \row \li \c Qt::center \li Same as setFieldAlignment(AlignCenter). - \row \li \c Qt::endl \li Same as operator<<('\\n') and flush(). - \row \li \c Qt::flush \li Same as flush(). - \row \li \c Qt::reset \li Same as reset(). - \row \li \c Qt::ws \li Same as skipWhiteSpace(). - \row \li \c Qt::bom \li Same as setGenerateByteOrderMark(true). + \row \li Qt::bin \li Same as setIntegerBase(2). + \row \li Qt::oct \li Same as setIntegerBase(8). + \row \li Qt::dec \li Same as setIntegerBase(10). + \row \li Qt::hex \li Same as setIntegerBase(16). + \row \li Qt::showbase \li Same as setNumberFlags(numberFlags() | ShowBase). + \row \li Qt::forcesign \li Same as setNumberFlags(numberFlags() | ForceSign). + \row \li Qt::forcepoint \li Same as setNumberFlags(numberFlags() | ForcePoint). + \row \li Qt::noshowbase \li Same as setNumberFlags(numberFlags() & ~ShowBase). + \row \li Qt::noforcesign \li Same as setNumberFlags(numberFlags() & ~ForceSign). + \row \li Qt::noforcepoint \li Same as setNumberFlags(numberFlags() & ~ForcePoint). + \row \li Qt::uppercasebase \li Same as setNumberFlags(numberFlags() | UppercaseBase). + \row \li Qt::uppercasedigits \li Same as setNumberFlags(numberFlags() | UppercaseDigits). + \row \li Qt::lowercasebase \li Same as setNumberFlags(numberFlags() & ~UppercaseBase). + \row \li Qt::lowercasedigits \li Same as setNumberFlags(numberFlags() & ~UppercaseDigits). + \row \li Qt::fixed \li Same as setRealNumberNotation(FixedNotation). + \row \li Qt::scientific \li Same as setRealNumberNotation(ScientificNotation). + \row \li Qt::left \li Same as setFieldAlignment(AlignLeft). + \row \li Qt::right \li Same as setFieldAlignment(AlignRight). + \row \li Qt::center \li Same as setFieldAlignment(AlignCenter). + \row \li Qt::endl \li Same as operator<<('\\n') and flush(). + \row \li Qt::flush \li Same as flush(). + \row \li Qt::reset \li Same as reset(). + \row \li Qt::ws \li Same as skipWhiteSpace(). + \row \li Qt::bom \li Same as setGenerateByteOrderMark(true). \endtable In addition, Qt provides three global manipulators that take a @@ -2693,8 +2693,12 @@ QTextStream &QTextStream::operator<<(const void *ptr) namespace Qt { /*! + \fn QTextStream &QTextStreamFunctions::bin(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::bin() instead. +*/ +/*! Calls QTextStream::setIntegerBase(2) on \a stream and returns \a stream. @@ -2707,8 +2711,12 @@ QTextStream &bin(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::oct(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::oct() instead. +*/ +/*! Calls QTextStream::setIntegerBase(8) on \a stream and returns \a stream. @@ -2721,8 +2729,12 @@ QTextStream &oct(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::dec(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::dec() instead. +*/ +/*! Calls QTextStream::setIntegerBase(10) on \a stream and returns \a stream. @@ -2735,8 +2747,12 @@ QTextStream &dec(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::hex(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::hex() instead. +*/ +/*! Calls QTextStream::setIntegerBase(16) on \a stream and returns \a stream. @@ -2750,8 +2766,12 @@ QTextStream &hex(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::showbase(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::showbase() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::ShowBase) on \a stream and returns \a stream. @@ -2764,8 +2784,12 @@ QTextStream &showbase(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::forcesign(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::forcesign() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::ForceSign) on \a stream and returns \a stream. @@ -2778,8 +2802,12 @@ QTextStream &forcesign(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::forcepoint(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::forcepoint() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::ForcePoint) on \a stream and returns \a stream. @@ -2792,8 +2820,12 @@ QTextStream &forcepoint(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::noshowbase(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::noshowbase() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ShowBase) on \a stream and returns \a stream. @@ -2806,8 +2838,12 @@ QTextStream &noshowbase(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::noforcesign(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::noforcesign() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ForceSign) on \a stream and returns \a stream. @@ -2820,8 +2856,12 @@ QTextStream &noforcesign(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::noforcepoint(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::noforcepoint() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::ForcePoint) on \a stream and returns \a stream. @@ -2834,8 +2874,12 @@ QTextStream &noforcepoint(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::uppercasebase(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::uppercasebase() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::UppercaseBase) on \a stream and returns \a stream. @@ -2848,8 +2892,12 @@ QTextStream &uppercasebase(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::uppercasedigits(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::uppercasedigits() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() | QTextStream::UppercaseDigits) on \a stream and returns \a stream. @@ -2862,8 +2910,12 @@ QTextStream &uppercasedigits(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::lowercasebase(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::lowercasebase() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::UppercaseBase) on \a stream and returns \a stream. @@ -2876,8 +2928,12 @@ QTextStream &lowercasebase(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::lowercasedigits(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::lowercasedigits() instead. +*/ +/*! Calls QTextStream::setNumberFlags(QTextStream::numberFlags() & ~QTextStream::UppercaseDigits) on \a stream and returns \a stream. @@ -2890,8 +2946,12 @@ QTextStream &lowercasedigits(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::fixed(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::fixed() instead. +*/ +/*! Calls QTextStream::setRealNumberNotation(QTextStream::FixedNotation) on \a stream and returns \a stream. @@ -2904,8 +2964,12 @@ QTextStream &fixed(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::scientific(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::scientific() instead. +*/ +/*! Calls QTextStream::setRealNumberNotation(QTextStream::ScientificNotation) on \a stream and returns \a stream. @@ -2918,8 +2982,12 @@ QTextStream &scientific(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::left(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::left() instead. +*/ +/*! Calls QTextStream::setFieldAlignment(QTextStream::AlignLeft) on \a stream and returns \a stream. @@ -2932,8 +3000,12 @@ QTextStream &left(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::right(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::right() instead. +*/ +/*! Calls QTextStream::setFieldAlignment(QTextStream::AlignRight) on \a stream and returns \a stream. @@ -2946,8 +3018,12 @@ QTextStream &right(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::center(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::center() instead. +*/ +/*! Calls QTextStream::setFieldAlignment(QTextStream::AlignCenter) on \a stream and returns \a stream. @@ -2960,8 +3036,12 @@ QTextStream ¢er(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::endl(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::endl() instead. +*/ +/*! Writes '\\n' to the \a stream and flushes the stream. Equivalent to @@ -2979,8 +3059,12 @@ QTextStream &endl(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::flush(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::flush() instead. +*/ +/*! Calls QTextStream::flush() on \a stream and returns \a stream. \sa endl(), reset(), {QTextStream manipulators} @@ -2992,8 +3076,12 @@ QTextStream &flush(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::reset(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::reset() instead. +*/ +/*! Calls QTextStream::reset() on \a stream and returns \a stream. \sa flush(), {QTextStream manipulators} @@ -3005,8 +3093,12 @@ QTextStream &reset(QTextStream &stream) } /*! + \fn QTextStream &QTextStreamFunctions::ws(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::ws() instead. +*/ +/*! Calls \l {QTextStream::}{skipWhiteSpace()} on \a stream and returns \a stream. \sa {QTextStream manipulators} @@ -3044,8 +3136,12 @@ QTextStream &ws(QTextStream &stream) namespace Qt { /*! + \fn QTextStream &QTextStreamFunctions::bom(QTextStream &stream) \relates QTextStream + \obsolete Use Qt::bom() instead. +*/ +/*! Toggles insertion of the Byte Order Mark on \a stream when QTextStream is used with a UTF codec. diff --git a/src/corelib/serialization/qtextstream.h b/src/corelib/serialization/qtextstream.h index 6f93826d8ae..0d8a9a548e5 100644 --- a/src/corelib/serialization/qtextstream.h +++ b/src/corelib/serialization/qtextstream.h @@ -268,7 +268,7 @@ Q_CORE_EXPORT QTextStream &ws(QTextStream &s); } // namespace Qt -#if QT_DEPRECATED_SINCE(5, 15) && !defined(Q_QDOC) +#if QT_DEPRECATED_SINCE(5, 15) // This namespace only exists for 'using namespace' declarations. namespace QTextStreamFunctions { Q_CORE_EXPORT QT_DEPRECATED_X("Use Qt::bin") QTextStream &bin(QTextStream &s); @@ -303,7 +303,7 @@ QT_WARNING_DISABLE_CLANG("-Wheader-hygiene") // conflicting definitions compiler errors. using namespace QTextStreamFunctions; QT_WARNING_POP -#endif // QT_DEPRECATED_SINCE(5, 15) && !defined(Q_QDOC) +#endif // QT_DEPRECATED_SINCE(5, 15) inline QTextStreamManipulator qSetFieldWidth(int width) { diff --git a/src/corelib/text/qbytearray_p.h b/src/corelib/text/qbytearray_p.h index d6a5e277b30..90552cb4428 100644 --- a/src/corelib/text/qbytearray_p.h +++ b/src/corelib/text/qbytearray_p.h @@ -56,10 +56,9 @@ QT_BEGIN_NAMESPACE -enum { - // Define as enum to force inlining. Don't expose MaxAllocSize in a public header. - MaxByteArraySize = MaxAllocSize - sizeof(std::remove_pointer::type) -}; +// -1 because of the terminating NUL +constexpr qsizetype MaxByteArraySize = MaxAllocSize - sizeof(std::remove_pointer::type) - 1; +constexpr qsizetype MaxStringSize = (MaxAllocSize - sizeof(std::remove_pointer::type)) / 2 - 1; QT_END_NAMESPACE diff --git a/src/corelib/text/qcollator_p.h b/src/corelib/text/qcollator_p.h index fc2d434a8da..444ae06a991 100644 --- a/src/corelib/text/qcollator_p.h +++ b/src/corelib/text/qcollator_p.h @@ -57,7 +57,7 @@ #include #if QT_CONFIG(icu) #include -#elif defined(Q_OS_OSX) +#elif defined(Q_OS_MACOS) #include #elif defined(Q_OS_WIN) #include @@ -70,7 +70,7 @@ typedef UCollator *CollatorType; typedef QByteArray CollatorKeyType; const CollatorType NoCollator = nullptr; -#elif defined(Q_OS_OSX) +#elif defined(Q_OS_MACOS) typedef CollatorRef CollatorType; typedef QVector CollatorKeyType; const CollatorType NoCollator = 0; diff --git a/src/corelib/text/qlocale.h b/src/corelib/text/qlocale.h index ca2b5a007fd..45e39aa60d3 100644 --- a/src/corelib/text/qlocale.h +++ b/src/corelib/text/qlocale.h @@ -73,8 +73,8 @@ class Q_CORE_EXPORT QLocale friend class QTextStreamPrivate; public: -// GENERATED PART STARTS HERE // see qlocale_data_p.h for more info on generated data +// GENERATED PART STARTS HERE enum Language { AnyLanguage = 0, C = 1, diff --git a/src/corelib/text/qlocale_data_p.h b/src/corelib/text/qlocale_data_p.h index 1a9ff67f5f2..0501c59e1a7 100644 --- a/src/corelib/text/qlocale_data_p.h +++ b/src/corelib/text/qlocale_data_p.h @@ -77,7 +77,7 @@ static const int ImperialMeasurementSystemsCount = // GENERATED PART STARTS HERE /* - This part of the file was generated on 2020-01-30 from the + This part of the file was generated on 2020-04-07 from the Common Locale Data Repository v36 http://www.unicode.org/cldr/ @@ -1282,298 +1282,298 @@ static const QLocaleData locale_data[] = { { 3, 7, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 45, 10, 22, 109, 109, 163, 163, 83, 83, 2, 2, 0, 5, 22, 0, 0, 4, 0, 0, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 17, 4, 0, 6, 10, {69,84,66}, 2, 1, 7, 6, 7 }, // Oromo/Latin/Ethiopia { 3, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 45, 0, 0, 109, 109, 163, 163, 190, 190, 2, 2, 0, 5, 22, 2, 0, 4, 0, 0, 16, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 4, 0, 6, 8, {75,69,83}, 2, 1, 7, 6, 7 }, // Oromo/Latin/Kenya { 4, 7, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,84,66}, 2, 1, 7, 6, 7 }, // Afar/Latin/Ethiopia - { 5, 7, 195, 0, 0, 7, 7, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 80, 70, 0, 0, 203, 203, 260, 260, 287, 287, 4, 4, 45, 5, 22, 5, 17, 4, 0, 24, 33, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 27, 27, 13, 13, 3, 3, 5, 17, 23, 1, 66, 4, 0, 9, 11, {90,65,82}, 2, 1, 7, 6, 7 }, // Afrikaans/Latin/South Africa - { 5, 7, 148, 0, 0, 7, 7, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 70, 10, 22, 203, 203, 260, 260, 287, 287, 4, 4, 45, 5, 22, 6, 83, 4, 0, 24, 44, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 57, 57, 27, 27, 13, 13, 3, 3, 5, 17, 23, 1, 54, 4, 0, 9, 7, {78,65,68}, 2, 1, 1, 6, 7 }, // Afrikaans/Latin/Namibia - { 6, 7, 2, 0, 0, 15, 15, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 0, 113, 29, 22, 300, 300, 357, 384, 411, 411, 7, 7, 50, 5, 22, 7, 137, 13, 0, 51, 56, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 7, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 4, 44, 5, 0, 5, 8, {65,76,76}, 0, 0, 1, 6, 7 }, // Albanian/Latin/Albania - { 6, 7, 127, 0, 0, 15, 15, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 0, 113, 0, 0, 300, 300, 357, 384, 411, 411, 7, 7, 50, 5, 22, 11, 181, 13, 0, 51, 64, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 3, 53, 5, 0, 5, 18, {77,75,68}, 2, 1, 1, 6, 7 }, // Albanian/Latin/Macedonia - { 6, 7, 257, 0, 0, 15, 15, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 0, 113, 0, 0, 300, 300, 357, 384, 411, 411, 7, 7, 50, 5, 22, 14, 234, 13, 0, 51, 82, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 1, 20, 5, 0, 5, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Albanian/Latin/Kosovo - { 7, 14, 69, 24, 24, 30, 39, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 17, 18, 53, 45, 10, 22, 425, 425, 452, 452, 478, 478, 18, 17, 54, 57, 22, 15, 254, 4, 0, 88, 92, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 27, 27, 26, 26, 13, 13, 3, 4, 3, 23, 23, 2, 33, 4, 0, 4, 5, {69,84,66}, 2, 1, 7, 6, 7 }, // Amharic/Ethiopic/Ethiopia - { 8, 1, 64, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 17, 287, 13, 0, 97, 104, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 80, 5, 0, 7, 3, {69,71,80}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Egypt - { 8, 1, 3, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 22, 367, 13, 0, 97, 107, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5,101, 5, 0, 7, 7, {68,90,68}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Algeria - { 8, 1, 17, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 27, 468, 13, 0, 97, 114, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 90, 5, 0, 7, 7, {66,72,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Bahrain - { 8, 1, 42, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 32, 558, 13, 0, 97, 121, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 4,111, 5, 0, 7, 4, {88,65,70}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Chad - { 8, 1, 48, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 0, 0, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 33, 669, 13, 0, 97, 125, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 10, 5, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 2,104, 5, 0, 7, 9, {75,77,70}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Comoros - { 8, 1, 59, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 36, 773, 13, 0, 97, 134, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 3, 83, 5, 0, 7, 6, {68,74,70}, 0, 0, 6, 6, 7 }, // Arabic/Arabic/Djibouti - { 8, 1, 67, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 39, 856, 13, 0, 97, 140, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 3, 90, 5, 0, 7, 7, {69,82,78}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Eritrea - { 8, 1, 103, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 42, 946, 13, 0, 97, 147, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 6, {73,81,68}, 0, 0, 6, 5, 6 }, // Arabic/Arabic/Iraq - { 8, 1, 105, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 1, 1, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 47, 1029, 13, 0, 97, 153, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 9, 4, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1,132, 5, 0, 7, 7, {73,76,83}, 2, 1, 7, 5, 6 }, // Arabic/Arabic/Israel - { 8, 1, 109, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 48, 1161, 13, 0, 97, 160, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 6, {74,79,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Jordan - { 8, 1, 115, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 53, 1244, 13, 0, 97, 166, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 6, {75,87,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Kuwait - { 8, 1, 119, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 58, 1327, 13, 0, 97, 172, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 5, {76,66,80}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Lebanon - { 8, 1, 122, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 63, 1410, 13, 0, 97, 177, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 87, 5, 0, 7, 5, {76,89,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Libya - { 8, 1, 136, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 68, 1497, 13, 0, 97, 182, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 4,111, 5, 0, 7, 9, {77,82,85}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Mauritania - { 8, 1, 145, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 0, 0, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 72, 1608, 13, 0, 97, 191, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 10, 5, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 86, 5, 0, 7, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Morocco - { 8, 1, 162, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 77, 1694, 13, 0, 97, 197, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 76, 5, 0, 7, 5, {79,77,82}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Oman - { 8, 1, 165, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 47, 1029, 13, 0, 97, 202, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1,132, 5, 0, 7, 18, {73,76,83}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Palestinian Territories - { 8, 1, 175, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 82, 1770, 13, 0, 97, 220, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 69, 5, 0, 7, 3, {81,65,82}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Qatar - { 8, 1, 186, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 87, 1839, 13, 0, 97, 223, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 76, 5, 0, 7, 24, {83,65,82}, 2, 1, 7, 5, 6 }, // Arabic/Arabic/Saudi Arabia - { 8, 1, 194, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 92, 1915, 13, 0, 97, 247, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1, 76, 5, 0, 7, 7, {83,79,83}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Somalia - { 8, 1, 201, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 93, 1991, 13, 0, 97, 254, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 4, 90, 5, 0, 7, 7, {83,68,71}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Sudan - { 8, 1, 207, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 97, 2081, 13, 0, 97, 261, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 76, 5, 0, 7, 5, {83,89,80}, 0, 0, 6, 5, 6 }, // Arabic/Arabic/Syria - { 8, 1, 216, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 102, 2157, 13, 0, 97, 266, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 94, 5, 0, 7, 4, {84,78,68}, 3, 0, 1, 6, 7 }, // Arabic/Arabic/Tunisia - { 8, 1, 223, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 107, 2251, 13, 0, 97, 270, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 90, 5, 0, 7, 24, {65,69,68}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/United Arab Emirates - { 8, 1, 236, 47, 47, 47, 47, 6, 0, 1, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 72, 1608, 13, 0, 97, 294, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 86, 5, 0, 7, 15, {77,65,68}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Western Sahara - { 8, 1, 237, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 112, 2341, 13, 0, 97, 309, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 69, 5, 0, 7, 5, {89,69,82}, 0, 0, 7, 5, 6 }, // Arabic/Arabic/Yemen - { 8, 1, 254, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 117, 2410, 13, 0, 97, 314, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1,131, 5, 0, 7, 12, {83,83,80}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/South Sudan - { 8, 1, 260, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 0, 0, 13, 0, 326, 348, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 0, 0, 5, 0, 22, 6, {0,0,0}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/World - { 9, 10, 11, 0, 0, 54, 54, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 15, 16, 146, 166, 0, 0, 555, 555, 616, 616, 643, 643, 0, 0, 131, 137, 22, 118, 2541, 13, 0, 354, 361, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 8, 10, 5, 61, 61, 27, 27, 13, 13, 2, 2, 6, 17, 23, 1, 45, 5, 0, 7, 8, {65,77,68}, 2, 0, 1, 6, 7 }, // Armenian/Armenian/Armenia + { 5, 7, 195, 0, 0, 7, 7, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 80, 70, 0, 0, 203, 203, 260, 260, 287, 287, 4, 4, 45, 5, 22, 5, 17, 4, 13, 24, 33, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 27, 27, 13, 13, 3, 3, 5, 17, 23, 1, 66, 4, 6, 9, 11, {90,65,82}, 2, 1, 7, 6, 7 }, // Afrikaans/Latin/South Africa + { 5, 7, 148, 0, 0, 7, 7, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 70, 10, 22, 203, 203, 260, 260, 287, 287, 4, 4, 45, 5, 22, 6, 83, 4, 13, 24, 44, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 57, 57, 27, 27, 13, 13, 3, 3, 5, 17, 23, 1, 54, 4, 6, 9, 7, {78,65,68}, 2, 1, 1, 6, 7 }, // Afrikaans/Latin/Namibia + { 6, 7, 2, 0, 0, 15, 15, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 0, 113, 29, 22, 300, 300, 357, 384, 411, 411, 7, 7, 50, 5, 22, 7, 137, 19, 24, 51, 56, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 13, 7, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 4, 44, 5, 7, 5, 8, {65,76,76}, 0, 0, 1, 6, 7 }, // Albanian/Latin/Albania + { 6, 7, 127, 0, 0, 15, 15, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 0, 113, 0, 0, 300, 300, 357, 384, 411, 411, 7, 7, 50, 5, 22, 11, 181, 19, 24, 51, 64, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 3, 53, 5, 7, 5, 18, {77,75,68}, 2, 1, 1, 6, 7 }, // Albanian/Latin/Macedonia + { 6, 7, 257, 0, 0, 15, 15, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 0, 113, 0, 0, 300, 300, 357, 384, 411, 411, 7, 7, 50, 5, 22, 14, 234, 19, 24, 51, 82, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 57, 57, 27, 27, 14, 14, 11, 10, 4, 17, 23, 1, 20, 5, 7, 5, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Albanian/Latin/Kosovo + { 7, 14, 69, 24, 24, 30, 39, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 17, 18, 53, 45, 10, 22, 425, 425, 452, 452, 478, 478, 18, 17, 54, 57, 22, 15, 254, 4, 13, 88, 92, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 27, 27, 26, 26, 13, 13, 3, 4, 3, 23, 23, 2, 33, 4, 6, 4, 5, {69,84,66}, 2, 1, 7, 6, 7 }, // Amharic/Ethiopic/Ethiopia + { 8, 1, 64, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 17, 287, 19, 0, 97, 104, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 80, 5, 0, 7, 3, {69,71,80}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Egypt + { 8, 1, 3, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 22, 367, 4, 13, 97, 107, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5,101, 4, 6, 7, 7, {68,90,68}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Algeria + { 8, 1, 17, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 27, 468, 19, 0, 97, 114, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 90, 5, 0, 7, 7, {66,72,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Bahrain + { 8, 1, 42, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 32, 558, 19, 0, 97, 121, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 4,111, 5, 0, 7, 4, {88,65,70}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Chad + { 8, 1, 48, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 0, 0, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 33, 669, 19, 0, 97, 125, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 10, 5, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 2,104, 5, 0, 7, 9, {75,77,70}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Comoros + { 8, 1, 59, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 36, 773, 19, 0, 97, 134, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 3, 83, 5, 0, 7, 6, {68,74,70}, 0, 0, 6, 6, 7 }, // Arabic/Arabic/Djibouti + { 8, 1, 67, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 39, 856, 19, 0, 97, 140, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 3, 90, 5, 0, 7, 7, {69,82,78}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Eritrea + { 8, 1, 103, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 42, 946, 19, 0, 97, 147, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 6, {73,81,68}, 0, 0, 6, 5, 6 }, // Arabic/Arabic/Iraq + { 8, 1, 105, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 1, 1, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 47, 1029, 19, 0, 97, 153, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 9, 4, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1,132, 5, 0, 7, 7, {73,76,83}, 2, 1, 7, 5, 6 }, // Arabic/Arabic/Israel + { 8, 1, 109, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 48, 1161, 19, 0, 97, 160, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 6, {74,79,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Jordan + { 8, 1, 115, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 53, 1244, 19, 0, 97, 166, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 6, {75,87,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Kuwait + { 8, 1, 119, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 58, 1327, 19, 0, 97, 172, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 83, 5, 0, 7, 5, {76,66,80}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Lebanon + { 8, 1, 122, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 63, 1410, 4, 13, 97, 177, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 87, 4, 6, 7, 5, {76,89,68}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Libya + { 8, 1, 136, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 68, 1497, 19, 0, 97, 182, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 4,111, 5, 0, 7, 9, {77,82,85}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Mauritania + { 8, 1, 145, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 0, 0, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 72, 1608, 4, 13, 97, 191, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 10, 5, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 86, 4, 6, 7, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Morocco + { 8, 1, 162, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 77, 1694, 19, 0, 97, 197, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 76, 5, 0, 7, 5, {79,77,82}, 3, 0, 6, 5, 6 }, // Arabic/Arabic/Oman + { 8, 1, 165, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 47, 1029, 19, 0, 97, 202, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1,132, 5, 0, 7, 18, {73,76,83}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Palestinian Territories + { 8, 1, 175, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 82, 1770, 19, 0, 97, 220, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 69, 5, 0, 7, 3, {81,65,82}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Qatar + { 8, 1, 186, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 87, 1839, 19, 0, 97, 223, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 76, 5, 0, 7, 24, {83,65,82}, 2, 1, 7, 5, 6 }, // Arabic/Arabic/Saudi Arabia + { 8, 1, 194, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 92, 1915, 19, 0, 97, 247, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1, 76, 5, 0, 7, 7, {83,79,83}, 0, 0, 1, 6, 7 }, // Arabic/Arabic/Somalia + { 8, 1, 201, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 93, 1991, 19, 0, 97, 254, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 4, 90, 5, 0, 7, 7, {83,68,71}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/Sudan + { 8, 1, 207, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 97, 2081, 19, 0, 97, 261, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 76, 5, 0, 7, 5, {83,89,80}, 0, 0, 6, 5, 6 }, // Arabic/Arabic/Syria + { 8, 1, 216, 47, 47, 47, 47, 6, 1, 0, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 102, 2157, 4, 13, 97, 266, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 94, 4, 6, 7, 4, {84,78,68}, 3, 0, 1, 6, 7 }, // Arabic/Arabic/Tunisia + { 8, 1, 223, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 107, 2251, 19, 0, 97, 270, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 90, 5, 0, 7, 24, {65,69,68}, 2, 1, 6, 5, 6 }, // Arabic/Arabic/United Arab Emirates + { 8, 1, 236, 47, 47, 47, 47, 6, 0, 1, 30, 3, 33, 35, 9, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 72, 1608, 4, 13, 97, 294, 6, 6, 6, 6, 1, 1, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 86, 4, 6, 7, 15, {77,65,68}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/Western Sahara + { 8, 1, 237, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 112, 2341, 19, 0, 97, 309, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 5, 69, 5, 0, 7, 5, {89,69,82}, 0, 0, 7, 5, 6 }, // Arabic/Arabic/Yemen + { 8, 1, 254, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 117, 2410, 19, 0, 97, 314, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 1,131, 5, 0, 7, 12, {83,83,80}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/South Sudan + { 8, 1, 260, 47, 47, 47, 47, 53, 19, 20, 21, 23, 24, 26, 28, 11, 10, 13, 12, 119, 136, 10, 22, 491, 491, 491, 491, 542, 542, 21, 21, 80, 84, 22, 0, 0, 19, 0, 326, 348, 6, 6, 6, 6, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 51, 51, 51, 51, 13, 13, 1, 1, 4, 47, 23, 0, 0, 5, 0, 22, 6, {0,0,0}, 2, 1, 1, 6, 7 }, // Arabic/Arabic/World + { 9, 10, 11, 0, 0, 54, 54, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 15, 16, 146, 166, 0, 0, 555, 555, 616, 616, 643, 643, 0, 0, 131, 137, 22, 118, 2541, 19, 0, 354, 361, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 8, 10, 5, 61, 61, 27, 27, 13, 13, 2, 2, 6, 17, 23, 1, 45, 5, 0, 7, 8, {65,77,68}, 2, 0, 1, 6, 7 }, // Armenian/Armenian/Armenia { 10, 11, 100, 0, 0, 61, 61, 6, 0, 1, 2, 37, 4, 5, 9, 10, 11, 12, 13, 174, 192, 42, 42, 656, 656, 713, 713, 744, 744, 22, 22, 154, 158, 22, 119, 2586, 8, 0, 369, 376, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 57, 57, 31, 31, 13, 13, 9, 7, 4, 37, 23, 1, 42, 5, 0, 7, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Assamese/Bengali/India - { 12, 7, 15, 0, 0, 70, 70, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 200, 166, 0, 0, 757, 757, 823, 849, 96, 96, 0, 0, 195, 5, 22, 120, 2628, 13, 0, 380, 390, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 66, 66, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 57, 5, 0, 10, 10, {65,90,78}, 2, 1, 1, 6, 7 }, // Azerbaijani/Latin/Azerbaijan + { 12, 7, 15, 0, 0, 70, 70, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 200, 166, 0, 0, 757, 757, 823, 849, 96, 96, 0, 0, 195, 5, 22, 120, 2628, 19, 0, 380, 390, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 66, 66, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 57, 5, 0, 10, 10, {65,90,78}, 2, 1, 1, 6, 7 }, // Azerbaijani/Latin/Azerbaijan { 12, 1, 102, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {73,82,82}, 0, 0, 6, 5, 5 }, // Azerbaijani/Arabic/Iran - { 12, 2, 15, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 17, 18, 200, 166, 0, 0, 875, 875, 941, 941, 96, 96, 31, 29, 0, 5, 22, 120, 2685, 13, 0, 400, 410, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 66, 66, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 5, 5, 0, 10, 10, {65,90,78}, 2, 1, 1, 6, 7 }, // Azerbaijani/Cyrillic/Azerbaijan + { 12, 2, 15, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 17, 18, 200, 166, 0, 0, 875, 875, 941, 941, 96, 96, 31, 29, 0, 5, 22, 120, 2685, 19, 0, 400, 410, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 66, 66, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 5, 5, 0, 10, 10, {65,90,78}, 2, 1, 1, 6, 7 }, // Azerbaijani/Cyrillic/Azerbaijan { 13, 2, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 121, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {82,85,66}, 2, 1, 1, 6, 7 }, // Bashkir/Cyrillic/Russia - { 14, 7, 197, 0, 0, 78, 78, 6, 1, 0, 2, 3, 38, 5, 9, 10, 11, 10, 11, 217, 253, 54, 0, 967, 967, 1034, 1034, 1061, 1061, 0, 0, 199, 5, 22, 14, 2690, 13, 0, 420, 427, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 36, 6, 12, 5, 67, 67, 27, 27, 13, 13, 2, 2, 7, 17, 23, 1, 19, 5, 0, 7, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // Basque/Latin/Spain - { 15, 11, 18, 0, 0, 87, 87, 6, 0, 1, 2, 37, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22, 1074, 1074, 1131, 1131, 1167, 1167, 0, 0, 154, 5, 22, 122, 2709, 0, 0, 435, 440, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 57, 57, 36, 36, 17, 17, 2, 2, 4, 17, 23, 1, 48, 4, 0, 5, 8, {66,68,84}, 2, 1, 7, 6, 7 }, // Bengali/Bengali/Bangladesh - { 15, 11, 100, 0, 0, 87, 87, 6, 0, 1, 2, 37, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22, 1074, 1074, 1131, 1131, 1167, 1167, 0, 0, 154, 5, 22, 119, 2757, 0, 0, 435, 448, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 57, 57, 36, 36, 17, 17, 2, 2, 4, 17, 23, 1, 42, 4, 0, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Bengali/Bengali/India + { 14, 7, 197, 0, 0, 78, 78, 6, 1, 0, 2, 3, 38, 5, 9, 10, 11, 10, 11, 217, 253, 54, 0, 967, 967, 1034, 1034, 1061, 1061, 0, 0, 199, 5, 22, 14, 2690, 19, 24, 420, 427, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 36, 6, 12, 5, 67, 67, 27, 27, 13, 13, 2, 2, 7, 17, 23, 1, 19, 5, 7, 7, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // Basque/Latin/Spain + { 15, 11, 18, 0, 0, 87, 87, 6, 0, 1, 2, 37, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22, 1074, 1074, 1131, 1131, 1167, 1167, 0, 0, 154, 5, 22, 122, 2709, 0, 31, 435, 440, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 57, 57, 36, 36, 17, 17, 2, 2, 4, 17, 23, 1, 48, 4, 6, 5, 8, {66,68,84}, 2, 1, 7, 6, 7 }, // Bengali/Bengali/Bangladesh + { 15, 11, 100, 0, 0, 87, 87, 6, 0, 1, 2, 37, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22, 1074, 1074, 1131, 1131, 1167, 1167, 0, 0, 154, 5, 22, 119, 2757, 0, 31, 435, 448, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 57, 57, 36, 36, 17, 17, 2, 2, 4, 17, 23, 1, 42, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Bengali/Bengali/India { 16, 31, 25, 96, 96, 96, 96, 6, 0, 1, 2, 39, 4, 5, 9, 10, 11, 12, 13, 265, 70, 66, 93, 1184, 1184, 1262, 1262, 1295, 1295, 33, 31, 0, 5, 22, 123, 2799, 4, 0, 452, 458, 9, 9, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 30, 10, 27, 22, 78, 78, 33, 33, 26, 26, 5, 6, 4, 17, 23, 3, 8, 4, 0, 6, 5, {66,84,78}, 2, 1, 7, 6, 7 }, // Dzongkha/Tibetan/Bhutan - { 19, 7, 74, 0, 0, 105, 105, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 1321, 1321, 1363, 1363, 1395, 1395, 38, 37, 206, 213, 230, 14, 2807, 13, 0, 463, 472, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 42, 42, 32, 32, 17, 17, 4, 4, 7, 17, 23, 1, 35, 5, 0, 9, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Breton/Latin/France - { 20, 2, 33, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 40, 10, 295, 317, 1, 1, 1412, 1412, 1466, 1466, 1486, 1486, 42, 41, 253, 5, 22, 126, 2842, 13, 0, 477, 486, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 12, 9, 4, 54, 54, 20, 20, 13, 13, 6, 6, 7, 17, 23, 3, 46, 5, 0, 9, 8, {66,71,78}, 2, 1, 1, 6, 7 }, // Bulgarian/Cyrillic/Bulgaria - { 21, 25, 147, 120, 120, 125, 125, 135, 0, 1, 2, 41, 4, 5, 9, 10, 11, 12, 13, 329, 347, 115, 125, 1499, 1499, 1499, 1499, 1552, 1552, 48, 47, 260, 5, 22, 2, 2888, 13, 0, 494, 494, 5, 5, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 6, 53, 53, 53, 53, 13, 13, 5, 3, 5, 17, 23, 1, 28, 5, 0, 6, 6, {77,77,75}, 0, 0, 7, 6, 7 }, // Burmese/Myanmar/Myanmar - { 22, 2, 20, 0, 0, 136, 136, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 167, 131, 0, 1565, 1565, 1620, 1620, 1640, 1640, 0, 0, 265, 270, 22, 0, 2916, 13, 0, 500, 510, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 7, 11, 5, 55, 55, 20, 20, 13, 13, 2, 2, 5, 17, 23, 2, 88, 5, 0, 10, 8, {66,89,78}, 2, 0, 1, 6, 7 }, // Belarusian/Cyrillic/Belarus - { 23, 20, 36, 0, 0, 143, 152, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 259, 10, 22, 1653, 1698, 1744, 1744, 1783, 1783, 0, 0, 287, 5, 22, 129, 3004, 0, 0, 518, 523, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 12, 7, 45, 46, 39, 39, 13, 13, 2, 2, 2, 17, 23, 1, 28, 4, 0, 5, 7, {75,72,82}, 2, 1, 7, 6, 7 }, // Khmer/Khmer/Cambodia - { 24, 7, 197, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 13, 0, 530, 536, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 0, 6, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/Spain - { 24, 7, 5, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 13, 0, 530, 543, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 0, 6, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/Andorra - { 24, 7, 74, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 13, 0, 530, 550, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/France - { 24, 7, 106, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 13, 0, 530, 556, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/Italy - { 25, 5, 44, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 390, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 130, 3051, 4, 0, 562, 566, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 1, 12, 4, 0, 4, 2, {67,78,89}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/China - { 25, 5, 97, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 259, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 131, 3063, 4, 0, 562, 568, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 6, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 3, 10, 4, 0, 4, 9, {72,75,68}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Hong Kong - { 25, 5, 126, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 259, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 134, 3073, 4, 0, 562, 577, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 6, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 4, 12, 4, 0, 4, 9, {77,79,80}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Macau - { 25, 5, 190, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 45, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 6, 3085, 4, 0, 562, 586, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 1, 14, 4, 0, 4, 3, {83,71,68}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Singapore - { 25, 6, 97, 168, 168, 178, 178, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 377, 398, 153, 27, 1902, 1902, 1962, 1962, 1949, 1949, 58, 55, 312, 5, 22, 131, 3063, 18, 0, 589, 593, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 13, 6, 27, 27, 20, 20, 13, 13, 2, 2, 3, 17, 23, 3, 10, 5, 0, 4, 9, {72,75,68}, 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Hong Kong - { 25, 6, 126, 168, 168, 178, 178, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 377, 398, 153, 27, 1902, 1902, 1962, 1962, 1949, 1949, 58, 55, 312, 5, 22, 134, 3099, 18, 0, 589, 602, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 13, 6, 27, 27, 20, 20, 13, 13, 2, 2, 3, 17, 23, 4, 12, 5, 0, 4, 9, {77,79,80}, 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau - { 25, 6, 208, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 406, 390, 153, 27, 1902, 1902, 1962, 1962, 1949, 1949, 58, 55, 0, 5, 22, 6, 3111, 4, 0, 589, 611, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 8, 13, 6, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 12, 4, 0, 4, 2, {84,87,68}, 2, 0, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan + { 19, 7, 74, 0, 0, 105, 105, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 1321, 1321, 1363, 1363, 1395, 1395, 38, 37, 206, 213, 230, 14, 2807, 19, 0, 463, 472, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 42, 42, 32, 32, 17, 17, 4, 4, 7, 17, 23, 1, 35, 5, 0, 9, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Breton/Latin/France + { 20, 2, 33, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 40, 10, 295, 317, 1, 1, 1412, 1412, 1466, 1466, 1486, 1486, 42, 41, 253, 5, 22, 126, 2842, 19, 24, 477, 486, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 12, 9, 4, 54, 54, 20, 20, 13, 13, 6, 6, 7, 17, 23, 3, 46, 5, 7, 9, 8, {66,71,78}, 2, 1, 1, 6, 7 }, // Bulgarian/Cyrillic/Bulgaria + { 21, 25, 147, 120, 120, 125, 125, 135, 0, 1, 2, 41, 4, 5, 9, 10, 11, 12, 13, 329, 347, 115, 125, 1499, 1499, 1499, 1499, 1552, 1552, 48, 47, 260, 5, 22, 2, 2888, 8, 0, 494, 494, 5, 5, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 6, 53, 53, 53, 53, 13, 13, 5, 3, 5, 17, 23, 1, 28, 5, 0, 6, 6, {77,77,75}, 0, 0, 7, 6, 7 }, // Burmese/Myanmar/Myanmar + { 22, 2, 20, 0, 0, 136, 136, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 167, 131, 0, 1565, 1565, 1620, 1620, 1640, 1640, 0, 0, 265, 270, 22, 0, 2916, 19, 0, 500, 510, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 7, 11, 5, 55, 55, 20, 20, 13, 13, 2, 2, 5, 17, 23, 2, 88, 5, 0, 10, 8, {66,89,78}, 2, 0, 1, 6, 7 }, // Belarusian/Cyrillic/Belarus + { 23, 20, 36, 0, 0, 143, 152, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 259, 10, 22, 1653, 1698, 1744, 1744, 1783, 1783, 0, 0, 287, 5, 22, 129, 3004, 0, 31, 518, 523, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 12, 7, 45, 46, 39, 39, 13, 13, 2, 2, 2, 17, 23, 1, 28, 4, 6, 5, 7, {75,72,82}, 2, 1, 7, 6, 7 }, // Khmer/Khmer/Cambodia + { 24, 7, 197, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 19, 24, 530, 536, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 7, 6, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/Spain + { 24, 7, 5, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 19, 24, 530, 543, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 7, 6, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/Andorra + { 24, 7, 74, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 19, 24, 530, 550, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/France + { 24, 7, 106, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 1, 1, 1796, 1796, 1855, 1855, 1882, 1882, 53, 50, 0, 5, 22, 14, 3032, 19, 24, 530, 556, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 9, 4, 59, 59, 27, 27, 20, 20, 5, 5, 5, 17, 23, 1, 19, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Catalan/Latin/Italy + { 25, 5, 44, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 390, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 130, 3051, 4, 13, 562, 566, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 1, 12, 4, 6, 4, 2, {67,78,89}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/China + { 25, 5, 97, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 259, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 131, 3063, 4, 13, 562, 568, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 6, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 3, 10, 4, 6, 4, 9, {72,75,68}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Hong Kong + { 25, 5, 126, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 259, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 134, 3073, 4, 13, 562, 577, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 6, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 4, 12, 4, 6, 4, 9, {77,79,80}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Macau + { 25, 5, 190, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 45, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 289, 291, 22, 6, 3085, 4, 13, 562, 586, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 2, 21, 23, 1, 14, 4, 6, 4, 3, {83,71,68}, 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Singapore + { 25, 6, 97, 168, 168, 178, 178, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 377, 398, 153, 27, 1902, 1902, 1962, 1962, 1949, 1949, 58, 55, 312, 5, 22, 131, 3063, 4, 13, 589, 593, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 13, 6, 27, 27, 20, 20, 13, 13, 2, 2, 3, 17, 23, 3, 10, 4, 6, 4, 9, {72,75,68}, 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Hong Kong + { 25, 6, 126, 168, 168, 178, 178, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 377, 398, 153, 27, 1902, 1902, 1962, 1962, 1949, 1949, 58, 55, 312, 5, 22, 134, 3099, 4, 13, 589, 602, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 13, 6, 27, 27, 20, 20, 13, 13, 2, 2, 3, 17, 23, 4, 12, 4, 6, 4, 9, {77,79,80}, 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau + { 25, 6, 208, 168, 168, 173, 173, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 406, 390, 153, 27, 1902, 1902, 1962, 1962, 1949, 1949, 58, 55, 0, 5, 22, 6, 3111, 4, 13, 589, 611, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 8, 13, 6, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 12, 4, 6, 4, 2, {84,87,68}, 2, 0, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan { 26, 7, 74, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Corsican/Latin/France - { 27, 7, 54, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 439, 54, 0, 1982, 1982, 2039, 2039, 2066, 2079, 0, 0, 315, 5, 22, 138, 3123, 13, 0, 613, 621, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 13, 12, 5, 57, 57, 27, 27, 13, 13, 2, 2, 7, 17, 23, 3, 59, 5, 0, 8, 8, {72,82,75}, 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia - { 27, 7, 27, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 452, 54, 0, 1982, 1982, 2039, 2039, 2079, 2079, 0, 0, 315, 5, 22, 141, 3182, 13, 0, 613, 629, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 9, 12, 5, 57, 57, 27, 27, 13, 13, 2, 2, 7, 17, 23, 2, 84, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Croatian/Latin/Bosnia And Herzegowina - { 28, 7, 57, 0, 0, 183, 183, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 46, 12, 461, 166, 1, 1, 2092, 2092, 2140, 2140, 2160, 2160, 60, 57, 322, 5, 22, 143, 3266, 13, 0, 648, 655, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 9, 4, 48, 48, 20, 20, 13, 13, 4, 4, 5, 17, 23, 2, 67, 5, 0, 7, 5, {67,90,75}, 2, 0, 1, 6, 7 }, // Czech/Latin/Czech Republic - { 29, 7, 58, 0, 0, 190, 190, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 478, 501, 166, 166, 2173, 2173, 2223, 2250, 2284, 2284, 0, 0, 0, 5, 22, 145, 3333, 13, 0, 660, 665, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 50, 50, 27, 34, 13, 13, 2, 2, 5, 17, 23, 3, 41, 5, 0, 5, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // Danish/Latin/Denmark - { 29, 7, 86, 0, 0, 190, 190, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 478, 501, 166, 166, 2173, 2173, 2223, 2250, 2284, 2284, 0, 0, 0, 5, 22, 145, 3333, 13, 0, 660, 672, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 50, 50, 27, 34, 13, 13, 2, 2, 5, 17, 23, 3, 41, 5, 0, 5, 8, {68,75,75}, 2, 0, 1, 6, 7 }, // Danish/Latin/Greenland - { 30, 7, 151, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 14, 3374, 13, 0, 680, 680, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 0, 10, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Netherlands - { 30, 7, 12, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 148, 3392, 13, 0, 680, 690, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 54, 5, 0, 10, 5, {65,87,71}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Aruba - { 30, 7, 21, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 46, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 14, 3374, 13, 0, 680, 695, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 0, 10, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Belgium - { 30, 7, 152, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 152, 3446, 13, 0, 680, 701, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 96, 5, 0, 10, 7, {65,78,71}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Cura Sao - { 30, 7, 202, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 6, 3542, 13, 0, 680, 708, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 57, 5, 0, 10, 8, {83,82,68}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Suriname - { 30, 7, 255, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 6, 3599, 13, 0, 680, 716, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 60, 5, 0, 10, 19, {85,83,68}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Bonaire - { 30, 7, 256, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 152, 3446, 13, 0, 680, 735, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 96, 5, 0, 10, 12, {65,78,71}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Sint Maarten - { 31, 7, 225, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 0, 747, 763, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 0, 16, 13, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/United States + { 27, 7, 54, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 439, 54, 0, 1982, 1982, 2039, 2039, 2066, 2079, 0, 0, 315, 5, 22, 138, 3123, 19, 0, 613, 621, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 13, 12, 5, 57, 57, 27, 27, 13, 13, 2, 2, 7, 17, 23, 3, 59, 5, 0, 8, 8, {72,82,75}, 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia + { 27, 7, 27, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 452, 54, 0, 1982, 1982, 2039, 2039, 2079, 2079, 0, 0, 315, 5, 22, 141, 3182, 19, 0, 613, 629, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 9, 12, 5, 57, 57, 27, 27, 13, 13, 2, 2, 7, 17, 23, 2, 84, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Croatian/Latin/Bosnia And Herzegowina + { 28, 7, 57, 0, 0, 183, 183, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 46, 12, 461, 166, 1, 1, 2092, 2092, 2140, 2140, 2160, 2160, 60, 57, 322, 5, 22, 143, 3266, 19, 0, 648, 655, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 9, 4, 48, 48, 20, 20, 13, 13, 4, 4, 5, 17, 23, 2, 67, 5, 0, 7, 5, {67,90,75}, 2, 0, 1, 6, 7 }, // Czech/Latin/Czech Republic + { 29, 7, 58, 0, 0, 190, 190, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 478, 501, 166, 166, 2173, 2173, 2223, 2250, 2284, 2284, 0, 0, 0, 5, 22, 145, 3333, 19, 0, 660, 665, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 50, 50, 27, 34, 13, 13, 2, 2, 5, 17, 23, 3, 41, 5, 0, 5, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // Danish/Latin/Denmark + { 29, 7, 86, 0, 0, 190, 190, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 478, 501, 166, 166, 2173, 2173, 2223, 2250, 2284, 2284, 0, 0, 0, 5, 22, 145, 3333, 19, 0, 660, 672, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 50, 50, 27, 34, 13, 13, 2, 2, 5, 17, 23, 3, 41, 5, 0, 5, 8, {68,75,75}, 2, 0, 1, 6, 7 }, // Danish/Latin/Greenland + { 30, 7, 151, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 14, 3374, 8, 37, 680, 680, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 7, 10, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Netherlands + { 30, 7, 12, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 148, 3392, 8, 37, 680, 690, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 54, 5, 7, 10, 5, {65,87,71}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Aruba + { 30, 7, 21, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 46, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 14, 3374, 8, 37, 680, 695, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 7, 10, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Belgium + { 30, 7, 152, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 152, 3446, 8, 37, 680, 701, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 96, 5, 7, 10, 7, {65,78,71}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Cura Sao + { 30, 7, 202, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 6, 3542, 8, 37, 680, 708, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 57, 5, 7, 10, 8, {83,82,68}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Suriname + { 30, 7, 255, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 6, 3599, 8, 37, 680, 716, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 1, 60, 5, 7, 10, 19, {85,83,68}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Bonaire + { 30, 7, 256, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 97, 511, 0, 0, 2297, 2297, 2355, 2355, 2375, 2375, 64, 61, 0, 5, 22, 152, 3446, 8, 37, 680, 735, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 58, 58, 20, 20, 13, 13, 4, 4, 4, 17, 23, 4, 96, 5, 7, 10, 12, {65,78,71}, 2, 1, 1, 6, 7 }, // Dutch/Latin/Sint Maarten + { 31, 7, 225, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 747, 763, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 16, 13, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/United States { 31, 3, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 156, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Deseret/United States - { 31, 7, 4, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 0, 756, 776, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 0, 7, 14, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/American Samoa - { 31, 7, 7, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 0, 756, 790, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 0, 7, 8, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Anguilla - { 31, 7, 9, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 0, 756, 798, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 0, 7, 17, {88,67,68}, 2, 1, 7, 6, 7 }, // English/Latin/Antigua And Barbuda - { 31, 7, 13, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 0, 259, 10, 22, 0, 0, 56, 56, 2388, 2388, 68, 65, 0, 5, 22, 6, 3763, 4, 0, 815, 815, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 27, 27, 24, 24, 2, 2, 5, 17, 23, 1, 58, 4, 0, 18, 9, {65,85,68}, 2, 1, 7, 6, 7 }, // English/Latin/Australia + { 31, 7, 4, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 776, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 14, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/American Samoa + { 31, 7, 7, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 790, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 8, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Anguilla + { 31, 7, 9, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 798, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 17, {88,67,68}, 2, 1, 7, 6, 7 }, // English/Latin/Antigua And Barbuda + { 31, 7, 13, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 0, 259, 10, 22, 0, 0, 56, 56, 2388, 2388, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 815, 815, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 27, 27, 24, 24, 2, 2, 5, 17, 23, 1, 58, 4, 6, 18, 9, {65,85,68}, 2, 1, 7, 6, 7 }, // English/Latin/Australia { 31, 7, 14, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 8, 0, 756, 833, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Austria - { 31, 7, 16, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3840, 4, 0, 756, 840, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 0, 7, 7, {66,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Bahamas - { 31, 7, 19, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3892, 4, 0, 756, 847, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 55, 4, 0, 7, 8, {66,66,68}, 2, 1, 1, 6, 7 }, // English/Latin/Barbados - { 31, 7, 21, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 13, 0, 756, 855, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Belgium - { 31, 7, 22, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3947, 4, 0, 756, 862, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 46, 4, 0, 7, 6, {66,90,68}, 2, 1, 7, 6, 7 }, // English/Latin/Belize - { 31, 7, 24, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3993, 4, 0, 756, 868, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 0, 7, 7, {66,77,68}, 2, 1, 1, 6, 7 }, // English/Latin/Bermuda - { 31, 7, 28, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 136, 4045, 4, 0, 756, 875, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 0, 7, 8, {66,87,80}, 2, 1, 7, 6, 7 }, // English/Latin/Botswana - { 31, 7, 31, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 0, 756, 883, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 0, 7, 30, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/British Indian Ocean Territory - { 31, 7, 35, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 0, 0, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 159, 4094, 4, 0, 756, 913, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 52, 4, 0, 7, 7, {66,73,70}, 0, 0, 1, 6, 7 }, // English/Latin/Burundi - { 31, 7, 37, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 32, 4146, 4, 0, 756, 920, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 82, 4, 0, 7, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // English/Latin/Cameroon - { 31, 7, 38, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 27, 70, 10, 22, 0, 0, 2412, 2412, 83, 83, 64, 61, 0, 5, 22, 6, 4228, 4, 0, 928, 944, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 12, 7, 56, 56, 34, 34, 13, 13, 4, 4, 5, 17, 23, 1, 52, 4, 0, 16, 6, {67,65,68}, 2, 0, 7, 6, 7 }, // English/Latin/Canada - { 31, 7, 40, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4280, 4, 0, 756, 950, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 0, 7, 14, {75,89,68}, 2, 1, 1, 6, 7 }, // English/Latin/Cayman Islands - { 31, 7, 45, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 0, 756, 964, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 0, 7, 16, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Christmas Island - { 31, 7, 46, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 0, 756, 980, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 0, 7, 23, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Cocos Islands - { 31, 7, 51, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 0, 756, 1003, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 0, 7, 12, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Cook Islands - { 31, 7, 56, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 4, 0, 756, 1015, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 4, 0, 7, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Cyprus - { 31, 7, 58, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 166, 166, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 145, 4411, 13, 0, 756, 1021, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 43, 5, 0, 7, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // English/Latin/Denmark - { 31, 7, 60, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 0, 756, 1028, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 0, 7, 8, {88,67,68}, 2, 1, 7, 6, 7 }, // English/Latin/Dominica - { 31, 7, 67, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 39, 4454, 4, 0, 756, 1036, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 49, 4, 0, 7, 7, {69,82,78}, 2, 1, 1, 6, 7 }, // English/Latin/Eritrea - { 31, 7, 70, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4503, 4, 0, 756, 1043, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 73, 4, 0, 7, 16, {70,75,80}, 2, 1, 1, 6, 7 }, // English/Latin/Falkland Islands - { 31, 7, 72, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4576, 4, 0, 756, 1059, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 46, 4, 0, 7, 4, {70,74,68}, 2, 1, 1, 6, 7 }, // English/Latin/Fiji - { 31, 7, 73, 0, 0, 208, 208, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 176, 167, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 13, 0, 756, 1063, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 9, 4, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Finland - { 31, 7, 75, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4622, 4, 0, 756, 1070, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 31, 4, 0, 7, 8, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/Guernsey - { 31, 7, 80, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 162, 4653, 4, 0, 756, 1078, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 0, 7, 6, {71,77,68}, 2, 1, 1, 6, 7 }, // English/Latin/Gambia - { 31, 7, 82, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 13, 0, 756, 1084, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Germany - { 31, 7, 83, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 163, 4702, 4, 0, 756, 1091, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 46, 4, 0, 7, 5, {71,72,83}, 2, 1, 1, 6, 7 }, // English/Latin/Ghana - { 31, 7, 84, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4748, 4, 0, 756, 1096, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 0, 7, 9, {71,73,80}, 2, 1, 1, 6, 7 }, // English/Latin/Gibraltar - { 31, 7, 87, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 0, 756, 1105, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 0, 7, 7, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Grenada - { 31, 7, 89, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 0, 756, 1112, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 0, 7, 4, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Guam - { 31, 7, 93, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4800, 4, 0, 756, 1116, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 55, 4, 0, 7, 6, {71,89,68}, 2, 0, 1, 6, 7 }, // English/Latin/Guyana - { 31, 7, 97, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 398, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 131, 4855, 4, 0, 756, 1122, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 55, 4, 0, 7, 19, {72,75,68}, 2, 1, 7, 6, 7 }, // English/Latin/Hong Kong - { 31, 7, 100, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 119, 4910, 4, 0, 756, 891, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 43, 4, 0, 7, 5, {73,78,82}, 2, 1, 7, 7, 7 }, // English/Latin/India - { 31, 7, 104, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0, 0, 0, 56, 56, 83, 83, 64, 61, 0, 5, 22, 14, 3821, 4, 0, 756, 1141, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 56, 56, 27, 27, 13, 13, 4, 4, 5, 17, 23, 1, 19, 4, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Ireland - { 31, 7, 105, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 1, 1, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 47, 4953, 4, 0, 756, 1148, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 9, 4, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 0, 7, 6, {73,76,83}, 2, 1, 7, 5, 6 }, // English/Latin/Israel - { 31, 7, 107, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5014, 4, 0, 756, 1154, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 0, 7, 7, {74,77,68}, 2, 1, 7, 6, 7 }, // English/Latin/Jamaica - { 31, 7, 111, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 2, 5066, 4, 0, 756, 1161, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 52, 4, 0, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // English/Latin/Kenya - { 31, 7, 112, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 0, 756, 1166, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 0, 7, 8, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Kiribati - { 31, 7, 120, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 5, 5118, 4, 0, 756, 1174, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 60, 4, 0, 7, 7, {90,65,82}, 2, 1, 1, 6, 7 }, // English/Latin/Lesotho - { 31, 7, 121, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5178, 4, 0, 756, 1181, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 0, 7, 7, {76,82,68}, 2, 1, 1, 6, 7 }, // English/Latin/Liberia - { 31, 7, 126, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 134, 5230, 4, 0, 756, 1188, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 52, 4, 0, 7, 15, {77,79,80}, 2, 1, 7, 6, 7 }, // English/Latin/Macau - { 31, 7, 128, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 166, 5282, 4, 0, 756, 1203, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 53, 4, 0, 7, 10, {77,71,65}, 0, 0, 1, 6, 7 }, // English/Latin/Madagascar - { 31, 7, 129, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 142, 5335, 4, 0, 756, 1213, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 52, 4, 0, 7, 6, {77,87,75}, 2, 1, 1, 6, 7 }, // English/Latin/Malawi - { 31, 7, 130, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 168, 5387, 4, 0, 756, 1219, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 58, 4, 0, 7, 8, {77,89,82}, 2, 1, 1, 6, 7 }, // English/Latin/Malaysia - { 31, 7, 133, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 4, 0, 756, 1227, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 4, 0, 7, 5, {69,85,82}, 2, 1, 7, 6, 7 }, // English/Latin/Malta - { 31, 7, 134, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 0, 756, 1232, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 0, 7, 16, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Marshall Islands - { 31, 7, 137, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 170, 5445, 4, 0, 756, 1248, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 52, 4, 0, 7, 9, {77,85,82}, 2, 0, 1, 6, 7 }, // English/Latin/Mauritius - { 31, 7, 140, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 0, 756, 1257, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 0, 7, 10, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Micronesia - { 31, 7, 144, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 0, 756, 1267, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 0, 7, 10, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Montserrat - { 31, 7, 148, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5497, 4, 0, 756, 1277, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 0, 7, 7, {78,65,68}, 2, 1, 1, 6, 7 }, // English/Latin/Namibia - { 31, 7, 149, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 0, 756, 1284, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 0, 7, 5, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Nauru - { 31, 7, 151, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 8, 23, 756, 1289, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 6, 7, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Netherlands - { 31, 7, 154, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 46, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 0, 756, 1300, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 0, 7, 11, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/New Zealand - { 31, 7, 157, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 172, 5549, 4, 0, 756, 1311, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 0, 7, 7, {78,71,78}, 2, 1, 1, 6, 7 }, // English/Latin/Nigeria - { 31, 7, 158, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 0, 756, 1318, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 0, 7, 4, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Niue - { 31, 7, 159, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 0, 756, 1322, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 0, 7, 14, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Norfolk Island - { 31, 7, 160, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 0, 756, 1336, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 0, 7, 24, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Northern Mariana Islands - { 31, 7, 163, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 170, 5598, 4, 0, 756, 1360, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 52, 4, 0, 7, 8, {80,75,82}, 2, 0, 7, 6, 7 }, // English/Latin/Pakistan - { 31, 7, 164, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 0, 756, 1368, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 0, 7, 5, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Palau - { 31, 7, 167, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 2, 5650, 4, 0, 756, 1373, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 72, 4, 0, 7, 16, {80,71,75}, 2, 1, 1, 6, 7 }, // English/Latin/Papua New Guinea - { 31, 7, 170, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 173, 5722, 4, 0, 756, 1389, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 0, 7, 11, {80,72,80}, 2, 1, 7, 6, 7 }, // English/Latin/Philippines - { 31, 7, 171, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 0, 756, 1400, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 0, 7, 16, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Pitcairn - { 31, 7, 174, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 0, 756, 1416, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 0, 7, 11, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Puerto Rico - { 31, 7, 179, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 174, 5774, 4, 0, 756, 1427, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 46, 4, 0, 7, 6, {82,87,70}, 0, 0, 1, 6, 7 }, // English/Latin/Rwanda - { 31, 7, 180, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 0, 756, 1433, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 0, 7, 16, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Kitts And Nevis - { 31, 7, 181, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 0, 756, 1449, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 0, 7, 8, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Lucia - { 31, 7, 182, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 0, 756, 1457, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 0, 7, 23, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Vincent And The Grenadines - { 31, 7, 183, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 176, 5820, 4, 0, 756, 785, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 39, 4, 0, 7, 5, {87,83,84}, 2, 1, 7, 6, 7 }, // English/Latin/Samoa - { 31, 7, 188, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 179, 5859, 4, 0, 756, 1480, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 58, 4, 0, 7, 10, {83,67,82}, 2, 1, 1, 6, 7 }, // English/Latin/Seychelles - { 31, 7, 189, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 7, 5917, 4, 0, 756, 1490, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 67, 4, 0, 7, 12, {83,76,76}, 0, 0, 1, 6, 7 }, // English/Latin/Sierra Leone - { 31, 7, 190, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5984, 4, 0, 756, 1502, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 55, 4, 0, 7, 9, {83,71,68}, 2, 1, 7, 6, 7 }, // English/Latin/Singapore - { 31, 7, 192, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 6, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 13, 29, 756, 1511, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 7, 7, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Slovenia - { 31, 7, 193, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 6039, 4, 0, 756, 1519, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 73, 4, 0, 7, 15, {83,66,68}, 2, 1, 1, 6, 7 }, // English/Latin/Solomon Islands - { 31, 7, 195, 0, 0, 208, 208, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 545, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 5, 5118, 4, 0, 756, 1534, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 60, 4, 0, 7, 12, {90,65,82}, 2, 1, 7, 6, 7 }, // English/Latin/South Africa - { 31, 7, 199, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 6112, 4, 0, 756, 1546, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 0, 7, 9, {83,72,80}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Helena - { 31, 7, 201, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 6164, 4, 0, 756, 1555, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 49, 4, 0, 7, 5, {83,68,71}, 2, 1, 6, 5, 6 }, // English/Latin/Sudan - { 31, 7, 204, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 181, 6213, 4, 0, 756, 1560, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 0, 7, 8, {83,90,76}, 2, 1, 1, 6, 7 }, // English/Latin/Swaziland - { 31, 7, 205, 0, 0, 208, 208, 6, 1, 14, 2, 3, 4, 5, 47, 10, 11, 12, 13, 0, 70, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 145, 6265, 13, 0, 756, 1568, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 46, 5, 0, 7, 6, {83,69,75}, 2, 0, 1, 6, 7 }, // English/Latin/Sweden - { 31, 7, 206, 0, 0, 208, 208, 6, 0, 13, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 6311, 8, 36, 756, 1574, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 40, 5, 5, 7, 11, {67,72,70}, 2, 0, 1, 6, 7 }, // English/Latin/Switzerland - { 31, 7, 210, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 182, 6351, 4, 0, 756, 1585, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 61, 4, 0, 7, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // English/Latin/Tanzania - { 31, 7, 213, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 0, 756, 1593, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 0, 7, 7, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Tokelau - { 31, 7, 214, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 185, 6412, 4, 0, 756, 1600, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 48, 4, 0, 7, 5, {84,79,80}, 2, 1, 1, 6, 7 }, // English/Latin/Tonga - { 31, 7, 215, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 6460, 4, 0, 756, 1605, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 79, 4, 0, 7, 17, {84,84,68}, 2, 1, 7, 6, 7 }, // English/Latin/Trinidad And Tobago - { 31, 7, 219, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 0, 756, 1622, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 0, 7, 22, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Turks And Caicos Islands - { 31, 7, 220, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 0, 756, 1644, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 0, 7, 6, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Tuvalu - { 31, 7, 221, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 187, 6539, 4, 0, 756, 1650, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 55, 4, 0, 7, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // English/Latin/Uganda - { 31, 7, 223, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 190, 6594, 4, 0, 756, 1656, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 54, 4, 0, 7, 20, {65,69,68}, 2, 1, 6, 5, 6 }, // English/Latin/United Arab Emirates - { 31, 7, 224, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 6648, 4, 0, 1676, 1691, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 46, 4, 0, 15, 14, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/United Kingdom - { 31, 7, 226, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 0, 756, 1705, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 0, 7, 21, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/United States Minor Outlying Islands - { 31, 7, 229, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 193, 6694, 4, 0, 756, 1726, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 43, 4, 0, 7, 7, {86,85,86}, 0, 0, 1, 6, 7 }, // English/Latin/Vanuatu - { 31, 7, 233, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 0, 756, 1733, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 0, 7, 22, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/British Virgin Islands - { 31, 7, 234, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 0, 756, 1755, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 0, 7, 19, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/United States Virgin Islands - { 31, 7, 239, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 2, 6737, 4, 0, 756, 1774, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 0, 7, 6, {90,77,87}, 2, 1, 1, 6, 7 }, // English/Latin/Zambia - { 31, 7, 240, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 398, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 0, 756, 1780, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 0, 7, 8, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Zimbabwe - { 31, 7, 249, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 0, 756, 1788, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 0, 7, 12, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Diego Garcia - { 31, 7, 251, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4622, 4, 0, 756, 1800, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 31, 4, 0, 7, 11, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/Isle Of Man - { 31, 7, 252, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4622, 4, 0, 756, 1811, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 31, 4, 0, 7, 6, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/Jersey - { 31, 7, 254, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 6786, 4, 0, 756, 1817, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 67, 4, 0, 7, 11, {83,83,80}, 2, 1, 1, 6, 7 }, // English/Latin/South Sudan - { 31, 7, 256, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 152, 6853, 4, 0, 756, 1828, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 94, 4, 0, 7, 12, {65,78,71}, 2, 1, 1, 6, 7 }, // English/Latin/Sint Maarten - { 31, 7, 260, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 0, 4, 0, 756, 1840, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 4, 0, 7, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // English/Latin/World - { 31, 7, 261, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 0, 13, 0, 756, 1845, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 5, 0, 7, 6, {0,0,0}, 2, 1, 1, 6, 7 }, // English/Latin/Europe - { 32, 7, 260, 0, 0, 217, 217, 6, 1, 14, 2, 3, 38, 5, 9, 10, 11, 12, 13, 555, 72, 185, 0, 2446, 2446, 2496, 2496, 2516, 2516, 70, 67, 327, 5, 22, 0, 0, 41, 0, 1851, 1860, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 8, 25, 5, 50, 50, 20, 20, 13, 13, 3, 3, 6, 17, 23, 0, 0, 6, 0, 9, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // Esperanto/Latin/World - { 33, 7, 68, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 47, 40, 10, 46, 12, 420, 166, 0, 0, 2529, 2529, 2591, 2591, 2591, 2591, 0, 0, 333, 5, 22, 14, 6947, 13, 0, 1865, 1870, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 13, 13, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 5, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Estonian/Latin/Estonia - { 34, 7, 71, 0, 0, 190, 190, 6, 1, 0, 2, 3, 38, 5, 9, 10, 11, 12, 13, 420, 166, 0, 0, 2604, 2604, 2677, 2704, 2738, 2738, 0, 0, 339, 5, 22, 145, 6966, 13, 0, 1875, 1883, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 73, 73, 27, 34, 13, 13, 2, 2, 3, 17, 23, 2, 42, 5, 0, 8, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // Faroese/Latin/Faroe Islands - { 34, 7, 58, 0, 0, 190, 190, 6, 1, 0, 2, 3, 38, 5, 9, 10, 11, 12, 13, 420, 166, 0, 0, 2604, 2604, 2677, 2704, 2738, 2738, 0, 0, 339, 5, 22, 145, 6966, 13, 0, 1875, 665, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 73, 73, 27, 34, 13, 13, 2, 2, 3, 17, 23, 3, 42, 5, 0, 8, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // Faroese/Latin/Denmark - { 36, 7, 73, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 9, 11, 11, 13, 13, 461, 581, 176, 167, 2751, 2817, 2897, 2897, 2917, 2917, 73, 70, 342, 347, 364, 14, 7008, 13, 0, 1890, 1895, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 9, 4, 66, 80, 20, 20, 13, 13, 3, 3, 5, 17, 23, 1, 19, 5, 0, 5, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Finnish/Latin/Finland - { 37, 7, 74, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 1908, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/France - { 37, 7, 3, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 195, 7027, 13, 0, 1900, 1914, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 0, 8, 7, {68,90,68}, 2, 1, 6, 5, 6 }, // French/Latin/Algeria - { 37, 7, 21, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 46, 210, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 1921, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 7, 23, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Belgium - { 37, 7, 23, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 13, 0, 1900, 1929, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 0, 8, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Benin - { 37, 7, 34, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 13, 0, 1900, 1934, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 0, 8, 12, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Burkina Faso - { 37, 7, 35, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 159, 7135, 13, 0, 1900, 913, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 52, 5, 0, 8, 7, {66,73,70}, 0, 0, 1, 6, 7 }, // French/Latin/Burundi - { 37, 7, 37, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 76, 73, 387, 213, 230, 32, 7187, 13, 0, 1900, 1946, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 5, 4, 6, 17, 23, 4, 55, 5, 0, 8, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Cameroon - { 37, 7, 38, 0, 0, 234, 234, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 11, 10, 97, 70, 233, 233, 2930, 2930, 2981, 2981, 3015, 3015, 64, 61, 387, 213, 230, 6, 7242, 47, 0, 1954, 944, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 24, 9, 51, 51, 34, 34, 13, 13, 4, 4, 6, 17, 23, 1, 53, 6, 0, 17, 6, {67,65,68}, 2, 0, 7, 6, 7 }, // French/Latin/Canada - { 37, 7, 41, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 13, 0, 1900, 1971, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 0, 8, 25, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Central African Republic - { 37, 7, 42, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 13, 0, 1900, 1996, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 0, 8, 5, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Chad - { 37, 7, 48, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7295, 13, 0, 1900, 2001, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 0, 8, 7, {75,77,70}, 0, 0, 1, 6, 7 }, // French/Latin/Comoros - { 37, 7, 49, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7345, 13, 0, 1900, 2008, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 52, 5, 0, 8, 14, {67,68,70}, 2, 1, 1, 6, 7 }, // French/Latin/Congo Kinshasa - { 37, 7, 50, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 13, 0, 1900, 2022, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 0, 8, 17, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Congo Brazzaville - { 37, 7, 53, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 13, 0, 1900, 2039, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 0, 8, 13, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Ivory Coast - { 37, 7, 59, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 36, 7397, 13, 0, 1900, 2052, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 56, 5, 0, 8, 8, {68,74,70}, 0, 0, 6, 6, 7 }, // French/Latin/Djibouti - { 37, 7, 66, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 13, 0, 1900, 2060, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 0, 8, 18, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Equatorial Guinea - { 37, 7, 76, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2078, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 16, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/French Guiana - { 37, 7, 77, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 197, 7453, 13, 0, 1900, 2094, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 34, 5, 0, 8, 19, {88,80,70}, 0, 0, 1, 6, 7 }, // French/Latin/French Polynesia - { 37, 7, 79, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 13, 0, 1900, 2113, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 0, 8, 5, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Gabon - { 37, 7, 88, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2118, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Guadeloupe - { 37, 7, 91, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 201, 7487, 13, 0, 1900, 2060, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 47, 5, 0, 8, 6, {71,78,70}, 0, 0, 1, 6, 7 }, // French/Latin/Guinea - { 37, 7, 94, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 163, 7534, 13, 0, 1900, 2128, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 56, 5, 0, 8, 5, {72,84,71}, 2, 1, 1, 6, 7 }, // French/Latin/Haiti - { 37, 7, 125, 0, 0, 234, 234, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2133, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Luxembourg - { 37, 7, 128, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 166, 7590, 13, 0, 1900, 1203, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 53, 5, 0, 8, 10, {77,71,65}, 0, 0, 1, 6, 7 }, // French/Latin/Madagascar - { 37, 7, 132, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 13, 0, 1900, 2143, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 0, 8, 4, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Mali - { 37, 7, 135, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2147, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Martinique - { 37, 7, 136, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 203, 7643, 13, 0, 1900, 2157, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 65, 5, 0, 8, 10, {77,82,85}, 2, 1, 1, 6, 7 }, // French/Latin/Mauritania - { 37, 7, 137, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 170, 7708, 13, 0, 1900, 2167, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 62, 5, 0, 8, 7, {77,85,82}, 2, 0, 1, 6, 7 }, // French/Latin/Mauritius - { 37, 7, 138, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2174, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Mayotte - { 37, 7, 142, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2181, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Monaco - { 37, 7, 145, 0, 0, 234, 234, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 64, 61, 387, 213, 230, 205, 7770, 13, 0, 1900, 2187, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 4, 4, 6, 17, 23, 3, 53, 5, 0, 8, 5, {77,65,68}, 2, 1, 1, 6, 7 }, // French/Latin/Morocco - { 37, 7, 153, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 197, 7453, 13, 0, 1900, 2192, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 34, 5, 0, 8, 18, {88,80,70}, 0, 0, 1, 6, 7 }, // French/Latin/New Caledonia - { 37, 7, 156, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 13, 0, 1900, 1311, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 0, 8, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Niger - { 37, 7, 176, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2210, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Reunion - { 37, 7, 179, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 174, 7823, 13, 0, 1900, 1427, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 49, 5, 0, 8, 6, {82,87,70}, 0, 0, 1, 6, 7 }, // French/Latin/Rwanda - { 37, 7, 187, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 13, 0, 1900, 2220, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 0, 8, 7, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Senegal - { 37, 7, 188, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 179, 7872, 13, 0, 1900, 1480, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 70, 5, 0, 8, 10, {83,67,82}, 2, 1, 1, 6, 7 }, // French/Latin/Seychelles - { 37, 7, 200, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2227, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 24, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Saint Pierre And Miquelon - { 37, 7, 206, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 17, 18, 0, 166, 257, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 208, 7942, 13, 0, 2251, 2266, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 14, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 44, 5, 0, 15, 6, {67,72,70}, 2, 0, 1, 6, 7 }, // French/Latin/Switzerland - { 37, 7, 207, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 211, 7986, 13, 0, 1900, 2272, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 0, 8, 5, {83,89,80}, 0, 0, 6, 5, 6 }, // French/Latin/Syria - { 37, 7, 212, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 13, 0, 1900, 2277, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 0, 8, 4, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Togo - { 37, 7, 216, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 213, 8036, 13, 0, 1900, 2281, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 0, 8, 7, {84,78,68}, 3, 0, 1, 6, 7 }, // French/Latin/Tunisia - { 37, 7, 229, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 193, 8086, 13, 0, 1900, 1726, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 0, 8, 7, {86,85,86}, 0, 0, 1, 6, 7 }, // French/Latin/Vanuatu - { 37, 7, 235, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 197, 7453, 13, 0, 1900, 2288, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 34, 5, 0, 8, 16, {88,80,70}, 0, 0, 1, 6, 7 }, // French/Latin/Wallis And Futuna Islands - { 37, 7, 244, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2304, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 16, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Saint Barthelemy - { 37, 7, 245, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 13, 0, 1900, 2320, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 0, 8, 12, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Saint Martin - { 38, 7, 151, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 347, 0, 0, 3028, 3028, 3081, 3081, 83, 83, 0, 0, 0, 5, 22, 14, 3374, 8, 53, 2332, 2337, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 53, 53, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 6, 5, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // Western Frisian/Latin/Netherlands - { 39, 7, 224, 0, 0, 242, 242, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 589, 45, 0, 0, 3101, 3101, 3169, 3169, 3196, 3196, 5, 77, 393, 5, 22, 117, 8136, 4, 0, 2345, 2353, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 10, 10, 5, 68, 68, 27, 27, 13, 13, 1, 1, 6, 17, 23, 1, 85, 4, 0, 8, 22, {71,66,80}, 2, 1, 1, 6, 7 }, // Gaelic/Latin/United Kingdom - { 40, 7, 197, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 45, 0, 0, 3209, 3257, 3305, 3339, 3373, 3386, 64, 61, 0, 5, 22, 14, 3032, 13, 0, 2375, 2381, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 48, 48, 34, 34, 13, 20, 4, 4, 5, 17, 23, 1, 19, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Galician/Latin/Spain - { 41, 15, 81, 0, 0, 259, 259, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 15, 16, 637, 166, 0, 0, 3406, 3406, 3467, 3467, 3494, 3494, 0, 0, 399, 404, 22, 215, 8221, 13, 0, 2387, 2394, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 10, 5, 61, 61, 27, 27, 13, 13, 2, 2, 5, 37, 23, 1, 42, 5, 0, 7, 10, {71,69,76}, 2, 1, 1, 6, 7 }, // Georgian/Georgian/Georgia - { 42, 7, 82, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 13, 0, 2404, 2411, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Germany - { 42, 7, 14, 0, 0, 267, 267, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 8, 0, 2422, 2422, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 24, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Austria - { 42, 7, 21, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 13, 0, 2404, 2446, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Belgium - { 42, 7, 106, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 13, 0, 2404, 2453, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Italy - { 42, 7, 123, 0, 0, 267, 267, 6, 0, 13, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 208, 8281, 8, 0, 2404, 2460, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 3, 57, 5, 0, 7, 13, {67,72,70}, 2, 0, 1, 6, 7 }, // German/Latin/Liechtenstein - { 42, 7, 125, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 13, 0, 2404, 2473, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Luxembourg - { 42, 7, 206, 0, 0, 267, 267, 6, 0, 13, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 208, 8281, 8, 36, 2482, 2482, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 3, 57, 5, 5, 21, 7, {67,72,70}, 2, 0, 1, 6, 7 }, // German/Latin/Switzerland - { 43, 16, 85, 0, 0, 276, 276, 6, 1, 0, 2, 3, 4, 5, 6, 15, 16, 10, 11, 0, 259, 10, 22, 3626, 3626, 3680, 3680, 3707, 3707, 81, 78, 0, 5, 22, 14, 8338, 13, 0, 2503, 2511, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 54, 54, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Greek/Greek/Greece - { 43, 16, 56, 0, 0, 276, 276, 6, 1, 0, 2, 3, 4, 5, 6, 15, 16, 10, 11, 0, 259, 10, 22, 3626, 3626, 3680, 3680, 3707, 3707, 81, 78, 0, 5, 22, 14, 8338, 13, 0, 2503, 2517, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 54, 54, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Greek/Greek/Cyprus - { 44, 7, 86, 0, 0, 285, 285, 6, 1, 0, 2, 3, 38, 5, 47, 16, 15, 18, 17, 80, 70, 166, 166, 3720, 3720, 3817, 3817, 3844, 3844, 0, 0, 0, 5, 22, 145, 8356, 4, 59, 2523, 2534, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 97, 97, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 61, 4, 5, 11, 16, {68,75,75}, 2, 0, 1, 6, 7 }, // Greenlandic/Latin/Greenland + { 31, 7, 16, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3840, 4, 13, 756, 840, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {66,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Bahamas + { 31, 7, 19, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3892, 4, 13, 756, 847, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 55, 4, 6, 7, 8, {66,66,68}, 2, 1, 1, 6, 7 }, // English/Latin/Barbados + { 31, 7, 21, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 19, 0, 756, 855, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Belgium + { 31, 7, 22, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3947, 4, 13, 756, 862, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 46, 4, 6, 7, 6, {66,90,68}, 2, 1, 7, 6, 7 }, // English/Latin/Belize + { 31, 7, 24, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3993, 4, 13, 756, 868, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {66,77,68}, 2, 1, 1, 6, 7 }, // English/Latin/Bermuda + { 31, 7, 28, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 136, 4045, 4, 13, 756, 875, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 6, 7, 8, {66,87,80}, 2, 1, 7, 6, 7 }, // English/Latin/Botswana + { 31, 7, 31, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 883, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 30, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/British Indian Ocean Territory + { 31, 7, 35, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 0, 0, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 159, 4094, 4, 13, 756, 913, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 52, 4, 6, 7, 7, {66,73,70}, 0, 0, 1, 6, 7 }, // English/Latin/Burundi + { 31, 7, 37, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 32, 4146, 4, 13, 756, 920, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 82, 4, 6, 7, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // English/Latin/Cameroon + { 31, 7, 38, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 27, 70, 10, 22, 0, 0, 2412, 2412, 83, 83, 64, 61, 0, 5, 22, 6, 4228, 4, 13, 928, 944, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 12, 7, 56, 56, 34, 34, 13, 13, 4, 4, 5, 17, 23, 1, 52, 4, 6, 16, 6, {67,65,68}, 2, 0, 7, 6, 7 }, // English/Latin/Canada + { 31, 7, 40, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4280, 4, 13, 756, 950, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 14, {75,89,68}, 2, 1, 1, 6, 7 }, // English/Latin/Cayman Islands + { 31, 7, 45, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 964, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 16, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Christmas Island + { 31, 7, 46, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 980, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 23, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Cocos Islands + { 31, 7, 51, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1003, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 12, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Cook Islands + { 31, 7, 56, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 4, 13, 756, 1015, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 4, 6, 7, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Cyprus + { 31, 7, 58, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 166, 166, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 145, 4411, 19, 0, 756, 1021, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 43, 5, 0, 7, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // English/Latin/Denmark + { 31, 7, 60, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1028, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 8, {88,67,68}, 2, 1, 7, 6, 7 }, // English/Latin/Dominica + { 31, 7, 67, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 39, 4454, 4, 13, 756, 1036, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 49, 4, 6, 7, 7, {69,82,78}, 2, 1, 1, 6, 7 }, // English/Latin/Eritrea + { 31, 7, 70, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4503, 4, 13, 756, 1043, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 73, 4, 6, 7, 16, {70,75,80}, 2, 1, 1, 6, 7 }, // English/Latin/Falkland Islands + { 31, 7, 72, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4576, 4, 13, 756, 1059, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 46, 4, 6, 7, 4, {70,74,68}, 2, 1, 1, 6, 7 }, // English/Latin/Fiji + { 31, 7, 73, 0, 0, 208, 208, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 176, 167, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 19, 0, 756, 1063, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 9, 4, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Finland + { 31, 7, 75, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4622, 4, 13, 756, 1070, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 31, 4, 6, 7, 8, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/Guernsey + { 31, 7, 80, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 162, 4653, 4, 13, 756, 1078, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 6, 7, 6, {71,77,68}, 2, 1, 1, 6, 7 }, // English/Latin/Gambia + { 31, 7, 82, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 19, 0, 756, 1084, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Germany + { 31, 7, 83, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 163, 4702, 4, 13, 756, 1091, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 46, 4, 6, 7, 5, {71,72,83}, 2, 1, 1, 6, 7 }, // English/Latin/Ghana + { 31, 7, 84, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4748, 4, 13, 756, 1096, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 9, {71,73,80}, 2, 1, 1, 6, 7 }, // English/Latin/Gibraltar + { 31, 7, 87, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1105, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 7, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Grenada + { 31, 7, 89, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1112, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 4, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Guam + { 31, 7, 93, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4800, 4, 13, 756, 1116, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 55, 4, 6, 7, 6, {71,89,68}, 2, 0, 1, 6, 7 }, // English/Latin/Guyana + { 31, 7, 97, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 398, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 131, 4855, 4, 13, 756, 1122, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 55, 4, 6, 7, 19, {72,75,68}, 2, 1, 7, 6, 7 }, // English/Latin/Hong Kong + { 31, 7, 100, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 119, 4910, 4, 13, 756, 891, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 43, 4, 6, 7, 5, {73,78,82}, 2, 1, 7, 7, 7 }, // English/Latin/India + { 31, 7, 104, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0, 0, 0, 56, 56, 83, 83, 64, 61, 0, 5, 22, 14, 3821, 4, 13, 756, 1141, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 56, 56, 27, 27, 13, 13, 4, 4, 5, 17, 23, 1, 19, 4, 6, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Ireland + { 31, 7, 105, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 1, 1, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 47, 4953, 4, 13, 756, 1148, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 9, 4, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 6, {73,76,83}, 2, 1, 7, 5, 6 }, // English/Latin/Israel + { 31, 7, 107, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5014, 4, 13, 756, 1154, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {74,77,68}, 2, 1, 7, 6, 7 }, // English/Latin/Jamaica + { 31, 7, 111, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 2, 5066, 4, 13, 756, 1161, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 52, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // English/Latin/Kenya + { 31, 7, 112, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 1166, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 8, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Kiribati + { 31, 7, 120, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 5, 5118, 4, 13, 756, 1174, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 60, 4, 6, 7, 7, {90,65,82}, 2, 1, 1, 6, 7 }, // English/Latin/Lesotho + { 31, 7, 121, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5178, 4, 13, 756, 1181, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {76,82,68}, 2, 1, 1, 6, 7 }, // English/Latin/Liberia + { 31, 7, 126, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 134, 5230, 4, 13, 756, 1188, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 52, 4, 6, 7, 15, {77,79,80}, 2, 1, 7, 6, 7 }, // English/Latin/Macau + { 31, 7, 128, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 166, 5282, 4, 13, 756, 1203, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 53, 4, 6, 7, 10, {77,71,65}, 0, 0, 1, 6, 7 }, // English/Latin/Madagascar + { 31, 7, 129, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 142, 5335, 4, 13, 756, 1213, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 52, 4, 6, 7, 6, {77,87,75}, 2, 1, 1, 6, 7 }, // English/Latin/Malawi + { 31, 7, 130, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 168, 5387, 4, 13, 756, 1219, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 58, 4, 6, 7, 8, {77,89,82}, 2, 1, 1, 6, 7 }, // English/Latin/Malaysia + { 31, 7, 133, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 4, 13, 756, 1227, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 4, 6, 7, 5, {69,85,82}, 2, 1, 7, 6, 7 }, // English/Latin/Malta + { 31, 7, 134, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1232, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 16, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Marshall Islands + { 31, 7, 137, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 170, 5445, 4, 13, 756, 1248, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 52, 4, 6, 7, 9, {77,85,82}, 2, 0, 1, 6, 7 }, // English/Latin/Mauritius + { 31, 7, 140, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1257, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 10, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Micronesia + { 31, 7, 144, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1267, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 10, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Montserrat + { 31, 7, 148, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5497, 4, 13, 756, 1277, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 7, {78,65,68}, 2, 1, 1, 6, 7 }, // English/Latin/Namibia + { 31, 7, 149, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 1284, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 5, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Nauru + { 31, 7, 151, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 8, 37, 756, 1289, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 7, 7, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Netherlands + { 31, 7, 154, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 46, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1300, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 11, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/New Zealand + { 31, 7, 157, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 172, 5549, 4, 13, 756, 1311, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 6, 7, 7, {78,71,78}, 2, 1, 1, 6, 7 }, // English/Latin/Nigeria + { 31, 7, 158, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1318, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 4, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Niue + { 31, 7, 159, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 1322, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 14, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Norfolk Island + { 31, 7, 160, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1336, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 24, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Northern Mariana Islands + { 31, 7, 163, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 170, 5598, 4, 13, 756, 1360, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 52, 4, 6, 7, 8, {80,75,82}, 2, 0, 7, 6, 7 }, // English/Latin/Pakistan + { 31, 7, 164, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1368, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 5, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Palau + { 31, 7, 167, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 2, 5650, 4, 13, 756, 1373, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 72, 4, 6, 7, 16, {80,71,75}, 2, 1, 1, 6, 7 }, // English/Latin/Papua New Guinea + { 31, 7, 170, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 173, 5722, 4, 13, 756, 1389, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 11, {80,72,80}, 2, 1, 7, 6, 7 }, // English/Latin/Philippines + { 31, 7, 171, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1400, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 16, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Pitcairn + { 31, 7, 174, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1416, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 11, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Puerto Rico + { 31, 7, 179, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 174, 5774, 4, 13, 756, 1427, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 46, 4, 6, 7, 6, {82,87,70}, 0, 0, 1, 6, 7 }, // English/Latin/Rwanda + { 31, 7, 180, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1433, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 16, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Kitts And Nevis + { 31, 7, 181, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1449, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 8, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Lucia + { 31, 7, 182, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3693, 4, 13, 756, 1457, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 70, 4, 6, 7, 23, {88,67,68}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Vincent And The Grenadines + { 31, 7, 183, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 176, 5820, 4, 13, 756, 785, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 39, 4, 6, 7, 5, {87,83,84}, 2, 1, 7, 6, 7 }, // English/Latin/Samoa + { 31, 7, 188, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 179, 5859, 4, 13, 756, 1480, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 58, 4, 6, 7, 10, {83,67,82}, 2, 1, 1, 6, 7 }, // English/Latin/Seychelles + { 31, 7, 189, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 7, 5917, 4, 13, 756, 1490, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 67, 4, 6, 7, 12, {83,76,76}, 0, 0, 1, 6, 7 }, // English/Latin/Sierra Leone + { 31, 7, 190, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 5984, 4, 13, 756, 1502, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 55, 4, 6, 7, 9, {83,71,68}, 2, 1, 7, 6, 7 }, // English/Latin/Singapore + { 31, 7, 192, 0, 0, 208, 208, 6, 1, 0, 2, 3, 4, 5, 6, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 14, 3821, 19, 24, 756, 1511, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 19, 5, 7, 7, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // English/Latin/Slovenia + { 31, 7, 193, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 6039, 4, 13, 756, 1519, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 73, 4, 6, 7, 15, {83,66,68}, 2, 1, 1, 6, 7 }, // English/Latin/Solomon Islands + { 31, 7, 195, 0, 0, 208, 208, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 545, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 5, 5118, 4, 13, 756, 1534, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 60, 4, 6, 7, 12, {90,65,82}, 2, 1, 7, 6, 7 }, // English/Latin/South Africa + { 31, 7, 199, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 6112, 4, 13, 756, 1546, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 9, {83,72,80}, 2, 1, 1, 6, 7 }, // English/Latin/Saint Helena + { 31, 7, 201, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 6164, 4, 13, 756, 1555, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 49, 4, 6, 7, 5, {83,68,71}, 2, 1, 6, 5, 6 }, // English/Latin/Sudan + { 31, 7, 204, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 181, 6213, 4, 13, 756, 1560, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 52, 4, 6, 7, 8, {83,90,76}, 2, 1, 1, 6, 7 }, // English/Latin/Swaziland + { 31, 7, 205, 0, 0, 208, 208, 6, 1, 14, 2, 3, 4, 5, 47, 10, 11, 12, 13, 0, 70, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 145, 6265, 19, 0, 756, 1568, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 46, 5, 0, 7, 6, {83,69,75}, 2, 0, 1, 6, 7 }, // English/Latin/Sweden + { 31, 7, 206, 0, 0, 208, 208, 6, 0, 13, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 6311, 8, 44, 756, 1574, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 40, 5, 5, 7, 11, {67,72,70}, 2, 0, 1, 6, 7 }, // English/Latin/Switzerland + { 31, 7, 210, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 182, 6351, 4, 13, 756, 1585, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 61, 4, 6, 7, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // English/Latin/Tanzania + { 31, 7, 213, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 4350, 4, 13, 756, 1593, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 61, 4, 6, 7, 7, {78,90,68}, 2, 1, 1, 6, 7 }, // English/Latin/Tokelau + { 31, 7, 214, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 185, 6412, 4, 13, 756, 1600, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 48, 4, 6, 7, 5, {84,79,80}, 2, 1, 1, 6, 7 }, // English/Latin/Tonga + { 31, 7, 215, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 6460, 4, 13, 756, 1605, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 79, 4, 6, 7, 17, {84,84,68}, 2, 1, 7, 6, 7 }, // English/Latin/Trinidad And Tobago + { 31, 7, 219, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1622, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 22, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Turks And Caicos Islands + { 31, 7, 220, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 6, 3763, 4, 13, 756, 1644, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 58, 4, 6, 7, 6, {65,85,68}, 2, 1, 1, 6, 7 }, // English/Latin/Tuvalu + { 31, 7, 221, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 187, 6539, 4, 13, 756, 1650, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 55, 4, 6, 7, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // English/Latin/Uganda + { 31, 7, 223, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 190, 6594, 4, 13, 756, 1656, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 54, 4, 6, 7, 20, {65,69,68}, 2, 1, 6, 5, 6 }, // English/Latin/United Arab Emirates + { 31, 7, 224, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 6648, 4, 13, 1676, 1691, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 46, 4, 6, 15, 14, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/United Kingdom + { 31, 7, 226, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1705, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 21, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/United States Minor Outlying Islands + { 31, 7, 229, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 193, 6694, 4, 13, 756, 1726, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 2, 43, 4, 6, 7, 7, {86,85,86}, 0, 0, 1, 6, 7 }, // English/Latin/Vanuatu + { 31, 7, 233, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1733, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 22, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/British Virgin Islands + { 31, 7, 234, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 0, 0, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 3659, 4, 13, 756, 1755, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 34, 4, 6, 7, 19, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/United States Virgin Islands + { 31, 7, 239, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 2, 6737, 4, 13, 756, 1774, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 49, 4, 6, 7, 6, {90,77,87}, 2, 1, 1, 6, 7 }, // English/Latin/Zambia + { 31, 7, 240, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 398, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1780, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 8, {85,83,68}, 2, 1, 7, 6, 7 }, // English/Latin/Zimbabwe + { 31, 7, 249, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 156, 3659, 4, 13, 756, 1788, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 3, 34, 4, 6, 7, 12, {85,83,68}, 2, 1, 1, 6, 7 }, // English/Latin/Diego Garcia + { 31, 7, 251, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4622, 4, 13, 756, 1800, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 31, 4, 6, 7, 11, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/Isle Of Man + { 31, 7, 252, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 4622, 4, 13, 756, 1811, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 31, 4, 6, 7, 6, {71,66,80}, 2, 1, 1, 6, 7 }, // English/Latin/Jersey + { 31, 7, 254, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 117, 6786, 4, 13, 756, 1817, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 67, 4, 6, 7, 11, {83,83,80}, 2, 1, 1, 6, 7 }, // English/Latin/South Sudan + { 31, 7, 256, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 152, 6853, 4, 13, 756, 1828, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 4, 94, 4, 6, 7, 12, {65,78,71}, 2, 1, 1, 6, 7 }, // English/Latin/Sint Maarten + { 31, 7, 260, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 0, 4, 13, 756, 1840, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 4, 6, 7, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // English/Latin/World + { 31, 7, 261, 0, 0, 208, 208, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 0, 0, 56, 56, 83, 83, 68, 65, 0, 5, 22, 0, 0, 19, 0, 756, 1845, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 5, 0, 7, 6, {0,0,0}, 2, 1, 1, 6, 7 }, // English/Latin/Europe + { 32, 7, 260, 0, 0, 217, 217, 6, 1, 14, 2, 3, 38, 5, 9, 10, 11, 12, 13, 555, 72, 185, 0, 2446, 2446, 2496, 2496, 2516, 2516, 70, 67, 327, 5, 22, 0, 0, 8, 0, 1851, 1860, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 8, 25, 5, 50, 50, 20, 20, 13, 13, 3, 3, 6, 17, 23, 0, 0, 5, 0, 9, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // Esperanto/Latin/World + { 33, 7, 68, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 47, 40, 10, 46, 12, 420, 166, 0, 0, 2529, 2529, 2591, 2591, 2591, 2591, 0, 0, 333, 5, 22, 14, 6947, 19, 24, 1865, 1870, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 13, 13, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 5, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Estonian/Latin/Estonia + { 34, 7, 71, 0, 0, 190, 190, 6, 1, 0, 2, 3, 38, 5, 9, 10, 11, 12, 13, 420, 166, 0, 0, 2604, 2604, 2677, 2704, 2738, 2738, 0, 0, 339, 5, 22, 145, 6966, 19, 24, 1875, 1883, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 73, 73, 27, 34, 13, 13, 2, 2, 3, 17, 23, 2, 42, 5, 7, 8, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // Faroese/Latin/Faroe Islands + { 34, 7, 58, 0, 0, 190, 190, 6, 1, 0, 2, 3, 38, 5, 9, 10, 11, 12, 13, 420, 166, 0, 0, 2604, 2604, 2677, 2704, 2738, 2738, 0, 0, 339, 5, 22, 145, 6966, 19, 24, 1875, 665, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 73, 73, 27, 34, 13, 13, 2, 2, 3, 17, 23, 3, 42, 5, 7, 8, 7, {68,75,75}, 2, 0, 1, 6, 7 }, // Faroese/Latin/Denmark + { 36, 7, 73, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 9, 11, 11, 13, 13, 461, 581, 176, 167, 2751, 2817, 2897, 2897, 2917, 2917, 73, 70, 342, 347, 364, 14, 7008, 19, 0, 1890, 1895, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 9, 4, 66, 80, 20, 20, 13, 13, 3, 3, 5, 17, 23, 1, 19, 5, 0, 5, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Finnish/Latin/Finland + { 37, 7, 74, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 1908, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/France + { 37, 7, 3, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 195, 7027, 19, 24, 1900, 1914, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 7, {68,90,68}, 2, 1, 6, 5, 6 }, // French/Latin/Algeria + { 37, 7, 21, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 46, 210, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 1921, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 7, 23, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Belgium + { 37, 7, 23, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 1929, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Benin + { 37, 7, 34, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 1934, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 12, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Burkina Faso + { 37, 7, 35, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 159, 7135, 19, 24, 1900, 913, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 52, 5, 7, 8, 7, {66,73,70}, 0, 0, 1, 6, 7 }, // French/Latin/Burundi + { 37, 7, 37, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 76, 73, 387, 213, 230, 32, 7187, 19, 24, 1900, 1946, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 5, 4, 6, 17, 23, 4, 55, 5, 7, 8, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Cameroon + { 37, 7, 38, 0, 0, 234, 234, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 11, 10, 97, 70, 233, 233, 2930, 2930, 2981, 2981, 3015, 3015, 64, 61, 387, 213, 230, 6, 7242, 19, 24, 1954, 944, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 24, 9, 51, 51, 34, 34, 13, 13, 4, 4, 6, 17, 23, 1, 53, 5, 7, 17, 6, {67,65,68}, 2, 0, 7, 6, 7 }, // French/Latin/Canada + { 37, 7, 41, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 1971, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 25, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Central African Republic + { 37, 7, 42, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 1996, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 5, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Chad + { 37, 7, 48, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7295, 19, 24, 1900, 2001, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 7, {75,77,70}, 0, 0, 1, 6, 7 }, // French/Latin/Comoros + { 37, 7, 49, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7345, 19, 24, 1900, 2008, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 52, 5, 7, 8, 14, {67,68,70}, 2, 1, 1, 6, 7 }, // French/Latin/Congo Kinshasa + { 37, 7, 50, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 2022, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 17, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Congo Brazzaville + { 37, 7, 53, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 2039, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 13, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Ivory Coast + { 37, 7, 59, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 36, 7397, 19, 24, 1900, 2052, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 56, 5, 7, 8, 8, {68,74,70}, 0, 0, 6, 6, 7 }, // French/Latin/Djibouti + { 37, 7, 66, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 2060, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 18, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Equatorial Guinea + { 37, 7, 76, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2078, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 16, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/French Guiana + { 37, 7, 77, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 197, 7453, 19, 24, 1900, 2094, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 34, 5, 7, 8, 19, {88,80,70}, 0, 0, 1, 6, 7 }, // French/Latin/French Polynesia + { 37, 7, 79, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 32, 7187, 19, 24, 1900, 2113, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 55, 5, 7, 8, 5, {88,65,70}, 0, 0, 1, 6, 7 }, // French/Latin/Gabon + { 37, 7, 88, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2118, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Guadeloupe + { 37, 7, 91, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 201, 7487, 19, 24, 1900, 2060, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 47, 5, 7, 8, 6, {71,78,70}, 0, 0, 1, 6, 7 }, // French/Latin/Guinea + { 37, 7, 94, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 163, 7534, 19, 24, 1900, 2128, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 56, 5, 7, 8, 5, {72,84,71}, 2, 1, 1, 6, 7 }, // French/Latin/Haiti + { 37, 7, 125, 0, 0, 234, 234, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2133, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Luxembourg + { 37, 7, 128, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 166, 7590, 19, 24, 1900, 1203, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 53, 5, 7, 8, 10, {77,71,65}, 0, 0, 1, 6, 7 }, // French/Latin/Madagascar + { 37, 7, 132, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 2143, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 4, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Mali + { 37, 7, 135, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2147, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Martinique + { 37, 7, 136, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 203, 7643, 19, 24, 1900, 2157, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 65, 5, 7, 8, 10, {77,82,85}, 2, 1, 1, 6, 7 }, // French/Latin/Mauritania + { 37, 7, 137, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 170, 7708, 19, 24, 1900, 2167, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 62, 5, 7, 8, 7, {77,85,82}, 2, 0, 1, 6, 7 }, // French/Latin/Mauritius + { 37, 7, 138, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2174, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Mayotte + { 37, 7, 142, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2181, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Monaco + { 37, 7, 145, 0, 0, 234, 234, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 64, 61, 387, 213, 230, 205, 7770, 19, 24, 1900, 2187, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 4, 4, 6, 17, 23, 3, 53, 5, 7, 8, 5, {77,65,68}, 2, 1, 1, 6, 7 }, // French/Latin/Morocco + { 37, 7, 153, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 197, 7453, 19, 24, 1900, 2192, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 34, 5, 7, 8, 18, {88,80,70}, 0, 0, 1, 6, 7 }, // French/Latin/New Caledonia + { 37, 7, 156, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 1311, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Niger + { 37, 7, 176, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2210, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Reunion + { 37, 7, 179, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 174, 7823, 19, 24, 1900, 1427, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 49, 5, 7, 8, 6, {82,87,70}, 0, 0, 1, 6, 7 }, // French/Latin/Rwanda + { 37, 7, 187, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 2220, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 7, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Senegal + { 37, 7, 188, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 179, 7872, 19, 24, 1900, 1480, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 70, 5, 7, 8, 10, {83,67,82}, 2, 1, 1, 6, 7 }, // French/Latin/Seychelles + { 37, 7, 200, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2227, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 24, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Saint Pierre And Miquelon + { 37, 7, 206, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 17, 18, 0, 166, 257, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 208, 7942, 19, 24, 2251, 2266, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 14, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 44, 5, 7, 15, 6, {67,72,70}, 2, 0, 1, 6, 7 }, // French/Latin/Switzerland + { 37, 7, 207, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 211, 7986, 19, 24, 1900, 2272, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 5, {83,89,80}, 0, 0, 6, 5, 6 }, // French/Latin/Syria + { 37, 7, 212, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 33, 7077, 19, 24, 1900, 2277, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 3, 58, 5, 7, 8, 4, {88,79,70}, 0, 0, 1, 6, 7 }, // French/Latin/Togo + { 37, 7, 216, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 213, 8036, 19, 24, 1900, 2281, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 7, {84,78,68}, 3, 0, 1, 6, 7 }, // French/Latin/Tunisia + { 37, 7, 229, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 10, 22, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 193, 8086, 19, 24, 1900, 1726, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 12, 7, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 2, 50, 5, 7, 8, 7, {86,85,86}, 0, 0, 1, 6, 7 }, // French/Latin/Vanuatu + { 37, 7, 235, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 197, 7453, 19, 24, 1900, 2288, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 4, 34, 5, 7, 8, 16, {88,80,70}, 0, 0, 1, 6, 7 }, // French/Latin/Wallis And Futuna Islands + { 37, 7, 244, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2304, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 16, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Saint Barthelemy + { 37, 7, 245, 0, 0, 234, 234, 6, 1, 51, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 45, 0, 0, 2930, 2930, 2981, 2981, 3015, 3015, 0, 0, 387, 213, 230, 14, 3032, 19, 24, 1900, 2320, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 51, 51, 34, 34, 13, 13, 2, 2, 6, 17, 23, 1, 19, 5, 7, 8, 12, {69,85,82}, 2, 1, 1, 6, 7 }, // French/Latin/Saint Martin + { 38, 7, 151, 0, 0, 7, 7, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 347, 0, 0, 3028, 3028, 3081, 3081, 83, 83, 0, 0, 0, 5, 22, 14, 3374, 8, 37, 2332, 2337, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 53, 53, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 7, 5, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // Western Frisian/Latin/Netherlands + { 39, 7, 224, 0, 0, 242, 242, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 589, 45, 0, 0, 3101, 3101, 3169, 3169, 3196, 3196, 5, 77, 393, 5, 22, 117, 8136, 4, 13, 2345, 2353, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 21, 10, 10, 5, 68, 68, 27, 27, 13, 13, 1, 1, 6, 17, 23, 1, 85, 4, 6, 8, 22, {71,66,80}, 2, 1, 1, 6, 7 }, // Gaelic/Latin/United Kingdom + { 40, 7, 197, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 45, 0, 0, 3209, 3257, 3305, 3339, 3373, 3386, 64, 61, 0, 5, 22, 14, 3032, 19, 0, 2375, 2381, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 48, 48, 34, 34, 13, 20, 4, 4, 5, 17, 23, 1, 19, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Galician/Latin/Spain + { 41, 15, 81, 0, 0, 259, 259, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 15, 16, 637, 166, 0, 0, 3406, 3406, 3467, 3467, 3494, 3494, 0, 0, 399, 404, 22, 215, 8221, 19, 0, 2387, 2394, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 10, 5, 61, 61, 27, 27, 13, 13, 2, 2, 5, 37, 23, 1, 42, 5, 0, 7, 10, {71,69,76}, 2, 1, 1, 6, 7 }, // Georgian/Georgian/Georgia + { 42, 7, 82, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2404, 2411, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Germany + { 42, 7, 14, 0, 0, 267, 267, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2422, 2422, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 24, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Austria + { 42, 7, 21, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2404, 2446, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Belgium + { 42, 7, 106, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2404, 2453, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Italy + { 42, 7, 123, 0, 0, 267, 267, 6, 0, 13, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 208, 8281, 19, 0, 2404, 2460, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 3, 57, 5, 0, 7, 13, {67,72,70}, 2, 0, 1, 6, 7 }, // German/Latin/Liechtenstein + { 42, 7, 125, 0, 0, 267, 267, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 14, 8263, 19, 0, 2404, 2473, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 1, 18, 5, 0, 7, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // German/Latin/Luxembourg + { 42, 7, 206, 0, 0, 267, 267, 6, 0, 13, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0, 3507, 3507, 3566, 3586, 3613, 3613, 0, 0, 441, 5, 22, 208, 8281, 19, 0, 2482, 2482, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 59, 59, 20, 27, 13, 13, 2, 2, 5, 17, 23, 3, 57, 5, 0, 21, 7, {67,72,70}, 2, 0, 1, 6, 7 }, // German/Latin/Switzerland + { 43, 16, 85, 0, 0, 276, 276, 6, 1, 0, 2, 3, 4, 5, 6, 15, 16, 10, 11, 0, 259, 10, 22, 3626, 3626, 3680, 3680, 3707, 3707, 81, 78, 0, 5, 22, 14, 8338, 19, 0, 2503, 2511, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 54, 54, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Greek/Greek/Greece + { 43, 16, 56, 0, 0, 276, 276, 6, 1, 0, 2, 3, 4, 5, 6, 15, 16, 10, 11, 0, 259, 10, 22, 3626, 3626, 3680, 3680, 3707, 3707, 81, 78, 0, 5, 22, 14, 8338, 19, 0, 2503, 2517, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 54, 54, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 18, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Greek/Greek/Cyprus + { 44, 7, 86, 0, 0, 285, 285, 6, 1, 0, 2, 3, 38, 5, 47, 16, 15, 18, 17, 80, 70, 166, 166, 3720, 3720, 3817, 3817, 3844, 3844, 0, 0, 0, 5, 22, 145, 8356, 4, 49, 2523, 2534, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 97, 97, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 61, 4, 5, 11, 16, {68,75,75}, 2, 0, 1, 6, 7 }, // Greenlandic/Latin/Greenland { 45, 7, 168, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 216, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {80,89,71}, 0, 0, 7, 6, 7 }, // Guarani/Latin/Paraguay - { 46, 17, 100, 0, 0, 296, 296, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 271, 284, 3857, 3857, 3909, 3909, 3940, 3940, 0, 0, 446, 450, 22, 119, 8417, 4, 0, 2550, 2557, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 8, 52, 52, 31, 31, 18, 18, 2, 2, 4, 19, 23, 1, 45, 4, 0, 7, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Gujarati/Gujarati/India - { 47, 7, 157, 0, 0, 305, 305, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 656, 259, 0, 0, 3958, 3958, 4009, 4009, 4036, 4036, 85, 82, 0, 5, 22, 172, 8462, 64, 0, 2561, 2566, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 51, 51, 27, 27, 13, 13, 6, 5, 4, 17, 23, 1, 53, 6, 0, 5, 8, {78,71,78}, 2, 1, 1, 6, 7 }, // Hausa/Latin/Nigeria + { 46, 17, 100, 0, 0, 296, 296, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 271, 284, 3857, 3857, 3909, 3909, 3940, 3940, 0, 0, 446, 450, 22, 119, 8417, 4, 13, 2550, 2557, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 8, 52, 52, 31, 31, 18, 18, 2, 2, 4, 19, 23, 1, 45, 4, 6, 7, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Gujarati/Gujarati/India + { 47, 7, 157, 0, 0, 305, 305, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 656, 259, 0, 0, 3958, 3958, 4009, 4009, 4036, 4036, 85, 82, 0, 5, 22, 172, 8462, 8, 0, 2561, 2566, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 51, 51, 27, 27, 13, 13, 6, 5, 4, 17, 23, 1, 53, 5, 0, 5, 8, {78,71,78}, 2, 1, 1, 6, 7 }, // Hausa/Latin/Nigeria { 47, 1, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 172, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {78,71,78}, 2, 1, 1, 6, 7 }, // Hausa/Arabic/Nigeria - { 47, 7, 83, 0, 0, 305, 305, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 656, 259, 10, 22, 3958, 3958, 4009, 4009, 4036, 4036, 85, 82, 0, 5, 22, 163, 0, 64, 0, 2561, 2574, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 51, 51, 27, 27, 13, 13, 6, 5, 4, 17, 23, 3, 0, 6, 0, 5, 4, {71,72,83}, 2, 1, 1, 6, 7 }, // Hausa/Latin/Ghana - { 47, 7, 156, 0, 0, 305, 305, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 656, 259, 0, 0, 3958, 3958, 4009, 4009, 4036, 4036, 85, 82, 0, 5, 22, 33, 8515, 64, 0, 2561, 2578, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 51, 51, 27, 27, 13, 13, 6, 5, 4, 17, 23, 3, 29, 6, 0, 5, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Hausa/Latin/Niger - { 48, 18, 105, 0, 0, 313, 313, 6, 0, 1, 2, 3, 33, 35, 9, 11, 11, 13, 13, 673, 581, 1, 1, 4049, 4049, 4113, 4113, 4158, 4158, 91, 87, 469, 5, 22, 47, 8544, 70, 76, 2583, 2588, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 18, 8, 9, 4, 64, 64, 45, 45, 20, 20, 6, 5, 4, 17, 23, 1, 53, 6, 8, 5, 5, {73,76,83}, 2, 1, 7, 5, 6 }, // Hebrew/Hebrew/Israel + { 47, 7, 83, 0, 0, 305, 305, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 656, 259, 10, 22, 3958, 3958, 4009, 4009, 4036, 4036, 85, 82, 0, 5, 22, 163, 0, 8, 0, 2561, 2574, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 51, 51, 27, 27, 13, 13, 6, 5, 4, 17, 23, 3, 0, 5, 0, 5, 4, {71,72,83}, 2, 1, 1, 6, 7 }, // Hausa/Latin/Ghana + { 47, 7, 156, 0, 0, 305, 305, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 656, 259, 0, 0, 3958, 3958, 4009, 4009, 4036, 4036, 85, 82, 0, 5, 22, 33, 8515, 8, 0, 2561, 2578, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 51, 51, 27, 27, 13, 13, 6, 5, 4, 17, 23, 3, 29, 5, 0, 5, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Hausa/Latin/Niger + { 48, 18, 105, 0, 0, 313, 313, 6, 0, 1, 2, 3, 33, 35, 9, 11, 11, 13, 13, 673, 581, 1, 1, 4049, 4049, 4113, 4113, 4158, 4158, 91, 87, 469, 5, 22, 47, 8544, 19, 0, 2583, 2588, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 18, 8, 9, 4, 64, 64, 45, 45, 20, 20, 6, 5, 4, 17, 23, 1, 53, 5, 0, 5, 5, {73,76,83}, 2, 1, 7, 5, 6 }, // Hebrew/Hebrew/Israel { 49, 13, 100, 0, 0, 319, 328, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 4178, 4178, 4230, 4230, 4261, 4261, 68, 65, 473, 5, 22, 119, 8597, 4, 0, 2593, 2599, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 52, 52, 31, 31, 18, 18, 2, 2, 4, 17, 23, 1, 41, 4, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Hindi/Devanagari/India - { 50, 7, 98, 0, 0, 336, 336, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 16, 15, 691, 710, 1, 1, 4279, 4279, 4330, 4330, 4348, 4348, 97, 92, 477, 5, 22, 217, 8638, 13, 0, 2603, 2609, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 13, 9, 4, 51, 51, 18, 18, 16, 16, 3, 3, 4, 17, 23, 2, 45, 5, 0, 6, 12, {72,85,70}, 2, 0, 1, 6, 7 }, // Hungarian/Latin/Hungary - { 51, 7, 99, 0, 0, 190, 190, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 581, 0, 0, 4364, 4364, 4444, 4444, 4478, 4478, 100, 95, 481, 5, 22, 219, 8683, 13, 0, 2621, 2629, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 80, 80, 34, 34, 13, 13, 4, 4, 4, 17, 23, 3, 48, 5, 0, 8, 6, {73,83,75}, 0, 0, 1, 6, 7 }, // Icelandic/Latin/Iceland + { 50, 7, 98, 0, 0, 336, 336, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 16, 15, 691, 710, 1, 1, 4279, 4279, 4330, 4330, 4348, 4348, 97, 92, 477, 5, 22, 217, 8638, 19, 0, 2603, 2609, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 13, 9, 4, 51, 51, 18, 18, 16, 16, 3, 3, 4, 17, 23, 2, 45, 5, 0, 6, 12, {72,85,70}, 2, 0, 1, 6, 7 }, // Hungarian/Latin/Hungary + { 51, 7, 99, 0, 0, 190, 190, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 581, 0, 0, 4364, 4364, 4444, 4444, 4478, 4478, 100, 95, 481, 5, 22, 219, 8683, 19, 0, 2621, 2629, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 80, 80, 34, 34, 13, 13, 4, 4, 4, 17, 23, 3, 48, 5, 0, 8, 6, {73,83,75}, 0, 0, 1, 6, 7 }, // Icelandic/Latin/Iceland { 52, 7, 101, 0, 0, 344, 354, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 166, 166, 4491, 4491, 4533, 4533, 4560, 4560, 0, 0, 0, 5, 22, 222, 8731, 4, 0, 2635, 2635, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 42, 42, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 38, 4, 0, 9, 9, {73,68,82}, 2, 0, 7, 6, 7 }, // Indonesian/Latin/Indonesia - { 53, 7, 260, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 723, 511, 0, 0, 4573, 4573, 4629, 4629, 4656, 4656, 0, 0, 0, 5, 22, 0, 0, 8, 0, 2644, 2655, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 5, 0, 11, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // Interlingua/Latin/World + { 53, 7, 260, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 723, 511, 0, 0, 4573, 4573, 4629, 4629, 4656, 4656, 0, 0, 0, 5, 22, 0, 0, 8, 37, 2644, 2655, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 10, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 5, 17, 23, 0, 0, 5, 7, 11, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // Interlingua/Latin/World { 55, 44, 38, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 224, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {67,65,68}, 2, 0, 7, 6, 7 }, // Inuktitut/Canadian Aboriginal/Canada { 55, 7, 38, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 224, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {67,65,68}, 2, 0, 7, 6, 7 }, // Inuktitut/Latin/Canada - { 57, 7, 104, 0, 0, 363, 242, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0, 4669, 4669, 4743, 4743, 4779, 4779, 104, 99, 485, 5, 22, 14, 8769, 4, 0, 2660, 2667, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 74, 74, 36, 36, 13, 13, 4, 4, 6, 17, 23, 1, 30, 4, 0, 7, 4, {69,85,82}, 2, 1, 1, 6, 7 }, // Irish/Latin/Ireland - { 57, 7, 224, 0, 0, 363, 242, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0, 4669, 4669, 4743, 4743, 4779, 4779, 104, 99, 485, 5, 22, 117, 8799, 4, 0, 2660, 2671, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 74, 74, 36, 36, 13, 13, 4, 4, 6, 17, 23, 1, 94, 4, 0, 7, 19, {71,66,80}, 2, 1, 1, 6, 7 }, // Irish/Latin/United Kingdom - { 58, 7, 106, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 14, 3032, 13, 0, 2690, 2698, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Italian/Latin/Italy - { 58, 7, 184, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 14, 3032, 13, 0, 2690, 2704, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Italian/Latin/San Marino - { 58, 7, 206, 0, 0, 252, 252, 6, 0, 13, 2, 3, 4, 5, 9, 15, 16, 17, 18, 0, 166, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 0, 8893, 8, 36, 2690, 2714, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 52, 5, 5, 8, 8, {67,72,70}, 2, 0, 1, 6, 7 }, // Italian/Latin/Switzerland - { 58, 7, 230, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 14, 3032, 13, 0, 2690, 2722, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 8, 18, {69,85,82}, 2, 1, 1, 6, 7 }, // Italian/Latin/Vatican City State - { 59, 19, 108, 168, 168, 168, 168, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 377, 545, 292, 1, 4888, 4888, 4915, 4915, 4915, 4915, 108, 103, 491, 494, 22, 227, 8945, 4, 0, 2740, 2740, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 10, 10, 4, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 1, 10, 4, 0, 3, 2, {74,80,89}, 0, 0, 7, 6, 7 }, // Japanese/Japanese/Japan + { 57, 7, 104, 0, 0, 363, 242, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0, 4669, 4669, 4743, 4743, 4779, 4779, 104, 99, 485, 5, 22, 14, 8769, 4, 13, 2660, 2667, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 74, 74, 36, 36, 13, 13, 4, 4, 6, 17, 23, 1, 30, 4, 6, 7, 4, {69,85,82}, 2, 1, 1, 6, 7 }, // Irish/Latin/Ireland + { 57, 7, 224, 0, 0, 363, 242, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0, 4669, 4669, 4743, 4743, 4779, 4779, 104, 99, 485, 5, 22, 117, 8799, 4, 13, 2660, 2671, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 74, 74, 36, 36, 13, 13, 4, 4, 6, 17, 23, 1, 94, 4, 6, 7, 19, {71,66,80}, 2, 1, 1, 6, 7 }, // Irish/Latin/United Kingdom + { 58, 7, 106, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 14, 3032, 19, 0, 2690, 2698, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 8, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Italian/Latin/Italy + { 58, 7, 184, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 14, 3032, 19, 0, 2690, 2704, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 8, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Italian/Latin/San Marino + { 58, 7, 206, 0, 0, 252, 252, 6, 0, 13, 2, 3, 4, 5, 9, 15, 16, 17, 18, 0, 166, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 0, 8893, 19, 0, 2690, 2714, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 52, 5, 0, 8, 8, {67,72,70}, 2, 0, 1, 6, 7 }, // Italian/Latin/Switzerland + { 58, 7, 230, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 45, 0, 0, 4792, 4792, 4848, 4848, 4875, 4875, 0, 0, 0, 5, 22, 14, 3032, 19, 0, 2690, 2722, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 56, 56, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 8, 18, {69,85,82}, 2, 1, 1, 6, 7 }, // Italian/Latin/Vatican City State + { 59, 19, 108, 168, 168, 168, 168, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 377, 545, 292, 1, 4888, 4888, 4915, 4915, 4915, 4915, 108, 103, 491, 494, 22, 227, 8945, 4, 13, 2740, 2740, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 10, 10, 4, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 1, 10, 4, 6, 3, 2, {74,80,89}, 0, 0, 7, 6, 7 }, // Japanese/Japanese/Japan { 60, 7, 101, 0, 0, 374, 384, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 511, 0, 0, 4928, 4928, 4968, 4968, 4996, 4996, 110, 105, 511, 5, 22, 222, 8731, 8, 0, 2743, 2747, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 40, 40, 28, 28, 13, 13, 4, 5, 4, 17, 23, 2, 38, 5, 0, 4, 9, {73,68,82}, 2, 0, 7, 6, 7 }, // Javanese/Latin/Indonesia - { 61, 21, 100, 0, 0, 393, 405, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 259, 271, 284, 5009, 5009, 5062, 5062, 5094, 5094, 114, 110, 515, 523, 22, 119, 8955, 4, 0, 2756, 2761, 6, 6, 12, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 8, 53, 53, 32, 32, 19, 19, 9, 7, 8, 35, 23, 1, 48, 4, 0, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Kannada/Kannada/India + { 61, 21, 100, 0, 0, 393, 405, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 259, 271, 284, 5009, 5009, 5062, 5062, 5094, 5094, 114, 110, 515, 523, 22, 119, 8955, 4, 13, 2756, 2761, 6, 6, 12, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 13, 8, 53, 53, 32, 32, 19, 19, 9, 7, 8, 35, 23, 1, 48, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Kannada/Kannada/India { 62, 1, 100, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 27, 521, 10, 22, 5113, 5113, 5164, 5164, 5213, 5213, 0, 0, 0, 5, 22, 119, 9003, 8, 0, 2765, 2770, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 6, 12, 7, 51, 51, 49, 49, 13, 13, 2, 2, 4, 17, 23, 1, 16, 5, 0, 5, 9, {73,78,82}, 2, 1, 7, 7, 7 }, // Kashmiri/Arabic/India - { 63, 2, 110, 0, 0, 0, 416, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 749, 166, 0, 0, 5226, 5226, 5281, 5281, 5301, 5301, 0, 0, 253, 558, 575, 228, 9019, 13, 0, 2779, 2789, 6, 6, 6, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 10, 5, 55, 55, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 57, 5, 0, 10, 9, {75,90,84}, 2, 1, 1, 6, 7 }, // Kazakh/Cyrillic/Kazakhstan + { 63, 2, 110, 0, 0, 0, 416, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 749, 166, 0, 0, 5226, 5226, 5281, 5281, 5301, 5301, 0, 0, 253, 558, 575, 228, 9019, 19, 0, 2779, 2789, 6, 6, 6, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 10, 5, 55, 55, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 57, 5, 0, 10, 9, {75,90,84}, 2, 1, 1, 6, 7 }, // Kazakh/Cyrillic/Kazakhstan { 64, 7, 179, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 12, 13, 53, 70, 0, 0, 5314, 5314, 5397, 5397, 83, 83, 0, 0, 0, 5, 22, 174, 0, 8, 0, 2798, 2809, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 83, 83, 34, 34, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 11, 8, {82,87,70}, 0, 0, 1, 6, 7 }, // Kinyarwanda/Latin/Rwanda - { 65, 2, 116, 0, 0, 426, 426, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 771, 259, 0, 0, 5431, 5431, 5487, 5487, 5524, 5524, 123, 117, 253, 598, 22, 229, 9076, 13, 0, 2817, 2825, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 10, 5, 56, 56, 37, 37, 13, 13, 5, 14, 4, 18, 23, 3, 51, 5, 0, 8, 10, {75,71,83}, 2, 1, 1, 6, 7 }, // Kirghiz/Cyrillic/Kyrgyzstan - { 66, 22, 114, 0, 0, 436, 436, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 794, 810, 302, 315, 5537, 5537, 5564, 5564, 5564, 5564, 128, 131, 616, 5, 22, 232, 9127, 4, 0, 2835, 2838, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 13, 7, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 1, 18, 4, 0, 3, 4, {75,82,87}, 0, 0, 7, 6, 7 }, // Korean/Korean/South Korea - { 66, 22, 113, 0, 0, 436, 436, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 794, 810, 302, 315, 5537, 5537, 5564, 5564, 5564, 5564, 128, 131, 616, 5, 22, 233, 9145, 4, 0, 2835, 2842, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 13, 7, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 3, 38, 4, 0, 3, 11, {75,80,87}, 0, 0, 1, 6, 7 }, // Korean/Korean/North Korea - { 67, 7, 217, 0, 0, 443, 443, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 5577, 5577, 5618, 5618, 5637, 5637, 130, 133, 0, 5, 22, 236, 0, 13, 0, 2853, 2858, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 41, 41, 19, 19, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 5, 7, {84,82,89}, 2, 1, 1, 6, 7 }, // Kurdish/Latin/Turkey + { 65, 2, 116, 0, 0, 426, 426, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 771, 259, 0, 0, 5431, 5431, 5487, 5487, 5524, 5524, 123, 117, 253, 598, 22, 229, 9076, 19, 0, 2817, 2825, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 10, 5, 56, 56, 37, 37, 13, 13, 5, 14, 4, 18, 23, 3, 51, 5, 0, 8, 10, {75,71,83}, 2, 1, 1, 6, 7 }, // Kirghiz/Cyrillic/Kyrgyzstan + { 66, 22, 114, 0, 0, 436, 436, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 794, 810, 302, 315, 5537, 5537, 5564, 5564, 5564, 5564, 128, 131, 616, 5, 22, 232, 9127, 4, 13, 2835, 2838, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 13, 7, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 1, 18, 4, 6, 3, 4, {75,82,87}, 0, 0, 7, 6, 7 }, // Korean/Korean/South Korea + { 66, 22, 113, 0, 0, 436, 436, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 794, 810, 302, 315, 5537, 5537, 5564, 5564, 5564, 5564, 128, 131, 616, 5, 22, 233, 9145, 4, 13, 2835, 2842, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 13, 7, 27, 27, 13, 13, 13, 13, 2, 2, 3, 17, 23, 3, 38, 4, 6, 3, 11, {75,80,87}, 0, 0, 1, 6, 7 }, // Korean/Korean/North Korea + { 67, 7, 217, 0, 0, 443, 443, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 5577, 5577, 5618, 5618, 5637, 5637, 130, 133, 0, 5, 22, 236, 0, 19, 24, 2853, 2858, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 41, 41, 19, 19, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 7, 5, 7, {84,82,89}, 2, 1, 1, 6, 7 }, // Kurdish/Latin/Turkey { 68, 7, 35, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 11, 11, 13, 13, 97, 398, 0, 0, 5650, 5650, 5738, 5738, 83, 83, 132, 135, 0, 5, 22, 159, 9183, 0, 0, 2865, 2873, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 88, 88, 33, 33, 13, 13, 5, 5, 4, 17, 23, 3, 20, 4, 0, 8, 8, {66,73,70}, 0, 0, 1, 6, 7 }, // Rundi/Latin/Burundi - { 69, 23, 117, 0, 0, 0, 450, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 819, 398, 322, 1, 5771, 5771, 5827, 5827, 5862, 5862, 137, 140, 0, 5, 22, 237, 9203, 4, 36, 2881, 2881, 6, 6, 6, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 24, 4, 56, 56, 35, 35, 16, 16, 8, 8, 4, 17, 23, 1, 20, 4, 5, 3, 3, {76,65,75}, 0, 0, 7, 6, 7 }, // Lao/Lao/Laos - { 71, 7, 118, 0, 0, 459, 459, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 838, 166, 0, 0, 5878, 5949, 6020, 6070, 6120, 6120, 145, 148, 619, 5, 22, 14, 9223, 13, 0, 2884, 2892, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 8, 10, 5, 71, 71, 50, 50, 13, 13, 14, 11, 5, 17, 23, 1, 22, 5, 0, 8, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Latvian/Latin/Latvia - { 72, 7, 49, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 32, 9245, 13, 0, 2899, 2906, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 2, 16, 5, 0, 7, 30, {67,68,70}, 2, 1, 1, 6, 7 }, // Lingala/Latin/Congo Kinshasa - { 72, 7, 6, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 238, 9261, 13, 0, 2899, 2936, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 2, 16, 5, 0, 7, 6, {65,79,65}, 2, 1, 1, 6, 7 }, // Lingala/Latin/Angola - { 72, 7, 41, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 32, 9277, 13, 0, 2899, 2942, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 4, 16, 5, 0, 7, 26, {88,65,70}, 0, 0, 1, 6, 7 }, // Lingala/Latin/Central African Republic - { 72, 7, 50, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 32, 9277, 13, 0, 2899, 2968, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 4, 16, 5, 0, 7, 5, {88,65,70}, 0, 0, 1, 6, 7 }, // Lingala/Latin/Congo Brazzaville - { 73, 7, 124, 0, 0, 476, 476, 6, 1, 14, 2, 3, 38, 5, 47, 40, 10, 40, 10, 864, 70, 0, 0, 6272, 6272, 6360, 6360, 6380, 6380, 167, 165, 624, 5, 22, 14, 9293, 13, 0, 2973, 2981, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 27, 10, 10, 5, 88, 88, 20, 20, 13, 13, 9, 6, 6, 17, 23, 1, 29, 5, 0, 8, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Lithuanian/Latin/Lithuania - { 74, 2, 127, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 0, 113, 0, 0, 6393, 6393, 6446, 6480, 1486, 1486, 176, 171, 630, 5, 22, 240, 9322, 13, 0, 2988, 2998, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 53, 53, 34, 33, 13, 13, 10, 8, 5, 17, 23, 4, 55, 5, 0, 10, 18, {77,75,68}, 2, 1, 1, 6, 7 }, // Macedonian/Cyrillic/Macedonia - { 75, 7, 128, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 70, 0, 0, 6513, 6513, 6572, 6572, 6605, 6605, 0, 0, 0, 5, 22, 166, 5291, 8, 0, 3016, 3024, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 59, 59, 33, 33, 13, 13, 2, 2, 4, 17, 23, 2, 6, 5, 0, 8, 12, {77,71,65}, 0, 0, 1, 6, 7 }, // Malagasy/Latin/Madagascar - { 76, 7, 130, 0, 0, 354, 354, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 46, 10, 22, 6618, 6618, 6660, 6660, 6687, 6687, 186, 179, 619, 5, 22, 168, 9377, 4, 0, 3036, 1219, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 12, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 2, 38, 4, 0, 6, 8, {77,89,82}, 2, 1, 1, 6, 7 }, // Malay/Latin/Malaysia + { 69, 23, 117, 0, 0, 0, 450, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 819, 398, 322, 1, 5771, 5771, 5827, 5827, 5862, 5862, 137, 140, 0, 5, 22, 237, 9203, 4, 44, 2881, 2881, 6, 6, 6, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 24, 4, 56, 56, 35, 35, 16, 16, 8, 8, 4, 17, 23, 1, 20, 4, 5, 3, 3, {76,65,75}, 0, 0, 7, 6, 7 }, // Lao/Lao/Laos + { 71, 7, 118, 0, 0, 459, 459, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 838, 166, 0, 0, 5878, 5949, 6020, 6070, 6120, 6120, 145, 148, 619, 5, 22, 14, 9223, 19, 0, 2884, 2892, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 26, 8, 10, 5, 71, 71, 50, 50, 13, 13, 14, 11, 5, 17, 23, 1, 22, 5, 0, 8, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Latvian/Latin/Latvia + { 72, 7, 49, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 32, 9245, 19, 0, 2899, 2906, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 2, 16, 5, 0, 7, 30, {67,68,70}, 2, 1, 1, 6, 7 }, // Lingala/Latin/Congo Kinshasa + { 72, 7, 6, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 238, 9261, 19, 0, 2899, 2936, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 2, 16, 5, 0, 7, 6, {65,79,65}, 2, 1, 1, 6, 7 }, // Lingala/Latin/Angola + { 72, 7, 41, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 32, 9277, 19, 0, 2899, 2942, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 4, 16, 5, 0, 7, 26, {88,65,70}, 0, 0, 1, 6, 7 }, // Lingala/Latin/Central African Republic + { 72, 7, 50, 0, 0, 467, 467, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0, 6133, 6133, 6232, 6232, 6259, 6259, 159, 159, 0, 5, 22, 32, 9277, 19, 0, 2899, 2968, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 99, 99, 27, 27, 13, 13, 8, 6, 4, 17, 23, 4, 16, 5, 0, 7, 5, {88,65,70}, 0, 0, 1, 6, 7 }, // Lingala/Latin/Congo Brazzaville + { 73, 7, 124, 0, 0, 476, 476, 6, 1, 14, 2, 3, 38, 5, 47, 40, 10, 40, 10, 864, 70, 0, 0, 6272, 6272, 6360, 6360, 6380, 6380, 167, 165, 624, 5, 22, 14, 9293, 19, 0, 2973, 2981, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 27, 10, 10, 5, 88, 88, 20, 20, 13, 13, 9, 6, 6, 17, 23, 1, 29, 5, 0, 8, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Lithuanian/Latin/Lithuania + { 74, 2, 127, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 0, 113, 0, 0, 6393, 6393, 6446, 6480, 1486, 1486, 176, 171, 630, 5, 22, 240, 9322, 19, 0, 2988, 2998, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 53, 53, 34, 33, 13, 13, 10, 8, 5, 17, 23, 4, 55, 5, 0, 10, 18, {77,75,68}, 2, 1, 1, 6, 7 }, // Macedonian/Cyrillic/Macedonia + { 75, 7, 128, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 70, 0, 0, 6513, 6513, 6572, 6572, 6605, 6605, 0, 0, 0, 5, 22, 166, 5291, 4, 0, 3016, 3024, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 59, 59, 33, 33, 13, 13, 2, 2, 4, 17, 23, 2, 6, 4, 0, 8, 12, {77,71,65}, 0, 0, 1, 6, 7 }, // Malagasy/Latin/Madagascar + { 76, 7, 130, 0, 0, 354, 354, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 46, 10, 22, 6618, 6618, 6660, 6660, 6687, 6687, 186, 179, 619, 5, 22, 168, 9377, 4, 13, 3036, 1219, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 12, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 2, 38, 4, 6, 6, 8, {77,89,82}, 2, 1, 1, 6, 7 }, // Malay/Latin/Malaysia { 76, 1, 130, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 168, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {77,89,82}, 2, 1, 1, 6, 7 }, // Malay/Arabic/Malaysia - { 76, 7, 32, 0, 0, 354, 354, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 85, 46, 10, 22, 6618, 6618, 6660, 6660, 6687, 6687, 186, 179, 619, 5, 22, 6, 9415, 8, 0, 3036, 3042, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 7, 12, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 1, 30, 5, 0, 6, 6, {66,78,68}, 2, 1, 1, 6, 7 }, // Malay/Latin/Brunei - { 76, 7, 190, 0, 0, 354, 354, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 46, 10, 22, 6618, 6618, 6660, 6660, 6687, 6687, 186, 179, 619, 5, 22, 6, 9445, 4, 0, 3036, 3048, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 12, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 1, 36, 4, 0, 6, 9, {83,71,68}, 2, 1, 7, 6, 7 }, // Malay/Latin/Singapore - { 77, 24, 100, 0, 0, 484, 497, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 891, 259, 10, 22, 6700, 6776, 6851, 6851, 6891, 6912, 0, 0, 635, 641, 22, 119, 9481, 4, 0, 3057, 3063, 6, 6, 13, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 76, 75, 40, 40, 21, 20, 2, 2, 6, 27, 23, 1, 39, 4, 0, 6, 6, {73,78,82}, 2, 1, 7, 7, 7 }, // Malayalam/Malayalam/India + { 76, 7, 32, 0, 0, 354, 354, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 85, 46, 10, 22, 6618, 6618, 6660, 6660, 6687, 6687, 186, 179, 619, 5, 22, 6, 9415, 4, 13, 3036, 3042, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 12, 7, 12, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 1, 30, 4, 6, 6, 6, {66,78,68}, 2, 1, 1, 6, 7 }, // Malay/Latin/Brunei + { 76, 7, 190, 0, 0, 354, 354, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 46, 10, 22, 6618, 6618, 6660, 6660, 6687, 6687, 186, 179, 619, 5, 22, 6, 9445, 4, 13, 3036, 3048, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 7, 12, 7, 42, 42, 27, 27, 13, 13, 2, 3, 4, 17, 23, 1, 36, 4, 6, 6, 9, {83,71,68}, 2, 1, 7, 6, 7 }, // Malay/Latin/Singapore + { 77, 24, 100, 0, 0, 484, 497, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 891, 259, 10, 22, 6700, 6776, 6851, 6851, 6891, 6912, 0, 0, 635, 641, 22, 119, 9481, 4, 13, 3057, 3063, 6, 6, 13, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 76, 75, 40, 40, 21, 20, 2, 2, 6, 27, 23, 1, 39, 4, 6, 6, 6, {73,78,82}, 2, 1, 7, 7, 7 }, // Malayalam/Malayalam/India { 78, 7, 133, 0, 0, 509, 517, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 909, 45, 0, 0, 6932, 6932, 6994, 6994, 7021, 7041, 0, 0, 0, 5, 22, 14, 9520, 4, 0, 3069, 1227, 6, 6, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 62, 62, 27, 27, 20, 19, 2, 2, 4, 17, 23, 1, 26, 4, 0, 5, 5, {69,85,82}, 2, 1, 7, 6, 7 }, // Maltese/Latin/Malta { 79, 7, 154, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 511, 10, 22, 7060, 7060, 7106, 7106, 7132, 7132, 0, 0, 0, 5, 22, 6, 9546, 8, 0, 3074, 3079, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 46, 46, 26, 26, 13, 13, 2, 2, 4, 17, 23, 1, 36, 5, 0, 5, 8, {78,90,68}, 2, 1, 1, 6, 7 }, // Maori/Latin/New Zealand - { 80, 13, 100, 0, 0, 524, 524, 6, 0, 1, 2, 60, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22, 7145, 7145, 7197, 7197, 4261, 4261, 188, 182, 473, 5, 22, 119, 9582, 4, 0, 3087, 2599, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 52, 52, 31, 31, 18, 18, 5, 4, 4, 17, 23, 1, 42, 4, 0, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Marathi/Devanagari/India + { 80, 13, 100, 0, 0, 524, 524, 6, 0, 1, 2, 60, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22, 7145, 7145, 7197, 7197, 4261, 4261, 188, 182, 473, 5, 22, 119, 9582, 4, 13, 3087, 2599, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 52, 52, 31, 31, 18, 18, 5, 4, 4, 17, 23, 1, 42, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Marathi/Devanagari/India { 82, 2, 143, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 932, 967, 54, 0, 7228, 7270, 7312, 7312, 7312, 7312, 193, 186, 253, 668, 22, 244, 9624, 8, 0, 3092, 3098, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 35, 10, 12, 5, 42, 42, 20, 20, 20, 20, 4, 4, 4, 17, 23, 1, 45, 5, 0, 6, 6, {77,78,84}, 2, 0, 1, 6, 7 }, // Mongolian/Cyrillic/Mongolia { 82, 8, 44, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 245, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {67,78,89}, 2, 1, 7, 6, 7 }, // Mongolian/Mongolian/China { 84, 13, 150, 533, 0, 538, 538, 6, 0, 1, 2, 60, 4, 5, 9, 10, 11, 12, 13, 53, 253, 0, 0, 7332, 7332, 7385, 7385, 7417, 7417, 197, 190, 473, 685, 22, 248, 9669, 8, 0, 3104, 3104, 5, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 53, 53, 32, 32, 17, 17, 9, 7, 4, 19, 23, 4, 48, 5, 0, 6, 5, {78,80,82}, 2, 1, 7, 6, 7 }, // Nepali/Devanagari/Nepal @@ -1581,143 +1581,143 @@ static const QLocaleData locale_data[] = { { 85, 7, 161, 0, 0, 190, 190, 6, 1, 14, 2, 3, 38, 5, 9, 15, 16, 12, 13, 461, 501, 0, 0, 2173, 2173, 2250, 2250, 2284, 2284, 64, 61, 0, 5, 22, 145, 9765, 8, 0, 3110, 3122, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 50, 50, 34, 34, 13, 13, 4, 4, 4, 17, 23, 2, 43, 5, 0, 12, 5, {78,79,75}, 2, 0, 1, 6, 7 }, // Norwegian Bokmal/Latin/Norway { 85, 7, 203, 0, 0, 190, 190, 6, 1, 14, 2, 3, 38, 5, 9, 15, 16, 12, 13, 461, 501, 0, 0, 2173, 2173, 2250, 2250, 2284, 2284, 64, 61, 0, 5, 22, 145, 9765, 8, 0, 3110, 3127, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 50, 50, 34, 34, 13, 13, 4, 4, 4, 17, 23, 2, 43, 5, 0, 12, 21, {78,79,75}, 2, 0, 1, 6, 7 }, // Norwegian Bokmal/Latin/Svalbard And Jan Mayen Islands { 86, 7, 74, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Occitan/Latin/France - { 87, 26, 100, 0, 0, 545, 553, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 7434, 7434, 7487, 7487, 7519, 7519, 0, 0, 704, 5, 22, 119, 9808, 4, 0, 3148, 3153, 6, 6, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 53, 53, 32, 32, 17, 17, 2, 2, 5, 17, 23, 1, 42, 4, 0, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Oriya/Oriya/India - { 88, 1, 1, 560, 560, 566, 575, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 977, 390, 55, 1, 7536, 7536, 7536, 7536, 83, 83, 206, 197, 709, 5, 22, 252, 9850, 13, 0, 3157, 3161, 6, 6, 9, 8, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 20, 8, 11, 4, 38, 38, 38, 38, 13, 13, 4, 4, 5, 17, 23, 1, 24, 5, 0, 4, 9, {65,70,78}, 0, 0, 6, 4, 5 }, // Pashto/Arabic/Afghanistan - { 88, 1, 163, 560, 560, 566, 575, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 977, 390, 10, 22, 7536, 7536, 7536, 7536, 83, 83, 206, 197, 709, 5, 22, 170, 9874, 13, 0, 3157, 3170, 6, 6, 9, 8, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 20, 8, 12, 7, 38, 38, 38, 38, 13, 13, 4, 4, 5, 17, 23, 2, 51, 5, 0, 4, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Pashto/Arabic/Pakistan - { 89, 1, 102, 583, 583, 590, 598, 53, 19, 20, 21, 52, 61, 35, 56, 15, 16, 17, 18, 97, 390, 55, 1, 7574, 7574, 7574, 7574, 7622, 7622, 210, 201, 714, 718, 22, 253, 9925, 84, 0, 3177, 3182, 7, 7, 8, 7, 1, 1, 1, 1, 1, 2, 2, 4, 1, 1, 1, 1, 16, 8, 11, 4, 48, 48, 48, 48, 13, 13, 9, 8, 4, 44, 23, 4, 36, 5, 0, 5, 5, {73,82,82}, 0, 0, 6, 5, 5 }, // Persian/Arabic/Iran - { 89, 1, 1, 583, 583, 590, 598, 53, 19, 20, 21, 52, 61, 35, 56, 15, 16, 17, 18, 97, 390, 55, 1, 7574, 7574, 7574, 7574, 7622, 7622, 210, 201, 714, 718, 22, 252, 9961, 8, 0, 3187, 3161, 7, 7, 8, 7, 1, 1, 1, 1, 1, 2, 2, 4, 1, 1, 1, 1, 16, 8, 11, 4, 48, 48, 48, 48, 13, 13, 9, 8, 4, 44, 23, 1, 54, 5, 0, 3, 9, {65,70,78}, 0, 0, 6, 4, 5 }, // Persian/Arabic/Afghanistan - { 90, 7, 172, 0, 0, 161, 161, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 15, 16, 0, 501, 0, 0, 7635, 7635, 7693, 7693, 7726, 7739, 0, 0, 322, 5, 22, 257,10015, 13, 0, 3190, 3196, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 58, 58, 33, 33, 13, 13, 2, 2, 5, 17, 23, 2, 76, 5, 0, 6, 6, {80,76,78}, 2, 1, 1, 6, 7 }, // Polish/Latin/Poland + { 87, 26, 100, 0, 0, 545, 553, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22, 7434, 7434, 7487, 7487, 7519, 7519, 0, 0, 704, 5, 22, 119, 9808, 4, 13, 3148, 3153, 6, 6, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 53, 53, 32, 32, 17, 17, 2, 2, 5, 17, 23, 1, 42, 4, 6, 5, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Oriya/Oriya/India + { 88, 1, 1, 560, 560, 566, 575, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 977, 390, 55, 1, 7536, 7536, 7536, 7536, 83, 83, 206, 197, 709, 5, 22, 252, 9850, 4, 13, 3157, 3161, 6, 6, 9, 8, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 20, 8, 11, 4, 38, 38, 38, 38, 13, 13, 4, 4, 5, 17, 23, 1, 24, 4, 6, 4, 9, {65,70,78}, 0, 0, 6, 4, 5 }, // Pashto/Arabic/Afghanistan + { 88, 1, 163, 560, 560, 566, 575, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 977, 390, 10, 22, 7536, 7536, 7536, 7536, 83, 83, 206, 197, 709, 5, 22, 170, 9874, 4, 13, 3157, 3170, 6, 6, 9, 8, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 20, 8, 12, 7, 38, 38, 38, 38, 13, 13, 4, 4, 5, 17, 23, 2, 51, 4, 6, 4, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Pashto/Arabic/Pakistan + { 89, 1, 102, 583, 583, 590, 598, 53, 19, 20, 21, 52, 61, 35, 56, 15, 16, 17, 18, 97, 390, 55, 1, 7574, 7574, 7574, 7574, 7622, 7622, 210, 201, 714, 718, 22, 253, 9925, 54, 60, 3177, 3182, 7, 7, 8, 7, 1, 1, 1, 1, 1, 2, 2, 4, 1, 1, 1, 1, 16, 8, 11, 4, 48, 48, 48, 48, 13, 13, 9, 8, 4, 44, 23, 4, 36, 6, 8, 5, 5, {73,82,82}, 0, 0, 6, 5, 5 }, // Persian/Arabic/Iran + { 89, 1, 1, 583, 583, 590, 598, 53, 19, 20, 21, 52, 61, 35, 56, 15, 16, 17, 18, 97, 390, 55, 1, 7574, 7574, 7574, 7574, 7622, 7622, 210, 201, 714, 718, 22, 252, 9961, 8, 60, 3187, 3161, 7, 7, 8, 7, 1, 1, 1, 1, 1, 2, 2, 4, 1, 1, 1, 1, 16, 8, 11, 4, 48, 48, 48, 48, 13, 13, 9, 8, 4, 44, 23, 1, 54, 5, 8, 3, 9, {65,70,78}, 0, 0, 6, 4, 5 }, // Persian/Arabic/Afghanistan + { 90, 7, 172, 0, 0, 161, 161, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 15, 16, 0, 501, 0, 0, 7635, 7635, 7693, 7693, 7726, 7739, 0, 0, 322, 5, 22, 257,10015, 19, 24, 3190, 3196, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 58, 58, 33, 33, 13, 13, 2, 2, 5, 17, 23, 2, 76, 5, 7, 6, 6, {80,76,78}, 2, 1, 1, 6, 7 }, // Polish/Latin/Poland { 91, 7, 30, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 45, 0, 0, 7752, 7752, 7830, 7830, 7864, 7864, 0, 0, 0, 5, 22, 5,10091, 8, 0, 3202, 3211, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 10, 10, 5, 78, 78, 34, 34, 13, 13, 2, 2, 5, 17, 23, 2, 53, 5, 0, 9, 6, {66,82,76}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Brazil - { 91, 7, 6, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 238,10144, 13, 0, 3202, 3217, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 2, 53, 5, 0, 9, 6, {65,79,65}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Angola - { 91, 7, 39, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 259,10197, 13, 0, 3202, 3223, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 68, 5, 0, 9, 10, {67,86,69}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Cape Verde - { 91, 7, 62, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 156,10265, 13, 0, 3202, 3233, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 80, 5, 0, 9, 11, {85,83,68}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/East Timor - { 91, 7, 66, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 32,10345, 13, 0, 3202, 3244, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 4, 58, 5, 0, 9, 16, {88,65,70}, 0, 0, 1, 6, 7 }, // Portuguese/Latin/Equatorial Guinea - { 91, 7, 92, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 33,10403, 13, 0, 3202, 3260, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 61, 5, 0, 9, 12, {88,79,70}, 0, 0, 1, 6, 7 }, // Portuguese/Latin/Guinea Bissau - { 91, 7, 125, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 14, 3032, 13, 0, 3202, 3272, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 19, 5, 0, 9, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Luxembourg - { 91, 7, 126, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 10, 22, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 134,10464, 13, 0, 3202, 3282, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 4, 53, 5, 0, 9, 19, {77,79,80}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Macau - { 91, 7, 146, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 260,10517, 13, 0, 3202, 3301, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 65, 5, 0, 9, 10, {77,90,78}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Mozambique - { 91, 7, 173, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 14, 3032, 13, 0, 3311, 3328, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 19, 5, 0, 17, 8, {69,85,82}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Portugal - { 91, 7, 185, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 263,10582, 13, 0, 3202, 3336, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 2, 91, 5, 0, 9, 19, {83,84,78}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Sao Tome And Principe - { 91, 7, 206, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 208,10673, 13, 0, 3202, 3355, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 44, 5, 0, 9, 5, {67,72,70}, 2, 0, 1, 6, 7 }, // Portuguese/Latin/Switzerland - { 92, 4, 100, 0, 0, 605, 605, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 7925, 7925, 7981, 7981, 8016, 8016, 227, 217, 762, 5, 22, 119,10717, 4, 0, 3360, 3366, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 35, 35, 22, 22, 6, 6, 4, 17, 23, 1, 38, 4, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Punjabi/Gurmukhi/India - { 92, 1, 163, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 527, 45, 10, 22, 8038, 8038, 8038, 8038, 83, 83, 0, 0, 0, 5, 22, 77,10755, 41, 0, 3370, 3170, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 10, 12, 7, 36, 36, 36, 36, 13, 13, 2, 2, 4, 17, 23, 1, 6, 6, 0, 6, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Punjabi/Arabic/Pakistan - { 93, 7, 169, 0, 0, 614, 625, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0, 8074, 8074, 8126, 8126, 8153, 8153, 64, 61, 0, 5, 22, 265,10761, 8, 0, 3376, 3384, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 2, 28, 5, 0, 8, 4, {80,69,78}, 2, 1, 7, 6, 7 }, // Quechua/Latin/Peru - { 93, 7, 26, 0, 0, 614, 625, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0, 8074, 8074, 8126, 8126, 8153, 8153, 64, 61, 0, 5, 22, 267,10789, 8, 0, 3376, 3388, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 2, 24, 5, 0, 8, 7, {66,79,66}, 2, 1, 1, 6, 7 }, // Quechua/Latin/Bolivia - { 93, 7, 63, 0, 0, 614, 625, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0, 8074, 8074, 8126, 8126, 8153, 8153, 64, 61, 0, 5, 22, 6,10813, 8, 0, 3376, 3395, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 36, 5, 0, 8, 7, {85,83,68}, 2, 1, 1, 6, 7 }, // Quechua/Latin/Ecuador - { 94, 7, 206, 0, 0, 0, 0, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 997, 347, 0, 0, 8166, 8166, 8221, 8221, 8243, 8243, 0, 0, 0, 5, 22, 208,10849, 13, 0, 3402, 3411, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 10, 5, 55, 55, 22, 22, 13, 13, 2, 2, 4, 17, 23, 3, 45, 5, 0, 9, 6, {67,72,70}, 2, 0, 1, 6, 7 }, // Romansh/Latin/Switzerland - { 95, 7, 177, 0, 0, 635, 635, 6, 1, 0, 2, 3, 4, 5, 9, 40, 11, 15, 16, 0, 501, 0, 0, 8256, 8256, 8303, 8303, 3015, 3015, 64, 61, 766, 5, 22, 269,10894, 13, 0, 3417, 3423, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 47, 47, 33, 33, 13, 13, 4, 4, 4, 17, 23, 3, 56, 5, 0, 6, 7, {82,79,78}, 2, 1, 1, 6, 7 }, // Romanian/Latin/Romania - { 95, 7, 141, 0, 0, 635, 635, 6, 1, 0, 2, 3, 4, 5, 9, 40, 11, 15, 16, 0, 501, 0, 0, 8256, 8256, 8336, 8336, 8363, 8363, 64, 61, 766, 5, 22, 7,10950, 13, 0, 3417, 3430, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 47, 47, 27, 27, 15, 15, 4, 4, 4, 17, 23, 1, 68, 5, 0, 6, 17, {77,68,76}, 2, 1, 1, 6, 7 }, // Romanian/Latin/Moldova - { 96, 2, 178, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 121,11018, 13, 0, 3447, 3454, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 88, 5, 0, 7, 6, {82,85,66}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Russia - { 96, 2, 20, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 0,11106, 13, 0, 3447, 510, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 2, 93, 5, 0, 7, 8, {66,89,78}, 2, 0, 1, 6, 7 }, // Russian/Cyrillic/Belarus - { 96, 2, 110, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 228,11199, 13, 0, 3447, 3460, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 82, 5, 0, 7, 9, {75,90,84}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kazakhstan - { 96, 2, 116, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 229,11281, 13, 0, 3447, 3469, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 3, 81, 5, 0, 7, 8, {75,71,83}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kyrgyzstan - { 96, 2, 141, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 7,11362, 13, 0, 3447, 3477, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 78, 5, 0, 7, 7, {77,68,76}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Moldova - { 96, 2, 222, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 272,11440, 13, 0, 3447, 3484, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 91, 5, 0, 7, 7, {85,65,72}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Ukraine - { 98, 7, 41, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0, 8472, 8472, 8537, 8537, 8564, 8564, 233, 223, 0, 5, 22, 32,11531, 4, 36, 3491, 3496, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 65, 65, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 18, 4, 5, 5, 22, {88,65,70}, 0, 0, 1, 6, 7 }, // Sango/Latin/Central African Republic + { 91, 7, 6, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 238,10144, 19, 24, 3202, 3217, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 2, 53, 5, 7, 9, 6, {65,79,65}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Angola + { 91, 7, 39, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 259,10197, 19, 24, 3202, 3223, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 68, 5, 7, 9, 10, {67,86,69}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Cape Verde + { 91, 7, 62, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 156,10265, 19, 24, 3202, 3233, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 80, 5, 7, 9, 11, {85,83,68}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/East Timor + { 91, 7, 66, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 32,10345, 19, 24, 3202, 3244, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 4, 58, 5, 7, 9, 16, {88,65,70}, 0, 0, 1, 6, 7 }, // Portuguese/Latin/Equatorial Guinea + { 91, 7, 92, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 33,10403, 19, 24, 3202, 3260, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 61, 5, 7, 9, 12, {88,79,70}, 0, 0, 1, 6, 7 }, // Portuguese/Latin/Guinea Bissau + { 91, 7, 125, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 14, 3032, 19, 24, 3202, 3272, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 19, 5, 7, 9, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Luxembourg + { 91, 7, 126, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 10, 22, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 134,10464, 19, 24, 3202, 3282, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 4, 53, 5, 7, 9, 19, {77,79,80}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Macau + { 91, 7, 146, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 260,10517, 19, 24, 3202, 3301, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 65, 5, 7, 9, 10, {77,90,78}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Mozambique + { 91, 7, 173, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 14, 3032, 19, 24, 3311, 3328, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 1, 19, 5, 7, 17, 8, {69,85,82}, 2, 1, 7, 6, 7 }, // Portuguese/Latin/Portugal + { 91, 7, 185, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 263,10582, 19, 24, 3202, 3336, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 2, 91, 5, 7, 9, 19, {83,84,78}, 2, 1, 1, 6, 7 }, // Portuguese/Latin/Sao Tome And Principe + { 91, 7, 206, 0, 0, 252, 252, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 45, 0, 0, 7752, 7752, 7877, 7877, 7864, 7864, 219, 209, 0, 5, 22, 208,10673, 19, 24, 3202, 3355, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 78, 78, 48, 48, 13, 13, 8, 8, 5, 17, 23, 3, 44, 5, 7, 9, 5, {67,72,70}, 2, 0, 1, 6, 7 }, // Portuguese/Latin/Switzerland + { 92, 4, 100, 0, 0, 605, 605, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22, 7925, 7925, 7981, 7981, 8016, 8016, 227, 217, 762, 5, 22, 119,10717, 8, 0, 3360, 3366, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 35, 35, 22, 22, 6, 6, 4, 17, 23, 1, 38, 5, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Punjabi/Gurmukhi/India + { 92, 1, 163, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 527, 45, 10, 22, 8038, 8038, 8038, 8038, 83, 83, 0, 0, 0, 5, 22, 77,10755, 8, 0, 3370, 3170, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 10, 12, 7, 36, 36, 36, 36, 13, 13, 2, 2, 4, 17, 23, 1, 6, 5, 0, 6, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Punjabi/Arabic/Pakistan + { 93, 7, 169, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0, 8074, 8074, 8126, 8126, 8153, 8153, 64, 61, 0, 5, 22, 265,10761, 8, 0, 3376, 3384, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 2, 28, 5, 0, 8, 4, {80,69,78}, 2, 1, 7, 6, 7 }, // Quechua/Latin/Peru + { 93, 7, 26, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0, 8074, 8074, 8126, 8126, 8153, 8153, 64, 61, 0, 5, 22, 267,10789, 8, 0, 3376, 3388, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 2, 24, 5, 0, 8, 7, {66,79,66}, 2, 1, 1, 6, 7 }, // Quechua/Latin/Bolivia + { 93, 7, 63, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0, 8074, 8074, 8126, 8126, 8153, 8153, 64, 61, 0, 5, 22, 6,10813, 8, 0, 3376, 3395, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 36, 5, 0, 8, 7, {85,83,68}, 2, 1, 1, 6, 7 }, // Quechua/Latin/Ecuador + { 94, 7, 206, 0, 0, 0, 0, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 997, 347, 0, 0, 8166, 8166, 8221, 8221, 8243, 8243, 0, 0, 0, 5, 22, 208,10849, 19, 0, 3402, 3411, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 10, 5, 55, 55, 22, 22, 13, 13, 2, 2, 4, 17, 23, 3, 45, 5, 0, 9, 6, {67,72,70}, 2, 0, 1, 6, 7 }, // Romansh/Latin/Switzerland + { 95, 7, 177, 0, 0, 614, 614, 6, 1, 0, 2, 3, 4, 5, 9, 40, 11, 15, 16, 0, 501, 0, 0, 8256, 8256, 8303, 8303, 3015, 3015, 64, 61, 766, 5, 22, 269,10894, 19, 24, 3417, 3423, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 47, 47, 33, 33, 13, 13, 4, 4, 4, 17, 23, 3, 56, 5, 7, 6, 7, {82,79,78}, 2, 1, 1, 6, 7 }, // Romanian/Latin/Romania + { 95, 7, 141, 0, 0, 614, 614, 6, 1, 0, 2, 3, 4, 5, 9, 40, 11, 15, 16, 0, 501, 0, 0, 8256, 8256, 8336, 8336, 8363, 8363, 64, 61, 766, 5, 22, 7,10950, 19, 24, 3417, 3430, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 47, 47, 27, 27, 15, 15, 4, 4, 4, 17, 23, 1, 68, 5, 7, 6, 17, {77,68,76}, 2, 1, 1, 6, 7 }, // Romanian/Latin/Moldova + { 96, 2, 178, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 121,11018, 19, 0, 3447, 3454, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 88, 5, 0, 7, 6, {82,85,66}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Russia + { 96, 2, 20, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 0,11106, 19, 0, 3447, 510, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 2, 93, 5, 0, 7, 8, {66,89,78}, 2, 0, 1, 6, 7 }, // Russian/Cyrillic/Belarus + { 96, 2, 110, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 228,11199, 19, 0, 3447, 3460, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 82, 5, 0, 7, 9, {75,90,84}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kazakhstan + { 96, 2, 116, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 229,11281, 19, 0, 3447, 3469, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 3, 81, 5, 0, 7, 8, {75,71,83}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kyrgyzstan + { 96, 2, 141, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 7,11362, 19, 0, 3447, 3477, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 78, 5, 0, 7, 7, {77,68,76}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Moldova + { 96, 2, 222, 0, 0, 113, 113, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 295, 501, 0, 0, 8378, 8378, 8439, 8439, 8459, 8439, 0, 0, 265, 668, 22, 272,11440, 19, 0, 3447, 3484, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 10, 10, 5, 61, 61, 20, 20, 13, 20, 2, 2, 5, 17, 23, 1, 91, 5, 0, 7, 7, {85,65,72}, 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Ukraine + { 98, 7, 41, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0, 8472, 8472, 8537, 8537, 8564, 8564, 233, 223, 0, 5, 22, 32,11531, 4, 44, 3491, 3496, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 65, 65, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 18, 4, 5, 5, 22, {88,65,70}, 0, 0, 1, 6, 7 }, // Sango/Latin/Central African Republic { 99, 13, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 119, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {73,78,82}, 2, 1, 7, 7, 7 }, // Sanskrit/Devanagari/India - { 100, 2, 243, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8577, 8577, 8628, 8628, 8655, 8655, 235, 225, 770, 5, 22, 273,11549, 13, 0, 3518, 3524, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 51, 51, 27, 27, 13, 13, 9, 8, 7, 17, 23, 3, 57, 5, 0, 6, 6, {82,83,68}, 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia - { 100, 7, 27, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8668, 8668, 8724, 8724, 2066, 2066, 244, 233, 315, 5, 22, 141,11606, 13, 0, 3530, 629, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 56, 56, 25, 25, 13, 13, 11, 8, 7, 17, 23, 2,173, 5, 0, 6, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Serbian/Latin/Bosnia And Herzegowina - { 100, 7, 242, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8668, 8668, 8749, 8749, 2066, 2066, 244, 233, 315, 5, 22, 14,11779, 13, 0, 3530, 3536, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 56, 56, 27, 27, 13, 13, 11, 8, 7, 17, 23, 1, 22, 5, 0, 6, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Latin/Montenegro - { 100, 7, 243, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8776, 8776, 8749, 8749, 2066, 2066, 255, 233, 315, 5, 22, 273,11801, 13, 0, 3530, 3545, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 53, 53, 27, 27, 13, 13, 9, 8, 7, 17, 23, 3, 57, 5, 0, 6, 6, {82,83,68}, 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia - { 100, 2, 27, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8829, 8829, 8883, 8883, 8655, 8655, 264, 225, 770, 5, 22, 276,11858, 13, 0, 3518, 3551, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 54, 54, 25, 25, 13, 13, 11, 8, 7, 17, 23, 2,173, 5, 0, 6, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Bosnia And Herzegowina - { 100, 2, 242, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8829, 8829, 8628, 8628, 8655, 8655, 264, 225, 770, 5, 22, 14,12031, 13, 0, 3518, 3570, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 54, 54, 27, 27, 13, 13, 11, 8, 7, 17, 23, 1, 22, 5, 0, 6, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Montenegro - { 100, 2, 257, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8577, 8577, 8628, 8628, 8655, 8655, 235, 225, 770, 5, 22, 14,12031, 13, 0, 3518, 3579, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 51, 51, 27, 27, 13, 13, 9, 8, 7, 17, 23, 1, 22, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Kosovo - { 100, 7, 257, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8776, 8776, 8749, 8749, 2066, 2066, 255, 233, 315, 5, 22, 14,11779, 13, 0, 3530, 3585, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 53, 53, 27, 27, 13, 13, 9, 8, 7, 17, 23, 1, 22, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Latin/Kosovo - { 101, 2, 81, 0, 0, 643, 643, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1047, 166, 0, 0, 8908, 8968, 9028, 9055, 9082, 9082, 275, 241, 0, 5, 22, 215,12053, 8, 0, 3591, 3595, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 10, 5, 60, 60, 27, 27, 13, 13, 15, 15, 4, 17, 23, 1, 16, 5, 0, 4, 11, {71,69,76}, 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Georgia - { 101, 2, 178, 0, 0, 643, 643, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1047, 166, 0, 0, 8908, 8968, 9028, 9055, 9082, 9082, 275, 241, 0, 5, 22, 121,12069, 8, 0, 3591, 3606, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 10, 5, 60, 60, 27, 27, 13, 13, 15, 15, 4, 17, 23, 1, 16, 5, 0, 4, 6, {82,85,66}, 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Russia + { 100, 2, 243, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8577, 8577, 8628, 8628, 8655, 8655, 235, 225, 770, 5, 22, 273,11549, 19, 24, 3518, 3524, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 51, 51, 27, 27, 13, 13, 9, 8, 7, 17, 23, 3, 57, 5, 7, 6, 6, {82,83,68}, 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia + { 100, 7, 27, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8668, 8668, 8724, 8724, 2066, 2066, 244, 233, 315, 5, 22, 141,11606, 19, 24, 3530, 629, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 56, 56, 25, 25, 13, 13, 11, 8, 7, 17, 23, 2,173, 5, 7, 6, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Serbian/Latin/Bosnia And Herzegowina + { 100, 7, 242, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8668, 8668, 8749, 8749, 2066, 2066, 244, 233, 315, 5, 22, 14,11779, 19, 24, 3530, 3536, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 56, 56, 27, 27, 13, 13, 11, 8, 7, 17, 23, 1, 22, 5, 7, 6, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Latin/Montenegro + { 100, 7, 243, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8776, 8776, 8749, 8749, 2066, 2066, 255, 233, 315, 5, 22, 273,11801, 19, 24, 3530, 3545, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 53, 53, 27, 27, 13, 13, 9, 8, 7, 17, 23, 3, 57, 5, 7, 6, 6, {82,83,68}, 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia + { 100, 2, 27, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8829, 8829, 8883, 8883, 8655, 8655, 264, 225, 770, 5, 22, 276,11858, 19, 24, 3518, 3551, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 54, 54, 25, 25, 13, 13, 11, 8, 7, 17, 23, 2,173, 5, 7, 6, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Bosnia And Herzegowina + { 100, 2, 242, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8829, 8829, 8628, 8628, 8655, 8655, 264, 225, 770, 5, 22, 14,12031, 19, 24, 3518, 3570, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 54, 54, 27, 27, 13, 13, 11, 8, 7, 17, 23, 1, 22, 5, 7, 6, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Montenegro + { 100, 2, 257, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8577, 8577, 8628, 8628, 8655, 8655, 235, 225, 770, 5, 22, 14,12031, 19, 24, 3518, 3579, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 51, 51, 27, 27, 13, 13, 9, 8, 7, 17, 23, 1, 22, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Kosovo + { 100, 7, 257, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 12, 12, 1020, 1040, 0, 0, 8776, 8776, 8749, 8749, 2066, 2066, 255, 233, 315, 5, 22, 14,11779, 19, 24, 3530, 3585, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 53, 53, 27, 27, 13, 13, 9, 8, 7, 17, 23, 1, 22, 5, 7, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Serbian/Latin/Kosovo + { 101, 2, 81, 0, 0, 622, 622, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1047, 166, 0, 0, 8908, 8968, 9028, 9055, 9082, 9082, 275, 241, 0, 5, 22, 215,12053, 8, 0, 3591, 3595, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 10, 5, 60, 60, 27, 27, 13, 13, 15, 15, 4, 17, 23, 1, 16, 5, 0, 4, 11, {71,69,76}, 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Georgia + { 101, 2, 178, 0, 0, 622, 622, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1047, 166, 0, 0, 8908, 8968, 9028, 9055, 9082, 9082, 275, 241, 0, 5, 22, 121,12069, 8, 0, 3591, 3606, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 10, 5, 60, 60, 27, 27, 13, 13, 15, 15, 4, 17, 23, 1, 16, 5, 0, 4, 6, {82,85,66}, 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Russia { 102, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Southern Sotho/Latin/South Africa { 103, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Tswana/Latin/South Africa - { 104, 7, 240, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 11, 11, 13, 13, 53, 70, 0, 0, 9095, 9095, 9149, 9149, 9176, 9176, 0, 0, 0, 5, 22, 156,12085, 4, 0, 3612, 1780, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 15, 4, 0, 8, 8, {85,83,68}, 2, 1, 7, 6, 7 }, // Shona/Latin/Zimbabwe - { 105, 1, 163, 0, 0, 652, 660, 53, 19, 20, 21, 23, 24, 26, 28, 10, 11, 12, 13, 53, 70, 10, 22, 9189, 9189, 9189, 9189, 9223, 9223, 290, 256, 777, 783, 22, 170,12100, 8, 0, 3620, 3624, 6, 6, 8, 7, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 34, 34, 34, 34, 30, 30, 11, 11, 6, 61, 23, 2, 42, 5, 0, 4, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Sindhi/Arabic/Pakistan - { 106, 32, 198, 0, 0, 667, 676, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 166, 166, 9253, 9253, 9314, 9314, 9352, 9352, 301, 267, 844, 849, 22, 278,12142, 4, 0, 3631, 3636, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 38, 38, 18, 18, 5, 4, 5, 42, 23, 3, 57, 4, 0, 5, 11, {76,75,82}, 2, 1, 1, 6, 7 }, // Sinhala/Sinhala/Sri Lanka + { 104, 7, 240, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 11, 11, 13, 13, 53, 70, 0, 0, 9095, 9095, 9149, 9149, 9176, 9176, 0, 0, 0, 5, 22, 156,12085, 4, 13, 3612, 1780, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 15, 4, 6, 8, 8, {85,83,68}, 2, 1, 7, 6, 7 }, // Shona/Latin/Zimbabwe + { 105, 1, 163, 0, 0, 631, 639, 53, 19, 20, 21, 23, 24, 26, 28, 10, 11, 12, 13, 53, 70, 10, 22, 9189, 9189, 9189, 9189, 9223, 9223, 290, 256, 777, 783, 22, 170,12100, 19, 0, 3620, 3624, 6, 6, 8, 7, 1, 1, 1, 2, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 34, 34, 34, 34, 30, 30, 11, 11, 6, 61, 23, 2, 42, 5, 0, 4, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Sindhi/Arabic/Pakistan + { 106, 32, 198, 0, 0, 646, 655, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 166, 166, 9253, 9253, 9314, 9314, 9352, 9352, 301, 267, 844, 849, 22, 278,12142, 4, 13, 3631, 3636, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 38, 38, 18, 18, 5, 4, 5, 42, 23, 3, 57, 4, 6, 5, 11, {76,75,82}, 2, 1, 1, 6, 7 }, // Sinhala/Sinhala/Sri Lanka { 107, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Swati/Latin/South Africa - { 108, 7, 191, 0, 0, 183, 684, 6, 1, 14, 2, 3, 4, 5, 6, 40, 10, 46, 12, 461, 1070, 1, 1, 9370, 9370, 9421, 9421, 9441, 9441, 0, 0, 322, 5, 22, 14,12199, 13, 0, 3647, 3657, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 9, 4, 51, 51, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 25, 5, 0, 10, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Slovak/Latin/Slovakia - { 109, 7, 192, 0, 0, 691, 691, 6, 1, 0, 2, 3, 38, 5, 6, 40, 10, 46, 12, 1020, 440, 0, 0, 9454, 9454, 9505, 9505, 9539, 9539, 60, 271, 50, 5, 22, 14,12224, 13, 0, 3666, 3677, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 9, 10, 5, 51, 51, 34, 34, 13, 13, 4, 4, 4, 17, 23, 1, 27, 5, 0, 11, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Slovenian/Latin/Slovenia - { 110, 7, 194, 0, 0, 699, 699, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 10, 22, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 92,12251, 4, 0, 3686, 3694, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 1, 20, 4, 0, 8, 10, {83,79,83}, 0, 0, 1, 6, 7 }, // Somali/Latin/Somalia - { 110, 7, 59, 0, 0, 699, 699, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 10, 22, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 36,12271, 4, 0, 3686, 3704, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 3, 49, 4, 0, 8, 7, {68,74,70}, 0, 0, 6, 6, 7 }, // Somali/Latin/Djibouti - { 110, 7, 69, 0, 0, 699, 699, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 10, 22, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 0,12320, 4, 0, 3686, 3711, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 2, 51, 4, 0, 8, 8, {69,84,66}, 2, 1, 7, 6, 7 }, // Somali/Latin/Ethiopia - { 110, 7, 111, 0, 0, 699, 699, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 0, 0, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 2,12371, 4, 0, 3686, 1161, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 10, 5, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 3, 51, 4, 0, 8, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Somali/Latin/Kenya - { 111, 7, 197, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 14, 3032, 13, 0, 3719, 2381, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 19, 5, 0, 17, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Spain - { 111, 7, 10, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 6,12422, 8, 0, 3719, 3736, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 50, 5, 0, 7, 9, {65,82,83}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Argentina - { 111, 7, 22, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 6,12472, 4, 0, 3719, 3745, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 1, 51, 4, 0, 7, 6, {66,90,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Belize - { 111, 7, 26, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 267,12523, 4, 0, 3719, 3388, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 2, 34, 4, 0, 7, 7, {66,79,66}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Bolivia - { 111, 7, 30, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 5,12557, 4, 0, 3719, 3211, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 2, 51, 4, 0, 7, 6, {66,82,76}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Brazil - { 111, 7, 43, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 347, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12608, 4, 36, 3719, 3751, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 44, 4, 5, 7, 5, {67,76,80}, 0, 0, 1, 6, 7 }, // Spanish/Latin/Chile - { 111, 7, 47, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 46, 10, 22, 9643, 9643, 9695, 9695, 4656, 3015, 53, 50, 0, 5, 22, 6,12652, 8, 0, 3719, 3756, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 53, 5, 0, 7, 8, {67,79,80}, 2, 0, 7, 6, 7 }, // Spanish/Latin/Colombia - { 111, 7, 52, 0, 0, 708, 708, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 281,12705, 4, 0, 3719, 3764, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 66, 4, 0, 7, 10, {67,82,67}, 2, 0, 1, 6, 7 }, // Spanish/Latin/Costa Rica - { 111, 7, 55, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 6,12771, 4, 0, 3719, 3774, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 1, 41, 4, 0, 7, 4, {67,85,80}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Cuba - { 111, 7, 61, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 10, 22, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 282,12812, 4, 89, 3719, 3778, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 3, 53, 4, 6, 7, 20, {68,79,80}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Dominican Republic - { 111, 7, 63, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12865, 4, 36, 3719, 3395, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 5, 7, 7, {85,83,68}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Ecuador - { 111, 7, 65, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 3798, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 11, {85,83,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/El Salvador - { 111, 7, 66, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 32,12934, 4, 0, 3719, 3809, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 4, 91, 4, 0, 7, 17, {88,65,70}, 0, 0, 1, 6, 7 }, // Spanish/Latin/Equatorial Guinea - { 111, 7, 90, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 46, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 285,13025, 18, 0, 3719, 3826, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 29, 5, 0, 7, 9, {71,84,81}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Guatemala - { 111, 7, 96, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1099, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 7,13054, 4, 0, 3719, 3835, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 59, 4, 0, 7, 8, {72,78,76}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Honduras - { 111, 7, 139, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 45, 1, 1, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 6,13113, 47, 0, 3843, 3860, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 9, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 47, 6, 0, 17, 6, {77,88,78}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Mexico - { 111, 7, 155, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 286,13160, 4, 0, 3719, 3866, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 2, 68, 4, 0, 7, 9, {78,73,79}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Nicaragua - { 111, 7, 166, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 1126, 10, 22, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 288,13228, 4, 0, 3719, 3875, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 3, 53, 4, 0, 7, 6, {80,65,66}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Panama - { 111, 7, 168, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 291,13281, 8, 23, 3719, 3881, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 3, 60, 5, 6, 7, 8, {80,89,71}, 0, 0, 7, 6, 7 }, // Spanish/Latin/Paraguay - { 111, 7, 169, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 46, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 265,13341, 8, 0, 3719, 3384, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 2, 42, 5, 0, 7, 4, {80,69,78}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Peru - { 111, 7, 170, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 10, 22, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 173,13383, 13, 0, 3719, 3889, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 47, 5, 0, 7, 9, {80,72,80}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Philippines - { 111, 7, 174, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 1126, 10, 22, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 1416, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 11, {85,83,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Puerto Rico - { 111, 7, 225, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 398, 10, 22, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 6,12865, 95, 0, 3719, 3898, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 7, 0, 7, 14, {85,83,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/United States - { 111, 7, 227, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,13430, 8, 0, 3719, 3912, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 47, 5, 0, 7, 7, {85,89,85}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Uruguay - { 111, 7, 231, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 10, 22, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 294,13477, 4, 36, 3719, 3919, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 4, 57, 4, 5, 7, 9, {86,69,83}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Venezuela - { 111, 7, 238, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 14, 3032, 13, 0, 3719, 3928, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 19, 5, 0, 7, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Canary Islands - { 111, 7, 246, 0, 0, 708, 708, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 0, 0, 4, 0, 3936, 3959, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 0, 0, 4, 0, 23, 13, {0,0,0}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Latin America - { 111, 7, 250, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 14, 3032, 13, 0, 3719, 3972, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 19, 5, 0, 7, 15, {69,85,82}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Ceuta And Melilla + { 108, 7, 191, 0, 0, 183, 663, 6, 1, 14, 2, 3, 4, 5, 6, 40, 10, 46, 12, 461, 1070, 1, 1, 9370, 9370, 9421, 9421, 9441, 9441, 0, 0, 322, 5, 22, 14,12199, 19, 24, 3647, 3657, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 9, 4, 51, 51, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 25, 5, 7, 10, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Slovak/Latin/Slovakia + { 109, 7, 192, 0, 0, 670, 670, 6, 1, 0, 2, 3, 38, 5, 6, 40, 10, 46, 12, 1020, 440, 0, 0, 9454, 9454, 9505, 9505, 9539, 9539, 60, 271, 50, 5, 22, 14,12224, 19, 24, 3666, 3677, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 9, 10, 5, 51, 51, 34, 34, 13, 13, 4, 4, 4, 17, 23, 1, 27, 5, 7, 11, 9, {69,85,82}, 2, 1, 1, 6, 7 }, // Slovenian/Latin/Slovenia + { 110, 7, 194, 0, 0, 678, 678, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 10, 22, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 92,12251, 4, 13, 3686, 3694, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 1, 20, 4, 6, 8, 10, {83,79,83}, 0, 0, 1, 6, 7 }, // Somali/Latin/Somalia + { 110, 7, 59, 0, 0, 678, 678, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 10, 22, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 36,12271, 4, 13, 3686, 3704, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 3, 49, 4, 6, 8, 7, {68,74,70}, 0, 0, 6, 6, 7 }, // Somali/Latin/Djibouti + { 110, 7, 69, 0, 0, 678, 678, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 10, 22, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 0,12320, 4, 13, 3686, 3711, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 7, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 2, 51, 4, 6, 8, 8, {69,84,66}, 2, 1, 7, 6, 7 }, // Somali/Latin/Ethiopia + { 110, 7, 111, 0, 0, 678, 678, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1080, 45, 0, 0, 9552, 9552, 9598, 9598, 9629, 9629, 306, 275, 891, 897, 22, 2,12371, 4, 13, 3686, 1161, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 10, 5, 46, 46, 31, 31, 14, 14, 2, 2, 6, 17, 23, 3, 51, 4, 6, 8, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Somali/Latin/Kenya + { 111, 7, 197, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 14, 3032, 19, 0, 3719, 2381, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 19, 5, 0, 17, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Spain + { 111, 7, 10, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 6,12422, 8, 37, 3719, 3736, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 50, 5, 7, 7, 9, {65,82,83}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Argentina + { 111, 7, 22, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 6,12472, 4, 0, 3719, 3745, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 1, 51, 4, 0, 7, 6, {66,90,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Belize + { 111, 7, 26, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 267,12523, 4, 0, 3719, 3388, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 2, 34, 4, 0, 7, 7, {66,79,66}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Bolivia + { 111, 7, 30, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 5,12557, 4, 0, 3719, 3211, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 2, 51, 4, 0, 7, 6, {66,82,76}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Brazil + { 111, 7, 43, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 347, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12608, 4, 0, 3719, 3751, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 44, 4, 0, 7, 5, {67,76,80}, 0, 0, 1, 6, 7 }, // Spanish/Latin/Chile + { 111, 7, 47, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 46, 10, 22, 9643, 9643, 9695, 9695, 4656, 3015, 53, 50, 0, 5, 22, 6,12652, 4, 0, 3719, 3756, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 53, 4, 0, 7, 8, {67,79,80}, 2, 0, 7, 6, 7 }, // Spanish/Latin/Colombia + { 111, 7, 52, 0, 0, 687, 687, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 281,12705, 4, 0, 3719, 3764, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 66, 4, 0, 7, 10, {67,82,67}, 2, 0, 1, 6, 7 }, // Spanish/Latin/Costa Rica + { 111, 7, 55, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 6,12771, 4, 0, 3719, 3774, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 1, 41, 4, 0, 7, 4, {67,85,80}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Cuba + { 111, 7, 61, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 10, 22, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 282,12812, 4, 13, 3719, 3778, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 3, 53, 4, 6, 7, 20, {68,79,80}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Dominican Republic + { 111, 7, 63, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 3395, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 7, {85,83,68}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Ecuador + { 111, 7, 65, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 3798, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 11, {85,83,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/El Salvador + { 111, 7, 66, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 32,12934, 19, 0, 3719, 3809, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 4, 91, 5, 0, 7, 17, {88,65,70}, 0, 0, 1, 6, 7 }, // Spanish/Latin/Equatorial Guinea + { 111, 7, 90, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 46, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 285,13025, 4, 0, 3719, 3826, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 29, 4, 0, 7, 9, {71,84,81}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Guatemala + { 111, 7, 96, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1099, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 7,13054, 4, 0, 3719, 3835, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 59, 4, 0, 7, 8, {72,78,76}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Honduras + { 111, 7, 139, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 45, 1, 1, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 6,13113, 4, 0, 3843, 3860, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 9, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 47, 4, 0, 17, 6, {77,88,78}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Mexico + { 111, 7, 155, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 286,13160, 4, 0, 3719, 3866, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 2, 68, 4, 0, 7, 9, {78,73,79}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Nicaragua + { 111, 7, 166, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 1126, 10, 22, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 288,13228, 4, 0, 3719, 3875, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 3, 53, 4, 0, 7, 6, {80,65,66}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Panama + { 111, 7, 168, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 291,13281, 4, 0, 3719, 3881, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 3, 60, 4, 0, 7, 8, {80,89,71}, 0, 0, 7, 6, 7 }, // Spanish/Latin/Paraguay + { 111, 7, 169, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 46, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 265,13341, 4, 0, 3719, 3384, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 7, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 2, 42, 4, 0, 7, 4, {80,69,78}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Peru + { 111, 7, 170, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 10, 22, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 173,13383, 19, 0, 3719, 3889, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 47, 5, 0, 7, 9, {80,72,80}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Philippines + { 111, 7, 174, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 1126, 10, 22, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 1416, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 11, {85,83,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Puerto Rico + { 111, 7, 225, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 398, 10, 22, 9643, 9643, 9695, 9695, 3015, 3015, 53, 50, 0, 5, 22, 6,12865, 4, 0, 3719, 3898, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 69, 4, 0, 7, 14, {85,83,68}, 2, 1, 7, 6, 7 }, // Spanish/Latin/United States + { 111, 7, 227, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 6,13430, 8, 37, 3719, 3912, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 47, 5, 7, 7, 7, {85,89,85}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Uruguay + { 111, 7, 231, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 10, 22, 9643, 9643, 9695, 9695, 3015, 4656, 53, 50, 0, 5, 22, 294,13477, 4, 0, 3719, 3919, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 12, 7, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 4, 57, 4, 0, 7, 9, {86,69,83}, 2, 1, 7, 6, 7 }, // Spanish/Latin/Venezuela + { 111, 7, 238, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 14, 3032, 19, 0, 3719, 3928, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 19, 5, 0, 7, 8, {69,85,82}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Canary Islands + { 111, 7, 246, 0, 0, 687, 687, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 259, 0, 0, 9643, 9643, 9695, 9695, 3015, 4656, 64, 61, 0, 5, 22, 0, 0, 4, 0, 3936, 3959, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 10, 5, 52, 52, 34, 34, 13, 13, 4, 4, 5, 17, 23, 0, 0, 4, 0, 23, 13, {0,0,0}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Latin America + { 111, 7, 250, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 610, 259, 55, 1, 9643, 9643, 9695, 9695, 8153, 8153, 53, 50, 0, 5, 22, 14, 3032, 19, 0, 3719, 3972, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 6, 11, 4, 52, 52, 34, 34, 13, 13, 5, 5, 5, 17, 23, 1, 19, 5, 0, 7, 15, {69,85,82}, 2, 1, 1, 6, 7 }, // Spanish/Latin/Ceuta And Melilla { 112, 7, 101, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 222, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {73,68,82}, 2, 0, 7, 6, 7 }, // Sundanese/Latin/Indonesia - { 113, 7, 210, 0, 0, 715, 715, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 182,13534, 8, 0, 3987, 1585, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 66, 5, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Swahili/Latin/Tanzania - { 113, 7, 49, 0, 0, 715, 715, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 32,13600, 8, 0, 3987, 3996, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 2, 54, 5, 0, 9, 32, {67,68,70}, 2, 1, 1, 6, 7 }, // Swahili/Latin/Congo Kinshasa - { 113, 7, 111, 0, 0, 715, 715, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 2,13654, 102, 108, 3987, 1161, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 57, 6, 6, 9, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Swahili/Latin/Kenya - { 113, 7, 221, 0, 0, 715, 715, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 187,13711, 8, 0, 3987, 1650, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 60, 5, 0, 9, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Swahili/Latin/Uganda - { 114, 7, 205, 0, 0, 723, 723, 6, 1, 14, 2, 3, 38, 5, 47, 11, 11, 13, 13, 97, 70, 346, 0, 9788, 9788, 9837, 9837, 2284, 2284, 308, 277, 0, 5, 22, 145,13771, 13, 0, 4028, 4035, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 16, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 2, 44, 5, 0, 7, 7, {83,69,75}, 2, 0, 1, 6, 7 }, // Swedish/Latin/Sweden - { 114, 7, 73, 0, 0, 723, 723, 6, 1, 14, 2, 3, 38, 5, 47, 11, 11, 13, 13, 97, 70, 346, 0, 9788, 9788, 9837, 9837, 2284, 2284, 308, 277, 0, 5, 22, 14, 3032, 13, 0, 4028, 1063, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 16, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Swedish/Latin/Finland - { 114, 7, 248, 0, 0, 723, 723, 6, 1, 14, 2, 3, 38, 5, 47, 11, 11, 13, 13, 97, 70, 346, 0, 9788, 9788, 9837, 9837, 2284, 2284, 308, 277, 0, 5, 22, 14, 3032, 13, 0, 4028, 4042, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 16, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 7, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Swedish/Latin/Aland Islands + { 113, 7, 210, 0, 0, 694, 694, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 182,13534, 8, 0, 3987, 1585, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 66, 5, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Swahili/Latin/Tanzania + { 113, 7, 49, 0, 0, 694, 694, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 32,13600, 8, 0, 3987, 3996, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 2, 54, 5, 0, 9, 32, {67,68,70}, 2, 1, 1, 6, 7 }, // Swahili/Latin/Congo Kinshasa + { 113, 7, 111, 0, 0, 694, 694, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 2,13654, 8, 0, 3987, 1161, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 57, 5, 0, 9, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Swahili/Latin/Kenya + { 113, 7, 221, 0, 0, 694, 694, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729, 9729, 9729, 83, 83, 0, 0, 619, 914, 22, 187,13711, 8, 0, 3987, 1650, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 59, 59, 13, 13, 2, 2, 5, 51, 23, 3, 60, 5, 0, 9, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Swahili/Latin/Uganda + { 114, 7, 205, 0, 0, 702, 702, 6, 1, 14, 2, 3, 38, 5, 47, 11, 11, 13, 13, 97, 70, 346, 0, 9788, 9788, 9837, 9837, 2284, 2284, 308, 277, 0, 5, 22, 145,13771, 19, 0, 4028, 4035, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 16, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 2, 44, 5, 0, 7, 7, {83,69,75}, 2, 0, 1, 6, 7 }, // Swedish/Latin/Sweden + { 114, 7, 73, 0, 0, 702, 702, 6, 1, 14, 2, 3, 38, 5, 47, 11, 11, 13, 13, 97, 70, 346, 0, 9788, 9788, 9837, 9837, 2284, 2284, 308, 277, 0, 5, 22, 14, 3032, 19, 0, 4028, 1063, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 16, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 7, 7, {69,85,82}, 2, 1, 1, 6, 7 }, // Swedish/Latin/Finland + { 114, 7, 248, 0, 0, 702, 702, 6, 1, 14, 2, 3, 38, 5, 47, 11, 11, 13, 13, 97, 70, 346, 0, 9788, 9788, 9837, 9837, 2284, 2284, 308, 277, 0, 5, 22, 14, 3032, 19, 0, 4028, 4042, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 16, 5, 49, 49, 28, 28, 13, 13, 2, 2, 4, 17, 23, 1, 18, 5, 0, 7, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Swedish/Latin/Aland Islands { 115, 7, 106, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Sardinian/Latin/Italy - { 116, 2, 209, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 0, 0, 9865, 9865, 9919, 9919, 9946, 9946, 0, 0, 0, 5, 22, 298,13815, 13, 0, 4047, 4053, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 18, 5, 0, 6, 10, {84,74,83}, 2, 1, 1, 6, 7 }, // Tajik/Cyrillic/Tajikistan - { 117, 27, 100, 0, 0, 732, 732, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 362, 315, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 119,13833, 8, 0, 4063, 4068, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 1, 48, 5, 0, 5, 7, {73,78,82}, 2, 1, 7, 7, 7 }, // Tamil/Tamil/India - { 117, 27, 130, 0, 0, 732, 732, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 362, 315, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 168,13881, 8, 0, 4063, 4075, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 2, 60, 5, 0, 5, 7, {77,89,82}, 2, 1, 1, 6, 7 }, // Tamil/Tamil/Malaysia - { 117, 27, 190, 0, 0, 732, 732, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 362, 315, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 6,13941, 8, 0, 4063, 4082, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 1, 60, 5, 0, 5, 11, {83,71,68}, 2, 1, 7, 6, 7 }, // Tamil/Tamil/Singapore - { 117, 27, 198, 0, 0, 732, 732, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 0, 0, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 302,14001, 8, 0, 4063, 4093, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 10, 5, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 3, 48, 5, 0, 5, 6, {76,75,82}, 2, 1, 1, 6, 7 }, // Tamil/Tamil/Sri Lanka - { 118, 2, 178, 0, 0, 745, 745, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1134, 501, 1, 1,10064,10064,10119,10119,10154,10154, 0, 0, 0, 5, 22, 121,14049, 0, 0, 4099, 3454, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 9, 4, 55, 55, 35, 35, 13, 13, 2, 2, 4, 17, 23, 1, 20, 4, 0, 5, 6, {82,85,66}, 2, 1, 1, 6, 7 }, // Tatar/Cyrillic/Russia - { 119, 28, 100, 0, 0, 754, 754, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1157, 347, 10, 22,10167,10167,10226,10226,10257,10257, 0, 0, 972, 979, 22, 119,14069, 4, 0, 4104, 4110, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 59, 59, 31, 31, 17, 17, 2, 2, 7, 29, 23, 1, 25, 4, 0, 6, 8, {73,78,82}, 2, 1, 7, 7, 7 }, // Telugu/Telugu/India - { 120, 30, 211, 120, 120, 765, 773, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1175, 259, 374, 0,10274,10274,10341,10341,10363,10363, 318, 287, 1008, 5, 22, 305,14094, 4, 0, 4118, 4118, 5, 5, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 6, 28, 5, 67, 67, 22, 22, 15, 15, 10, 10, 4, 17, 23, 1, 15, 4, 0, 3, 3, {84,72,66}, 2, 1, 7, 6, 7 }, // Thai/Thai/Thailand + { 116, 2, 209, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 527, 45, 0, 0, 9865, 9865, 9919, 9919, 9946, 9946, 0, 0, 0, 5, 22, 298,13815, 19, 0, 4047, 4053, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 18, 5, 0, 6, 10, {84,74,83}, 2, 1, 1, 6, 7 }, // Tajik/Cyrillic/Tajikistan + { 117, 27, 100, 0, 0, 711, 711, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 362, 315, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 119,13833, 4, 13, 4063, 4068, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 1, 48, 4, 6, 5, 7, {73,78,82}, 2, 1, 7, 7, 7 }, // Tamil/Tamil/India + { 117, 27, 130, 0, 0, 711, 711, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 362, 315, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 168,13881, 4, 13, 4063, 4075, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 2, 60, 4, 6, 5, 7, {77,89,82}, 2, 1, 1, 6, 7 }, // Tamil/Tamil/Malaysia + { 117, 27, 190, 0, 0, 711, 711, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 362, 315, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 6,13941, 4, 13, 4063, 4082, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 1, 60, 4, 6, 5, 11, {83,71,68}, 2, 1, 7, 6, 7 }, // Tamil/Tamil/Singapore + { 117, 27, 198, 0, 0, 711, 711, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 259, 0, 0, 9959, 9959,10007,10007,10045,10045, 310, 279, 965, 5, 22, 302,14001, 4, 13, 4063, 4093, 6, 6, 13, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 10, 5, 48, 48, 38, 38, 19, 19, 8, 8, 7, 17, 23, 3, 48, 4, 6, 5, 6, {76,75,82}, 2, 1, 1, 6, 7 }, // Tamil/Tamil/Sri Lanka + { 118, 2, 178, 0, 0, 724, 724, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1134, 501, 1, 1,10064,10064,10119,10119,10154,10154, 0, 0, 0, 5, 22, 121,14049, 19, 0, 4099, 3454, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 9, 4, 55, 55, 35, 35, 13, 13, 2, 2, 4, 17, 23, 1, 20, 5, 0, 5, 6, {82,85,66}, 2, 1, 1, 6, 7 }, // Tatar/Cyrillic/Russia + { 119, 28, 100, 0, 0, 733, 733, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1157, 347, 10, 22,10167,10167,10226,10226,10257,10257, 0, 0, 972, 979, 22, 119,14069, 4, 13, 4104, 4110, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 59, 59, 31, 31, 17, 17, 2, 2, 7, 29, 23, 1, 25, 4, 6, 6, 8, {73,78,82}, 2, 1, 7, 7, 7 }, // Telugu/Telugu/India + { 120, 30, 211, 120, 120, 744, 752, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1175, 259, 374, 0,10274,10274,10341,10341,10363,10363, 318, 287, 1008, 5, 22, 305,14094, 4, 13, 4118, 4118, 5, 5, 8, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 6, 28, 5, 67, 67, 22, 22, 15, 15, 10, 10, 4, 17, 23, 1, 15, 4, 6, 3, 3, {84,72,66}, 2, 1, 7, 6, 7 }, // Thai/Thai/Thailand { 121, 31, 44, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1194, 70, 10, 22,10378,10378,10456,10456,10506,10506, 328, 297, 0, 5, 22, 130,14109, 8, 0, 4121, 4129, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 12, 7, 78, 78, 50, 50, 26, 26, 7, 8, 4, 17, 23, 1, 6, 5, 0, 8, 6, {67,78,89}, 2, 1, 7, 6, 7 }, // Tibetan/Tibetan/China { 121, 31, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1194, 70, 10, 22,10378,10378,10456,10456,10506,10506, 328, 297, 0, 5, 22, 119,14115, 8, 0, 4121, 4135, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 12, 7, 78, 78, 50, 50, 26, 26, 7, 8, 4, 17, 23, 1, 12, 5, 0, 8, 7, {73,78,82}, 2, 1, 7, 7, 7 }, // Tibetan/Tibetan/India { 122, 14, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1217, 45, 10, 22,10532,10532,10560,10560,10580,10593, 335, 305, 0, 5, 22, 0, 254, 4, 0, 4142, 92, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 12, 7, 28, 28, 20, 20, 13, 13, 7, 7, 4, 17, 23, 2, 9, 4, 0, 4, 5, {69,84,66}, 2, 1, 7, 6, 7 }, // Tigrinya/Ethiopic/Ethiopia { 122, 14, 67, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 12, 13, 10, 11, 1217, 45, 10, 22,10532,10532,10560,10560,10593,10593, 335, 305, 0, 5, 22, 39, 0, 4, 0, 4142, 4146, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 8, 12, 7, 28, 28, 20, 20, 13, 13, 7, 7, 4, 17, 23, 3, 0, 4, 0, 4, 4, {69,82,78}, 2, 1, 1, 6, 7 }, // Tigrinya/Ethiopic/Eritrea - { 123, 7, 214, 780, 780, 780, 780, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 259, 10, 22,10606,10606,10665,10665,10693,10693, 342, 312, 1012, 1017, 1076, 185,14127, 13, 0, 4150, 1600, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 12, 7, 59, 59, 28, 28, 13, 13, 10, 6, 5, 59, 65, 2, 40, 5, 0, 13, 5, {84,79,80}, 2, 1, 1, 6, 7 }, // Tongan/Latin/Tonga + { 123, 7, 214, 759, 759, 759, 759, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 259, 10, 22,10606,10606,10665,10665,10693,10693, 342, 312, 1012, 1017, 1076, 185,14127, 8, 0, 4150, 1600, 8, 8, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 12, 7, 59, 59, 28, 28, 13, 13, 10, 6, 5, 59, 65, 2, 40, 5, 0, 13, 5, {84,79,80}, 2, 1, 1, 6, 7 }, // Tongan/Latin/Tonga { 124, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Tsonga/Latin/South Africa - { 125, 7, 217, 0, 0, 788, 788, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1240, 502, 0, 0,10706,10706,10759,10759,10786,10786, 352, 318, 195, 5, 22, 236,14167, 4, 0, 4163, 4169, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 10, 5, 53, 53, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 39, 4, 0, 6, 7, {84,82,89}, 2, 1, 1, 6, 7 }, // Turkish/Latin/Turkey - { 125, 7, 56, 0, 0, 788, 788, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1240, 502, 10, 22,10706,10706,10759,10759,10786,10786, 352, 318, 195, 5, 22, 14, 8263, 4, 0, 4163, 4176, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 12, 7, 53, 53, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 4, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Turkish/Latin/Cyprus - { 126, 7, 218, 0, 0, 796, 796, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 10, 11, 1240, 501, 0, 0,10799,10852,10905,10932,10959,10959, 354, 320, 1141, 5, 22, 306,14206, 13, 0, 4182, 4194, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 53, 53, 27, 27, 13, 13, 13, 14, 4, 17, 23, 3, 48, 5, 0, 12, 12, {84,77,84}, 2, 1, 1, 6, 7 }, // Turkmen/Latin/Turkmenistan - { 128, 1, 44, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 16, 15, 18, 17, 1256, 70, 10, 22,10972,10972,11026,11026,11046,11046, 367, 334, 0, 5, 22, 227,14254, 4, 0, 4206, 4214, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 54, 54, 20, 20, 13, 13, 12, 12, 4, 17, 23, 1, 39, 4, 0, 8, 5, {67,78,89}, 2, 1, 7, 6, 7 }, // Uighur/Arabic/China - { 129, 2, 222, 0, 0, 136, 136, 6, 1, 14, 2, 3, 4, 5, 63, 15, 16, 40, 10, 1273, 166, 0, 0,11059,11059, 1466, 1466,11114,11114, 379, 346, 1145, 668, 22, 272,14293, 13, 0, 4219, 4229, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 10, 5, 55, 55, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 48, 5, 0, 10, 7, {85,65,72}, 2, 1, 1, 6, 7 }, // Ukrainian/Cyrillic/Ukraine - { 130, 1, 163, 560, 560, 804, 814, 6, 0, 1, 2, 3, 33, 35, 9, 11, 10, 13, 12, 1295, 259, 10, 22,11127,11127,11127,11127, 83, 83, 0, 0, 1150, 1154, 22, 170,14341, 4, 0, 4236, 3170, 6, 6, 10, 9, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 18, 6, 12, 7, 35, 35, 35, 35, 13, 13, 2, 2, 4, 20, 23, 2, 48, 4, 0, 4, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Urdu/Arabic/Pakistan - { 130, 1, 100, 560, 560, 823, 823, 6, 19, 20, 2, 52, 33, 53, 56, 11, 10, 13, 12, 1295, 259, 10, 22,11127,11127,11127,11127, 83, 83, 0, 0, 1150, 1154, 22, 119,14389, 8, 0, 4236, 4240, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 6, 12, 7, 35, 35, 35, 35, 13, 13, 2, 2, 4, 20, 23, 1, 41, 5, 0, 4, 5, {73,78,82}, 2, 1, 7, 7, 7 }, // Urdu/Arabic/India - { 131, 7, 228, 0, 0, 829, 829, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 13, 12, 1313, 45, 55, 0,11162,11162,11222,11222,11253,11253, 381, 348, 195, 5, 22, 309,14430, 13, 0, 4245, 4251, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 11, 5, 60, 60, 31, 31, 13, 13, 2, 2, 4, 17, 23, 4, 57, 5, 0, 6, 11, {85,90,83}, 2, 0, 1, 6, 7 }, // Uzbek/Latin/Uzbekistan - { 131, 1, 1, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 1331, 390, 55, 1, 7574, 7574,11266,11266, 83, 83, 0, 0, 0, 5, 22, 252, 9961, 13, 0, 4262, 3161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 33, 8, 11, 4, 48, 48, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 6, 5, 0, 6, 9, {65,70,78}, 0, 0, 6, 4, 5 }, // Uzbek/Arabic/Afghanistan - { 131, 2, 228, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 637, 45, 54, 0,11286,11286,11338,11338,11365,11365, 383, 350, 0, 5, 22, 313,14487, 13, 0, 4268, 4275, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 5, 52, 52, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 48, 5, 0, 7, 10, {85,90,83}, 2, 0, 1, 6, 7 }, // Uzbek/Cyrillic/Uzbekistan - { 132, 7, 232, 0, 0, 837, 837, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0,11378,11378,11432,11432,11464,11464, 385, 352, 0, 5, 22, 316,14535, 13, 0, 4285, 4295, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 54, 54, 32, 32, 20, 20, 2, 2, 4, 17, 23, 1, 32, 5, 0, 10, 8, {86,78,68}, 0, 0, 1, 6, 7 }, // Vietnamese/Latin/Vietnam + { 125, 7, 217, 0, 0, 767, 767, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1240, 502, 0, 0,10706,10706,10759,10759,10786,10786, 352, 318, 195, 5, 22, 236,14167, 4, 13, 4163, 4169, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 10, 5, 53, 53, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 39, 4, 6, 6, 7, {84,82,89}, 2, 1, 1, 6, 7 }, // Turkish/Latin/Turkey + { 125, 7, 56, 0, 0, 767, 767, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1240, 502, 10, 22,10706,10706,10759,10759,10786,10786, 352, 318, 195, 5, 22, 14, 8263, 4, 13, 4163, 4176, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 12, 7, 53, 53, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 18, 4, 6, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Turkish/Latin/Cyprus + { 126, 7, 218, 0, 0, 775, 775, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 10, 11, 1240, 501, 0, 0,10799,10852,10905,10932,10959,10959, 354, 320, 1141, 5, 22, 306,14206, 19, 0, 4182, 4194, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 53, 53, 27, 27, 13, 13, 13, 14, 4, 17, 23, 3, 48, 5, 0, 12, 12, {84,77,84}, 2, 1, 1, 6, 7 }, // Turkmen/Latin/Turkmenistan + { 128, 1, 44, 0, 0, 198, 208, 6, 0, 1, 2, 3, 4, 5, 9, 16, 15, 18, 17, 1256, 70, 10, 22,10972,10972,11026,11026,11046,11046, 367, 334, 0, 5, 22, 227,14254, 4, 13, 4206, 4214, 6, 6, 10, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 54, 54, 20, 20, 13, 13, 12, 12, 4, 17, 23, 1, 39, 4, 6, 8, 5, {67,78,89}, 2, 1, 7, 6, 7 }, // Uighur/Arabic/China + { 129, 2, 222, 0, 0, 136, 136, 6, 1, 14, 2, 3, 4, 5, 63, 15, 16, 40, 10, 1273, 166, 0, 0,11059,11059, 1466, 1466,11114,11114, 379, 346, 1145, 668, 22, 272,14293, 19, 0, 4219, 4229, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 8, 10, 5, 55, 55, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 48, 5, 0, 10, 7, {85,65,72}, 2, 1, 1, 6, 7 }, // Ukrainian/Cyrillic/Ukraine + { 130, 1, 163, 560, 560, 783, 793, 6, 0, 1, 2, 3, 33, 35, 9, 11, 10, 13, 12, 1295, 259, 10, 22,11127,11127,11127,11127, 83, 83, 0, 0, 1150, 1154, 22, 170,14341, 4, 13, 4236, 3170, 6, 6, 10, 9, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 18, 6, 12, 7, 35, 35, 35, 35, 13, 13, 2, 2, 4, 20, 23, 2, 48, 4, 6, 4, 7, {80,75,82}, 2, 0, 7, 6, 7 }, // Urdu/Arabic/Pakistan + { 130, 1, 100, 560, 560, 783, 793, 6, 19, 20, 2, 52, 33, 53, 56, 11, 10, 13, 12, 1295, 259, 10, 22,11127,11127,11127,11127, 83, 83, 0, 0, 1150, 1154, 22, 119,14389, 4, 13, 4236, 4240, 6, 6, 10, 9, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 18, 6, 12, 7, 35, 35, 35, 35, 13, 13, 2, 2, 4, 20, 23, 1, 41, 4, 6, 4, 5, {73,78,82}, 2, 1, 7, 7, 7 }, // Urdu/Arabic/India + { 131, 7, 228, 0, 0, 802, 802, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 13, 12, 1313, 45, 55, 0,11162,11162,11222,11222,11253,11253, 381, 348, 195, 5, 22, 309,14430, 19, 0, 4245, 4251, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 11, 5, 60, 60, 31, 31, 13, 13, 2, 2, 4, 17, 23, 4, 57, 5, 0, 6, 11, {85,90,83}, 2, 0, 1, 6, 7 }, // Uzbek/Latin/Uzbekistan + { 131, 1, 1, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 1331, 390, 55, 1, 7574, 7574,11266,11266, 83, 83, 0, 0, 0, 5, 22, 252, 9961, 19, 0, 4262, 3161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 33, 8, 11, 4, 48, 48, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 6, 5, 0, 6, 9, {65,70,78}, 0, 0, 6, 4, 5 }, // Uzbek/Arabic/Afghanistan + { 131, 2, 228, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 637, 45, 54, 0,11286,11286,11338,11338,11365,11365, 383, 350, 0, 5, 22, 313,14487, 19, 0, 4268, 4275, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 12, 5, 52, 52, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 48, 5, 0, 7, 10, {85,90,83}, 2, 0, 1, 6, 7 }, // Uzbek/Cyrillic/Uzbekistan + { 132, 7, 232, 0, 0, 810, 810, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 174, 45, 0, 0,11378,11378,11432,11432,11464,11464, 385, 352, 0, 5, 22, 316,14535, 19, 0, 4285, 4295, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 54, 54, 32, 32, 20, 20, 2, 2, 4, 17, 23, 1, 32, 5, 0, 10, 8, {86,78,68}, 0, 0, 1, 6, 7 }, // Vietnamese/Latin/Vietnam { 133, 7, 260, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1364, 70, 0, 0,11484,11484,11526,11546,11573,11573, 0, 0, 0, 5, 22, 0, 0, 8, 0, 4303, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 42, 42, 20, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 7, 0, {0,0,0}, 2, 1, 1, 6, 7 }, // Volapuk/Latin/World - { 134, 7, 224, 0, 0, 845, 856, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,11586,11586,11662,11690,11719,11719, 387, 354, 1174, 5, 22, 117,14567, 4, 0, 4310, 4317, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 76, 76, 28, 29, 14, 14, 2, 2, 7, 17, 23, 1, 90, 4, 0, 7, 16, {71,66,80}, 2, 1, 1, 6, 7 }, // Welsh/Latin/United Kingdom + { 134, 7, 224, 0, 0, 818, 829, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,11586,11586,11662,11690,11719,11719, 387, 354, 1174, 5, 22, 117,14567, 4, 13, 4310, 4317, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 76, 76, 28, 29, 14, 14, 2, 2, 7, 17, 23, 1, 90, 4, 6, 7, 16, {71,66,80}, 2, 1, 1, 6, 7 }, // Welsh/Latin/United Kingdom { 135, 7, 187, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1387, 511, 0, 0,11733,11733,11782,11782,11782,11782, 389, 356, 0, 5, 22, 33,14657, 8, 0, 4333, 4338, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 49, 49, 27, 27, 27, 27, 3, 3, 4, 17, 23, 3, 64, 5, 0, 5, 8, {88,79,70}, 0, 0, 1, 6, 7 }, // Wolof/Latin/Senegal { 136, 7, 195, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 12, 13, 10, 11, 53, 70, 0, 0,11809,11809,11869,11869, 83, 83, 0, 0, 0, 5, 22, 5,14721, 4, 0, 4346, 4354, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 60, 60, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 78, 4, 0, 8, 15, {90,65,82}, 2, 1, 7, 6, 7 }, // Xhosa/Latin/South Africa - { 137, 18, 260, 0, 0, 866, 866, 6, 0, 1, 2, 3, 4, 5, 9, 11, 11, 13, 13, 1404, 45, 0, 0,11896,11896,11896,11896, 83, 83, 392, 359, 0, 5, 22, 0, 0, 41, 0, 4369, 4375, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 10, 5, 53, 53, 53, 53, 13, 13, 11, 10, 4, 17, 23, 0, 0, 6, 0, 6, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // Yiddish/Hebrew/World - { 138, 7, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1423, 398, 0, 1,11949,11992,12060,12060,12092,12092, 403, 369, 0, 5, 22, 172,14799, 4, 0, 4380, 4390, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 3, 43, 68, 32, 32, 13, 13, 5, 5, 4, 17, 23, 1, 48, 4, 0, 10, 19, {78,71,78}, 2, 1, 1, 6, 7 }, // Yoruba/Latin/Nigeria - { 138, 7, 23, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1423, 398, 0, 1,12105,12148,12216,12216,12248,12248, 408, 374, 0, 5, 22, 33,14847, 4, 0, 4380, 4409, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 3, 43, 68, 32, 32, 13, 13, 5, 5, 4, 17, 23, 3, 27, 4, 0, 10, 16, {88,79,70}, 0, 0, 1, 6, 7 }, // Yoruba/Latin/Benin - { 140, 7, 195, 0, 0, 875, 884, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 0, 0,12261,12261,12334,12334,12361,12361, 0, 0, 0, 5, 22, 5,14874, 4, 0, 4425, 4432, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 10, 5, 73, 73, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 66, 4, 0, 7, 17, {90,65,82}, 2, 1, 7, 6, 7 }, // Zulu/Latin/South Africa - { 141, 7, 161, 0, 0, 190, 190, 6, 1, 14, 2, 3, 38, 5, 9, 15, 16, 12, 13, 461, 501, 346, 0,12374,12374,12424,12451, 2284, 2284, 413, 379, 0, 5, 22, 145, 9765, 13, 0, 4449, 4456, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 16, 5, 50, 50, 27, 27, 13, 13, 9, 11, 4, 17, 23, 2, 43, 5, 0, 7, 5, {78,79,75}, 2, 0, 1, 6, 7 }, // Norwegian Nynorsk/Latin/Norway - { 142, 7, 27, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 11, 12, 13, 420, 1439, 0, 0, 1982, 1982, 2039, 2039, 2066, 2079, 422, 390, 315, 5, 22, 141,14940, 13, 0, 4461, 629, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 11, 10, 5, 57, 57, 27, 27, 13, 13, 10, 7, 7, 17, 23, 2,169, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Bosnian/Latin/Bosnia And Herzegowina - { 142, 2, 27, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 1020, 1040, 0, 0,12478,12478,12533,12533, 8655, 8655, 264, 397, 0, 5, 22, 276,15109, 13, 0, 4469, 3551, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 55, 55, 27, 27, 13, 13, 11, 13, 4, 17, 23, 2,151, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/Bosnia And Herzegowina + { 137, 18, 260, 0, 0, 839, 839, 6, 0, 1, 2, 3, 4, 5, 9, 11, 11, 13, 13, 1404, 45, 0, 0,11896,11896,11896,11896, 83, 83, 392, 359, 0, 5, 22, 0, 0, 8, 0, 4369, 4375, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 8, 10, 5, 53, 53, 53, 53, 13, 13, 11, 10, 4, 17, 23, 0, 0, 5, 0, 6, 5, {0,0,0}, 2, 1, 1, 6, 7 }, // Yiddish/Hebrew/World + { 138, 7, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1423, 398, 0, 1,11949,11992,12060,12060,12092,12092, 403, 369, 0, 5, 22, 172,14799, 4, 13, 4380, 4390, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 3, 43, 68, 32, 32, 13, 13, 5, 5, 4, 17, 23, 1, 48, 4, 6, 10, 19, {78,71,78}, 2, 1, 1, 6, 7 }, // Yoruba/Latin/Nigeria + { 138, 7, 23, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1423, 398, 0, 1,12105,12148,12216,12216,12248,12248, 408, 374, 0, 5, 22, 33,14847, 4, 13, 4380, 4409, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 3, 43, 68, 32, 32, 13, 13, 5, 5, 4, 17, 23, 3, 27, 4, 6, 10, 16, {88,79,70}, 0, 0, 1, 6, 7 }, // Yoruba/Latin/Benin + { 140, 7, 195, 0, 0, 848, 857, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 0, 0,12261,12261,12334,12334,12361,12361, 0, 0, 0, 5, 22, 5,14874, 4, 13, 4425, 4432, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 10, 5, 73, 73, 27, 27, 13, 13, 2, 2, 5, 17, 23, 1, 66, 4, 6, 7, 17, {90,65,82}, 2, 1, 7, 6, 7 }, // Zulu/Latin/South Africa + { 141, 7, 161, 0, 0, 190, 190, 6, 1, 14, 2, 3, 38, 5, 9, 15, 16, 12, 13, 461, 501, 346, 0,12374,12374,12424,12451, 2284, 2284, 413, 379, 0, 5, 22, 145, 9765, 19, 0, 4449, 4456, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 16, 5, 50, 50, 27, 27, 13, 13, 9, 11, 4, 17, 23, 2, 43, 5, 0, 7, 5, {78,79,75}, 2, 0, 1, 6, 7 }, // Norwegian Nynorsk/Latin/Norway + { 142, 7, 27, 0, 0, 161, 161, 6, 1, 0, 2, 3, 4, 5, 9, 40, 11, 12, 13, 420, 1439, 0, 0, 1982, 1982, 2039, 2039, 2066, 2079, 422, 390, 315, 5, 22, 141,14940, 19, 0, 4461, 629, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 19, 11, 10, 5, 57, 57, 27, 27, 13, 13, 10, 7, 7, 17, 23, 2,169, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Bosnian/Latin/Bosnia And Herzegowina + { 142, 2, 27, 0, 0, 113, 113, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 1020, 1040, 0, 0,12478,12478,12533,12533, 8655, 8655, 264, 397, 0, 5, 22, 276,15109, 19, 0, 4469, 3551, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 20, 7, 10, 5, 55, 55, 27, 27, 13, 13, 11, 13, 4, 17, 23, 2,151, 5, 0, 8, 19, {66,65,77}, 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/Bosnia And Herzegowina { 143, 29, 131, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {77,86,82}, 2, 1, 5, 6, 7 }, // Divehi/Thaana/Maldives { 144, 7, 251, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 80, 45, 0, 0,12560,12560,12616,12616, 83, 83, 64, 61, 0, 5, 22, 117, 0, 4, 0, 4477, 4482, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 8, 10, 5, 56, 56, 29, 29, 13, 13, 4, 4, 4, 17, 23, 1, 0, 4, 0, 5, 12, {71,66,80}, 2, 1, 1, 6, 7 }, // Manx/Latin/Isle Of Man { 145, 7, 224, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 45, 0, 0,12645,12645,12705,12705, 83, 83, 64, 61, 0, 5, 22, 117, 0, 4, 0, 4494, 4502, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 10, 10, 5, 60, 60, 27, 27, 13, 13, 4, 4, 4, 17, 23, 1, 0, 4, 0, 8, 14, {71,66,80}, 2, 1, 1, 6, 7 }, // Cornish/Latin/United Kingdom { 146, 7, 83, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1450, 547, 10, 22,12732,12732,12780,12780,12807,12807, 432, 410, 0, 5, 22, 163,15260, 4, 0, 4516, 4520, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 12, 7, 48, 48, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 10, 4, 0, 4, 5, {71,72,83}, 2, 1, 1, 6, 7 }, // Akan/Latin/Ghana - { 147, 13, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 192, 10, 22,12820,12820,12820,12820,12868,12868, 0, 0, 1181, 5, 22, 119,15270, 4, 0, 4525, 2599, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 12, 7, 48, 48, 48, 48, 19, 19, 2, 2, 4, 17, 23, 1, 30, 4, 0, 6, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Konkani/Devanagari/India + { 147, 13, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 192, 10, 22,12820,12820,12820,12820,12868,12868, 0, 0, 1181, 5, 22, 119,15270, 4, 13, 4525, 2599, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 6, 12, 7, 48, 48, 48, 48, 19, 19, 2, 2, 4, 17, 23, 1, 30, 4, 6, 6, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Konkani/Devanagari/India { 148, 7, 83, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {71,72,83}, 2, 1, 1, 6, 7 }, // Ga/Latin/Ghana - { 149, 7, 157, 0, 0, 892, 715, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 0, 0,12887,12887,12940,12940, 83, 83, 434, 412, 0, 5, 22, 172,15300, 4, 0, 4531, 4541, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 53, 53, 28, 28, 13, 13, 7, 7, 4, 17, 23, 1, 5, 4, 0, 10, 8, {78,71,78}, 2, 1, 1, 6, 7 }, // Igbo/Latin/Nigeria - { 150, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,12968,12968,13041,13041,13068,13068, 441, 419, 0, 5, 22, 2,15305, 4, 0, 4549, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 73, 73, 27, 27, 13, 13, 9, 7, 4, 17, 23, 3, 16, 4, 0, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Kamba/Latin/Kenya + { 149, 7, 157, 0, 0, 865, 694, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 0, 0,12887,12887,12940,12940, 83, 83, 434, 412, 0, 5, 22, 172,15300, 4, 13, 4531, 4541, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 10, 5, 53, 53, 28, 28, 13, 13, 7, 7, 4, 17, 23, 1, 5, 4, 6, 10, 8, {78,71,78}, 2, 1, 1, 6, 7 }, // Igbo/Latin/Nigeria + { 150, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,12968,12968,13041,13041,13068,13068, 441, 419, 0, 5, 22, 2,15305, 4, 13, 4549, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 73, 73, 27, 27, 13, 13, 9, 7, 4, 17, 23, 3, 16, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Kamba/Latin/Kenya { 151, 33, 103, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {73,81,68}, 0, 0, 6, 5, 6 }, // Syriac/Syriac/Iraq { 152, 14, 67, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,82,78}, 2, 1, 1, 6, 7 }, // Blin/Ethiopic/Eritrea { 153, 14, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,84,66}, 2, 1, 7, 6, 7 }, // Geez/Ethiopic/Ethiopia @@ -1727,147 +1727,147 @@ static const QLocaleData locale_data[] = { { 158, 7, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 172, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {78,71,78}, 2, 1, 1, 6, 7 }, // Jju/Latin/Nigeria { 159, 7, 106, 0, 0, 252, 252, 6, 1, 0, 2, 3, 4, 5, 9, 12, 13, 10, 11, 1468, 45, 0, 0,13081,13081,13130,13130, 3015, 3015, 53, 50, 0, 5, 22, 14, 3032, 8, 0, 4556, 2453, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 19, 5, 0, 6, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Friulian/Latin/Italy { 160, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Venda/Latin/South Africa - { 161, 7, 83, 0, 0, 901, 912, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1495, 521, 402, 402,13157,13157,13200,13200,13227,13227, 450, 426, 0, 5, 22, 163,15321, 4, 0, 4562, 4568, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 17, 12, 43, 43, 27, 27, 13, 13, 3, 5, 4, 17, 23, 3, 36, 4, 0, 6, 12, {71,72,83}, 2, 1, 1, 6, 7 }, // Ewe/Latin/Ghana - { 161, 7, 212, 0, 0, 901, 912, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1495, 521, 0, 0,13157,13157,13200,13200,13227,13227, 450, 426, 0, 5, 22, 33,15357, 4, 0, 4562, 4580, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 10, 5, 43, 43, 27, 27, 13, 13, 3, 5, 4, 17, 23, 3,105, 4, 0, 6, 11, {88,79,70}, 0, 0, 1, 6, 7 }, // Ewe/Latin/Togo + { 161, 7, 83, 0, 0, 874, 885, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1495, 521, 402, 402,13157,13157,13200,13200,13227,13227, 450, 426, 0, 5, 22, 163,15321, 4, 13, 4562, 4568, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 17, 12, 43, 43, 27, 27, 13, 13, 3, 5, 4, 17, 23, 3, 36, 4, 6, 6, 12, {71,72,83}, 2, 1, 1, 6, 7 }, // Ewe/Latin/Ghana + { 161, 7, 212, 0, 0, 874, 885, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1495, 521, 0, 0,13157,13157,13200,13200,13227,13227, 450, 426, 0, 5, 22, 33,15357, 4, 13, 4562, 4580, 6, 6, 11, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 6, 10, 5, 43, 43, 27, 27, 13, 13, 3, 5, 4, 17, 23, 3,105, 4, 6, 6, 11, {88,79,70}, 0, 0, 1, 6, 7 }, // Ewe/Latin/Togo { 162, 14, 69, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,84,66}, 2, 1, 7, 6, 7 }, // Walamo/Ethiopic/Ethiopia - { 163, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22,13240,13240,13296,13296, 83, 83, 0, 0, 0, 5, 22, 6, 0, 4, 0, 4591, 4605, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 14, 19, {85,83,68}, 2, 1, 7, 6, 7 }, // Hawaiian/Latin/United States + { 163, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 259, 10, 22,13240,13240,13296,13296, 83, 83, 0, 0, 0, 5, 22, 6, 0, 4, 13, 4591, 4605, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 6, 12, 7, 56, 56, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 6, 14, 19, {85,83,68}, 2, 1, 7, 6, 7 }, // Hawaiian/Latin/United States { 164, 7, 157, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 172, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {78,71,78}, 2, 1, 1, 6, 7 }, // Tyap/Latin/Nigeria { 165, 7, 129, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {77,87,75}, 2, 1, 1, 6, 7 }, // Nyanja/Latin/Malawi - { 166, 7, 170, 0, 0, 922, 931, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,13316,13316,13370,13370,13370,13370, 0, 0, 0, 5, 22, 173,15462, 4, 0, 4624, 4632, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 54, 54, 27, 27, 27, 27, 2, 2, 5, 17, 23, 1, 57, 4, 0, 8, 9, {80,72,80}, 2, 1, 7, 6, 7 }, // Filipino/Latin/Philippines - { 167, 7, 206, 0, 0, 267, 267, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 420, 166, 0, 0,13397,13397,13459,13459, 3613, 3613, 453, 431, 0, 5, 22, 208,15519, 13, 0, 4641, 4641, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 3, 54, 5, 0, 16, 7, {67,72,70}, 2, 0, 1, 6, 7 }, // Swiss German/Latin/Switzerland - { 167, 7, 74, 0, 0, 267, 267, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 420, 166, 0, 0,13397,13397,13459,13459, 3613, 3613, 453, 431, 0, 5, 22, 14, 8263, 13, 0, 4641, 4657, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 1, 18, 5, 0, 16, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Swiss German/Latin/France - { 167, 7, 123, 0, 0, 267, 267, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 420, 166, 0, 0,13397,13397,13459,13459, 3613, 3613, 453, 431, 0, 5, 22, 208,15519, 13, 0, 4641, 4667, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 3, 54, 5, 0, 16, 13, {67,72,70}, 2, 0, 1, 6, 7 }, // Swiss German/Latin/Liechtenstein + { 166, 7, 170, 0, 0, 895, 904, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,13316,13316,13370,13370,13370,13370, 0, 0, 0, 5, 22, 173,15462, 4, 13, 4624, 4632, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 54, 54, 27, 27, 27, 27, 2, 2, 5, 17, 23, 1, 57, 4, 6, 8, 9, {80,72,80}, 2, 1, 7, 6, 7 }, // Filipino/Latin/Philippines + { 167, 7, 206, 0, 0, 267, 267, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 420, 166, 0, 0,13397,13397,13459,13459, 3613, 3613, 453, 431, 0, 5, 22, 208,15519, 19, 0, 4641, 4641, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 3, 54, 5, 0, 16, 7, {67,72,70}, 2, 0, 1, 6, 7 }, // Swiss German/Latin/Switzerland + { 167, 7, 74, 0, 0, 267, 267, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 420, 166, 0, 0,13397,13397,13459,13459, 3613, 3613, 453, 431, 0, 5, 22, 14, 8263, 19, 0, 4641, 4657, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 1, 18, 5, 0, 16, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Swiss German/Latin/France + { 167, 7, 123, 0, 0, 267, 267, 6, 0, 13, 2, 3, 38, 5, 9, 15, 16, 17, 18, 420, 166, 0, 0,13397,13397,13459,13459, 3613, 3613, 453, 431, 0, 5, 22, 208,15519, 19, 0, 4641, 4667, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 62, 62, 27, 27, 13, 13, 12, 11, 4, 17, 23, 3, 54, 5, 0, 16, 13, {67,72,70}, 2, 0, 1, 6, 7 }, // Swiss German/Latin/Liechtenstein { 168, 34, 44, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 10, 22,13486,13486,13513,13513,13533,13533, 465, 442, 0, 5, 22, 130, 0, 8, 0, 4680, 4683, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 3, 2, {67,78,89}, 2, 1, 7, 6, 7 }, // Sichuan Yi/Yi/China { 169, 7, 121, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {76,82,68}, 2, 1, 1, 6, 7 }, // Kpelle/Latin/Liberia - { 170, 7, 82, 0, 0, 459, 459, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 1518, 167, 419, 438,13546,13546,13610,13610, 3613, 3613, 0, 0, 0, 5, 22, 14,15573, 13, 0, 4685, 4699, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 7, 19, 10, 64, 64, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 14, 5, 0, 14, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // Low German/Latin/Germany - { 170, 7, 151, 0, 0, 459, 459, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 1518, 167, 419, 438,13546,13546,13610,13610, 3613, 3613, 0, 0, 0, 5, 22, 14,15573, 13, 0, 4685, 4710, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 7, 19, 10, 64, 64, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 14, 5, 0, 14, 12, {69,85,82}, 2, 1, 1, 6, 7 }, // Low German/Latin/Netherlands + { 170, 7, 82, 0, 0, 459, 459, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 1518, 167, 419, 438,13546,13546,13610,13610, 3613, 3613, 0, 0, 0, 5, 22, 14,15573, 19, 0, 4685, 4699, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 7, 19, 10, 64, 64, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 14, 5, 0, 14, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // Low German/Latin/Germany + { 170, 7, 151, 0, 0, 459, 459, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 1518, 167, 419, 438,13546,13546,13610,13610, 3613, 3613, 0, 0, 0, 5, 22, 14,15573, 19, 0, 4685, 4710, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 7, 19, 10, 64, 64, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 14, 5, 0, 14, 12, {69,85,82}, 2, 1, 1, 6, 7 }, // Low German/Latin/Netherlands { 171, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // South Ndebele/Latin/South Africa { 172, 7, 195, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 5, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {90,65,82}, 2, 1, 7, 6, 7 }, // Northern Sotho/Latin/South Africa - { 173, 7, 161, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 64, 11, 11, 13, 13, 53, 70, 0, 0,13637,13637,13711,13711,13743,13743, 467, 444, 0, 5, 22, 145,15587, 13, 0, 4722, 4737, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 74, 74, 32, 32, 13, 13, 11, 13, 4, 17, 23, 2, 62, 5, 0, 15, 5, {78,79,75}, 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Norway - { 173, 7, 73, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 64, 11, 11, 13, 13, 97, 501, 0, 0,13756,13756,13825,13825,13845,13845, 478, 457, 0, 5, 22, 14,15649, 13, 0, 4722, 4742, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 10, 5, 69, 69, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 22, 5, 0, 15, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Finland - { 173, 7, 205, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 64, 11, 11, 13, 13, 53, 70, 0, 0,13637,13637,13711,13711,13743,13743, 467, 444, 0, 5, 22, 145,15671, 13, 0, 4722, 4748, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 74, 74, 32, 32, 13, 13, 11, 13, 4, 17, 23, 2, 62, 5, 0, 15, 6, {83,69,75}, 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Sweden + { 173, 7, 161, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 64, 11, 11, 13, 13, 53, 70, 0, 0,13637,13637,13711,13711,13743,13743, 467, 444, 0, 5, 22, 145,15587, 19, 0, 4722, 4737, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 74, 74, 32, 32, 13, 13, 11, 13, 4, 17, 23, 2, 62, 5, 0, 15, 5, {78,79,75}, 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Norway + { 173, 7, 73, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 64, 11, 11, 13, 13, 97, 501, 0, 0,13756,13756,13825,13825,13845,13845, 478, 457, 0, 5, 22, 14,15649, 19, 0, 4722, 4742, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 16, 10, 10, 5, 69, 69, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 22, 5, 0, 15, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Finland + { 173, 7, 205, 0, 0, 226, 226, 6, 1, 14, 2, 3, 38, 5, 64, 11, 11, 13, 13, 53, 70, 0, 0,13637,13637,13711,13711,13743,13743, 467, 444, 0, 5, 22, 145,15671, 19, 0, 4722, 4748, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 17, 10, 10, 5, 74, 74, 32, 32, 13, 13, 11, 13, 4, 17, 23, 2, 62, 5, 0, 15, 6, {83,69,75}, 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Sweden { 174, 7, 208, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 317, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {84,87,68}, 2, 0, 7, 6, 7 }, // Taroko/Latin/Taiwan - { 175, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,13858,13858,13919,13919,13946,13946, 480, 459, 0, 5, 22, 2,13654, 4, 0, 4754, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 27, 27, 13, 13, 6, 3, 4, 17, 23, 3, 17, 4, 0, 8, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Gusii/Latin/Kenya - { 176, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,13959,13959,14063,14063,14090,14090, 486, 462, 0, 5, 22, 2,13654, 4, 0, 4762, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5,104,104, 27, 27, 13, 13, 10, 10, 4, 17, 23, 3, 17, 4, 0, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Taita/Latin/Kenya - { 177, 7, 187, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 13, 0, 4769, 4338, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 8, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Senegal - { 177, 7, 34, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 13, 0, 4769, 4775, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 14, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Burkina Faso - { 177, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 32,15752, 13, 0, 4769, 4789, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 4, 18, 5, 0, 6, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Cameroon - { 177, 7, 80, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 162,15770, 13, 0, 4769, 4797, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 13, 5, 0, 6, 6, {71,77,68}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Gambia - { 177, 7, 83, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 163, 0, 13, 0, 4769, 4803, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 0, 5, 0, 6, 5, {71,72,83}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Ghana - { 177, 7, 91, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 201, 0, 13, 0, 4769, 4808, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 0, 5, 0, 6, 4, {71,78,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea - { 177, 7, 92, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 13, 0, 4769, 4812, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 12, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea Bissau - { 177, 7, 121, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 6,15783, 13, 0, 4769, 4824, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 16, 5, 0, 6, 9, {76,82,68}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Liberia - { 177, 7, 136, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 203,15799, 13, 0, 4769, 4833, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 15, 5, 0, 6, 8, {77,82,85}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Mauritania - { 177, 7, 156, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 13, 0, 4769, 4841, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 6, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Niger - { 177, 7, 157, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 172,15814, 13, 0, 4769, 4847, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 16, 5, 0, 6, 9, {78,71,78}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Nigeria - { 177, 7, 189, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 7,15830, 13, 0, 4769, 4856, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 18, 5, 0, 6, 11, {83,76,76}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Sierra Leone + { 175, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,13858,13858,13919,13919,13946,13946, 480, 459, 0, 5, 22, 2,13654, 4, 13, 4754, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 27, 27, 13, 13, 6, 3, 4, 17, 23, 3, 17, 4, 6, 8, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Gusii/Latin/Kenya + { 176, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,13959,13959,14063,14063,14090,14090, 486, 462, 0, 5, 22, 2,13654, 4, 13, 4762, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5,104,104, 27, 27, 13, 13, 10, 10, 4, 17, 23, 3, 17, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Taita/Latin/Kenya + { 177, 7, 187, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 19, 0, 4769, 4338, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 8, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Senegal + { 177, 7, 34, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 19, 0, 4769, 4775, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 14, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Burkina Faso + { 177, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 32,15752, 19, 0, 4769, 4789, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 4, 18, 5, 0, 6, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Cameroon + { 177, 7, 80, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 162,15770, 19, 0, 4769, 4797, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 13, 5, 0, 6, 6, {71,77,68}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Gambia + { 177, 7, 83, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 163, 0, 19, 0, 4769, 4803, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 0, 5, 0, 6, 5, {71,72,83}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Ghana + { 177, 7, 91, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 201, 0, 19, 0, 4769, 4808, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 0, 5, 0, 6, 4, {71,78,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea + { 177, 7, 92, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 19, 0, 4769, 4812, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 12, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea Bissau + { 177, 7, 121, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 6,15783, 19, 0, 4769, 4824, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 16, 5, 0, 6, 9, {76,82,68}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Liberia + { 177, 7, 136, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 203,15799, 19, 0, 4769, 4833, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 15, 5, 0, 6, 8, {77,82,85}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Mauritania + { 177, 7, 156, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 33,15733, 19, 0, 4769, 4841, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 3, 19, 5, 0, 6, 6, {88,79,70}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Niger + { 177, 7, 157, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 172,15814, 19, 0, 4769, 4847, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 1, 16, 5, 0, 6, 9, {78,71,78}, 2, 1, 1, 6, 7 }, // Fulah/Latin/Nigeria + { 177, 7, 189, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 10, 22,14103,14103,14161,14161,14188,14188, 496, 472, 0, 5, 22, 7,15830, 19, 0, 4769, 4856, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 58, 58, 27, 27, 13, 13, 6, 7, 4, 17, 23, 2, 18, 5, 0, 6, 11, {83,76,76}, 0, 0, 1, 6, 7 }, // Fulah/Latin/Sierra Leone { 177, 134, 91, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 201, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {71,78,70}, 0, 0, 1, 6, 7 }, // Fulah/Adlam/Guinea - { 178, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14201,14201,14263,14263,14290,14290, 502, 479, 0, 5, 22, 2,15848, 4, 0, 4867, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 62, 62, 27, 27, 13, 13, 6, 8, 4, 17, 23, 3, 16, 4, 0, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Kikuyu/Latin/Kenya - { 179, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14303,14303,14407,14407,14434,14434, 508, 487, 0, 5, 22, 2,15864, 4, 0, 4873, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5,104,104, 27, 27, 13, 13, 7, 5, 4, 17, 23, 3, 18, 4, 0, 8, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Samburu/Latin/Kenya + { 178, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14201,14201,14263,14263,14290,14290, 502, 479, 0, 5, 22, 2,15848, 4, 13, 4867, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 62, 62, 27, 27, 13, 13, 6, 8, 4, 17, 23, 3, 16, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Kikuyu/Latin/Kenya + { 179, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14303,14303,14407,14407,14434,14434, 508, 487, 0, 5, 22, 2,15864, 4, 13, 4873, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5,104,104, 27, 27, 13, 13, 7, 5, 4, 17, 23, 3, 18, 4, 6, 8, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Samburu/Latin/Kenya { 180, 7, 146, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 610, 398, 0, 0,14447,14447,14501,14501,14528,14528, 0, 0, 0, 5, 22, 260,15882, 0, 0, 4881, 3301, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 54, 54, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 21, 4, 0, 4, 10, {77,90,78}, 2, 1, 7, 6, 7 }, // Sena/Latin/Mozambique - { 181, 7, 240, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14541,14541,14590,14590,14617,14617, 0, 0, 0, 5, 22, 156,15903, 4, 0, 4885, 1780, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 0, 10, 8, {85,83,68}, 2, 1, 7, 6, 7 }, // North Ndebele/Latin/Zimbabwe + { 181, 7, 240, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14541,14541,14590,14590,14617,14617, 0, 0, 0, 5, 22, 156,15903, 4, 13, 4885, 1780, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 10, 8, {85,83,68}, 2, 1, 7, 6, 7 }, // North Ndebele/Latin/Zimbabwe { 182, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,14630,14630,14694,14694,14722,14722, 515, 492, 0, 5, 22, 182,15920, 4, 0, 4895, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 64, 64, 28, 28, 13, 13, 8, 7, 4, 17, 23, 3, 18, 4, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Rombo/Latin/Tanzania { 183, 9, 145, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 11, 97, 398, 0, 0,14735,14735,14781,14781, 83, 83, 523, 499, 0, 5, 22, 0,15938, 0, 0, 4904, 4911, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 46, 46, 29, 29, 13, 13, 6, 8, 4, 17, 23, 0, 14, 4, 0, 7, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Tachelhit/Tifinagh/Morocco { 183, 7, 145, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 11, 97, 398, 0, 0,14810,14810,14857,14857, 83, 83, 529, 507, 0, 5, 22, 0,15952, 0, 0, 4917, 4927, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 47, 47, 29, 29, 13, 13, 6, 8, 4, 17, 23, 0, 14, 4, 0, 10, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Tachelhit/Latin/Morocco - { 184, 7, 3, 0, 0, 939, 951, 6, 1, 14, 2, 3, 4, 5, 68, 15, 16, 10, 11, 97, 398, 10, 22,14886,14919,14969,14996,15025,15038, 535, 515, 1185, 1192, 22, 195,15966, 0, 0, 4933, 4942, 6, 6, 12, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 33, 50, 27, 29, 13, 13, 7, 9, 7, 21, 23, 2, 52, 4, 0, 9, 8, {68,90,68}, 2, 1, 6, 5, 6 }, // Kabyle/Latin/Algeria + { 184, 7, 3, 0, 0, 912, 924, 6, 1, 14, 2, 3, 4, 5, 68, 15, 16, 10, 11, 97, 398, 10, 22,14886,14919,14969,14996,15025,15038, 535, 515, 1185, 1192, 22, 195,15966, 0, 0, 4933, 4942, 6, 6, 12, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 12, 7, 33, 50, 27, 29, 13, 13, 7, 9, 7, 21, 23, 2, 52, 4, 0, 9, 8, {68,90,68}, 2, 1, 6, 5, 6 }, // Kabyle/Latin/Algeria { 185, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15051,15051,15124,15124,15151,15151, 0, 0, 0, 5, 22, 187,16018, 4, 0, 4950, 1650, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 73, 73, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 0, 10, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Nyankole/Latin/Uganda { 186, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15164,15164,15245,15245,15272,15272, 542, 524, 0, 5, 22, 182,16037, 0, 0, 4960, 4966, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 81, 81, 27, 27, 13, 13, 7, 7, 4, 17, 23, 3, 22, 4, 0, 6, 10, {84,90,83}, 2, 0, 1, 6, 7 }, // Bena/Latin/Tanzania { 187, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15285,15285,15346,15346,15373,15373, 549, 531, 0, 5, 22, 182,13534, 4, 0, 4976, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 27, 27, 13, 13, 5, 9, 4, 17, 23, 3, 20, 4, 0, 8, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Vunjo/Latin/Tanzania - { 188, 7, 132, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,15386,15386,15429,15429,15456,15456, 0, 0, 0, 5, 22, 33,16059, 4, 0, 4984, 2143, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 43, 43, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 0, 9, 4, {88,79,70}, 0, 0, 1, 6, 7 }, // Bambara/Latin/Mali + { 188, 7, 132, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,15386,15386,15429,15429,15456,15456, 0, 0, 0, 5, 22, 33,16059, 4, 13, 4984, 2143, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 43, 43, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 9, 4, {88,79,70}, 0, 0, 1, 6, 7 }, // Bambara/Latin/Mali { 188, 75, 132, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 33, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {88,79,70}, 0, 0, 1, 6, 7 }, // Bambara/Nko/Mali - { 189, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15469,15469,15532,15532,15559,15559, 554, 540, 0, 5, 22, 2,13654, 4, 0, 4993, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 63, 63, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 0, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Embu/Latin/Kenya - { 190, 12, 225, 0, 0, 962, 971, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,15572,15572,15620,15620,15647,15647, 556, 542, 1213, 5, 22, 6,16076, 4, 0, 4999, 5002, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 27, 27, 13, 13, 3, 6, 6, 17, 23, 1, 24, 4, 0, 3, 15, {85,83,68}, 2, 1, 7, 6, 7 }, // Cherokee/Cherokee/United States - { 191, 7, 137, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,15660,15660,15707,15707,15733,15733, 0, 0, 0, 5, 22, 170,16100, 41, 0, 5017, 5031, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 47, 47, 26, 26, 13, 13, 2, 2, 4, 17, 23, 2, 14, 6, 0, 14, 5, {77,85,82}, 2, 0, 1, 6, 7 }, // Morisyen/Latin/Mauritius - { 192, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15746,15746,15878,15878,14722,14722, 559, 548, 0, 5, 22, 182,13534, 4, 0, 5036, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5,132,132, 27, 27, 13, 13, 4, 5, 4, 17, 23, 3, 20, 4, 0, 10, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Makonde/Latin/Tanzania - { 193, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 11, 11, 13, 13, 0, 45, 0, 0,15905,15905,15967,15967,16002,16002, 563, 553, 0, 5, 22, 182,16114, 41, 0, 5046, 5054, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 62, 62, 35, 35, 13, 13, 3, 3, 4, 17, 23, 3, 22, 6, 0, 8, 9, {84,90,83}, 2, 0, 1, 6, 7 }, // Langi/Latin/Tanzania + { 189, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15469,15469,15532,15532,15559,15559, 554, 540, 0, 5, 22, 2,13654, 4, 13, 4993, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 63, 63, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Embu/Latin/Kenya + { 190, 12, 225, 0, 0, 935, 944, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,15572,15572,15620,15620,15647,15647, 556, 542, 1213, 5, 22, 6,16076, 4, 13, 4999, 5002, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 48, 48, 27, 27, 13, 13, 3, 6, 6, 17, 23, 1, 24, 4, 6, 3, 15, {85,83,68}, 2, 1, 7, 6, 7 }, // Cherokee/Cherokee/United States + { 191, 7, 137, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,15660,15660,15707,15707,15733,15733, 0, 0, 0, 5, 22, 170,16100, 8, 0, 5017, 5031, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 47, 47, 26, 26, 13, 13, 2, 2, 4, 17, 23, 2, 14, 5, 0, 14, 5, {77,85,82}, 2, 0, 1, 6, 7 }, // Morisyen/Latin/Mauritius + { 192, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15746,15746,15878,15878,14722,14722, 559, 548, 0, 5, 22, 182,13534, 4, 13, 5036, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5,132,132, 27, 27, 13, 13, 4, 5, 4, 17, 23, 3, 20, 4, 6, 10, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Makonde/Latin/Tanzania + { 193, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 11, 11, 13, 13, 0, 45, 0, 0,15905,15905,15967,15967,16002,16002, 563, 553, 0, 5, 22, 182,16114, 8, 0, 5046, 5054, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 62, 62, 35, 35, 13, 13, 3, 3, 4, 17, 23, 3, 22, 5, 0, 8, 9, {84,90,83}, 2, 0, 1, 6, 7 }, // Langi/Latin/Tanzania { 194, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16015,16015,16080,16080,16107,16107, 0, 0, 0, 5, 22, 187,16136, 0, 0, 5063, 5070, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 65, 65, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 0, 7, 7, {85,71,88}, 0, 0, 1, 7, 7 }, // Ganda/Latin/Uganda - { 195, 7, 239, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,16120,16120,16120,16120, 83, 83, 566, 556, 0, 5, 22, 2, 0, 4, 0, 5077, 1774, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 79, 79, 79, 79, 13, 13, 8, 7, 4, 17, 23, 1, 0, 4, 0, 9, 6, {90,77,87}, 2, 1, 1, 6, 7 }, // Bemba/Latin/Zambia - { 196, 7, 39, 0, 0, 161, 161, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1541, 45, 0, 0,16199,16271,16343,16343,16370,16370, 68, 65, 0, 5, 22, 259,16155, 13, 0, 5086, 5098, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 10, 10, 5, 72, 72, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 42, 5, 0, 12, 10, {67,86,69}, 2, 1, 1, 6, 7 }, // Kabuverdianu/Latin/Cape Verde - { 197, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16383,16383,16433,16433,16460,16460, 574, 563, 0, 5, 22, 2,13654, 4, 0, 5108, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 50, 50, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 0, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Meru/Latin/Kenya - { 198, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16473,16473,16525,16525,16552,16552, 576, 565, 0, 5, 22, 2,16197, 4, 0, 5114, 5122, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 52, 52, 27, 27, 13, 13, 6, 10, 4, 17, 23, 3, 19, 4, 0, 8, 12, {75,69,83}, 2, 1, 7, 6, 7 }, // Kalenjin/Latin/Kenya + { 195, 7, 239, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,16120,16120,16120,16120, 83, 83, 566, 556, 0, 5, 22, 2, 0, 4, 13, 5077, 1774, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 79, 79, 79, 79, 13, 13, 8, 7, 4, 17, 23, 1, 0, 4, 6, 9, 6, {90,77,87}, 2, 1, 1, 6, 7 }, // Bemba/Latin/Zambia + { 196, 7, 39, 0, 0, 161, 161, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1541, 45, 0, 0,16199,16271,16343,16343,16370,16370, 68, 65, 0, 5, 22, 259,16155, 19, 24, 5086, 5098, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 10, 10, 5, 72, 72, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 42, 5, 7, 12, 10, {67,86,69}, 2, 1, 1, 6, 7 }, // Kabuverdianu/Latin/Cape Verde + { 197, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16383,16383,16433,16433,16460,16460, 574, 563, 0, 5, 22, 2,13654, 4, 13, 5108, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 50, 50, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 17, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Meru/Latin/Kenya + { 198, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16473,16473,16525,16525,16552,16552, 576, 565, 0, 5, 22, 2,16197, 4, 13, 5114, 5122, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 52, 52, 27, 27, 13, 13, 6, 10, 4, 17, 23, 3, 19, 4, 6, 8, 12, {75,69,83}, 2, 1, 7, 6, 7 }, // Kalenjin/Latin/Kenya { 199, 7, 148, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,16565,16565,16656,16656,16678,16678, 582, 575, 0, 5, 22, 6,16216, 4, 0, 5134, 5147, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 91, 91, 22, 22, 13, 13, 7, 5, 4, 17, 23, 1, 15, 4, 0, 13, 8, {78,65,68}, 2, 1, 1, 6, 7 }, // Nama/Latin/Namibia { 200, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15285,15285,15346,15346,15373,15373, 549, 531, 0, 5, 22, 182,13534, 4, 0, 5155, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 27, 27, 13, 13, 5, 9, 4, 17, 23, 3, 20, 4, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Machame/Latin/Tanzania - { 201, 7, 82, 0, 0, 459, 459, 6, 1, 14, 2, 3, 38, 5, 47, 40, 10, 46, 12, 1568, 1070, 0, 0,16691,16691,16762,16762, 3613, 3613, 589, 580, 0, 5, 22, 14, 234, 13, 0, 5164, 5170, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 23, 10, 10, 5, 71, 71, 27, 27, 13, 13, 16, 16, 4, 17, 23, 1, 4, 5, 0, 6, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // Colognian/Latin/Germany - { 202, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16789,16789,15346,15346,14722,14722, 605, 596, 0, 5, 22, 2,16231, 4, 0, 740, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 18, 4, 0, 3, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Masai/Latin/Kenya - { 202, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16789,16789,15346,15346,14722,14722, 605, 596, 0, 5, 22, 182,16249, 4, 0, 740, 5181, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 21, 4, 0, 3, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Masai/Latin/Tanzania - { 203, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16846,16846,16910,16910,16944,16944, 614, 602, 0, 5, 22, 187,16136, 13, 0, 5189, 5070, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 64, 64, 34, 34, 13, 13, 6, 6, 4, 17, 23, 3, 19, 5, 0, 7, 7, {85,71,88}, 0, 0, 1, 7, 7 }, // Soga/Latin/Uganda - { 204, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 40, 10, 46, 12, 0, 45, 0, 0,16957,16957,17031,17031, 83, 83, 64, 61, 0, 5, 22, 2,16270, 4, 114, 5196, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 74, 74, 20, 20, 13, 13, 4, 4, 4, 17, 23, 3, 16, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Luyia/Latin/Kenya - { 205, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729,17051,17051,15373,15373, 620, 608, 0, 5, 22, 182,16286, 13, 0, 5203, 5209, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 27, 27, 13, 13, 9, 8, 4, 17, 23, 3, 21, 5, 0, 6, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Asu/Latin/Tanzania - { 206, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17078,17078,17146,17146,17173,17173, 629, 616, 0, 5, 22, 187,16307, 4, 0, 5217, 1650, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 68, 68, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 21, 4, 0, 6, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Teso/Latin/Uganda - { 206, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17078,17078,17146,17146,17173,17173, 629, 616, 0, 5, 22, 2,16328, 4, 0, 5217, 5223, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 68, 68, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 20, 4, 0, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Teso/Latin/Kenya + { 201, 7, 82, 0, 0, 459, 459, 6, 1, 14, 2, 3, 38, 5, 47, 40, 10, 46, 12, 1568, 1070, 0, 0,16691,16691,16762,16762, 3613, 3613, 589, 580, 0, 5, 22, 14, 234, 19, 0, 5164, 5170, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 4, 1, 1, 1, 1, 23, 10, 10, 5, 71, 71, 27, 27, 13, 13, 16, 16, 4, 17, 23, 1, 4, 5, 0, 6, 11, {69,85,82}, 2, 1, 1, 6, 7 }, // Colognian/Latin/Germany + { 202, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16789,16789,15346,15346,14722,14722, 605, 596, 0, 5, 22, 2,16231, 4, 13, 740, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 18, 4, 6, 3, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Masai/Latin/Kenya + { 202, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16789,16789,15346,15346,14722,14722, 605, 596, 0, 5, 22, 182,16249, 4, 13, 740, 5181, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 21, 4, 6, 3, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Masai/Latin/Tanzania + { 203, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,16846,16846,16910,16910,16944,16944, 614, 602, 0, 5, 22, 187,16136, 19, 0, 5189, 5070, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 64, 64, 34, 34, 13, 13, 6, 6, 4, 17, 23, 3, 19, 5, 0, 7, 7, {85,71,88}, 0, 0, 1, 7, 7 }, // Soga/Latin/Uganda + { 204, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 40, 10, 46, 12, 0, 45, 0, 0,16957,16957,17031,17031, 83, 83, 64, 61, 0, 5, 22, 2,16270, 4, 68, 5196, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 74, 74, 20, 20, 13, 13, 4, 4, 4, 17, 23, 3, 16, 4, 6, 7, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Luyia/Latin/Kenya + { 205, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0, 9729, 9729,17051,17051,15373,15373, 620, 608, 0, 5, 22, 182,16286, 19, 0, 5203, 5209, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 27, 27, 13, 13, 9, 8, 4, 17, 23, 3, 21, 5, 0, 6, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Asu/Latin/Tanzania + { 206, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17078,17078,17146,17146,17173,17173, 629, 616, 0, 5, 22, 187,16307, 4, 13, 5217, 1650, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 68, 68, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 21, 4, 6, 6, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Teso/Latin/Uganda + { 206, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17078,17078,17146,17146,17173,17173, 629, 616, 0, 5, 22, 2,16328, 4, 13, 5217, 5223, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 68, 68, 27, 27, 13, 13, 9, 6, 4, 17, 23, 3, 20, 4, 6, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Teso/Latin/Kenya { 207, 7, 67, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {69,82,78}, 2, 1, 1, 6, 7 }, // Saho/Latin/Eritrea { 208, 7, 132, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,17186,17186,17238,17238,17265,17265, 638, 622, 0, 5, 22, 33,16348, 0, 0, 5228, 5239, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 52, 52, 27, 27, 13, 13, 6, 6, 4, 17, 23, 3, 16, 4, 0, 11, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Koyra Chiini/Latin/Mali { 209, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15285,15285,15346,15346,15373,15373, 549, 531, 0, 5, 22, 182,13534, 0, 0, 5244, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 61, 61, 27, 27, 13, 13, 5, 9, 4, 17, 23, 3, 20, 4, 0, 6, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Rwa/Latin/Tanzania { 210, 7, 111, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17278,17278,17346,17346,17373,17373, 644, 628, 0, 5, 22, 2,16364, 0, 0, 5250, 1161, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 68, 68, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 16, 4, 0, 6, 5, {75,69,83}, 2, 1, 7, 6, 7 }, // Luo/Latin/Kenya { 211, 7, 221, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,15051,15051,15124,15124,15151,15151, 0, 0, 0, 5, 22, 187,16018, 4, 0, 5256, 1650, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 73, 73, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 19, 4, 0, 6, 6, {85,71,88}, 0, 0, 1, 7, 7 }, // Chiga/Latin/Uganda - { 212, 7, 145, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17386,17386,17433,17433,17460,17460, 646, 630, 0, 5, 22, 0,16380, 13, 0, 5262, 5279, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 47, 47, 27, 27, 13, 13, 9, 10, 4, 17, 23, 0, 15, 5, 0, 17, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Central Morocco Tamazight/Latin/Morocco + { 212, 7, 145, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17386,17386,17433,17433,17460,17460, 646, 630, 0, 5, 22, 0,16380, 19, 0, 5262, 5279, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 47, 47, 27, 27, 13, 13, 9, 10, 4, 17, 23, 0, 15, 5, 0, 17, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Central Morocco Tamazight/Latin/Morocco { 213, 7, 132, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,17473,17473,17526,17526,17265,17265, 638, 622, 0, 5, 22, 33,16348, 0, 0, 5285, 5239, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 53, 53, 27, 27, 13, 13, 6, 6, 4, 17, 23, 3, 16, 4, 0, 15, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Koyraboro Senni/Latin/Mali { 214, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,17553,17553,17615,17615,17642,17642, 655, 640, 0, 5, 22, 182,13556, 0, 0, 5300, 1585, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 62, 62, 27, 27, 13, 13, 5, 8, 4, 17, 23, 3, 20, 4, 0, 9, 8, {84,90,83}, 2, 0, 1, 6, 7 }, // Shambala/Latin/Tanzania { 215, 13, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,17655,17655,17708,17708,17740,17740, 660, 648, 0, 5, 22, 119,16395, 8, 0, 5309, 2599, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 53, 53, 32, 32, 18, 18, 3, 6, 4, 17, 23, 1, 3, 5, 0, 4, 4, {73,78,82}, 2, 1, 7, 7, 7 }, // Bodo/Devanagari/India - { 218, 2, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0,17758,17758,17802,17802,17826,17802, 0, 0, 0, 5, 22, 121,16398, 13, 0, 5313, 3454, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 44, 44, 24, 24, 16, 24, 2, 2, 4, 17, 23, 1, 42, 5, 0, 7, 5, {82,85,66}, 2, 1, 1, 6, 7 }, // Chechen/Cyrillic/Russia - { 219, 2, 178, 0, 0, 979, 979, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1591, 967, 0, 0,17842,17842,17909,17909,11114,11114, 0, 0, 0, 5, 22, 121,16440, 13, 0, 5320, 5339, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 67, 67, 36, 36, 13, 13, 2, 2, 4, 17, 23, 1, 43, 5, 0, 19, 7, {82,85,66}, 2, 1, 1, 6, 7 }, // Church/Cyrillic/Russia + { 218, 2, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0,17758,17758,17802,17802,17826,17802, 0, 0, 0, 5, 22, 121,16398, 19, 0, 5313, 3454, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 44, 44, 24, 24, 16, 24, 2, 2, 4, 17, 23, 1, 42, 5, 0, 7, 5, {82,85,66}, 2, 1, 1, 6, 7 }, // Chechen/Cyrillic/Russia + { 219, 2, 178, 0, 0, 952, 952, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1591, 967, 0, 0,17842,17842,17909,17909,11114,11114, 0, 0, 0, 5, 22, 121,16440, 19, 0, 5320, 5339, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 10, 10, 5, 67, 67, 36, 36, 13, 13, 2, 2, 4, 17, 23, 1, 43, 5, 0, 19, 7, {82,85,66}, 2, 1, 1, 6, 7 }, // Church/Cyrillic/Russia { 220, 2, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 121, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {82,85,66}, 2, 1, 1, 6, 7 }, // Chuvash/Cyrillic/Russia { 230, 7, 49, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,17945,17945,17994,17994,18021,18021, 663, 654, 0, 5, 22, 32,16483, 0, 0, 5346, 5354, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 49, 49, 27, 27, 13, 13, 5, 6, 4, 17, 23, 2, 17, 4, 0, 8, 16, {67,68,70}, 2, 1, 1, 6, 7 }, // Luba Katanga/Latin/Congo Kinshasa - { 231, 7, 125, 0, 0, 987, 987, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0,18034,18034,18098,18125, 3613, 3613, 668, 660, 441, 5, 22, 14, 8263, 13, 0, 5370, 5370, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 64, 64, 27, 34, 13, 13, 5, 8, 5, 17, 23, 1, 18, 5, 0, 14, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Luxembourgish/Latin/Luxembourg + { 231, 7, 125, 0, 0, 960, 960, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 166, 0, 0,18034,18034,18098,18125, 3613, 3613, 668, 660, 441, 5, 22, 14, 8263, 19, 0, 5370, 5370, 6, 6, 10, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 10, 5, 64, 64, 27, 34, 13, 13, 5, 8, 5, 17, 23, 1, 18, 5, 0, 14, 10, {69,85,82}, 2, 1, 1, 6, 7 }, // Luxembourgish/Latin/Luxembourg { 236, 7, 21, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Walloon/Latin/Belgium { 237, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 46, 13, 97, 398, 0, 0,18159,18159,18230,18230,18257,18257, 673, 668, 0, 5, 22, 32,16500, 0, 0, 5384, 5389, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 71, 71, 27, 27, 13, 13, 3, 3, 4, 17, 23, 4, 14, 4, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Aghem/Latin/Cameroon - { 238, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 97, 398, 0, 0,18270,18270,18339,18339,18366,18366, 676, 671, 0, 5, 22, 32,16514, 13, 0, 5396, 5401, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 69, 69, 27, 27, 13, 13, 10, 9, 4, 17, 23, 4, 15, 5, 0, 5, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // Basaa/Latin/Cameroon + { 238, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 97, 398, 0, 0,18270,18270,18339,18339,18366,18366, 676, 671, 0, 5, 22, 32,16514, 19, 0, 5396, 5401, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 69, 69, 27, 27, 13, 13, 10, 9, 4, 17, 23, 4, 15, 5, 0, 5, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // Basaa/Latin/Cameroon { 239, 7, 156, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,18379,18379,17526,17526,18431,18431, 686, 680, 0, 5, 22, 33,16348, 0, 0, 5409, 5419, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 52, 52, 27, 27, 13, 13, 8, 10, 4, 17, 23, 3, 16, 4, 0, 10, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Zarma/Latin/Niger - { 240, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 12, 13, 97, 398, 0, 0,18444,18444,18488,18488,18515,18515, 694, 690, 0, 5, 22, 32, 0, 13, 0, 5424, 1946, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 44, 44, 27, 27, 13, 13, 5, 6, 4, 17, 23, 4, 0, 5, 0, 5, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // Duala/Latin/Cameroon - { 241, 7, 187, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,18528,18528,18577,18577,18604,18604, 0, 0, 0, 5, 22, 33,16529, 13, 0, 5429, 5434, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 16, 5, 0, 5, 7, {88,79,70}, 0, 0, 1, 6, 7 }, // Jola Fonyi/Latin/Senegal - { 242, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,18617,18617,18701,18701,18730,18730, 699, 696, 0, 5, 22, 32,16545, 13, 0, 5441, 5447, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 84, 84, 29, 29, 13, 13, 7, 9, 4, 17, 23, 4, 16, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Ewondo/Latin/Cameroon - { 243, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 12, 13, 97, 398, 0, 0,18743,18743,18787,18787,18815,18815, 706, 705, 0, 5, 22, 32,16561, 13, 0, 5454, 5459, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 44, 44, 28, 28, 13, 13, 6, 7, 4, 17, 23, 4, 4, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Bafia/Latin/Cameroon - { 244, 7, 146, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,18828,18828,18886,18886,18913,18913, 712, 712, 0, 5, 22, 260, 0, 41, 0, 5466, 5471, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 58, 58, 27, 27, 13, 13, 8, 10, 4, 17, 23, 3, 0, 6, 0, 5, 10, {77,90,78}, 2, 1, 7, 6, 7 }, // Makhuwa Meetto/Latin/Mozambique - { 245, 7, 37, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,18926,18926,18999,18999,19026,19026, 720, 722, 0, 5, 22, 32,16565, 4, 0, 5481, 5487, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 73, 73, 27, 27, 13, 13, 5, 5, 4, 17, 23, 4, 10, 4, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Mundang/Latin/Cameroon - { 246, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 15, 16, 97, 398, 0, 0,19039,19039,19127,19127,19156,19156, 725, 727, 0, 5, 22, 32,16575, 13, 0, 5494, 5500, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 88, 88, 29, 29, 13, 13, 4, 4, 4, 17, 23, 4, 13, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Kwasio/Latin/Cameroon - { 247, 7, 254, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 46, 448, 22,19169,19169,19247,19247,19284,19284, 729, 731, 0, 5, 22, 117, 0, 4, 0, 5507, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 12, 7, 78, 78, 37, 37, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 0, 9, 0, {83,83,80}, 2, 1, 1, 6, 7 }, // Nuer/Latin/South Sudan - { 248, 2, 178, 0, 0, 997, 997, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1614, 253, 0, 0,19297,19297,19367,19367,19387,19387, 731, 733, 1219, 1224, 22, 121,16588, 13, 0, 5516, 5525, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 30, 6, 10, 5, 70, 70, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 46, 5, 0, 9, 9, {82,85,66}, 2, 1, 1, 6, 7 }, // Sakha/Cyrillic/Russia + { 240, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 12, 13, 97, 398, 0, 0,18444,18444,18488,18488,18515,18515, 694, 690, 0, 5, 22, 32, 0, 19, 0, 5424, 1946, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 44, 44, 27, 27, 13, 13, 5, 6, 4, 17, 23, 4, 0, 5, 0, 5, 8, {88,65,70}, 0, 0, 1, 6, 7 }, // Duala/Latin/Cameroon + { 241, 7, 187, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,18528,18528,18577,18577,18604,18604, 0, 0, 0, 5, 22, 33,16529, 19, 0, 5429, 5434, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 49, 49, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 16, 5, 0, 5, 7, {88,79,70}, 0, 0, 1, 6, 7 }, // Jola Fonyi/Latin/Senegal + { 242, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,18617,18617,18701,18701,18730,18730, 699, 696, 0, 5, 22, 32,16545, 19, 0, 5441, 5447, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 84, 84, 29, 29, 13, 13, 7, 9, 4, 17, 23, 4, 16, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Ewondo/Latin/Cameroon + { 243, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 12, 13, 97, 398, 0, 0,18743,18743,18787,18787,18815,18815, 706, 705, 0, 5, 22, 32,16561, 19, 0, 5454, 5459, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 44, 44, 28, 28, 13, 13, 6, 7, 4, 17, 23, 4, 4, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Bafia/Latin/Cameroon + { 244, 7, 146, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,18828,18828,18886,18886,18913,18913, 712, 712, 0, 5, 22, 260, 0, 8, 0, 5466, 5471, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 58, 58, 27, 27, 13, 13, 8, 10, 4, 17, 23, 3, 0, 5, 0, 5, 10, {77,90,78}, 2, 1, 7, 6, 7 }, // Makhuwa Meetto/Latin/Mozambique + { 245, 7, 37, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 97, 398, 0, 0,18926,18926,18999,18999,19026,19026, 720, 722, 0, 5, 22, 32,16565, 4, 13, 5481, 5487, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 73, 73, 27, 27, 13, 13, 5, 5, 4, 17, 23, 4, 10, 4, 6, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Mundang/Latin/Cameroon + { 246, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 40, 11, 15, 16, 97, 398, 0, 0,19039,19039,19127,19127,19156,19156, 725, 727, 0, 5, 22, 32,16575, 19, 0, 5494, 5500, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 88, 88, 29, 29, 13, 13, 4, 4, 4, 17, 23, 4, 13, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Kwasio/Latin/Cameroon + { 247, 7, 254, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 46, 448, 22,19169,19169,19247,19247,19284,19284, 729, 731, 0, 5, 22, 117, 0, 4, 13, 5507, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 9, 12, 7, 78, 78, 37, 37, 13, 13, 2, 2, 4, 17, 23, 1, 0, 4, 6, 9, 0, {83,83,80}, 2, 1, 1, 6, 7 }, // Nuer/Latin/South Sudan + { 248, 2, 178, 0, 0, 970, 970, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 10, 1614, 253, 0, 0,19297,19297,19367,19367,19387,19387, 731, 733, 1219, 1224, 22, 121,16588, 19, 0, 5516, 5525, 6, 6, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 30, 6, 10, 5, 70, 70, 20, 20, 13, 13, 2, 2, 5, 17, 23, 1, 46, 5, 0, 9, 9, {82,85,66}, 2, 1, 1, 6, 7 }, // Sakha/Cyrillic/Russia { 249, 7, 210, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 0, 0,19400,19400,19459,19459,19486,19486, 733, 735, 0, 5, 22, 182,16634, 0, 0, 5534, 5543, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 59, 59, 27, 27, 13, 13, 9, 9, 4, 17, 23, 3, 18, 4, 0, 9, 9, {84,90,83}, 2, 0, 1, 6, 7 }, // Sangu/Latin/Tanzania { 251, 7, 156, 0, 0, 0, 0, 6, 0, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 97, 398, 0, 0,17473,17473,17526,17526,17265,17265, 686, 680, 0, 5, 22, 33,16348, 0, 0, 5552, 5419, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 53, 53, 27, 27, 13, 13, 8, 10, 4, 17, 23, 3, 16, 4, 0, 13, 5, {88,79,70}, 0, 0, 1, 6, 7 }, // Tasawaq/Latin/Niger - { 252, 35, 121, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,19499,19499,19499,19499, 83, 83, 0, 0, 0, 5, 22, 6,16652, 4, 0, 5565, 5567, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 29, 29, 29, 29, 13, 13, 2, 2, 4, 17, 23, 1, 8, 4, 0, 2, 4, {76,82,68}, 2, 1, 1, 6, 7 }, // Vai/Vai/Liberia - { 252, 7, 121, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,19528,19528,19528,19528, 83, 83, 0, 0, 0, 5, 22, 6,16660, 4, 0, 5571, 5574, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 47, 47, 47, 47, 13, 13, 2, 2, 4, 17, 23, 1, 13, 4, 0, 3, 8, {76,82,68}, 2, 1, 1, 6, 7 }, // Vai/Latin/Liberia - { 253, 7, 206, 0, 0, 267, 267, 6, 1, 13, 2, 3, 4, 5, 9, 15, 16, 17, 18, 420, 70, 0, 0,19575,19575,19627,19627,19654,19654, 0, 0, 0, 5, 22, 0, 0, 41, 0, 5582, 5588, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 6, 0, 6, 6, {67,72,70}, 2, 0, 1, 6, 7 }, // Walser/Latin/Switzerland - { 254, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 398, 0, 0,19667,19667,19737,19737,19757,19757, 742, 744, 0, 5, 22, 32, 0, 13, 0, 5594, 5600, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 70, 70, 20, 20, 13, 13, 8, 8, 4, 17, 23, 4, 0, 5, 0, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Yangben/Latin/Cameroon - { 256, 7, 197, 0, 0, 708, 708, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 0, 0,19770,19770,19823,19823, 3373, 3373, 750, 752, 0, 5, 22, 14, 3032, 13, 0, 5607, 2381, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 10, 5, 53, 53, 27, 27, 13, 13, 12, 11, 5, 17, 23, 1, 19, 5, 0, 9, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Asturian/Latin/Spain - { 257, 7, 37, 1008, 1008, 1019, 1035, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 17, 18, 1450, 70, 0, 0,19850,19850,19850,19850,19909,19909, 762, 763, 0, 5, 22, 32,16673, 8, 0, 5616, 5621, 11, 11, 16, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 59, 59, 59, 59, 24, 24, 8, 13, 4, 17, 23, 4, 5, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Ngomba/Latin/Cameroon - { 258, 7, 37, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 17, 18, 80, 1644, 0, 0,19933,19933,19933,19933,19986,19986, 0, 0, 0, 5, 22, 32,14657, 41, 0, 5628, 5632, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 53, 53, 53, 53, 20, 20, 2, 2, 4, 17, 23, 4, 9, 6, 0, 4, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Kako/Latin/Cameroon + { 252, 35, 121, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,19499,19499,19499,19499, 83, 83, 0, 0, 0, 5, 22, 6,16652, 4, 13, 5565, 5567, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 29, 29, 29, 29, 13, 13, 2, 2, 4, 17, 23, 1, 8, 4, 6, 2, 4, {76,82,68}, 2, 1, 1, 6, 7 }, // Vai/Vai/Liberia + { 252, 7, 121, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 0, 45, 10, 22,19528,19528,19528,19528, 83, 83, 0, 0, 0, 5, 22, 6,16660, 4, 13, 5571, 5574, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 12, 7, 47, 47, 47, 47, 13, 13, 2, 2, 4, 17, 23, 1, 13, 4, 6, 3, 8, {76,82,68}, 2, 1, 1, 6, 7 }, // Vai/Latin/Liberia + { 253, 7, 206, 0, 0, 267, 267, 6, 1, 13, 2, 3, 4, 5, 9, 15, 16, 17, 18, 420, 70, 0, 0,19575,19575,19627,19627,19654,19654, 0, 0, 0, 5, 22, 0, 0, 8, 0, 5582, 5588, 6, 6, 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 52, 52, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 6, 6, {67,72,70}, 2, 0, 1, 6, 7 }, // Walser/Latin/Switzerland + { 254, 7, 37, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 15, 16, 97, 398, 0, 0,19667,19667,19737,19737,19757,19757, 742, 744, 0, 5, 22, 32, 0, 19, 24, 5594, 5600, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 70, 70, 20, 20, 13, 13, 8, 8, 4, 17, 23, 4, 0, 5, 7, 6, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Yangben/Latin/Cameroon + { 256, 7, 197, 0, 0, 687, 687, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 355, 259, 0, 0,19770,19770,19823,19823, 3373, 3373, 750, 752, 0, 5, 22, 14, 3032, 19, 0, 5607, 2381, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 22, 6, 10, 5, 53, 53, 27, 27, 13, 13, 12, 11, 5, 17, 23, 1, 19, 5, 0, 9, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Asturian/Latin/Spain + { 257, 7, 37, 981, 981, 992, 1008, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 17, 18, 1450, 70, 0, 0,19850,19850,19850,19850,19909,19909, 762, 763, 0, 5, 22, 32,16673, 8, 0, 5616, 5621, 11, 11, 16, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 59, 59, 59, 59, 24, 24, 8, 13, 4, 17, 23, 4, 5, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Ngomba/Latin/Cameroon + { 258, 7, 37, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 17, 18, 80, 1644, 0, 0,19933,19933,19933,19933,19986,19986, 0, 0, 0, 5, 22, 32,14657, 8, 0, 5628, 5632, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 53, 53, 53, 53, 20, 20, 2, 2, 4, 17, 23, 4, 9, 5, 0, 4, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Kako/Latin/Cameroon { 259, 7, 37, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1450, 70, 0, 0,20006,20006,20006,20006,20054,20054, 0, 0, 0, 5, 22, 32,16678, 8, 0, 5639, 5644, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 10, 10, 5, 48, 48, 48, 48, 20, 20, 2, 2, 4, 17, 23, 4, 5, 5, 0, 5, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Meta/Latin/Cameroon { 260, 7, 37, 0, 0, 0, 0, 6, 1, 0, 2, 3, 4, 5, 9, 15, 16, 10, 11, 1654, 45, 0, 0,20074,20074,20074,20074, 83, 83, 770, 776, 0, 5, 22, 32,16683, 8, 0, 5651, 5667, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 32, 8, 10, 5,110,110,110,110, 13, 13, 9, 8, 4, 17, 23, 4, 9, 5, 0, 16, 7, {88,65,70}, 0, 0, 1, 6, 7 }, // Ngiemboon/Latin/Cameroon { 261, 7, 197, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Aragonese/Latin/Spain - { 272, 46, 18, 0, 0, 1044, 1044, 6, 0, 1, 2, 69, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22,20184,20184,20310,20310,20394,20394, 0, 0, 1241, 5, 22, 122,16692, 0, 0, 5674, 5686, 6, 6, 12, 12, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7,126,126, 84, 84, 38, 38, 2, 2, 8, 17, 23, 1, 69, 4, 0, 12, 14, {66,68,84}, 2, 1, 7, 6, 7 }, // Chakma/Chakma/Bangladesh - { 272, 46, 100, 0, 0, 1044, 1044, 6, 0, 1, 2, 69, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22,20184,20184,20310,20310,20394,20394, 0, 0, 1241, 5, 22, 119,16761, 0, 0, 5674, 5700, 6, 6, 12, 12, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7,126,126, 84, 84, 38, 38, 2, 2, 8, 17, 23, 1, 87, 4, 0, 12, 10, {73,78,82}, 2, 1, 7, 7, 7 }, // Chakma/Chakma/India + { 272, 46, 18, 0, 0, 1017, 1017, 6, 0, 1, 2, 69, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22,20184,20184,20310,20310,20394,20394, 0, 0, 1241, 5, 22, 122,16692, 0, 31, 5674, 5686, 6, 6, 12, 12, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7,126,126, 84, 84, 38, 38, 2, 2, 8, 17, 23, 1, 69, 4, 6, 12, 14, {66,68,84}, 2, 1, 7, 6, 7 }, // Chakma/Chakma/Bangladesh + { 272, 46, 100, 0, 0, 1017, 1017, 6, 0, 1, 2, 69, 4, 5, 9, 10, 11, 12, 13, 174, 259, 10, 22,20184,20184,20310,20310,20394,20394, 0, 0, 1241, 5, 22, 119,16761, 0, 31, 5674, 5700, 6, 6, 12, 12, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7,126,126, 84, 84, 38, 38, 2, 2, 8, 17, 23, 1, 87, 4, 6, 12, 10, {73,78,82}, 2, 1, 7, 7, 7 }, // Chakma/Chakma/India { 290, 11, 100, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 119, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {73,78,82}, 2, 1, 7, 7, 7 }, // Manipuri/Bengali/India { 309, 100, 232, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 316, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {86,78,68}, 0, 0, 1, 6, 7 }, // Tai Dam/Tai Viet/Vietnam { 312, 7, 37, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 32, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 0, 5, 0, 0, 0, {88,65,70}, 0, 0, 1, 6, 7 }, // Akoose/Latin/Cameroon - { 313, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,20432,20432,20432,20432, 83,20518, 0, 0, 0, 5, 22, 6, 0, 41, 0, 5710, 5722, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 86, 86, 86, 86, 13, 13, 2, 2, 4, 17, 23, 1, 0, 6, 0, 12, 22, {85,83,68}, 2, 1, 7, 6, 7 }, // Lakota/Latin/United States + { 313, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,20432,20432,20432,20432, 83,20518, 0, 0, 0, 5, 22, 6, 0, 8, 0, 5710, 5722, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 86, 86, 86, 86, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 12, 22, {85,83,68}, 2, 1, 7, 6, 7 }, // Lakota/Latin/United States { 314, 9, 145, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 15, 16, 40, 11, 97, 398, 0, 0,20531,20531,14781,14781, 83, 83, 523, 499, 0, 5, 22, 0,15938, 0, 0, 5744, 4911, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 16, 8, 10, 5, 47, 47, 29, 29, 13, 13, 6, 8, 4, 17, 23, 0, 14, 4, 0, 8, 6, {77,65,68}, 2, 1, 1, 6, 7 }, // Standard Moroccan Tamazight/Tifinagh/Morocco { 315, 7, 43, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 6, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {67,76,80}, 0, 0, 1, 6, 7 }, // Mapuche/Latin/Chile - { 316, 1, 103, 0, 0, 0, 0, 53, 19, 20, 21, 23, 71, 73, 28, 10, 11, 12, 13, 53, 70, 10, 22,20578,20578,20578,20578,20635,20635, 779, 784, 0, 5, 22, 42,16848, 13, 0, 5752, 5766, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 57, 57, 57, 57, 13, 13, 3, 3, 4, 17, 23, 5, 13, 5, 0, 14, 5, {73,81,68}, 0, 0, 6, 5, 6 }, // Central Kurdish/Arabic/Iraq - { 316, 1, 102, 0, 0, 0, 0, 53, 19, 20, 21, 23, 71, 73, 28, 10, 11, 12, 13, 53, 70, 0, 0,20578,20578,20578,20578,20635,20635, 779, 784, 0, 5, 22, 0,16861, 13, 0, 5752, 5771, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 57, 57, 13, 13, 3, 3, 4, 17, 23, 0, 12, 5, 0, 14, 5, {73,82,82}, 0, 0, 6, 5, 5 }, // Central Kurdish/Arabic/Iran - { 317, 7, 82, 0, 0, 183, 183, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 113, 1, 1,20648,20648,20700,20700,20727,20727, 782, 787, 0, 5, 22, 14,16873, 13, 0, 5776, 5790, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 9, 4, 52, 52, 27, 27, 13, 13, 9, 10, 4, 17, 23, 1, 26, 5, 0, 14, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Lower Sorbian/Latin/Germany - { 318, 7, 82, 0, 0, 183, 183, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 113, 1, 460,20740,20740,20792,20792,20819,20819, 782, 797, 1249, 5, 22, 14,16899, 13, 0, 5796, 5811, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 9, 12, 52, 52, 27, 27, 13, 13, 9, 9, 5, 17, 23, 1, 28, 5, 0, 15, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Upper Sorbian/Latin/Germany + { 316, 1, 103, 0, 0, 0, 0, 53, 19, 20, 21, 23, 71, 73, 28, 10, 11, 12, 13, 53, 70, 10, 22,20578,20578,20578,20578,20635,20635, 779, 784, 0, 5, 22, 42,16848, 19, 0, 5752, 5766, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 12, 7, 57, 57, 57, 57, 13, 13, 3, 3, 4, 17, 23, 5, 13, 5, 0, 14, 5, {73,81,68}, 0, 0, 6, 5, 6 }, // Central Kurdish/Arabic/Iraq + { 316, 1, 102, 0, 0, 0, 0, 53, 19, 20, 21, 23, 71, 73, 28, 10, 11, 12, 13, 53, 70, 0, 0,20578,20578,20578,20578,20635,20635, 779, 784, 0, 5, 22, 0,16861, 19, 0, 5752, 5771, 6, 6, 6, 6, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 17, 10, 10, 5, 57, 57, 57, 57, 13, 13, 3, 3, 4, 17, 23, 0, 12, 5, 0, 14, 5, {73,82,82}, 0, 0, 6, 5, 5 }, // Central Kurdish/Arabic/Iran + { 317, 7, 82, 0, 0, 183, 183, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 113, 1, 1,20648,20648,20700,20700,20727,20727, 782, 787, 0, 5, 22, 14,16873, 19, 0, 5776, 5790, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 9, 4, 52, 52, 27, 27, 13, 13, 9, 10, 4, 17, 23, 1, 26, 5, 0, 14, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Lower Sorbian/Latin/Germany + { 318, 7, 82, 0, 0, 183, 183, 6, 1, 0, 2, 3, 4, 5, 9, 40, 10, 46, 12, 420, 113, 1, 460,20740,20740,20792,20792,20819,20819, 782, 797, 1249, 5, 22, 14,16899, 19, 0, 5796, 5811, 6, 6, 7, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 9, 12, 52, 52, 27, 27, 13, 13, 9, 9, 5, 17, 23, 1, 28, 5, 0, 15, 6, {69,85,82}, 2, 1, 1, 6, 7 }, // Upper Sorbian/Latin/Germany { 319, 7, 37, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 32, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 4, 0, 5, 0, 0, 0, {88,65,70}, 0, 0, 1, 6, 7 }, // Kenyang/Latin/Cameroon { 320, 7, 38, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 224, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {67,65,68}, 2, 0, 7, 6, 7 }, // Mohawk/Latin/Canada { 321, 75, 91, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 201, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {71,78,70}, 0, 0, 1, 6, 7 }, // Nko/Nko/Guinea - { 322, 7, 260, 0, 0, 1056, 1056, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 40, 10, 1686, 166, 0, 0,20832,20832,20900,20900,20927,20927, 0, 0, 0, 5, 22, 0, 0, 13, 0, 5817, 5826, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 68, 68, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 9, 6, {0,0,0}, 2, 1, 1, 6, 7 }, // Prussian/Latin/World + { 322, 7, 260, 0, 0, 1029, 1029, 6, 1, 14, 2, 3, 4, 5, 9, 40, 10, 40, 10, 1686, 166, 0, 0,20832,20832,20900,20900,20927,20927, 0, 0, 0, 5, 22, 0, 0, 19, 0, 5817, 5826, 6, 6, 8, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 27, 8, 10, 5, 68, 68, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 9, 6, {0,0,0}, 2, 1, 1, 6, 7 }, // Prussian/Latin/World { 323, 7, 90, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 285, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {71,84,81}, 2, 1, 7, 6, 7 }, // Kiche/Latin/Guatemala { 324, 7, 205, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 145, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {83,69,75}, 2, 0, 1, 6, 7 }, // Southern Sami/Latin/Sweden { 325, 7, 205, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 145, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {83,69,75}, 2, 0, 1, 6, 7 }, // Lule Sami/Latin/Sweden - { 326, 7, 73, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1713, 581, 176, 167,20940,21009,21081,21081, 83,21108, 791, 806, 0, 5, 22, 14, 242, 13, 0, 5832, 5843, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 9, 4, 69, 72, 27, 27, 13, 13, 3, 3, 4, 17, 23, 1, 4, 5, 0, 11, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Inari Sami/Latin/Finland + { 326, 7, 73, 0, 0, 0, 0, 6, 1, 14, 2, 3, 4, 5, 9, 10, 11, 12, 13, 1713, 581, 176, 167,20940,21009,21081,21081, 83,21108, 791, 806, 0, 5, 22, 14, 242, 19, 0, 5832, 5843, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 8, 9, 4, 69, 72, 27, 27, 13, 13, 3, 3, 4, 17, 23, 1, 4, 5, 0, 11, 5, {69,85,82}, 2, 1, 1, 6, 7 }, // Inari Sami/Latin/Finland { 327, 7, 73, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Skolt Sami/Latin/Finland { 328, 7, 13, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 225, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {65,85,68}, 2, 1, 7, 6, 7 }, // Warlpiri/Latin/Australia { 346, 1, 102, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 15, 16, 17, 18, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 714, 1254, 22, 320,16927, 8, 0, 5848, 3182, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 39, 23, 3, 26, 5, 0, 7, 5, {73,82,82}, 0, 0, 6, 5, 5 }, // Mazanderani/Arabic/Iran { 349, 1, 102, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 5855, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 11, 0, {73,82,82}, 0, 0, 6, 5, 5 }, // Northern Luri/Arabic/Iran { 349, 1, 103, 0, 0, 0, 0, 53, 19, 20, 21, 52, 33, 53, 56, 10, 11, 12, 13, 53, 70, 10, 22, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 42, 0, 8, 0, 5855, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 3, 3, 4, 1, 1, 1, 1, 17, 10, 12, 7, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 5, 0, 5, 0, 11, 0, {73,81,68}, 0, 0, 6, 5, 6 }, // Northern Luri/Arabic/Iraq - { 357, 6, 97, 168, 168, 1064, 1064, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 406, 390, 153, 27, 1902, 1902, 1902, 1902, 1949, 1949, 58, 55, 0, 5, 22, 131,16953, 4, 0, 5866, 5868, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 8, 13, 6, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 10, 4, 0, 2, 14, {72,75,68}, 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/Hong Kong - { 357, 5, 44, 168, 168, 1064, 1064, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 390, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 0, 5, 22, 227, 3051, 4, 0, 5882, 5884, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 12, 4, 0, 2, 7, {67,78,89}, 2, 1, 7, 6, 7 }, // Cantonese/Simplified Han/China + { 357, 6, 97, 168, 168, 1037, 1037, 6, 0, 1, 2, 3, 4, 5, 9, 42, 43, 44, 45, 406, 390, 153, 27, 1902, 1902, 1902, 1902, 1949, 1949, 58, 55, 0, 5, 22, 131,16953, 4, 13, 5866, 5868, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 14, 8, 13, 6, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 10, 4, 6, 2, 14, {72,75,68}, 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/Hong Kong + { 357, 5, 44, 168, 168, 1037, 1037, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 377, 390, 142, 27, 1902, 1902, 1929, 1929, 1949, 1949, 58, 55, 0, 5, 22, 227, 3051, 4, 13, 5882, 5884, 5, 5, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 13, 8, 11, 6, 27, 27, 20, 20, 13, 13, 2, 2, 4, 17, 23, 1, 12, 4, 6, 2, 7, {67,78,89}, 2, 1, 7, 6, 7 }, // Cantonese/Simplified Han/China { 358, 138, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 156, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {85,83,68}, 2, 1, 7, 6, 7 }, // Osage/Osage/United States { 360, 7, 260, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {0,0,0}, 2, 1, 1, 6, 7 }, // Ido/Latin/World { 361, 7, 260, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {0,0,0}, 2, 1, 1, 6, 7 }, // Lojban/Latin/World { 362, 7, 106, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 14, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {69,85,82}, 2, 1, 1, 6, 7 }, // Sicilian/Latin/Italy { 363, 1, 102, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 0, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 0, 0, 5, 0, 0, 0, {73,82,82}, 0, 0, 6, 5, 5 }, // Southern Kurdish/Arabic/Iran { 364, 1, 163, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 170, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 2, 0, 5, 0, 0, 0, {80,75,82}, 2, 0, 7, 6, 7 }, // Western Balochi/Arabic/Pakistan - { 365, 7, 170, 0, 0, 922, 931, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,21121,21121,21176,21176,21200,21200, 0, 0, 1293, 5, 22, 173,16963, 4, 0, 5891, 4632, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 55, 55, 24, 24, 13, 13, 2, 2, 8, 17, 23, 1, 55, 4, 0, 8, 9, {80,72,80}, 2, 1, 7, 6, 7 }, // Cebuano/Latin/Philippines + { 365, 7, 170, 0, 0, 895, 904, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 27, 521, 10, 22,21121,21121,21176,21176,21200,21200, 0, 0, 1293, 5, 22, 173,16963, 4, 13, 5891, 4632, 6, 6, 9, 8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 18, 6, 12, 7, 55, 55, 24, 24, 13, 13, 2, 2, 8, 17, 23, 1, 55, 4, 6, 8, 9, {80,72,80}, 2, 1, 7, 6, 7 }, // Cebuano/Latin/Philippines { 366, 2, 178, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 121, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 1, 0, 5, 0, 0, 0, {82,85,66}, 2, 1, 1, 6, 7 }, // Erzya/Cyrillic/Russia { 367, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 156, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {85,83,68}, 2, 1, 7, 6, 7 }, // Chickasaw/Latin/United States { 368, 7, 225, 0, 0, 0, 0, 6, 0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, 53, 70, 0, 0, 56, 56, 56, 56, 83, 83, 0, 0, 0, 5, 22, 156, 0, 8, 0, 0, 0, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 17, 10, 10, 5, 27, 27, 27, 27, 13, 13, 2, 2, 4, 17, 23, 3, 0, 5, 0, 0, 0, {85,83,68}, 2, 1, 7, 6, 7 }, // Muscogee/Latin/United States @@ -1906,30 +1906,29 @@ static const char16_t list_pattern_part_data[] = { 0x20, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xb13, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xb13, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x200f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, -0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xa05, 0xa24, 0xa47, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x75, 0x74, -0x61, 0x71, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x74, 0x61, 0x71, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x219, 0x69, -0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4d5, 0x43c, 0x4d5, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x6fd, 0x20, 0x25, 0x32, -0x25, 0x31, 0x20, 0x6fd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xdc3, -0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0xa0, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x32, 0x25, -0x31, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x79, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x61, -0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x63, 0x68, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xbae, 0xbb1, 0xbcd, 0xbb1, 0xbc1, -0xbae, 0xbcd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4bb, 0x4d9, 0x43c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xc2e, 0xc30, 0xc3f, -0xc2f, 0xc41, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0xe41, 0xe25, 0xe30, 0x25, 0x32, -0x25, 0x31, 0x20, 0x6d, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x77, -0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648, 0x631, -0x20, 0x25, 0x32, 0x25, 0x32, 0x60c, 0x20, 0x25, 0x31, 0x25, 0x31, 0x20, 0x76, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, -0x76, 0xe0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x28, 0x63, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, -0x28, 0x63, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x5d0, 0x5d5, 0x5df, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, -0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x61, 0x20, 0x25, -0x32, 0x25, 0x31, 0x2c, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, -0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, -0x31, 0x2c, 0x20, 0x61, 0x6b, 0x6b, 0x65, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x6b, 0x6b, 0x65, 0x64, 0x20, -0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x13a0, 0x13b4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x13a0, 0x13b4, 0x20, 0x25, 0x32, 0x25, -0x31, 0x20, 0x438, 0x486, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x28, 0x6e, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, -0x443, 0x43e, 0x43d, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, -0x31, 0x2c, 0x20, 0x1e3f, 0x62, 0x25b, 0x6e, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x70, 0x254, -0x70, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xd804, 0xdd03, 0xd804, 0xdd33, 0xd804, 0xdd03, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x62, -0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x540c, 0x25, 0x32 +0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xa05, 0xa24, 0xa47, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x219, 0x69, 0x20, +0x25, 0x32, 0x25, 0x31, 0x20, 0x4d5, 0x43c, 0x4d5, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x6fd, 0x20, 0x25, 0x32, 0x25, +0x31, 0x20, 0x6fd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xdc3, 0xdc4, +0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0xa0, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, +0x20, 0x69, 0x79, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x79, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x61, 0x20, +0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x63, 0x68, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xbae, 0xbb1, 0xbcd, 0xbb1, 0xbc1, 0xbae, +0xbcd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4bb, 0x4d9, 0x43c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xc2e, 0xc30, 0xc3f, 0xc2f, +0xc41, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, +0x31, 0x20, 0x6d, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x77, 0x65, +0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648, 0x631, 0x20, +0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0xe0, 0x20, 0x25, 0x32, 0x25, 0x31, +0x2c, 0x20, 0x61, 0x28, 0x63, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x28, 0x63, 0x29, 0x20, 0x25, 0x32, 0x25, +0x31, 0x20, 0x5d0, 0x5d5, 0x5df, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x20, +0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6b, 0x70, +0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, +0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x6b, 0x6b, 0x65, +0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x6b, 0x6b, 0x65, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x13a0, +0x13b4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x13a0, 0x13b4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438, 0x486, 0x20, 0x25, 0x32, +0x25, 0x31, 0x20, 0x61, 0x28, 0x6e, 0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x443, 0x43e, 0x43d, 0x43d, 0x430, 0x20, 0x25, +0x32, 0x25, 0x31, 0x2c, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x1e3f, 0x62, 0x25b, 0x6e, +0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x70, 0x254, 0x70, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, +0xd804, 0xdd03, 0xd804, 0xdd33, 0xd804, 0xdd03, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x62, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x540c, +0x25, 0x32 }; static const char16_t single_character_data[] = { @@ -4151,12 +4150,10 @@ static const char16_t currency_display_name_data[] = { }; static const char16_t currency_format_data[] = { -0x25, 0x31, 0x25, 0x32, 0x25, 0x32, 0x25, 0x31, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x25, 0x32, -0x25, 0x31, 0x4b, 0x25, 0x32, 0xa0, 0x2d, 0x25, 0x31, 0x28, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x29, 0x25, 0x32, 0x2d, 0x25, -0x31, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x4b, 0x25, 0x31, 0xa0, 0x6b, 0x25, 0x32, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x2d, 0x25, -0x32, 0x2212, 0x25, 0x31, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x44, 0x200f, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x200f, 0x200e, 0x2d, 0x25, -0x31, 0xa0, 0x25, 0x32, 0x200e, 0x25, 0x32, 0x25, 0x31, 0x28, 0x25, 0x32, 0x25, 0x31, 0x29, 0x25, 0x31, 0xa0, 0x4b, 0xa0, -0x25, 0x32, 0x25, 0x32, 0xa0, 0x4d, 0x25, 0x31, 0x25, 0x32, 0x2d, 0x4d, 0x25, 0x31, 0x25, 0x32, 0x2d, 0xa0, 0x25, 0x31 +0x25, 0x31, 0x25, 0x32, 0x25, 0x32, 0x25, 0x31, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x28, 0x25, 0x32, 0x25, 0x31, 0x29, 0x25, +0x31, 0xa0, 0x25, 0x32, 0x28, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x29, 0x28, 0x25, 0x31, 0x25, 0x32, 0x29, 0x28, 0x25, 0x32, +0xa0, 0x25, 0x31, 0x29, 0x25, 0x32, 0x2d, 0x25, 0x31, 0x25, 0x32, 0x2212, 0x25, 0x31, 0x200e, 0x25, 0x32, 0xa0, 0x25, 0x31, +0x200e, 0x28, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x29, 0x25, 0x32, 0x2d, 0xa0, 0x25, 0x31 }; static const char16_t endonyms_data[] = { @@ -6540,6 +6537,7 @@ static const unsigned char script_code_list[] = "Hanb" // Han with Bopomofo "Jamo" // Jamo ; + static const unsigned char country_code_list[] = "ZZ\0" // AnyCountry "AF\0" // Afghanistan diff --git a/src/corelib/thread/qatomic_cxx11.h b/src/corelib/thread/qatomic_cxx11.h index 7386aee1266..9669554515a 100644 --- a/src/corelib/thread/qatomic_cxx11.h +++ b/src/corelib/thread/qatomic_cxx11.h @@ -191,26 +191,26 @@ template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<2>::isLockFree() template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; # define Q_ATOMIC_INT64_IS_SUPPORTED # if ATOMIC_LLONG_LOCK_FREE == 2 -# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT16_TEST_AND_SET_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() { return true; } # elif ATOMIC_LLONG_LOCK_FREE == 1 -# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT16_TEST_AND_SET_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_SOMETIMES_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT64_TEST_AND_SET_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_SOMETIMES_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_SOMETIMES_NATIVE template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() { return false; } # else -# define Q_ATOMIC_INT16_REFERENCE_COUNTING_IS_NEVER_NATIVE -# define Q_ATOMIC_INT16_TEST_AND_SET_IS_NEVER_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_NEVER_NATIVE -# define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_NEVER_NATIVE +# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_NEVER_NATIVE +# define Q_ATOMIC_INT64_TEST_AND_SET_IS_NEVER_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_NEVER_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_NEVER_NATIVE template <> Q_DECL_CONSTEXPR inline bool QAtomicTraits<8>::isLockFree() { return false; } diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 155bff1758d..d5752534082 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -67,7 +67,9 @@ QThreadData::QThreadData(int initialRefCount) QThreadData::~QThreadData() { +#if QT_CONFIG(thread) Q_ASSERT(_ref.loadRelaxed() == 0); +#endif // In the odd case that Qt is running on a secondary thread, the main // thread instance will have been dereffed asunder because of the deref in diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 47539141bdc..5cd410c0b0d 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -375,10 +375,11 @@ static int fromOffsetString(QStringView offsetString, bool *valid) noexcept \reentrant \brief The QDate class provides date functions. - - A QDate object represents a particular date. This can be expressed as a - calendar date, i.e. year, month, and day numbers, in the proleptic Gregorian - calendar. + A QDate object represents a particular day, regardless of calendar, + locale or other settings used when creating it or supplied by the system. + It can report the year, month and day of the month that represent the + day with respect to the proleptic Gregorian calendar or any calendar supplied + as a QCalendar object. A QDate object is typically created by giving the year, month, and day numbers explicitly. Note that QDate interprets year numbers less than 100 as @@ -1676,9 +1677,8 @@ qint64 QDate::daysTo(QDate d) const /*! \fn bool QDate::operator==(QDate d) const - Returns \c true if this date is equal to \a d; otherwise returns - false. - + Returns \c true if this date and \a d represent the same day, otherwise + \c false. */ /*! @@ -1686,6 +1686,8 @@ qint64 QDate::daysTo(QDate d) const Returns \c true if this date is different from \a d; otherwise returns \c false. + + \sa operator==() */ /*! diff --git a/src/corelib/time/qhijricalendar_data_p.h b/src/corelib/time/qhijricalendar_data_p.h index 2708db66bec..5445375c3ce 100644 --- a/src/corelib/time/qhijricalendar_data_p.h +++ b/src/corelib/time/qhijricalendar_data_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE // GENERATED PART STARTS HERE /* - This part of the file was generated on 2020-01-30 from the + This part of the file was generated on 2020-04-07 from the Common Locale Data Repository v36 http://www.unicode.org/cldr/ @@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE */ static const QCalendarLocale locale_data[] = { - // lang script terr sLng long sSrt shrt sNrw naro Sizes... + // lang script terr sLong long sShrt short sNarw narow Sizes... { 1, 0, 0, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// C/AnyScript/AnyCountry { 3, 7, 69, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Oromo/Latin/Ethiopia { 3, 7, 111, 0, 0, 106, 106, 184, 184,106,106, 78, 78, 26, 26 },// Oromo/Latin/Kenya diff --git a/src/corelib/time/qjalalicalendar_data_p.h b/src/corelib/time/qjalalicalendar_data_p.h index cc0d23da1f2..c21c106e603 100644 --- a/src/corelib/time/qjalalicalendar_data_p.h +++ b/src/corelib/time/qjalalicalendar_data_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE // GENERATED PART STARTS HERE /* - This part of the file was generated on 2020-01-30 from the + This part of the file was generated on 2020-04-07 from the Common Locale Data Repository v36 http://www.unicode.org/cldr/ @@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE */ static const QCalendarLocale locale_data[] = { - // lang script terr sLng long sSrt shrt sNrw naro Sizes... + // lang script terr sLong long sShrt short sNarw narow Sizes... { 1, 0, 0, 0, 0, 83, 83, 130, 153, 83, 83, 47, 47, 23, 26 },// C/AnyScript/AnyCountry { 3, 7, 69, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Oromo/Latin/Ethiopia { 3, 7, 111, 0, 0, 0, 0, 153, 153, 83, 83, 83, 83, 26, 26 },// Oromo/Latin/Kenya diff --git a/src/corelib/time/qromancalendar_data_p.h b/src/corelib/time/qromancalendar_data_p.h index 94b8fe0d18d..8a0ec14d496 100644 --- a/src/corelib/time/qromancalendar_data_p.h +++ b/src/corelib/time/qromancalendar_data_p.h @@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE // GENERATED PART STARTS HERE /* - This part of the file was generated on 2020-01-30 from the + This part of the file was generated on 2020-04-07 from the Common Locale Data Repository v36 http://www.unicode.org/cldr/ @@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE */ static const QCalendarLocale locale_data[] = { - // lang script terr sLng long sSrt shrt sNrw naro Sizes... + // lang script terr sLong long sShrt short sNarw narow Sizes... { 1, 0, 0, 0, 0, 85, 85, 132, 155, 85, 85, 47, 47, 23, 26 },// C/AnyScript/AnyCountry { 3, 7, 69, 181, 181, 291, 291, 132, 132,110,110, 47, 47, 23, 23 },// Oromo/Latin/Ethiopia { 3, 7, 111, 181, 181, 291, 291, 338, 132,110,110, 47, 47, 23, 23 },// Oromo/Latin/Kenya diff --git a/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp index 5cb8155dcc7..fc3653752ac 100644 --- a/src/corelib/time/qtimezoneprivate_android.cpp +++ b/src/corelib/time/qtimezoneprivate_android.cpp @@ -102,7 +102,7 @@ void QAndroidTimeZonePrivate::init(const QByteArray &ianaId) for (int style = 1; m_id.isEmpty() && style-- > 0;) { for (int dst = 1; m_id.isEmpty() && dst-- > 0;) { m_id = match(androidTimeZone.callObjectMethod( - "getDisplayName", "(ZI;)Ljava/lang/String;", bool(dst), style)); + "getDisplayName", "(ZI)Ljava/lang/String;", bool(dst), style)); } } } diff --git a/src/corelib/time/qtimezoneprivate_data_p.h b/src/corelib/time/qtimezoneprivate_data_p.h index 822af9c703d..6d2bbc83c18 100644 --- a/src/corelib/time/qtimezoneprivate_data_p.h +++ b/src/corelib/time/qtimezoneprivate_data_p.h @@ -115,8 +115,8 @@ struct QUtcData { // GENERATED PART STARTS HERE /* - This part of the file was generated on 2019-10-24 from the - Common Locale Data Repository v36 supplemental/windowsZones.xml file $Revision$ + This part of the file was generated on 2020-02-28 from the + Common Locale Data Repository v36 file supplemental/windowsZones.xml http://www.unicode.org/cldr/ diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h index a57f61f381d..f1b7fea1f95 100644 --- a/src/corelib/time/qtimezoneprivate_p.h +++ b/src/corelib/time/qtimezoneprivate_p.h @@ -290,6 +290,16 @@ Q_DECL_CONSTEXPR inline bool operator==(const QTzTransitionRule &lhs, const QTzT Q_DECL_CONSTEXPR inline bool operator!=(const QTzTransitionRule &lhs, const QTzTransitionRule &rhs) noexcept { return !operator==(lhs, rhs); } +// These are stored separately from QTzTimeZonePrivate so that they can be +// cached, avoiding the need to re-parse them from disk constantly. +struct QTzTimeZoneCacheEntry +{ + QVector m_tranTimes; + QVector m_tranRules; + QList m_abbreviations; + QByteArray m_posixRule; +}; + class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate { QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default; @@ -337,13 +347,11 @@ private: QVector getPosixTransitions(qint64 msNear) const; Data dataForTzTransition(QTzTransitionTime tran) const; - QVector m_tranTimes; - QVector m_tranRules; - QList m_abbreviations; #if QT_CONFIG(icu) mutable QSharedDataPointer m_icu; #endif - QByteArray m_posixRule; + QTzTimeZoneCacheEntry cached_data; + QVector tranCache() const { return cached_data.m_tranTimes; } }; #endif // Q_OS_UNIX diff --git a/src/corelib/time/qtimezoneprivate_tz.cpp b/src/corelib/time/qtimezoneprivate_tz.cpp index 5e55c6897da..01f9a6cce0e 100644 --- a/src/corelib/time/qtimezoneprivate_tz.cpp +++ b/src/corelib/time/qtimezoneprivate_tz.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 Crimson AS ** Copyright (C) 2013 John Layt ** Contact: https://www.qt.io/licensing/ ** @@ -42,6 +43,7 @@ #include "private/qlocale_tools_p.h" #include +#include #include #include #include @@ -637,7 +639,7 @@ QTzTimeZonePrivate::QTzTimeZonePrivate() // Create a named time zone QTzTimeZonePrivate::QTzTimeZonePrivate(const QByteArray &ianaId) { - init(ianaId); + init(ianaId.isEmpty() ? systemTimeZoneId() : ianaId); } QTzTimeZonePrivate::~QTzTimeZonePrivate() @@ -649,14 +651,26 @@ QTzTimeZonePrivate *QTzTimeZonePrivate::clone() const return new QTzTimeZonePrivate(*this); } -void QTzTimeZonePrivate::init(const QByteArray &ianaId) +class QTzTimeZoneCache { +public: + QTzTimeZoneCacheEntry fetchEntry(const QByteArray &ianaId); + +private: + QTzTimeZoneCacheEntry findEntry(const QByteArray &ianaId); + QHash m_cache; + QMutex m_mutex; +}; + +QTzTimeZoneCacheEntry QTzTimeZoneCache::findEntry(const QByteArray &ianaId) +{ + QTzTimeZoneCacheEntry ret; QFile tzif; if (ianaId.isEmpty()) { // Open system tz tzif.setFileName(QStringLiteral("/etc/localtime")); if (!tzif.open(QIODevice::ReadOnly)) - return; + return ret; } else { // Open named tz, try modern path first, if fails try legacy path tzif.setFileName(QLatin1String("/usr/share/zoneinfo/") + QString::fromLocal8Bit(ianaId)); @@ -669,9 +683,9 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId) if (PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset() && (begin == zoneInfo.constEnd() || PosixZone::parse(begin, zoneInfo.constEnd()).hasValidOffset())) { - m_id = m_posixRule = ianaId; + ret.m_posixRule = ianaId; } - return; + return ret; } } } @@ -682,59 +696,59 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId) bool ok = false; QTzHeader hdr = parseTzHeader(ds, &ok); if (!ok || ds.status() != QDataStream::Ok) - return; + return ret; QVector tranList = parseTzTransitions(ds, hdr.tzh_timecnt, false); if (ds.status() != QDataStream::Ok) - return; + return ret; QVector typeList = parseTzTypes(ds, hdr.tzh_typecnt); if (ds.status() != QDataStream::Ok) - return; + return ret; QMap abbrevMap = parseTzAbbreviations(ds, hdr.tzh_charcnt, typeList); if (ds.status() != QDataStream::Ok) - return; + return ret; parseTzLeapSeconds(ds, hdr.tzh_leapcnt, false); if (ds.status() != QDataStream::Ok) - return; + return ret; typeList = parseTzIndicators(ds, typeList, hdr.tzh_ttisstdcnt, hdr.tzh_ttisgmtcnt); if (ds.status() != QDataStream::Ok) - return; + return ret; // If version 2 then parse the second block of data if (hdr.tzh_version == '2' || hdr.tzh_version == '3') { ok = false; QTzHeader hdr2 = parseTzHeader(ds, &ok); if (!ok || ds.status() != QDataStream::Ok) - return; + return ret; tranList = parseTzTransitions(ds, hdr2.tzh_timecnt, true); if (ds.status() != QDataStream::Ok) - return; + return ret; typeList = parseTzTypes(ds, hdr2.tzh_typecnt); if (ds.status() != QDataStream::Ok) - return; + return ret; abbrevMap = parseTzAbbreviations(ds, hdr2.tzh_charcnt, typeList); if (ds.status() != QDataStream::Ok) - return; + return ret; parseTzLeapSeconds(ds, hdr2.tzh_leapcnt, true); if (ds.status() != QDataStream::Ok) - return; + return ret; typeList = parseTzIndicators(ds, typeList, hdr2.tzh_ttisstdcnt, hdr2.tzh_ttisgmtcnt); if (ds.status() != QDataStream::Ok) - return; - m_posixRule = parseTzPosixRule(ds); + return ret; + ret.m_posixRule = parseTzPosixRule(ds); if (ds.status() != QDataStream::Ok) - return; + return ret; } // Translate the TZ file into internal format // Translate the array index based tz_abbrind into list index const int size = abbrevMap.size(); - m_abbreviations.clear(); - m_abbreviations.reserve(size); + ret.m_abbreviations.clear(); + ret.m_abbreviations.reserve(size); QVector abbrindList; abbrindList.reserve(size); for (auto it = abbrevMap.cbegin(), end = abbrevMap.cend(); it != end; ++it) { - m_abbreviations.append(it.value()); + ret.m_abbreviations.append(it.value()); abbrindList.append(it.key()); } for (int i = 0; i < typeList.size(); ++i) @@ -752,7 +766,7 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId) // Now for each transition time calculate and store our rule: const int tranCount = tranList.count();; - m_tranTimes.reserve(tranCount); + ret.m_tranTimes.reserve(tranCount); // The DST offset when in effect: usually stable, usually an hour: int lastDstOff = 3600; for (int i = 0; i < tranCount; i++) { @@ -806,24 +820,48 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId) rule.abbreviationIndex = tz_type.tz_abbrind; // If the rule already exist then use that, otherwise add it - int ruleIndex = m_tranRules.indexOf(rule); + int ruleIndex = ret.m_tranRules.indexOf(rule); if (ruleIndex == -1) { - m_tranRules.append(rule); - tran.ruleIndex = m_tranRules.size() - 1; + ret.m_tranRules.append(rule); + tran.ruleIndex = ret.m_tranRules.size() - 1; } else { tran.ruleIndex = ruleIndex; } tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000; - m_tranTimes.append(tran); + ret.m_tranTimes.append(tran); } - if (m_tranTimes.isEmpty() && m_posixRule.isEmpty()) + + return ret; +} + +QTzTimeZoneCacheEntry QTzTimeZoneCache::fetchEntry(const QByteArray &ianaId) +{ + QMutexLocker locker(&m_mutex); + + // search the cache... + const auto& it = m_cache.find(ianaId); + if (it != m_cache.constEnd()) + return *it; + + // ... or build a new entry from scratch + QTzTimeZoneCacheEntry ret = findEntry(ianaId); + m_cache[ianaId] = ret; + return ret; +} + +void QTzTimeZonePrivate::init(const QByteArray &ianaId) +{ + // System ID defaults to UTC, so is never empty; and our callers default to + // the system ID if what they're given is empty. + Q_ASSERT(!ianaId.isEmpty()); + static QTzTimeZoneCache tzCache; + const auto &entry = tzCache.fetchEntry(ianaId); + if (entry.m_tranTimes.isEmpty() && entry.m_posixRule.isEmpty()) return; // Invalid after all ! - if (ianaId.isEmpty()) - m_id = systemTimeZoneId(); - else - m_id = ianaId; + cached_data = std::move(entry); + m_id = ianaId; } QLocale::Country QTzTimeZonePrivate::country() const @@ -903,12 +941,12 @@ QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType, } // Otherwise is strange sequence, so work backwards through trans looking for first match, if any - auto it = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(), + auto it = std::partition_point(tranCache().cbegin(), tranCache().cend(), [currentMSecs](const QTzTransitionTime &at) { return at.atMSecsSinceEpoch <= currentMSecs; }); - while (it != m_tranTimes.cbegin()) { + while (it != tranCache().cbegin()) { --it; tran = dataForTzTransition(*it); int offset = tran.daylightTimeOffset; @@ -944,7 +982,7 @@ int QTzTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch) const bool QTzTimeZonePrivate::hasDaylightTime() const { // TODO Perhaps cache as frequently accessed? - for (const QTzTransitionRule &rule : m_tranRules) { + for (const QTzTransitionRule &rule : cached_data.m_tranRules) { if (rule.dstOffset != 0) return true; } @@ -960,11 +998,11 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime { QTimeZonePrivate::Data data; data.atMSecsSinceEpoch = tran.atMSecsSinceEpoch; - QTzTransitionRule rule = m_tranRules.at(tran.ruleIndex); + QTzTransitionRule rule = cached_data.m_tranRules.at(tran.ruleIndex); data.standardTimeOffset = rule.stdOffset; data.daylightTimeOffset = rule.dstOffset; data.offsetFromUtc = rule.stdOffset + rule.dstOffset; - data.abbreviation = QString::fromUtf8(m_abbreviations.at(rule.abbreviationIndex)); + data.abbreviation = QString::fromUtf8(cached_data.m_abbreviations.at(rule.abbreviationIndex)); return data; } @@ -972,37 +1010,37 @@ QVector QTzTimeZonePrivate::getPosixTransitions(qint64 m { const int year = QDateTime::fromMSecsSinceEpoch(msNear, Qt::UTC).date().year(); // The Data::atMSecsSinceEpoch of the single entry if zone is constant: - qint64 atTime = m_tranTimes.isEmpty() ? msNear : m_tranTimes.last().atMSecsSinceEpoch; - return calculatePosixTransitions(m_posixRule, year - 1, year + 1, atTime); + qint64 atTime = tranCache().isEmpty() ? msNear : tranCache().last().atMSecsSinceEpoch; + return calculatePosixTransitions(cached_data.m_posixRule, year - 1, year + 1, atTime); } QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const { // If the required time is after the last transition (or there were none) // and we have a POSIX rule, then use it: - if (!m_posixRule.isEmpty() - && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch)) { + if (!cached_data.m_posixRule.isEmpty() + && (tranCache().isEmpty() || tranCache().last().atMSecsSinceEpoch < forMSecsSinceEpoch)) { QVector posixTrans = getPosixTransitions(forMSecsSinceEpoch); auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(), [forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) { return at.atMSecsSinceEpoch <= forMSecsSinceEpoch; }); // Use most recent, if any in the past; or the first if we have no other rules: - if (it > posixTrans.cbegin() || (m_tranTimes.isEmpty() && it < posixTrans.cend())) { + if (it > posixTrans.cbegin() || (tranCache().isEmpty() && it < posixTrans.cend())) { QTimeZonePrivate::Data data = *(it > posixTrans.cbegin() ? it - 1 : it); data.atMSecsSinceEpoch = forMSecsSinceEpoch; return data; } } - if (m_tranTimes.isEmpty()) // Only possible if !isValid() + if (tranCache().isEmpty()) // Only possible if !isValid() return invalidData(); // Otherwise, use the rule for the most recent or first transition: - auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(), + auto last = std::partition_point(tranCache().cbegin(), tranCache().cend(), [forMSecsSinceEpoch] (const QTzTransitionTime &at) { return at.atMSecsSinceEpoch <= forMSecsSinceEpoch; }); - if (last > m_tranTimes.cbegin()) + if (last > tranCache().cbegin()) --last; Data data = dataForTzTransition(*last); data.atMSecsSinceEpoch = forMSecsSinceEpoch; @@ -1018,8 +1056,8 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince { // If the required time is after the last transition (or there were none) // and we have a POSIX rule, then use it: - if (!m_posixRule.isEmpty() - && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < afterMSecsSinceEpoch)) { + if (!cached_data.m_posixRule.isEmpty() + && (tranCache().isEmpty() || tranCache().last().atMSecsSinceEpoch < afterMSecsSinceEpoch)) { QVector posixTrans = getPosixTransitions(afterMSecsSinceEpoch); auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(), [afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) { @@ -1030,19 +1068,19 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince } // Otherwise, if we can find a valid tran, use its rule: - auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(), + auto last = std::partition_point(tranCache().cbegin(), tranCache().cend(), [afterMSecsSinceEpoch] (const QTzTransitionTime &at) { return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch; }); - return last != m_tranTimes.cend() ? dataForTzTransition(*last) : invalidData(); + return last != tranCache().cend() ? dataForTzTransition(*last) : invalidData(); } QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const { // If the required time is after the last transition (or there were none) // and we have a POSIX rule, then use it: - if (!m_posixRule.isEmpty() - && (m_tranTimes.isEmpty() || m_tranTimes.last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)) { + if (!cached_data.m_posixRule.isEmpty() + && (tranCache().isEmpty() || tranCache().last().atMSecsSinceEpoch < beforeMSecsSinceEpoch)) { QVector posixTrans = getPosixTransitions(beforeMSecsSinceEpoch); auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(), [beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) { @@ -1051,15 +1089,15 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs if (it > posixTrans.cbegin()) return *--it; // It fell between the last transition (if any) and the first of the POSIX rule: - return m_tranTimes.isEmpty() ? invalidData() : dataForTzTransition(m_tranTimes.last()); + return tranCache().isEmpty() ? invalidData() : dataForTzTransition(tranCache().last()); } // Otherwise if we can find a valid tran then use its rule - auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(), + auto last = std::partition_point(tranCache().cbegin(), tranCache().cend(), [beforeMSecsSinceEpoch] (const QTzTransitionTime &at) { return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch; }); - return last > m_tranTimes.cbegin() ? dataForTzTransition(*--last) : invalidData(); + return last > tranCache().cbegin() ? dataForTzTransition(*--last) : invalidData(); } static long getSymloopMax() @@ -1088,15 +1126,15 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const { // Check TZ env var first, if not populated try find it QByteArray ianaId = qgetenv("TZ"); - if (!ianaId.isEmpty() && ianaId.at(0) == ':') - ianaId = ianaId.mid(1); // The TZ value can be ":/etc/localtime" which libc considers // to be a "default timezone", in which case it will be read // by one of the blocks below, so unset it here so it is not // considered as a valid/found ianaId - if (ianaId == "/etc/localtime") + if (ianaId == ":/etc/localtime") ianaId.clear(); + else if (ianaId.startsWith(':')) + ianaId = ianaId.mid(1); // On most distros /etc/localtime is a symlink to a real file so extract name from the path if (ianaId.isEmpty()) { @@ -1115,36 +1153,6 @@ QByteArray QTzTimeZonePrivate::systemTimeZoneId() const } } - // On Debian Etch up to Jessie, /etc/localtime is a regular file while the actual name is in /etc/timezone - if (ianaId.isEmpty()) { - QFile tzif(QStringLiteral("/etc/timezone")); - if (tzif.open(QIODevice::ReadOnly)) { - // TODO QTextStream inefficient, replace later - QTextStream ts(&tzif); - if (!ts.atEnd()) - ianaId = ts.readLine().toUtf8(); - } - } - - // On some Red Hat distros /etc/localtime is real file with name held in /etc/sysconfig/clock - // in a line like ZONE="Europe/Oslo" or TIMEZONE="Europe/Oslo" - if (ianaId.isEmpty()) { - QFile tzif(QStringLiteral("/etc/sysconfig/clock")); - if (tzif.open(QIODevice::ReadOnly)) { - // TODO QTextStream inefficient, replace later - QTextStream ts(&tzif); - QString line; - while (ianaId.isEmpty() && !ts.atEnd() && ts.status() == QTextStream::Ok) { - line = ts.readLine(); - if (line.startsWith(QLatin1String("ZONE="))) { - ianaId = line.midRef(6, line.size() - 7).toUtf8(); - } else if (line.startsWith(QLatin1String("TIMEZONE="))) { - ianaId = line.midRef(10, line.size() - 11).toUtf8(); - } - } - } - } - // Some systems (e.g. uClibc) have a default value for $TZ in /etc/TZ: if (ianaId.isEmpty()) { QFile zone(QStringLiteral("/etc/TZ")); diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index 46f87f4902c..ca5b7ffd55d 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -1483,7 +1483,7 @@ uint qHash(long double key, uint seed) noexcept /*! \fn template QList QHash::uniqueKeys() const \since 4.2 - \obsolete + \obsolete Use QMultiHash for storing multiple values with the same key. Returns a list containing all the keys in the map. Keys that occur multiple times in the map (because items were inserted with insertMulti(), or @@ -1529,8 +1529,8 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QList QHash::values(const Key &key) const - \obsolete \overload + \obsolete Use QMultiHash for storing multiple values with the same key. Returns a list of all the values associated with the \a key, from the most recently inserted to the least recently inserted. @@ -2095,6 +2095,7 @@ uint qHash(long double key, uint seed) noexcept /*! \fn template QHash::iterator &QHash::iterator::operator--() + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. The prefix -- operator (\c{--i}) makes the preceding item current and returns an iterator pointing to the new current item. @@ -2107,6 +2108,7 @@ uint qHash(long double key, uint seed) noexcept /*! \fn template QHash::iterator QHash::iterator::operator--(int) + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. \overload @@ -2116,6 +2118,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::iterator QHash::iterator::operator+(int j) const + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. Returns an iterator to the item at \a j positions forward from this iterator. (If \a j is negative, the iterator goes backward.) @@ -2127,6 +2130,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::iterator QHash::iterator::operator-(int j) const + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. Returns an iterator to the item at \a j positions backward from this iterator. (If \a j is negative, the iterator goes forward.) @@ -2137,6 +2141,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::iterator &QHash::iterator::operator+=(int j) + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. Advances the iterator by \a j items. (If \a j is negative, the iterator goes backward.) @@ -2145,6 +2150,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::iterator &QHash::iterator::operator-=(int j) + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. Makes the iterator go back by \a j items. (If \a j is negative, the iterator goes forward.) @@ -2288,6 +2294,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::const_iterator &QHash::const_iterator::operator--() + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. The prefix -- operator (\c{--i}) makes the preceding item current and returns an iterator pointing to the new current item. @@ -2299,6 +2306,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::const_iterator QHash::const_iterator::operator--(int) + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. \overload @@ -2308,6 +2316,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::const_iterator QHash::const_iterator::operator+(int j) const + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. Returns an iterator to the item at \a j positions forward from this iterator. (If \a j is negative, the iterator goes backward.) @@ -2318,6 +2327,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::const_iterator QHash::const_iterator::operator-(int j) const + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. Returns an iterator to the item at \a j positions backward from this iterator. (If \a j is negative, the iterator goes forward.) @@ -2328,6 +2338,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::const_iterator &QHash::const_iterator::operator+=(int j) + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. Advances the iterator by \a j items. (If \a j is negative, the iterator goes backward.) @@ -2338,6 +2349,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::const_iterator &QHash::const_iterator::operator-=(int j) + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. Makes the iterator go back by \a j items. (If \a j is negative, the iterator goes forward.) @@ -2432,6 +2444,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::key_iterator &QHash::key_iterator::operator--() + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. The prefix -- operator (\c{--i}) makes the preceding item current and returns an iterator pointing to the new current item. @@ -2443,6 +2456,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::key_iterator QHash::key_iterator::operator--(int) + \obsolete This operator is deprecated in order to align with std::unordered_map functionality. \overload diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc index 8cfa665ffdf..9efc1bb48a5 100644 --- a/src/corelib/tools/qiterator.qdoc +++ b/src/corelib/tools/qiterator.qdoc @@ -637,12 +637,9 @@ \sa hasNext(), next(), peekPrevious() */ -/*! \fn template bool QListIterator::hasPrevious() const - \fn template bool QVectorIterator::hasPrevious() const - \fn template bool QSetIterator::hasPrevious() const - \fn template bool QMutableListIterator::hasPrevious() const - \fn template bool QMutableVectorIterator::hasPrevious() const +/*! \fn template bool QMutableSetIterator::hasPrevious() const + \obsolete Deprecated in order to align with std::unordered_set functionality. Returns \c true if there is at least one item behind the iterator, i.e. the iterator is \e not at the front of the container; @@ -651,10 +648,35 @@ \sa hasNext(), previous() */ +/*! \fn template bool QListIterator::hasPrevious() const + \fn template bool QVectorIterator::hasPrevious() const + \fn template bool QSetIterator::hasPrevious() const + \fn template bool QMutableListIterator::hasPrevious() const + \fn template bool QMutableVectorIterator::hasPrevious() const + + Returns \c true if there is at least one item behind the iterator, + i.e. the iterator is \e not at the front of the container; + otherwise returns \c false. + + \sa hasNext(), previous() +*/ + +/*! + \fn template const T &QMutableSetIterator::previous() + \obsolete Deprecated in order to align with std::unordered_set functionality. + + Returns the previous item and moves the iterator back by one + position. + + Calling this function on an iterator located at the front of the + container leads to undefined results. + + \sa hasPrevious(), peekPrevious(), next() +*/ + /*! \fn template const T &QListIterator::previous() \fn template const T &QVectorIterator::previous() \fn template const T &QSetIterator::previous() - \fn template const T &QMutableSetIterator::previous() Returns the previous item and moves the iterator back by one position. @@ -677,10 +699,21 @@ \sa hasPrevious(), peekPrevious(), next() */ +/*! + \fn template const T &QMutableSetIterator::peekPrevious() const + \obsolete Deprecated in order to align with std::unordered_set functionality. + + Returns the previous item without moving the iterator. + + Calling this function on an iterator located at the front of the + container leads to undefined results. + + \sa hasPrevious(), previous(), peekNext() +*/ + /*! \fn template const T &QListIterator::peekPrevious() const \fn template const T &QVectorIterator::peekPrevious() const \fn template const T &QSetIterator::peekPrevious() const - \fn template const T &QMutableSetIterator::peekPrevious() const Returns the previous item without moving the iterator. @@ -701,12 +734,25 @@ \sa hasPrevious(), previous(), peekNext() */ +/*! + \fn template bool QMutableSetIterator::findNext(const T &value) + \obsolete Deprecated in order to align with std::unordered_set functionality. + + Searches for \a value starting from the current iterator position + forward. Returns \c true if \a value is found; otherwise returns \c false. + + After the call, if \a value was found, the iterator is positioned + just after the matching item; otherwise, the iterator is + positioned at the back of the container. + + \sa findPrevious() +*/ + /*! \fn template bool QListIterator::findNext(const T &value) \fn template bool QVectorIterator::findNext(const T &value) \fn template bool QSetIterator::findNext(const T &value) \fn template bool QMutableListIterator::findNext(const T &value) \fn template bool QMutableVectorIterator::findNext(const T &value) - \fn template bool QMutableSetIterator::findNext(const T &value) Searches for \a value starting from the current iterator position forward. Returns \c true if \a value is found; otherwise returns \c false. diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp index dde66ed0936..3afd23d76b4 100644 --- a/src/corelib/tools/qline.cpp +++ b/src/corelib/tools/qline.cpp @@ -374,7 +374,7 @@ QDataStream &operator>>(QDataStream &stream, QLine &line) */ /*! - \enum QLineF::IntersectType + \enum QLineF::IntersectionType Describes the intersection between two lines. diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index 1dcbaeec946..6c9eba0c66f 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -740,7 +740,7 @@ void QMapDataBase::freeData(QMapDataBase *d) /*! \fn template QList QMap::uniqueKeys() const \since 4.2 - \obsolete + \obsolete Use QMultiMap for storing multiple values with the same key. Returns a list containing all the keys in the map in ascending order. Keys that occur multiple times in the map (because items @@ -802,9 +802,8 @@ void QMapDataBase::freeData(QMapDataBase *d) */ /*! \fn template QList QMap::values(const Key &key) const - \obsolete - \overload + \obsolete Use QMultiMap for maps storing multiple values with the same key. Returns a list containing all the values associated with key \a key, from the most recently inserted to the least recently @@ -1162,7 +1161,7 @@ void QMapDataBase::freeData(QMapDataBase *d) */ /*! \fn template QMap::iterator QMap::insertMulti(const Key &key, const T &value) - \obsolete + \obsolete Use QMultiMap for storing multiple values with the same key. Inserts a new item with the key \a key and a value of \a value. @@ -1177,7 +1176,7 @@ void QMapDataBase::freeData(QMapDataBase *d) /*! \fn template QMap::iterator QMap::insertMulti(const_iterator pos, const Key &key, const T &value) \overload \since 5.1 - \obsolete + \obsolete Use QMultiMap for storing multiple values with the same key. Inserts a new item with the key \a key and value \a value and with hint \a pos suggesting where to do the insert. @@ -1196,7 +1195,7 @@ void QMapDataBase::freeData(QMapDataBase *d) /*! \fn template QMap &QMap::unite(const QMap &other) - \obsolete + \obsolete Use QMultiMap for storing multiple values with the same key. Inserts all the items in the \a other map into this map. If a key is common to both maps, the resulting map will contain the diff --git a/src/corelib/tools/qscopeguard.h b/src/corelib/tools/qscopeguard.h index 6a5bc6cc61e..d288fd63fcc 100644 --- a/src/corelib/tools/qscopeguard.h +++ b/src/corelib/tools/qscopeguard.h @@ -96,6 +96,7 @@ private: template QScopeGuard(F(&)()) -> QScopeGuard; #endif +//! [qScopeGuard] template #if __has_cpp_attribute(nodiscard) Q_REQUIRED_RESULT diff --git a/src/corelib/tools/qscopeguard.qdoc b/src/corelib/tools/qscopeguard.qdoc index 572934d8906..b36299d2960 100644 --- a/src/corelib/tools/qscopeguard.qdoc +++ b/src/corelib/tools/qscopeguard.qdoc @@ -69,7 +69,7 @@ QT_BEGIN_NAMESPACE */ /*! - \fn template const QScopeGuard qScopeGuard(F f) + \fn [qScopeGuard] template QScopeGuard::type> qScopeGuard(F &&f) \inmodule QtCore \relates QScopeGuard \brief The qScopeGuard function can be used to call a function at the end diff --git a/src/corelib/tools/qset.qdoc b/src/corelib/tools/qset.qdoc index 33a0697e129..42dd1288aca 100644 --- a/src/corelib/tools/qset.qdoc +++ b/src/corelib/tools/qset.qdoc @@ -399,6 +399,7 @@ */ /*! \fn template QSet::reverse_iterator QSet::rbegin() + \obsolete Deprecated in order to align with std::unordered_set functionality. \since 5.6 Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to the first @@ -408,11 +409,13 @@ */ /*! \fn template QSet::const_reverse_iterator QSet::rbegin() const + \obsolete Deprecated in order to align with std::unordered_set functionality. \since 5.6 \overload */ /*! \fn template QSet::const_reverse_iterator QSet::crbegin() const + \obsolete Deprecated in order to align with std::unordered_set functionality. \since 5.6 Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first @@ -422,6 +425,7 @@ */ /*! \fn template QSet::reverse_iterator QSet::rend() + \obsolete Deprecated in order to align with std::unordered_set functionality. \since 5.6 Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past @@ -431,11 +435,13 @@ */ /*! \fn template QSet::const_reverse_iterator QSet::rend() const + \obsolete Deprecated in order to align with std::unordered_set functionality. \since 5.6 \overload */ /*! \fn template QSet::const_reverse_iterator QSet::crend() const + \obsolete Deprecated in order to align with std::unordered_set functionality. \since 5.6 Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to one @@ -507,6 +513,7 @@ /*! \typedef QSet::reverse_iterator \since 5.6 + \obsolete Deprecated in order to align with std::unordered_set functionality. The QSet::reverse_iterator typedef provides an STL-style non-const reverse iterator for QSet. @@ -523,6 +530,7 @@ /*! \typedef QSet::const_reverse_iterator \since 5.6 + \obsolete Deprecated in order to align with std::unordered_set functionality. The QSet::const_reverse_iterator typedef provides an STL-style const reverse iterator for QSet. @@ -921,8 +929,20 @@ /*! \fn template QSet::iterator &QSet::iterator::operator--() + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. + + The prefix -- operator (\c{--it}) makes the preceding item + current and returns an iterator to the new current item. + + Calling this function on QSet::begin() leads to undefined + results. + + \sa operator++() +*/ + +/*! \fn template QSet::const_iterator &QSet::const_iterator::operator--() - \obsolete + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. The prefix -- operator (\c{--it}) makes the preceding item current and returns an iterator to the new current item. @@ -935,8 +955,17 @@ /*! \fn template QSet::iterator QSet::iterator::operator--(int) + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. + + \overload + + The postfix -- operator (\c{it--}) makes the preceding item + current and returns an iterator to the previously current item. +*/ + +/*! \fn template QSet::const_iterator QSet::const_iterator::operator--(int) - \obsolete + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. \overload @@ -946,8 +975,19 @@ /*! \fn template QSet::iterator QSet::iterator::operator+(int j) const + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. + + Returns an iterator to the item at \a j positions forward from + this iterator. (If \a j is negative, the iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-() +*/ + +/*! \fn template QSet::const_iterator QSet::const_iterator::operator+(int j) const - \obsolete + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. Returns an iterator to the item at \a j positions forward from this iterator. (If \a j is negative, the iterator goes backward.) @@ -959,8 +999,19 @@ /*! \fn template QSet::iterator QSet::iterator::operator-(int j) const + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. + + Returns an iterator to the item at \a j positions backward from + this iterator. (If \a j is negative, the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+() +*/ + +/*! \fn template QSet::const_iterator QSet::const_iterator::operator-(int j) const - \obsolete + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. Returns an iterator to the item at \a j positions backward from this iterator. (If \a j is negative, the iterator goes forward.) @@ -972,8 +1023,20 @@ /*! \fn template QSet::iterator &QSet::iterator::operator+=(int j) + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. + + Advances the iterator by \a j items. (If \a j is negative, the + iterator goes backward.) + + This operation can be slow for large \a j values. + + \sa operator-=(), operator+() + +*/ + +/*! \fn template QSet::const_iterator &QSet::const_iterator::operator+=(int j) - \obsolete + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. Advances the iterator by \a j items. (If \a j is negative, the iterator goes backward.) @@ -985,8 +1048,19 @@ /*! \fn template QSet::iterator &QSet::iterator::operator-=(int j) + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. + + Makes the iterator go back by \a j items. (If \a j is negative, + the iterator goes forward.) + + This operation can be slow for large \a j values. + + \sa operator+=(), operator-() +*/ + +/*! \fn template QSet::const_iterator &QSet::const_iterator::operator-=(int j) - \obsolete + \obsolete This operator is deprecated in order to align with std::unordered_set functionality. Makes the iterator go back by \a j items. (If \a j is negative, the iterator goes forward.) diff --git a/src/dbus/qdbusreply.cpp b/src/dbus/qdbusreply.cpp index cd7193e02fe..33bfadd7010 100644 --- a/src/dbus/qdbusreply.cpp +++ b/src/dbus/qdbusreply.cpp @@ -74,6 +74,13 @@ QT_BEGIN_NAMESPACE \sa QDBusMessage, QDBusInterface */ +/*! + \fn template QDBusReply::QDBusReply(const QDBusReply &other) + \since 5.15 + + Constructs a copy of \a other. +*/ + /*! \fn template QDBusReply::QDBusReply(const QDBusMessage &reply) Automatically construct a QDBusReply object from the reply message \a reply, extracting the diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc index b7c731cf437..a9631248496 100644 --- a/src/gui/doc/src/richtext.qdoc +++ b/src/gui/doc/src/richtext.qdoc @@ -1191,16 +1191,16 @@ \li none | dotted | dashed | dot-dash | dot-dot-dash | solid | double | groove | ridge | inset | outset \li Border style for text tables and table cells. \row \li \c border-top-style - \li + \li \li Top border style for table cells. \row \li \c border-bottom-style - \li + \li \li Bottom border style for table cells. \row \li \c border-left-style - \li + \li \li Left border style for table cells. \row \li \c border-right-style - \li + \li \li Right border style for table cells. \row \li \c border-width \li px diff --git a/src/gui/image/qbmphandler_p.h b/src/gui/image/qbmphandler_p.h index fd044fc4420..e1d744e5390 100644 --- a/src/gui/image/qbmphandler_p.h +++ b/src/gui/image/qbmphandler_p.h @@ -98,7 +98,7 @@ struct BMP_INFOHDR { // BMP information header // BMP-Handler, which is also able to read and write the DIB // (Device-Independent-Bitmap) format used internally in the Windows operating // system for OLE/clipboard operations. DIB is a subset of BMP (without file -// header). The Windows-Lighthouse plugin accesses the DIB-functionality. +// header). The Windows platform plugin accesses the DIB-functionality. class QBmpHandler : public QImageIOHandler { diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp index e67b3879815..15ab1b3cd90 100644 --- a/src/gui/image/qiconloader.cpp +++ b/src/gui/image/qiconloader.cpp @@ -797,8 +797,12 @@ QPixmap ScalableEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State if (svgIcon.isNull()) svgIcon = QIcon(filename); - // Simply reuse svg icon engine - return svgIcon.pixmap(size, mode, state); + // Bypass QIcon API, as that will scale by device pixel ratio of the + // highest DPR screen since we're not passing on any QWindow. + if (QIconEngine *engine = svgIcon.data_ptr() ? svgIcon.data_ptr()->engine : nullptr) + return engine->pixmap(size, mode, state); + + return QPixmap(); } QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode, diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 6ddd08d08d9..34d2b8d8c75 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -48,6 +48,11 @@ #if QT_CONFIG(thread) #include #include +#ifdef Q_OS_WASM +// WebAssembly has threads; however we can't block the main thread. +#else +#define QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS +#endif #endif QT_BEGIN_NAMESPACE @@ -227,7 +232,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio } }; -#if QT_CONFIG(thread) +#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS int segments = src->nbytes / (1<<16); segments = std::min(segments, src->height); @@ -281,7 +286,7 @@ void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::Image destData += dest->bytes_per_line; } }; -#if QT_CONFIG(thread) +#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS int segments = src->nbytes / (1<<16); segments = std::min(segments, src->height); @@ -388,7 +393,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im destData += params.bytesPerLine; } }; -#if QT_CONFIG(thread) +#ifdef QT_USE_THREAD_PARALLEL_IMAGE_CONVERSIONS int segments = data->nbytes / (1<<16); segments = std::min(segments, data->height); if (segments > 1) { @@ -426,8 +431,8 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im data->nbytes = params.totalSize; } data->bytes_per_line = params.bytesPerLine; - data->depth = destDepth; } + data->depth = destDepth; data->format = dst_format; return true; } diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp index 3eb1e01863b..5cb7e1328e8 100644 --- a/src/gui/image/qimagereader.cpp +++ b/src/gui/image/qimagereader.cpp @@ -101,7 +101,7 @@ This can be disabled by setting the environment variable \c QT_HIGHDPI_DISABLE_2X_IMAGE_LOADING. - \sa QImageWriter, QImageIOHandler, QImageIOPlugin, QMimeDatabase + \sa QImageWriter, QImageIOHandler, QImageIOPlugin, QMimeDatabase, QColorSpace \sa QImage::devicePixelRatio(), QPixmap::devicePixelRatio(), QIcon, QPainter::drawPixmap(), QPainter::drawImage(), Qt::AA_UseHighDpiPixmaps */ @@ -1152,6 +1152,7 @@ bool QImageReader::autoTransform() const #if QT_DEPRECATED_SINCE(5, 15) /*! \since 5.6 + \obsolete Use QColorSpace conversion on the QImage instead. This is an image format specific function that forces images with gamma information to be gamma corrected to \a gamma. For image formats @@ -1169,6 +1170,7 @@ void QImageReader::setGamma(float gamma) /*! \since 5.6 + \obsolete Use QImage::colorSpace() and QColorSpace::gamma() instead. Returns the gamma level of the decoded image. If setGamma() has been called and gamma correction is supported it will return the gamma set. diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp index 6e74b23f76e..33f5e491c7e 100644 --- a/src/gui/image/qimagewriter.cpp +++ b/src/gui/image/qimagewriter.cpp @@ -47,19 +47,18 @@ \ingroup painting \ingroup io - QImageWriter supports setting format specific options, such as the - gamma level, compression level and quality, prior to storing the + QImageWriter supports setting format specific options, such as + compression level and quality, prior to storing the image. If you do not need such options, you can use QImage::save() or QPixmap::save() instead. To store an image, you start by constructing a QImageWriter object. Pass either a file name or a device pointer, and the image format to QImageWriter's constructor. You can then set - several options, such as the gamma level (by calling setGamma()) - and quality (by calling setQuality()). canWrite() returns \c true if - QImageWriter can write the image (i.e., the image format is - supported and the device is open for writing). Call write() to - write the image to the device. + several options, such as quality (by calling setQuality()). + canWrite() returns \c true if QImageWriter can write the image + (i.e., the image format is supported and the device is open for + writing). Call write() to write the image to the device. If any error occurs when writing the image, write() will return false. You can then call error() to find the type of error that @@ -81,7 +80,7 @@ \snippet qimagewriter/main.cpp 0 - \sa QImageReader, QImageIOHandler, QImageIOPlugin + \sa QImageReader, QImageIOHandler, QImageIOPlugin, QColorSpace */ /*! @@ -500,6 +499,8 @@ int QImageWriter::compression() const #if QT_DEPRECATED_SINCE(5, 15) /*! + \obsolete Use QColorSpace conversion on the QImage instead. + This is an image format specific function that sets the gamma level of the image to \a gamma. For image formats that do not support setting the gamma level, this value is ignored. @@ -515,6 +516,8 @@ void QImageWriter::setGamma(float gamma) } /*! + \obsolete Use QImage::colorSpace() and QColorSpace::gamma() instead. + Returns the gamma level of the image. \sa setGamma() diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index c162b706cbe..a4c5296d9f5 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -78,7 +78,7 @@ static bool qt_pixmap_thread_test() if (qApp->thread() != QThread::currentThread()) { bool fail = false; if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ThreadedPixmaps)) { - printf("Lighthouse plugin does not support threaded pixmaps!\n"); + printf("Platform plugin does not support threaded pixmaps!\n"); fail = true; } if (fail) { diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 1716cbc5579..dc49d8b3244 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -2224,14 +2224,14 @@ QVariant QInputMethodQueryEvent::value(Qt::InputMethodQuery query) const (pressing the stylus tip against the tablet surface is equivalent to a left mouse button). But tablet events also pass through some extra information that the tablet device driver provides; for example, you might want to do - subpixel rendering with higher resolution coordinates (\l hiResGlobalX() - and \l hiResGlobalY()), adjust color brightness based on the \l pressure() - of the tool against the tablet surface, use different brushes depending on - the type of tool in use (\l device()), modulate the brush shape in some way - according to the X-axis and Y-axis tilt of the tool with respect to the - tablet surface (\l xTilt() and \l yTilt()), and use a virtual eraser - instead of a brush if the user switches to the other end of a double-ended - stylus (\l pointerType()). + subpixel rendering with higher resolution coordinates (\l globalPosF()), + adjust color brightness based on the \l pressure() of the tool against the + tablet surface, use different brushes depending on the type of tool in use + (\l deviceType()), modulate the brush shape in some way according to the + X-axis and Y-axis tilt of the tool with respect to the tablet surface + (\l xTilt() and \l yTilt()), and use a virtual eraser instead of a brush if + the user switches to the other end of a double-ended stylus + (\l pointerType()). Every event contains an accept flag that indicates whether the receiver wants the event. You should call QTabletEvent::accept() if you handle the @@ -4572,19 +4572,12 @@ QPointF QTouchEvent::TouchPoint::lastNormalizedPos() const return d->lastNormalizedPos; } +#if QT_DEPRECATED_SINCE(5, 15) /*! - Returns the rect for this touch point, relative to the widget - or QGraphicsItem that received the event. The rect is centered - around the point returned by pos(). - - \note This function returns an empty rect if the device does not report touch point sizes. - - \obsolete This function is deprecated in 5.9 because it returns the outer bounds + \deprecated This function is deprecated since 5.9 because it returns the outer bounds of the touchpoint regardless of rotation, whereas a touchpoint is more correctly modeled as an ellipse at position pos() with ellipseDiameters() which are independent of rotation(). - - \sa scenePos(), ellipseDiameters() */ QRectF QTouchEvent::TouchPoint::rect() const { @@ -4594,16 +4587,10 @@ QRectF QTouchEvent::TouchPoint::rect() const } /*! - Returns the rect for this touch point in scene coordinates. - - \note This function returns an empty rect if the device does not report touch point sizes. - - \obsolete This function is deprecated in 5.9 because it returns the outer bounds + \deprecated This function is deprecated since 5.9 because it returns the outer bounds of the touchpoint regardless of rotation, whereas a touchpoint is more correctly modeled as an ellipse at position scenePos() with ellipseDiameters() which are independent of rotation(). - - \sa scenePos(), ellipseDiameters() */ QRectF QTouchEvent::TouchPoint::sceneRect() const { @@ -4613,16 +4600,10 @@ QRectF QTouchEvent::TouchPoint::sceneRect() const } /*! - Returns the rect for this touch point in screen coordinates. - - \note This function returns an empty rect if the device does not report touch point sizes. - - \obsolete This function is deprecated because it returns the outer bounds of the + \deprecated This function is deprecated since 5.9 because it returns the outer bounds of the touchpoint regardless of rotation, whereas a touchpoint is more correctly modeled as an ellipse at position screenPos() with ellipseDiameters() which are independent of rotation(). - - \sa screenPos(), ellipseDiameters() */ QRectF QTouchEvent::TouchPoint::screenRect() const { @@ -4630,6 +4611,7 @@ QRectF QTouchEvent::TouchPoint::screenRect() const ret.moveCenter(d->screenPos); return ret; } +#endif /*! Returns the pressure of this touch point. The return value is in @@ -4828,6 +4810,7 @@ void QTouchEvent::TouchPoint::setLastNormalizedPos(const QPointF &lastNormalized d->lastNormalizedPos = lastNormalizedPos; } +#if QT_DEPRECATED_SINCE(5, 15) // ### remove the following 3 setRect functions and their usages soon /*! \internal \obsolete @@ -4861,6 +4844,7 @@ void QTouchEvent::TouchPoint::setScreenRect(const QRectF &screenRect) d->screenPos = screenRect.center(); d->ellipseDiameters = screenRect.size(); } +#endif /*! \internal */ void QTouchEvent::TouchPoint::setPressure(qreal pressure) diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 8a4acec2578..05d79ad803b 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -888,10 +888,23 @@ public: QPointF startNormalizedPos() const; QPointF lastNormalizedPos() const; +#if QT_DEPRECATED_SINCE(5, 15) + // All these are actually deprecated since 5.9, in docs + QT_DEPRECATED_VERSION_X_5_15("Use pos() and ellipseDiameters()") QRectF rect() const; + QT_DEPRECATED_VERSION_X_5_15("Use scenePos() and ellipseDiameters()") QRectF sceneRect() const; + QT_DEPRECATED_VERSION_X_5_15("Use screenPos() and ellipseDiameters()") QRectF screenRect() const; + // internal + QT_DEPRECATED_VERSION_X_5_15("Use setPos() and setEllipseDiameters()") + void setRect(const QRectF &rect); // deprecated + QT_DEPRECATED_VERSION_X_5_15("Use setScenePos() and setEllipseDiameters()") + void setSceneRect(const QRectF &sceneRect); // deprecated + QT_DEPRECATED_VERSION_X_5_15("Use setScreenPos() and setEllipseDiameters()") + void setScreenRect(const QRectF &screenRect); // deprecated +#endif qreal pressure() const; qreal rotation() const; QSizeF ellipseDiameters() const; @@ -916,9 +929,6 @@ public: void setLastScenePos(const QPointF &lastScenePos); void setLastScreenPos(const QPointF &lastScreenPos); void setLastNormalizedPos(const QPointF &lastNormalizedPos); - void setRect(const QRectF &rect); // deprecated - void setSceneRect(const QRectF &sceneRect); // deprecated - void setScreenRect(const QRectF &screenRect); // deprecated void setPressure(qreal pressure); void setRotation(qreal angle); void setEllipseDiameters(const QSizeF &dia); diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 0ad6272a7c1..92256078dc7 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -134,6 +134,7 @@ QT_BEGIN_NAMESPACE return __VA_ARGS__; \ } +Q_CORE_EXPORT void qt_call_post_routines(); Q_GUI_EXPORT bool qt_is_gui_used = true; Qt::MouseButtons QGuiApplicationPrivate::mouse_buttons = Qt::NoButton; @@ -685,6 +686,8 @@ QGuiApplication::~QGuiApplication() { Q_D(QGuiApplication); + qt_call_post_routines(); + d->eventDispatcher->closingDown(); d->eventDispatcher = nullptr; @@ -2328,7 +2331,7 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE static bool menuKeyPressAccepted = false; #endif -#if !defined(Q_OS_OSX) +#if !defined(Q_OS_MACOS) // FIXME: Include OS X in this code path by passing the key event through // QPlatformInputContext::filterEvent(). if (e->keyType == QEvent::KeyPress && window) { diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 57a89bb8c2d..cdcb6e8fafd 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -1286,7 +1286,7 @@ QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat QString p = keyName(key, format); -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) if (nativeText) s += p; else diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp index d2e079b57ff..443f5d25520 100644 --- a/src/gui/kernel/qplatformdialoghelper.cpp +++ b/src/gui/kernel/qplatformdialoghelper.cpp @@ -980,7 +980,7 @@ QPlatformDialogHelper::ButtonRole QPlatformDialogHelper::buttonRole(QPlatformDia const int *QPlatformDialogHelper::buttonLayout(Qt::Orientation orientation, ButtonLayout policy) { if (policy == UnknownLayout) { -#if defined (Q_OS_OSX) +#if defined (Q_OS_MACOS) policy = MacLayout; #elif defined (Q_OS_LINUX) || defined (Q_OS_UNIX) policy = KdeLayout; diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 9d90bf5db20..e8f0892b959 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -498,7 +498,7 @@ QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, QEvent::Type QT_DEFINE_QPA_EVENT_HANDLER(bool, handleKeyEvent, QWindow *window, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) if (t == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window, timestamp, k, mods, 0, 0, 0, text, autorep, count)) return true; #endif @@ -526,7 +526,7 @@ bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *window, ulong times const QString& text, bool autorep, ushort count, bool tryShortcutOverride) { -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(window, timestamp, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count)) { return true; diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index adca5367970..3066b832827 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -295,7 +295,7 @@ QString OsTypeTerm::hostOs() return QStringLiteral("win"); #elif defined(Q_OS_LINUX) return QStringLiteral("linux"); -#elif defined(Q_OS_OSX) +#elif defined(Q_OS_MACOS) return QStringLiteral("macosx"); #elif defined(Q_OS_ANDROID) return QStringLiteral("android"); diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index e4e83056209..793986467ee 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -4482,9 +4482,8 @@ static void blend_color_generic(int count, const QSpan *spans, void *userData) uint buffer[BufferSize]; Operator op = getOperator(data, nullptr, 0); const uint color = data->solidColor.toArgb32(); - bool solidFill = data->rasterBuffer->compositionMode == QPainter::CompositionMode_Source - || (data->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && qAlpha(color) == 255); - QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp; + const bool solidFill = op.mode == QPainter::CompositionMode_Source; + const QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp; while (count--) { int x = spans->x; @@ -4522,6 +4521,10 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData) uint *target = ((uint *)data->rasterBuffer->scanLine(spans->y)) + spans->x; if (spans->coverage == 255) { qt_memfill(target, color, spans->len); +#ifdef __SSE2__ + } else if (spans->len > 16) { + op.funcSolid(target, spans->len, color, spans->coverage); +#endif } else { uint c = BYTE_MUL(color, spans->coverage); int ialpha = 255 - spans->coverage; @@ -4552,9 +4555,8 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData) alignas(8) QRgba64 buffer[BufferSize]; const QRgba64 color = data->solidColor; - bool solidFill = data->rasterBuffer->compositionMode == QPainter::CompositionMode_Source - || (data->rasterBuffer->compositionMode == QPainter::CompositionMode_SourceOver && color.isOpaque()); - QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp; + const bool solidFill = op.mode == QPainter::CompositionMode_Source; + const QPixelLayout::BPP bpp = qPixelLayouts[data->rasterBuffer->format].bpp; while (count--) { int x = spans->x; @@ -5137,7 +5139,8 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD yoff += image_height; bool isBpp32 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP32; - if (op.destFetch64 == destFetch64Undefined && image_width <= BufferSize && isBpp32) { + bool isBpp64 = qPixelLayouts[data->rasterBuffer->format].bpp == QPixelLayout::BPP64; + if (op.destFetch64 == destFetch64Undefined && image_width <= BufferSize && (isBpp32 || isBpp64)) { // If destination isn't blended into the result, we can do the tiling directly on destination pixels. while (count--) { int x = spans->x; @@ -5171,9 +5174,14 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD if (sx >= image_width) sx = 0; } - uint *dest = (uint*)data->rasterBuffer->scanLine(y) + x - image_width; - for (int i = image_width; i < length; ++i) { - dest[i] = dest[i - image_width]; + if (isBpp32) { + uint *dest = reinterpret_cast(data->rasterBuffer->scanLine(y)) + x - image_width; + for (int i = image_width; i < length; ++i) + dest[i] = dest[i - image_width]; + } else { + quint64 *dest = reinterpret_cast(data->rasterBuffer->scanLine(y)) + x - image_width; + for (int i = image_width; i < length; ++i) + dest[i] = dest[i - image_width]; } ++spans; } @@ -6766,10 +6774,12 @@ static void qInitDrawhelperFunctions() extern void QT_FASTCALL comp_func_SourceOver_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); extern void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha); extern void QT_FASTCALL comp_func_Source_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); + extern void QT_FASTCALL comp_func_solid_Source_sse2(uint *destPixels, int length, uint color, uint const_alpha); extern void QT_FASTCALL comp_func_Plus_sse2(uint *destPixels, const uint *srcPixels, int length, uint const_alpha); qt_functionForMode_C[QPainter::CompositionMode_SourceOver] = comp_func_SourceOver_sse2; qt_functionForModeSolid_C[QPainter::CompositionMode_SourceOver] = comp_func_solid_SourceOver_sse2; qt_functionForMode_C[QPainter::CompositionMode_Source] = comp_func_Source_sse2; + qt_functionForModeSolid_C[QPainter::CompositionMode_Source] = comp_func_solid_Source_sse2; qt_functionForMode_C[QPainter::CompositionMode_Plus] = comp_func_Plus_sse2; #ifdef QT_COMPILER_SUPPORTS_SSSE3 diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index dd42b96d79a..f1ad369906a 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -601,7 +601,7 @@ public: FETCH_RADIAL_LOOP(FETCH_RADIAL_LOOP_CLAMP_PAD) break; default: - Q_ASSERT(false); + Q_UNREACHABLE(); } } }; diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index c82f41ec88b..77b5ab42c5b 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -319,6 +319,35 @@ void qt_memfill32_sse2(quint32 *dest, quint32 value, qsizetype count) } #endif // !__AVX2__ +void QT_FASTCALL comp_func_solid_Source_sse2(uint *destPixels, int length, uint color, uint const_alpha) +{ + if (const_alpha == 255) { + qt_memfill32(destPixels, color, length); + } else { + const quint32 ialpha = 255 - const_alpha; + color = BYTE_MUL(color, const_alpha); + int x = 0; + + quint32 *dst = (quint32 *) destPixels; + const __m128i colorVector = _mm_set1_epi32(color); + const __m128i colorMask = _mm_set1_epi32(0x00ff00ff); + const __m128i half = _mm_set1_epi16(0x80); + const __m128i iAlphaVector = _mm_set1_epi16(ialpha); + + ALIGNMENT_PROLOGUE_16BYTES(dst, x, length) + destPixels[x] = color + BYTE_MUL(destPixels[x], ialpha); + + for (; x < length-3; x += 4) { + __m128i dstVector = _mm_load_si128((__m128i *)&dst[x]); + BYTE_MUL_SSE2(dstVector, dstVector, iAlphaVector, colorMask, half); + dstVector = _mm_add_epi8(colorVector, dstVector); + _mm_store_si128((__m128i *)&dst[x], dstVector); + } + SIMD_EPILOGUE(x, length, 3) + destPixels[x] = color + BYTE_MUL(destPixels[x], ialpha); + } +} + void QT_FASTCALL comp_func_solid_SourceOver_sse2(uint *destPixels, int length, uint color, uint const_alpha) { if ((const_alpha & qAlpha(color)) == 255) { diff --git a/src/gui/painting/qdrawhelper_x86_p.h b/src/gui/painting/qdrawhelper_x86_p.h index 5749d8c9fb5..869abcc6370 100644 --- a/src/gui/painting/qdrawhelper_x86_p.h +++ b/src/gui/painting/qdrawhelper_x86_p.h @@ -77,9 +77,6 @@ void qt_blend_rgb32_on_rgb32_sse2(uchar *destPixels, int dbpl, int w, int h, int const_alpha); -extern CompositionFunction qt_functionForMode_SSE2[]; -extern CompositionFunctionSolid qt_functionForModeSolid_SSE2[]; - void qt_memfill64_avx2(quint64 *dest, quint64 value, qsizetype count); void qt_memfill32_avx2(quint32 *dest, quint32 value, qsizetype count); #endif // __SSE2__ diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp index 1785fcd12dc..fc5c125b72c 100644 --- a/src/gui/painting/qpaintengine.cpp +++ b/src/gui/painting/qpaintengine.cpp @@ -158,7 +158,7 @@ QFont QTextItem::font() const X11 and \macos, it is the backend for painting on QImage and it is used as a fallback for paint engines that do not support a certain capability. In addition we provide QPaintEngine implementations for - OpenGL (accessible through QGLWidget) and printing (which allows using + OpenGL (accessible through QOpenGLWidget) and printing (which allows using QPainter to draw on a QPrinter object). If one wants to use QPainter to draw to a different backend, diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 10920c38fe1..5b7f8511bac 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1713,8 +1713,11 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) width / line.length(), s->lastPen.capStyle() == Qt::SquareCap); } else { - d->rasterizeLine_dashed(line, width, - &dashIndex, &dashOffset, &inDash); + // LinesHint means each line is distinct, so restart dashing + int dIndex = dashIndex; + qreal dOffset = dashOffset; + bool inD = inDash; + d->rasterizeLine_dashed(line, width, &dIndex, &dOffset, &inD); } } } diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index ea9bce08e44..227dace90f8 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -1191,7 +1191,18 @@ void QRhiGles2::beginExternal(QRhiCommandBuffer *cb) } QGles2CommandBuffer *cbD = QRHI_RES(QGles2CommandBuffer, cb); + + if (cbD->recordingPass == QGles2CommandBuffer::ComputePass + && !cbD->computePassState.writtenResources.isEmpty()) + { + QGles2CommandBuffer::Command cmd; + cmd.cmd = QGles2CommandBuffer::Command::Barrier; + cmd.args.barrier.barriers = GL_ALL_BARRIER_BITS; + cbD->commands.append(cmd); + } + executeCommandBuffer(cbD); + cbD->resetCommands(); if (vao) @@ -1931,6 +1942,10 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) GLenum indexType = GL_UNSIGNED_SHORT; quint32 indexStride = sizeof(quint16); quint32 indexOffset = 0; + GLuint currentArrayBuffer = 0; + static const int TRACKED_ATTRIB_COUNT = 16; + bool enabledAttribArrays[TRACKED_ATTRIB_COUNT]; + memset(enabledAttribArrays, 0, sizeof(enabledAttribArrays)); for (const QGles2CommandBuffer::Command &cmd : qAsConst(cbD->commands)) { switch (cmd.cmd) { @@ -1963,8 +1978,10 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) { QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, cmd.args.stencilRef.ps); if (psD) { - f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), GLint(cmd.args.stencilRef.ref), psD->m_stencilReadMask); - f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), GLint(cmd.args.stencilRef.ref), psD->m_stencilReadMask); + const GLint ref = GLint(cmd.args.stencilRef.ref); + f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), ref, psD->m_stencilReadMask); + f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), ref, psD->m_stencilReadMask); + cbD->graphicsPassState.dynamic.stencilRef = ref; } else { qWarning("No graphics pipeline active for setStencilRef; ignored"); } @@ -1981,8 +1998,11 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) if (bindingIdx != cmd.args.bindVertexBuffer.binding) continue; - // we do not support more than one vertex buffer - f->glBindBuffer(GL_ARRAY_BUFFER, cmd.args.bindVertexBuffer.buffer); + if (cmd.args.bindVertexBuffer.buffer != currentArrayBuffer) { + currentArrayBuffer = cmd.args.bindVertexBuffer.buffer; + // we do not support more than one vertex buffer + f->glBindBuffer(GL_ARRAY_BUFFER, currentArrayBuffer); + } const QRhiVertexInputBinding *inputBinding = psD->m_vertexInputLayout.bindingAt(bindingIdx); const int stride = int(inputBinding->stride()); @@ -2029,7 +2049,11 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) quint32 ofs = it->offset() + cmd.args.bindVertexBuffer.offset; f->glVertexAttribPointer(GLuint(locationIdx), size, type, normalize, stride, reinterpret_cast(quintptr(ofs))); - f->glEnableVertexAttribArray(GLuint(locationIdx)); + if (locationIdx >= TRACKED_ATTRIB_COUNT || !enabledAttribArrays[locationIdx]) { + if (locationIdx < TRACKED_ATTRIB_COUNT) + enabledAttribArrays[locationIdx] = true; + f->glEnableVertexAttribArray(GLuint(locationIdx)); + } if (inputBinding->classification() == QRhiVertexInputBinding::PerInstance && caps.instancing) f->glVertexAttribDivisor(GLuint(locationIdx), GLuint(inputBinding->instanceStepRate())); } @@ -2100,7 +2124,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) } break; case QGles2CommandBuffer::Command::BindGraphicsPipeline: - executeBindGraphicsPipeline(cmd.args.bindGraphicsPipeline.ps); + executeBindGraphicsPipeline(cbD, QRHI_RES(QGles2GraphicsPipeline, cmd.args.bindGraphicsPipeline.ps)); break; case QGles2CommandBuffer::Command::BindShaderResources: bindShaderResources(cmd.args.bindShaderResources.maybeGraphicsPs, @@ -2146,6 +2170,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) if (cmd.args.clear.mask & GL_STENCIL_BUFFER_BIT) f->glClearStencil(GLint(cmd.args.clear.s)); f->glClear(cmd.args.clear.mask); + cbD->graphicsPassState.reset(); // altered depth/color write, invalidate in order to avoid confusing the state tracking break; case QGles2CommandBuffer::Command::BufferSubData: f->glBindBuffer(cmd.args.bufferSubData.target, cmd.args.bufferSubData.buffer); @@ -2326,83 +2351,179 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb) } } -void QRhiGles2::executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps) +void QRhiGles2::executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2GraphicsPipeline *psD) { - QGles2GraphicsPipeline *psD = QRHI_RES(QGles2GraphicsPipeline, ps); + QGles2CommandBuffer::GraphicsPassState &state(cbD->graphicsPassState); + const bool forceUpdate = !state.valid; + state.valid = true; - // No state tracking logic as of now. Could introduce something to reduce - // the number of gl* calls (when using and changing between multiple - // pipelines), but then begin/endExternal() should invalidate the cached - // state as appropriate. - - if (psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor)) - f->glEnable(GL_SCISSOR_TEST); - else - f->glDisable(GL_SCISSOR_TEST); - if (psD->m_cullMode == QRhiGraphicsPipeline::None) { - f->glDisable(GL_CULL_FACE); - } else { - f->glEnable(GL_CULL_FACE); - f->glCullFace(toGlCullMode(psD->m_cullMode)); + const bool scissor = psD->m_flags.testFlag(QRhiGraphicsPipeline::UsesScissor); + if (forceUpdate || scissor != state.scissor) { + state.scissor = scissor; + if (scissor) + f->glEnable(GL_SCISSOR_TEST); + else + f->glDisable(GL_SCISSOR_TEST); } - f->glFrontFace(toGlFrontFace(psD->m_frontFace)); - if (!psD->m_targetBlends.isEmpty()) { - const QRhiGraphicsPipeline::TargetBlend &blend(psD->m_targetBlends.first()); // no MRT - GLboolean wr = blend.colorWrite.testFlag(QRhiGraphicsPipeline::R); - GLboolean wg = blend.colorWrite.testFlag(QRhiGraphicsPipeline::G); - GLboolean wb = blend.colorWrite.testFlag(QRhiGraphicsPipeline::B); - GLboolean wa = blend.colorWrite.testFlag(QRhiGraphicsPipeline::A); - f->glColorMask(wr, wg, wb, wa); - if (blend.enable) { - f->glEnable(GL_BLEND); - f->glBlendFuncSeparate(toGlBlendFactor(blend.srcColor), - toGlBlendFactor(blend.dstColor), - toGlBlendFactor(blend.srcAlpha), - toGlBlendFactor(blend.dstAlpha)); - f->glBlendEquationSeparate(toGlBlendOp(blend.opColor), toGlBlendOp(blend.opAlpha)); + + const bool cullFace = psD->m_cullMode != QRhiGraphicsPipeline::None; + const GLenum cullMode = cullFace ? toGlCullMode(psD->m_cullMode) : GL_NONE; + if (forceUpdate || cullFace != state.cullFace || cullMode != state.cullMode) { + state.cullFace = cullFace; + state.cullMode = cullMode; + if (cullFace) { + f->glEnable(GL_CULL_FACE); + f->glCullFace(cullMode); } else { - f->glDisable(GL_BLEND); + f->glDisable(GL_CULL_FACE); + } + } + + const GLenum frontFace = toGlFrontFace(psD->m_frontFace); + if (forceUpdate || frontFace != state.frontFace) { + state.frontFace = frontFace; + f->glFrontFace(frontFace); + } + + if (!psD->m_targetBlends.isEmpty()) { + // We do not have MRT support here, meaning all targets use the blend + // params from the first one. This is technically incorrect, even if + // nothing in Qt relies on it. However, considering that + // glBlendFuncSeparatei is only available in GL 4.0+ and GLES 3.2+, we + // may just live with this for now because no point in bothering if it + // won't be usable on many GLES (3.1 or 3.0) systems. + const QRhiGraphicsPipeline::TargetBlend &targetBlend(psD->m_targetBlends.first()); + + const QGles2CommandBuffer::GraphicsPassState::ColorMask colorMask = { + targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::R), + targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::G), + targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::B), + targetBlend.colorWrite.testFlag(QRhiGraphicsPipeline::A) + }; + if (forceUpdate || colorMask != state.colorMask) { + state.colorMask = colorMask; + f->glColorMask(colorMask.r, colorMask.g, colorMask.b, colorMask.a); + } + + const bool blendEnabled = targetBlend.enable; + const QGles2CommandBuffer::GraphicsPassState::Blend blend = { + toGlBlendFactor(targetBlend.srcColor), + toGlBlendFactor(targetBlend.dstColor), + toGlBlendFactor(targetBlend.srcAlpha), + toGlBlendFactor(targetBlend.dstAlpha), + toGlBlendOp(targetBlend.opColor), + toGlBlendOp(targetBlend.opAlpha) + }; + if (forceUpdate || blendEnabled != state.blendEnabled || (blendEnabled && blend != state.blend)) { + state.blendEnabled = blendEnabled; + if (blendEnabled) { + state.blend = blend; + f->glEnable(GL_BLEND); + f->glBlendFuncSeparate(blend.srcColor, blend.dstColor, blend.srcAlpha, blend.dstAlpha); + f->glBlendEquationSeparate(blend.opColor, blend.opAlpha); + } else { + f->glDisable(GL_BLEND); + } } } else { - f->glDisable(GL_BLEND); - f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - } - if (psD->m_depthTest) - f->glEnable(GL_DEPTH_TEST); - else - f->glDisable(GL_DEPTH_TEST); - if (psD->m_depthWrite) - f->glDepthMask(GL_TRUE); - else - f->glDepthMask(GL_FALSE); - f->glDepthFunc(toGlCompareOp(psD->m_depthOp)); - if (psD->m_stencilTest) { - f->glEnable(GL_STENCIL_TEST); - f->glStencilFuncSeparate(GL_FRONT, toGlCompareOp(psD->m_stencilFront.compareOp), 0, psD->m_stencilReadMask); - f->glStencilOpSeparate(GL_FRONT, - toGlStencilOp(psD->m_stencilFront.failOp), - toGlStencilOp(psD->m_stencilFront.depthFailOp), - toGlStencilOp(psD->m_stencilFront.passOp)); - f->glStencilMaskSeparate(GL_FRONT, psD->m_stencilWriteMask); - f->glStencilFuncSeparate(GL_BACK, toGlCompareOp(psD->m_stencilBack.compareOp), 0, psD->m_stencilReadMask); - f->glStencilOpSeparate(GL_BACK, - toGlStencilOp(psD->m_stencilBack.failOp), - toGlStencilOp(psD->m_stencilBack.depthFailOp), - toGlStencilOp(psD->m_stencilBack.passOp)); - f->glStencilMaskSeparate(GL_BACK, psD->m_stencilWriteMask); - } else { - f->glDisable(GL_STENCIL_TEST); + const QGles2CommandBuffer::GraphicsPassState::ColorMask colorMask = { true, true, true, true }; + if (forceUpdate || colorMask != state.colorMask) { + state.colorMask = colorMask; + f->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + const bool blendEnabled = false; + if (forceUpdate || blendEnabled != state.blendEnabled) { + state.blendEnabled = blendEnabled; + f->glDisable(GL_BLEND); + } } - if (psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias)) { - f->glPolygonOffset(psD->m_slopeScaledDepthBias, psD->m_depthBias); - f->glEnable(GL_POLYGON_OFFSET_FILL); - } else { - f->glDisable(GL_POLYGON_OFFSET_FILL); + const bool depthTest = psD->m_depthTest; + if (forceUpdate || depthTest != state.depthTest) { + state.depthTest = depthTest; + if (depthTest) + f->glEnable(GL_DEPTH_TEST); + else + f->glDisable(GL_DEPTH_TEST); } - if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) - f->glLineWidth(psD->m_lineWidth); + const bool depthWrite = psD->m_depthWrite; + if (forceUpdate || depthWrite != state.depthWrite) { + state.depthWrite = depthWrite; + f->glDepthMask(depthWrite); + } + + const GLenum depthFunc = toGlCompareOp(psD->m_depthOp); + if (forceUpdate || depthFunc != state.depthFunc) { + state.depthFunc = depthFunc; + f->glDepthFunc(depthFunc); + } + + const bool stencilTest = psD->m_stencilTest; + const GLuint stencilReadMask = psD->m_stencilReadMask; + const GLuint stencilWriteMask = psD->m_stencilWriteMask; + const QGles2CommandBuffer::GraphicsPassState::StencilFace stencilFront = { + toGlCompareOp(psD->m_stencilFront.compareOp), + toGlStencilOp(psD->m_stencilFront.failOp), + toGlStencilOp(psD->m_stencilFront.depthFailOp), + toGlStencilOp(psD->m_stencilFront.passOp) + }; + const QGles2CommandBuffer::GraphicsPassState::StencilFace stencilBack = { + toGlCompareOp(psD->m_stencilBack.compareOp), + toGlStencilOp(psD->m_stencilBack.failOp), + toGlStencilOp(psD->m_stencilBack.depthFailOp), + toGlStencilOp(psD->m_stencilBack.passOp) + }; + if (forceUpdate || stencilTest != state.stencilTest + || (stencilTest + && (stencilReadMask != state.stencilReadMask || stencilWriteMask != state.stencilWriteMask + || stencilFront != state.stencil[0] || stencilBack != state.stencil[1]))) + { + state.stencilTest = stencilTest; + if (stencilTest) { + state.stencilReadMask = stencilReadMask; + state.stencilWriteMask = stencilWriteMask; + state.stencil[0] = stencilFront; + state.stencil[1] = stencilBack; + + f->glEnable(GL_STENCIL_TEST); + + f->glStencilFuncSeparate(GL_FRONT, stencilFront.func, state.dynamic.stencilRef, stencilReadMask); + f->glStencilOpSeparate(GL_FRONT, stencilFront.failOp, stencilFront.zfailOp, stencilFront.zpassOp); + f->glStencilMaskSeparate(GL_FRONT, stencilWriteMask); + + f->glStencilFuncSeparate(GL_BACK, stencilBack.func, state.dynamic.stencilRef, stencilReadMask); + f->glStencilOpSeparate(GL_BACK, stencilBack.failOp, stencilBack.zfailOp, stencilBack.zpassOp); + f->glStencilMaskSeparate(GL_BACK, stencilWriteMask); + } else { + f->glDisable(GL_STENCIL_TEST); + } + } + + const bool polyOffsetFill = psD->m_depthBias != 0 || !qFuzzyIsNull(psD->m_slopeScaledDepthBias); + const float polyOffsetFactor = psD->m_slopeScaledDepthBias; + const float polyOffsetUnits = psD->m_depthBias; + if (forceUpdate || state.polyOffsetFill != polyOffsetFill + || polyOffsetFactor != state.polyOffsetFactor || polyOffsetUnits != state.polyOffsetUnits) + { + state.polyOffsetFill = polyOffsetFill; + state.polyOffsetFactor = polyOffsetFactor; + state.polyOffsetUnits = polyOffsetUnits; + if (polyOffsetFill) { + f->glPolygonOffset(polyOffsetFactor, polyOffsetUnits); + f->glEnable(GL_POLYGON_OFFSET_FILL); + } else { + f->glDisable(GL_POLYGON_OFFSET_FILL); + } + } + + if (psD->m_topology == QRhiGraphicsPipeline::Lines || psD->m_topology == QRhiGraphicsPipeline::LineStrip) { + const float lineWidth = psD->m_lineWidth; + if (forceUpdate || lineWidth != state.lineWidth) { + state.lineWidth = lineWidth; + f->glLineWidth(lineWidth); + } + } f->glUseProgram(psD->program); } @@ -2825,8 +2946,6 @@ void QRhiGles2::beginComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch cbD->recordingPass = QGles2CommandBuffer::ComputePass; cbD->resetCachedState(); - - cbD->computePassState.reset(); } void QRhiGles2::endComputePass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates) @@ -3135,11 +3254,12 @@ void QRhiGles2::gatherUniforms(GLuint program, QByteArray prefix = ub.structName.toUtf8() + '.'; for (const QShaderDescription::BlockVariable &blockMember : ub.members) { if (blockMember.type == QShaderDescription::Struct) { - prefix += blockMember.name.toUtf8(); + QByteArray structPrefix = prefix + blockMember.name.toUtf8(); + const int baseOffset = blockMember.offset; if (blockMember.arrayDims.isEmpty()) { for (const QShaderDescription::BlockVariable &structMember : blockMember.structMembers) - registerUniformIfActive(structMember, prefix, ub.binding, baseOffset, program, dst); + registerUniformIfActive(structMember, structPrefix, ub.binding, baseOffset, program, dst); } else { if (blockMember.arrayDims.count() > 1) { qWarning("Array of struct '%s' has more than one dimension. Only the first dimension is used.", @@ -3149,7 +3269,7 @@ void QRhiGles2::gatherUniforms(GLuint program, const int elemSize = blockMember.size / dim; int elemOffset = baseOffset; for (int di = 0; di < dim; ++di) { - const QByteArray arrayPrefix = prefix + '[' + QByteArray::number(di) + ']' + '.'; + const QByteArray arrayPrefix = structPrefix + '[' + QByteArray::number(di) + ']' + '.'; for (const QShaderDescription::BlockVariable &structMember : blockMember.structMembers) registerUniformIfActive(structMember, arrayPrefix, ub.binding, elemOffset, program, dst); elemOffset += elemSize; diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h index 8b7d01532a2..ac7b384cb6f 100644 --- a/src/gui/rhi/qrhigles2_p_p.h +++ b/src/gui/rhi/qrhigles2_p_p.h @@ -522,6 +522,45 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer QRhiShaderResourceBindings *currentComputeSrb; uint currentSrbGeneration; + struct GraphicsPassState { + bool valid = false; + bool scissor; + bool cullFace; + GLenum cullMode; + GLenum frontFace; + bool blendEnabled; + struct ColorMask { bool r, g, b, a; } colorMask; + struct Blend { + GLenum srcColor; + GLenum dstColor; + GLenum srcAlpha; + GLenum dstAlpha; + GLenum opColor; + GLenum opAlpha; + } blend; + bool depthTest; + bool depthWrite; + GLenum depthFunc; + bool stencilTest; + GLuint stencilReadMask; + GLuint stencilWriteMask; + struct StencilFace { + GLenum func; + GLenum failOp; + GLenum zfailOp; + GLenum zpassOp; + } stencil[2]; // front, back + bool polyOffsetFill; + float polyOffsetFactor; + float polyOffsetUnits; + float lineWidth; + void reset() { valid = false; } + struct { + // not part of QRhiGraphicsPipeline but used by setGraphicsPipeline() + GLint stencilRef = 0; + } dynamic; + } graphicsPassState; + struct ComputePassState { enum Access { Read = 0x01, @@ -566,11 +605,57 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer currentGraphicsSrb = nullptr; currentComputeSrb = nullptr; currentSrbGeneration = 0; + graphicsPassState.reset(); + computePassState.reset(); } }; Q_DECLARE_TYPEINFO(QGles2CommandBuffer::Command, Q_MOVABLE_TYPE); +inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a, + const QGles2CommandBuffer::GraphicsPassState::StencilFace &b) +{ + return a.func == b.func + && a.failOp == b.failOp + && a.zfailOp == b.zfailOp + && a.zpassOp == b.zpassOp; +} + +inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::StencilFace &a, + const QGles2CommandBuffer::GraphicsPassState::StencilFace &b) +{ + return !(a == b); +} + +inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a, + const QGles2CommandBuffer::GraphicsPassState::ColorMask &b) +{ + return a.r == b.r && a.g == b.g && a.b == b.b && a.a == b.a; +} + +inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::ColorMask &a, + const QGles2CommandBuffer::GraphicsPassState::ColorMask &b) +{ + return !(a == b); +} + +inline bool operator==(const QGles2CommandBuffer::GraphicsPassState::Blend &a, + const QGles2CommandBuffer::GraphicsPassState::Blend &b) +{ + return a.srcColor == b.srcColor + && a.dstColor == b.dstColor + && a.srcAlpha == b.srcAlpha + && a.dstAlpha == b.dstAlpha + && a.opColor == b.opColor + && a.opAlpha == b.opAlpha; +} + +inline bool operator!=(const QGles2CommandBuffer::GraphicsPassState::Blend &a, + const QGles2CommandBuffer::GraphicsPassState::Blend &b) +{ + return !(a == b); +} + struct QGles2SwapChain : public QRhiSwapChain { QGles2SwapChain(QRhiImplementation *rhi); @@ -709,7 +794,7 @@ public: QRhiPassResourceTracker::TextureAccess access, QRhiPassResourceTracker::TextureStage stage); void executeCommandBuffer(QRhiCommandBuffer *cb); - void executeBindGraphicsPipeline(QRhiGraphicsPipeline *ps); + void executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2GraphicsPipeline *psD); void bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiComputePipeline *maybeComputePs, QRhiShaderResourceBindings *srb, const uint *dynOfsPairs, int dynOfsCount); diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 70cc20cbe63..32fbd8cfed5 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -2120,7 +2120,7 @@ bool QFontEngineMulti::canRender(const QChar *string, int len) const return true; } -/* Implement alphaMapForGlyph() which is called by Lighthouse/Windows code. +/* Implement alphaMapForGlyph() which is called by QPA Windows code. * Ideally, that code should be fixed to correctly handle QFontEngineMulti. */ QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph) diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp index 61eed3fff1b..ede4ccd4827 100644 --- a/src/gui/util/qvalidator.cpp +++ b/src/gui/util/qvalidator.cpp @@ -363,8 +363,9 @@ QIntValidator::~QIntValidator() \fn QValidator::State QIntValidator::validate(QString &input, int &pos) const Returns \l Acceptable if the \a input is an integer within the - valid range, \l Intermediate if the \a input is a prefix of an integer in the - valid range, and \l Invalid otherwise. + valid range. If \a input has at most as many digits as the top of the range, + or is a prefix of an integer in the valid range, returns \l Intermediate. + Otherwise, returns \l Invalid. If the valid range consists of just positive integers (e.g., 32 to 100) and \a input is a negative integer, then Invalid is returned. (On the other @@ -373,6 +374,10 @@ QIntValidator::~QIntValidator() the user might be just about to type the minus (especially for right-to-left languages). + Similarly, if the valid range is between 46 and 53, then 41 and 59 will be + evaluated as \l Intermediate, as otherwise the user wouldn't be able to + change a value from 49 to 51. + \snippet code/src_gui_util_qvalidator.cpp 2 By default, the \a pos parameter is not used by this validator. diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index efbeb17d395..ac907141322 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -220,6 +220,12 @@ void QHttp2ProtocolHandler::handleConnectionClosure() goingAway = true; } +void QHttp2ProtocolHandler::ensureClientPrefaceSent() +{ + if (!prefaceSent) + sendClientPreface(); +} + void QHttp2ProtocolHandler::_q_uploadDataReadyRead() { if (!sender()) // QueuedConnection, firing after sender (byte device) was deleted. diff --git a/src/network/access/qhttp2protocolhandler_p.h b/src/network/access/qhttp2protocolhandler_p.h index 43fdb136cd8..14deabd70b2 100644 --- a/src/network/access/qhttp2protocolhandler_p.h +++ b/src/network/access/qhttp2protocolhandler_p.h @@ -93,6 +93,7 @@ public: QHttp2ProtocolHandler &operator = (QHttp2ProtocolHandler &&rhs) = delete; Q_INVOKABLE void handleConnectionClosure(); + Q_INVOKABLE void ensureClientPrefaceSent(); private slots: void _q_uploadDataReadyRead(); diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 4ea98ff9783..ba05e757948 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -478,6 +478,9 @@ void QHttpNetworkConnectionChannel::allDone() QHttp2ProtocolHandler *h2c = static_cast(protocolHandler.data()); QMetaObject::invokeMethod(h2c, "_q_receiveReply", Qt::QueuedConnection); QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + // If we only had one request sent with H2 allowed, we may fail to send + // a client preface and SETTINGS, which is required by RFC 7540, 3.2. + QMetaObject::invokeMethod(h2c, "ensureClientPrefaceSent", Qt::QueuedConnection); return; } else { // Ok, whatever happened, we do not try HTTP/2 anymore ... diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 62cc760ada4..63a816b9dc6 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1211,16 +1211,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera bool isLocalFile = req.url().isLocalFile(); QString scheme = req.url().scheme(); -#ifdef Q_OS_WASM - // Support http, https, and relateive urls - if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme.isEmpty()) { - QNetworkReplyWasmImpl *reply = new QNetworkReplyWasmImpl(this); - QNetworkReplyWasmImplPrivate *priv = reply->d_func(); - priv->manager = this; - priv->setup(op, req, outgoingData); - return reply; - } -#endif +#ifndef Q_OS_WASM // fast path for GET on file:// URLs // The QNetworkAccessFileBackend will right now only be used for PUT @@ -1273,7 +1264,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera if (!d->statusMonitor.isMonitoring() && !d->statusMonitor.start()) qWarning(lcNetMon, "failed to start network status monitoring"); } - +#endif QNetworkRequest request = req; if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() && outgoingData && !outgoingData->isSequential()) { @@ -1291,6 +1282,16 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies)); } } +#ifdef Q_OS_WASM + // Support http, https, and relative urls + if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme.isEmpty()) { + QNetworkReplyWasmImpl *reply = new QNetworkReplyWasmImpl(this); + QNetworkReplyWasmImplPrivate *priv = reply->d_func(); + priv->manager = this; + priv->setup(op, request, outgoingData); + return reply; + } +#endif #if QT_CONFIG(http) // Since Qt 5 we use the new QNetworkReplyHttpImpl @@ -1632,7 +1633,7 @@ void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QUrl &url, } } -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) //now we try to get the username and password from keychain //if not successful signal will be emitted QString username; diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index 6784bc734dd..30e4e290eab 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -868,7 +868,7 @@ void QNetworkReply::setRequest(const QNetworkRequest &request) Sets the error condition to be \a errorCode. The human-readable message is set with \a errorString. - Calling setError() does not emit the error(QNetworkReply::NetworkError) + Calling setError() does not emit the errorOccurred(QNetworkReply::NetworkError) signal. \sa error(), errorString() diff --git a/src/network/access/qnetworkreplyfileimpl.cpp b/src/network/access/qnetworkreplyfileimpl.cpp index afab8ffd943..68fac55feb8 100644 --- a/src/network/access/qnetworkreplyfileimpl.cpp +++ b/src/network/access/qnetworkreplyfileimpl.cpp @@ -89,7 +89,7 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con // we handle only local files QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Request for opening non-local file %1").arg(url.toString()); setError(QNetworkReply::ProtocolInvalidOperationError, msg); - QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProtocolInvalidOperationError)); fileOpenFinished(false); return; @@ -134,7 +134,7 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con if (fi.isDir()) { QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Cannot open %1: Path is a directory").arg(url.toString()); setError(QNetworkReply::ContentOperationNotPermittedError, msg); - QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + QMetaObject::invokeMethod(this, "errorOccured", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentOperationNotPermittedError)); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); return; @@ -149,11 +149,11 @@ QNetworkReplyFileImpl::QNetworkReplyFileImpl(QNetworkAccessManager *manager, con if (fi.exists()) { setError(QNetworkReply::ContentAccessDenied, msg); - QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentAccessDenied)); } else { setError(QNetworkReply::ContentNotFoundError, msg); - QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, + QMetaObject::invokeMethod(this, "errorOccurred", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ContentNotFoundError)); } QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); diff --git a/src/network/access/qnetworkreplywasmimpl.cpp b/src/network/access/qnetworkreplywasmimpl.cpp index 8c0f9bdf55c..af8b39bab6f 100644 --- a/src/network/access/qnetworkreplywasmimpl.cpp +++ b/src/network/access/qnetworkreplywasmimpl.cpp @@ -50,180 +50,10 @@ #include #include -#include -#include +#include QT_BEGIN_NAMESPACE -using namespace emscripten; - -static void q_requestErrorCallback(val event) -{ - if (event.isNull() || event.isUndefined()) - return; - - val xhr = event["target"]; - if (xhr.isNull() || xhr.isUndefined()) - return; - - quintptr func = xhr["data-handler"].as(); - QNetworkReplyWasmImplPrivate *reply = reinterpret_cast(func); - Q_ASSERT(reply); - - int statusCode = xhr["status"].as(); - - QString reasonStr = QString::fromStdString(xhr["statusText"].as()); - - reply->setReplyAttributes(func, statusCode, reasonStr); - - if (statusCode >= 400 && !reasonStr.isEmpty()) - reply->emitReplyError(reply->statusCodeFromHttp(statusCode, reply->request.url()), reasonStr); -} - -static void q_progressCallback(val event) -{ - if (event.isNull() || event.isUndefined()) - return; - - val xhr = event["target"]; - if (xhr.isNull() || xhr.isUndefined()) - return; - - QNetworkReplyWasmImplPrivate *reply = - reinterpret_cast(xhr["data-handler"].as()); - Q_ASSERT(reply); - - if (xhr["status"].as() < 400) - reply->emitDataReadProgress(event["loaded"].as(), event["total"].as()); -} - -static void q_loadCallback(val event) -{ - if (event.isNull() || event.isUndefined()) - return; - - val xhr = event["target"]; - if (xhr.isNull() || xhr.isUndefined()) - return; - - QNetworkReplyWasmImplPrivate *reply = - reinterpret_cast(xhr["data-handler"].as()); - Q_ASSERT(reply); - - int status = xhr["status"].as(); - if (status >= 300) { - q_requestErrorCallback(event); - return; - } - QString statusText = QString::fromStdString(xhr["statusText"].as()); - int readyState = xhr["readyState"].as(); - - if (status == 200 || status == 203) { - QString responseString; - const std::string responseType = xhr["responseType"].as(); - if (responseType.length() == 0 || responseType == "document" || responseType == "text") { - responseString = QString::fromStdWString(xhr["responseText"].as()); - } else if (responseType == "json") { - responseString = - QString::fromStdWString(val::global("JSON").call("stringify", xhr["response"])); - } else if (responseType == "arraybuffer" || responseType == "blob") { - // handle this data in the FileReader, triggered by the call to readAsArrayBuffer - val blob = xhr["response"]; - if (blob.isNull() || blob.isUndefined()) - return; - - val reader = val::global("FileReader").new_(); - if (reader.isNull() || reader.isUndefined()) - return; - - reader.set("onload", val::module_property("qt_QNetworkReplyWasmImplPrivate_readBinary")); - reader.set("data-handler", xhr["data-handler"]); - - reader.call("readAsArrayBuffer", blob); - val::global("Module").delete_(reader); - } - - - if (readyState == 4) { // done - reply->setReplyAttributes(xhr["data-handler"].as(), status, statusText); - if (!responseString.isEmpty()) { - QByteArray responseStringArray = responseString.toUtf8(); - reply->dataReceived(responseStringArray, responseStringArray.size()); - } - } - } - if (status >= 400 && !statusText.isEmpty()) - reply->emitReplyError(reply->statusCodeFromHttp(status, reply->request.url()), statusText); -} - -static void q_responseHeadersCallback(val event) -{ - if (event.isNull() || event.isUndefined()) - return; - - val xhr = event["target"]; - if (xhr.isNull() || xhr.isUndefined()) - return; - - if (xhr["readyState"].as() == 2) { // HEADERS_RECEIVED - std::string responseHeaders = xhr.call("getAllResponseHeaders"); - if (!responseHeaders.empty()) { - QNetworkReplyWasmImplPrivate *reply = - reinterpret_cast(xhr["data-handler"].as()); - Q_ASSERT(reply); - - reply->headersReceived(QString::fromStdString(responseHeaders)); - } - } -} - -static void q_readBinary(val event) -{ - if (event.isNull() || event.isUndefined()) - return; - - val fileReader = event["target"]; - if (fileReader.isNull() || fileReader.isUndefined()) - return; - - QNetworkReplyWasmImplPrivate *reply = - reinterpret_cast(fileReader["data-handler"].as()); - Q_ASSERT(reply); - - if (reply->state == QNetworkReplyPrivate::Finished || reply->state == QNetworkReplyPrivate::Aborted) - return; - - // Set up source typed array - val result = fileReader["result"]; // ArrayBuffer - if (result.isNull() || result.isUndefined()) - return; - - val Uint8Array = val::global("Uint8Array"); - val sourceTypedArray = Uint8Array.new_(result); - - // Allocate and set up destination typed array - const quintptr size = result["byteLength"].as(); - QByteArray buffer(size, Qt::Uninitialized); - - val destinationTypedArray = Uint8Array.new_(val::module_property("HEAPU8")["buffer"], - reinterpret_cast(buffer.data()), size); - destinationTypedArray.call("set", sourceTypedArray); - reply->dataReceived(buffer, buffer.size()); - - event.delete_(fileReader); - Uint8Array.delete_(sourceTypedArray); - - QCoreApplication::processEvents(); -} - -EMSCRIPTEN_BINDINGS(qtNetworkModule) { - function("qt_QNetworkReplyWasmImplPrivate_requestErrorCallback", q_requestErrorCallback); - function("qt_QNetworkReplyWasmImplPrivate_progressCallback", q_progressCallback); - function("qt_QNetworkReplyWasmImplPrivate_loadCallback", q_loadCallback); - function("qt_QNetworkReplyWasmImplPrivate_responseHeadersCallback", q_responseHeadersCallback); - function("qt_QNetworkReplyWasmImplPrivate_readBinary", q_readBinary); -} - QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate() : QNetworkReplyPrivate() , managerPrivate(0) @@ -236,11 +66,7 @@ QNetworkReplyWasmImplPrivate::QNetworkReplyWasmImplPrivate() QNetworkReplyWasmImplPrivate::~QNetworkReplyWasmImplPrivate() { - m_xhr.set("onerror", val::null()); - m_xhr.set("onload", val::null()); - m_xhr.set("onprogress", val::null()); - m_xhr.set("onreadystatechange", val::null()); - m_xhr.set("data-handler", val::null()); + emscripten_fetch_close(m_fetch); } QNetworkReplyWasmImpl::QNetworkReplyWasmImpl(QObject *parent) @@ -373,7 +199,11 @@ void QNetworkReplyWasmImplPrivate::setReplyAttributes(quintptr data, int statusC void QNetworkReplyWasmImplPrivate::doAbort() const { - m_xhr.call("abort"); + emscripten_fetch_close(m_fetch); +} + +constexpr int getArraySize (int factor) { + return 2 * factor + 1; } void QNetworkReplyWasmImplPrivate::doSendRequest() @@ -381,38 +211,68 @@ void QNetworkReplyWasmImplPrivate::doSendRequest() Q_Q(QNetworkReplyWasmImpl); totalDownloadSize = 0; - m_xhr = val::global("XMLHttpRequest").new_(); - std::string verb = q->methodName().toStdString(); + emscripten_fetch_attr_t attr; + emscripten_fetch_attr_init(&attr); + strcpy(attr.requestMethod, q->methodName().constData()); - m_xhr.call("open", verb, request.url().toString().toStdString()); + QList headersData = request.rawHeaderList(); + int arrayLength = getArraySize(headersData.count()); - m_xhr.set("onerror", val::module_property("qt_QNetworkReplyWasmImplPrivate_requestErrorCallback")); - m_xhr.set("onload", val::module_property("qt_QNetworkReplyWasmImplPrivate_loadCallback")); - m_xhr.set("onprogress", val::module_property("qt_QNetworkReplyWasmImplPrivate_progressCallback")); - m_xhr.set("onreadystatechange", val::module_property("qt_QNetworkReplyWasmImplPrivate_responseHeadersCallback")); - - m_xhr.set("data-handler", val(quintptr(reinterpret_cast(this)))); - - QByteArray contentType = request.rawHeader("Content-Type"); - - // handle extra data - val dataToSend = val::null(); - QByteArray extraData; - - if (outgoingData) // data from post request - extraData = outgoingData->readAll(); - - if (!extraData.isEmpty()) { - dataToSend = val(typed_memory_view(extraData.size(), - reinterpret_cast - (extraData.constData()))); + if (headersData.count() > 0) { + const char* customHeaders[arrayLength]; + int i = 0; + for (i; i < headersData.count() * 2; (i = i + 2)) { + customHeaders[i] = headersData[i].constData(); + customHeaders[i + 1] = request.rawHeader(headersData[i]).constData(); + } + customHeaders[i] = nullptr; + attr.requestHeaders = customHeaders; } - m_xhr.set("responseType", val("blob")); - // set request headers - for (auto header : request.rawHeaderList()) { - m_xhr.call("setRequestHeader", header.toStdString(), request.rawHeader(header).toStdString()); + + if (outgoingData) { // data from post request + // handle extra data + QByteArray extraData; + extraData = outgoingData->readAll(); // is there a size restriction here? + if (!extraData.isEmpty()) { + attr.requestData = extraData.constData(); + attr.requestDataSize = extraData.size(); + } } - m_xhr.call("send", dataToSend); + + // username & password + if (!request.url().userInfo().isEmpty()) { + attr.userName = request.url().userName().toUtf8(); + attr.password = request.url().password().toUtf8(); + } + + attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY | EMSCRIPTEN_FETCH_PERSIST_FILE | EMSCRIPTEN_FETCH_REPLACE; + + QNetworkRequest::CacheLoadControl CacheLoadControlAttribute = + (QNetworkRequest::CacheLoadControl)request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt(); + + if (CacheLoadControlAttribute == QNetworkRequest::AlwaysCache) { + attr.attributes += EMSCRIPTEN_FETCH_NO_DOWNLOAD; + } + if (CacheLoadControlAttribute == QNetworkRequest::PreferCache) { + attr.attributes += EMSCRIPTEN_FETCH_APPEND; + } + + if (CacheLoadControlAttribute == QNetworkRequest::AlwaysNetwork || + request.attribute(QNetworkRequest::CacheSaveControlAttribute, false).toBool()) { + attr.attributes -= EMSCRIPTEN_FETCH_PERSIST_FILE; + } + + attr.onsuccess = QNetworkReplyWasmImplPrivate::downloadSucceeded; + attr.onerror = QNetworkReplyWasmImplPrivate::downloadFailed; + attr.onprogress = QNetworkReplyWasmImplPrivate::downloadProgress; + attr.onreadystatechange = QNetworkReplyWasmImplPrivate::stateChange; + attr.timeoutMSecs = 2 * 6000; // FIXME + attr.userData = reinterpret_cast(this); + + QString dPath = QStringLiteral("/home/web_user/") + request.url().fileName(); + attr.destinationPath = dPath.toUtf8(); + + m_fetch = emscripten_fetch(&attr, request.url().toString().toUtf8()); } void QNetworkReplyWasmImplPrivate::emitReplyError(QNetworkReply::NetworkError errorCode, const QString &errorString) @@ -511,7 +371,6 @@ void QNetworkReplyWasmImplPrivate::headersReceived(const QString &bufferString) if (!bufferString.isEmpty()) { QStringList headers = bufferString.split(QString::fromUtf8("\r\n"), Qt::SkipEmptyParts); - for (int i = 0; i < headers.size(); i++) { QString headerName = headers.at(i).split(QString::fromUtf8(": ")).at(0); QString headersValue = headers.at(i).split(QString::fromUtf8(": ")).at(1); @@ -589,6 +448,56 @@ void QNetworkReplyWasmImplPrivate::_q_bufferOutgoingData() } } +void QNetworkReplyWasmImplPrivate::downloadSucceeded(emscripten_fetch_t *fetch) +{ + QByteArray buffer(fetch->data, fetch->numBytes); + + QNetworkReplyWasmImplPrivate *reply = + reinterpret_cast(fetch->userData); + if (reply) { + reply->dataReceived(buffer, buffer.size()); + } +} + +void QNetworkReplyWasmImplPrivate::stateChange(emscripten_fetch_t *fetch) +{ + if (fetch->readyState == /*HEADERS_RECEIVED*/ 2) { + size_t headerLength = emscripten_fetch_get_response_headers_length(fetch); + char *dst = nullptr; + emscripten_fetch_get_response_headers(fetch, dst, headerLength + 1); + std::string str = dst; + QNetworkReplyWasmImplPrivate *reply = + reinterpret_cast(fetch->userData); + reply->headersReceived(QString::fromStdString(str)); + } +} + +void QNetworkReplyWasmImplPrivate::downloadProgress(emscripten_fetch_t *fetch) +{ + QNetworkReplyWasmImplPrivate *reply = + reinterpret_cast(fetch->userData); + Q_ASSERT(reply); + + if (fetch->status < 400) + reply->emitDataReadProgress((fetch->dataOffset + fetch->numBytes), fetch->totalBytes); +} + +void QNetworkReplyWasmImplPrivate::downloadFailed(emscripten_fetch_t *fetch) +{ + QNetworkReplyWasmImplPrivate *reply = reinterpret_cast(fetch->userData); + Q_ASSERT(reply); + + QString reasonStr = QString::fromUtf8(fetch->statusText); + + reply->setReplyAttributes(reinterpret_cast(fetch->userData), fetch->status, reasonStr); + + if (fetch->status >= 400 && !reasonStr.isEmpty()) + reply->emitReplyError(reply->statusCodeFromHttp(fetch->status, reply->request.url()), reasonStr); + + if (fetch->status >= 400) + emscripten_fetch_close(fetch); // Also free data on failure. +} + //taken from qhttpthreaddelegate.cpp QNetworkReply::NetworkError QNetworkReplyWasmImplPrivate::statusCodeFromHttp(int httpStatusCode, const QUrl &url) { diff --git a/src/network/access/qnetworkreplywasmimpl_p.h b/src/network/access/qnetworkreplywasmimpl_p.h index e1e6bf4e240..5463ce8a985 100644 --- a/src/network/access/qnetworkreplywasmimpl_p.h +++ b/src/network/access/qnetworkreplywasmimpl_p.h @@ -61,8 +61,7 @@ #include #include -#include -#include +#include QT_BEGIN_NAMESPACE @@ -135,10 +134,17 @@ public: QIODevice *outgoingData; QSharedPointer outgoingDataBuffer; - emscripten::val m_xhr = emscripten::val::null(); - void doAbort() const; + void doAbort() const; + + static void downloadProgress(emscripten_fetch_t *fetch); + static void downloadFailed(emscripten_fetch_t *fetch); + static void downloadSucceeded(emscripten_fetch_t *fetch); + static void stateChange(emscripten_fetch_t *fetch); static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const QUrl &url); + + emscripten_fetch_t *m_fetch; + Q_DECLARE_PUBLIC(QNetworkReplyWasmImpl) }; diff --git a/src/network/configure.json b/src/network/configure.json index 07f0e349f66..254a36d7251 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -61,11 +61,11 @@ "export": "openssl", "test": { "tail": [ - "#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L", - "# error OpenSSL >= 1.1.0 is required", + "#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10101000L", + "# error OpenSSL >= 1.1.1 is required", "#endif", "#if !defined(OPENSSL_NO_EC) && !defined(SSL_CTRL_SET_CURVES)", - "# error OpenSSL was reported as >= 1.1.0 but is missing required features, possibly it's libressl which is unsupported", + "# error OpenSSL was reported as >= 1.1.1 but is missing required features, possibly it's libressl which is unsupported", "#endif" ] }, diff --git a/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp b/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp index d3a4cfc1162..39a3199bf75 100644 --- a/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp +++ b/src/network/doc/snippets/code/src_network_access_qnetworkaccessmanager.cpp @@ -64,7 +64,7 @@ request.setRawHeader("User-Agent", "MyOwnBrowser 1.0"); QNetworkReply *reply = manager->get(request); connect(reply, &QIODevice::readyRead, this, &MyClass::slotReadyRead); -connect(reply, QOverload::of(&QNetworkReply::error), +connect(reply, &QNetworkReply::errorOccurred, this, &MyClass::slotError); connect(reply, &QNetworkReply::sslErrors, this, &MyClass::slotSslErrors); diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index b7d4f4fa3e5..4d3f7d8ddb4 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. @@ -141,9 +141,9 @@ public: QByteArray toDer() const; QString toText() const; - static QList fromPath( - const QString &path, QSsl::EncodingFormat format = QSsl::Pem, - PatternSyntax syntax = PatternSyntax::FixedString); + static QList fromPath(const QString &path, + QSsl::EncodingFormat format = QSsl::Pem, + PatternSyntax syntax = PatternSyntax::FixedString); static QList fromDevice( QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem); diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index fe1c43d992f..1ae32b0330f 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -66,7 +66,7 @@ #include -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include #endif diff --git a/src/network/ssl/qsslsocket_mac_shared.cpp b/src/network/ssl/qsslsocket_mac_shared.cpp index 4f0adf16f9b..0bc4647e8b5 100644 --- a/src/network/ssl/qsslsocket_mac_shared.cpp +++ b/src/network/ssl/qsslsocket_mac_shared.cpp @@ -57,14 +57,14 @@ #include -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS # include #endif QT_BEGIN_NAMESPACE -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS namespace { bool hasTrustedSslServerPolicy(SecPolicyRef policy, CFDictionaryRef props) { @@ -119,7 +119,7 @@ bool isCaCertificateTrusted(SecCertificateRef cfCert, int domain) } } // anon namespace -#endif // Q_OS_OSX +#endif // Q_OS_MACOS QList QSslSocketPrivate::systemCaCertificates() { @@ -127,7 +127,7 @@ QList QSslSocketPrivate::systemCaCertificates() QList systemCerts; // SecTrustSettingsCopyCertificates is not defined on iOS. -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // iterate through all enum members, order: // kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin, kSecTrustSettingsDomainSystem for (int dom = kSecTrustSettingsDomainUser; dom <= int(kSecTrustSettingsDomainSystem); dom++) { diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 2419ec5e38b..69c4e041489 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -2154,6 +2154,12 @@ bool QSslSocketPrivate::ensureLibraryLoaded() // Initialize OpenSSL. if (q_OPENSSL_init_ssl(0, nullptr) != 1) return false; + + if (q_OpenSSL_version_num() < 0x10101000L) { + qCWarning(lcSsl, "QSslSocket: OpenSSL >= 1.1.1 is required; %s was found instead", q_OpenSSL_version(OPENSSL_VERSION)); + return false; + } + q_SSL_load_error_strings(); q_OpenSSL_add_all_algorithms(); diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 93b1c8fbf93..2e4e5fd48c2 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -1193,6 +1193,9 @@ QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime) { size_t lTimeLength = aTime->length; char *pString = (char *) aTime->data; + auto isValidPointer = [pString, lTimeLength](const char *const probe){ + return size_t(probe - pString) < lTimeLength; + }; if (aTime->type == V_ASN1_UTCTIME) { @@ -1211,12 +1214,21 @@ QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime) *pBuffer++ = '0'; } else { *pBuffer++ = *pString++; + if (!isValidPointer(pString)) // Nah. + return {}; *pBuffer++ = *pString++; + if (!isValidPointer(pString)) // Nah. + return {}; // Skip any fractional seconds... if (*pString == '.') { pString++; - while ((*pString >= '0') && (*pString <= '9')) + if (!isValidPointer(pString)) // Oh no, cannot dereference (see below). + return {}; + while ((*pString >= '0') && (*pString <= '9')) { pString++; + if (!isValidPointer(pString)) // No and no. + return {}; + } } } @@ -1230,6 +1242,10 @@ QDateTime q_getTimeFromASN1(const ASN1_TIME *aTime) if ((*pString != '+') && (*pString != '-')) return QDateTime(); + if (!isValidPointer(pString + 4)) { + // What kind of input parameters we were provided with? To hell with them! + return {}; + } lSecondsFromUCT = ((pString[1] - '0') * 10 + (pString[2] - '0')) * 60; lSecondsFromUCT += (pString[3] - '0') * 10 + (pString[4] - '0'); lSecondsFromUCT *= 60; diff --git a/src/network/ssl/qsslsocket_qt.cpp b/src/network/ssl/qsslsocket_qt.cpp index 9ff9a66c058..2f5d692162b 100644 --- a/src/network/ssl/qsslsocket_qt.cpp +++ b/src/network/ssl/qsslsocket_qt.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include "qsslsocket_p.h" #include "qasn1element_p.h" @@ -138,7 +139,7 @@ static QByteArray _q_PKCS12_salt() QByteArray salt; salt.resize(8); for (int i = 0; i < salt.size(); ++i) - salt[i] = (qrand() & 0xff); + salt[i] = (QRandomGenerator::global()->generate() & 0xff); return salt; } diff --git a/src/platformsupport/clipboard/qmacmime.mm b/src/platformsupport/clipboard/qmacmime.mm index 76e9c8712c9..c97d961260f 100644 --- a/src/platformsupport/clipboard/qmacmime.mm +++ b/src/platformsupport/clipboard/qmacmime.mm @@ -42,7 +42,7 @@ #include #include -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) #import #else #include diff --git a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp index 20cfb5155ec..ca4bc4091ba 100644 --- a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp +++ b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp @@ -53,11 +53,10 @@ QT_BEGIN_NAMESPACE Maintains a global stack storing the current event dispatcher and its processing flags for access from the Windows procedure - qWindowsWndProc. Handling the Lighthouse gui events should be done + qWindowsWndProc. Handling the QPA gui events should be done from within the qWindowsWndProc to ensure correct processing of messages. \internal - \ingroup qt-lighthouse-win */ QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject *parent) : diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index c6dad12b95a..7cf91b996be 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -615,7 +615,7 @@ void QFontconfigDatabase::populateFontDatabase() ++f; } - //Lighthouse has very lazy population of the font db. We want it to be initialized when + //QPA has very lazy population of the font db. We want it to be initialized when //QApplication is constructed, so that the population procedure can do something like this to //set the default font // const FcDefaultFont *s = defaults; diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 546dd65b17a..664e532d7c7 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -41,7 +41,7 @@ #include -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) #import #import #elif defined(QT_PLATFORM_UIKIT) diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h index 51d839688d5..fe5be960b3d 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext_p.h @@ -55,7 +55,7 @@ #include #include -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include #else #include diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index 635d2af0ab9..0266f19cd36 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -100,7 +100,6 @@ static inline bool useDirectWrite(QFont::HintingPreference hintingPreference, /*! \struct QWindowsFontEngineData \brief Static constant data shared by the font engines. - \ingroup qt-lighthouse-win */ QWindowsFontEngineData::QWindowsFontEngineData() @@ -154,10 +153,9 @@ qreal QWindowsFontDatabase::fontSmoothingGamma() delayed population of the database again passing a font name to EnumFontFamiliesEx(), working around the fact that EnumFontFamiliesEx() does not list all fonts by default. - This should be introduced to Lighthouse as well? + This should be introduced to QPA as well? \internal - \ingroup qt-lighthouse-win */ #ifndef QT_NO_DEBUG_STREAM diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp index 2ae378c5586..8cf224337b6 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp @@ -215,7 +215,6 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa \class QWindowsFontEngine \brief Standard Windows font engine. \internal - \ingroup qt-lighthouse-win Will probably be superseded by a common Free Type font engine in Qt 5.X. */ diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp index 4e6b22ce947..04b6c6888d1 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp @@ -219,7 +219,6 @@ static DWRITE_RENDERING_MODE hintingPreferenceToRenderingMode(QFont::HintingPref \class QWindowsFontEngineDirectWrite \brief Windows font engine using Direct Write. \internal - \ingroup qt-lighthouse-win Font engine for subpixel positioned text on Windows Vista (with platform update) and later. If selected during diff --git a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp index b1133dca223..ad277ea7cde 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsnativeimage.cpp @@ -60,7 +60,6 @@ typedef struct { \sa QWindowsBackingStore \internal - \ingroup qt-lighthouse-win */ static inline HDC createDC() diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp index 5387214e8c7..823adf52ea5 100644 --- a/src/platformsupport/glxconvenience/qglxconvenience.cpp +++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp @@ -224,6 +224,8 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format } QXlibPointer visual(glXGetVisualFromFBConfig(display, candidate)); + if (!visual) + continue; int actualRed; int actualGreen; int actualBlue; diff --git a/src/platformsupport/linuxaccessibility/dbusconnection.cpp b/src/platformsupport/linuxaccessibility/dbusconnection.cpp index cacbfdae9f0..45ddc8e4963 100644 --- a/src/platformsupport/linuxaccessibility/dbusconnection.cpp +++ b/src/platformsupport/linuxaccessibility/dbusconnection.cpp @@ -120,8 +120,7 @@ void DBusConnection::serviceRegistered() //debugging. static const bool a11yAlwaysOn = qEnvironmentVariableIsSet("QT_LINUX_ACCESSIBILITY_ALWAYS_ON"); - // a11yStatus->isEnabled() returns always true (since Gnome 3.6) - bool enabled = a11yAlwaysOn || a11yStatus->screenReaderEnabled(); + bool enabled = a11yAlwaysOn || a11yStatus->screenReaderEnabled() || a11yStatus->isEnabled(); if (enabled != m_enabled) { m_enabled = enabled; diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index b57deacb57b..3d9dfd8359e 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -47,6 +47,8 @@ #include #include "qiosurfacegraphicsbuffer.h" +#include + QT_BEGIN_NAMESPACE class QCocoaBackingStore : public QRasterBackingStore @@ -71,8 +73,9 @@ private: void redrawRoundedBottomCorners(CGRect) const; }; -class QCALayerBackingStore : public QCocoaBackingStore +class QCALayerBackingStore : public QObject, public QCocoaBackingStore { + Q_OBJECT public: QCALayerBackingStore(QWindow *window); ~QCALayerBackingStore(); @@ -119,6 +122,11 @@ private: QMacNotificationObserver m_backingPropertiesObserver; std::list> m_buffers; + + void flushSubWindow(QWindow *window); + std::unordered_map> m_subWindowBackingstores; + void windowDestroyed(QObject *object); + bool m_clearSurfaceOnPaint = true; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 2947c8c885e..102f00a25d3 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -381,7 +381,7 @@ void QCALayerBackingStore::beginPaint(const QRegion ®ion) // Although undocumented, QBackingStore::beginPaint expects the painted region // to be cleared before use if the window has a surface format with an alpha. // Fresh IOSurfaces are already cleared, so we don't need to clear those. - if (!bufferWasRecreated && window()->format().hasAlpha()) { + if (m_clearSurfaceOnPaint && !bufferWasRecreated && window()->format().hasAlpha()) { qCDebug(lcQpaBackingStore) << "Clearing" << region << "before use"; QPainter painter(m_buffers.back()->asImage()); painter.setCompositionMode(QPainter::CompositionMode_Source); @@ -510,9 +510,13 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, if (!prepareForFlush()) return; + if (flushedWindow != window()) { + flushSubWindow(flushedWindow); + return; + } + QMacAutoReleasePool pool; - NSView *backingStoreView = static_cast(window()->handle())->view(); NSView *flushedView = static_cast(flushedWindow->handle())->view(); // If the backingstore is just flushed, without being painted to first, then we may @@ -547,7 +551,7 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, // are committed as part of a display-cycle instead of on the next runloop pass. This // means CA won't try to throttle us if we flush too fast, and we'll coalesce our flush // with other pending view and layer updates. - backingStoreView.window.viewsNeedDisplay = YES; + flushedView.window.viewsNeedDisplay = YES; if (window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer) { // The private API [CALayer reloadValueForKeyPath:@"contents"] would be preferable, @@ -555,28 +559,10 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, flushedView.layer.contents = nil; } - if (flushedView == backingStoreView) { - qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface - << "to" << flushedView.layer << "of" << flushedView; - flushedView.layer.contents = backBufferSurface; - } else { - auto subviewRect = [flushedView convertRect:flushedView.bounds toView:backingStoreView]; - auto scale = flushedView.layer.contentsScale; - subviewRect = CGRectApplyAffineTransform(subviewRect, CGAffineTransformMakeScale(scale, scale)); + qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface + << "to" << flushedView.layer << "of" << flushedView; - // We make a copy of the image data up front, which means we don't - // need to mark the IOSurface as being in use. FIXME: Investigate - // if there's a cheaper way to get sub-image data to a layer. - m_buffers.back()->lock(QPlatformGraphicsBuffer::SWReadAccess); - QImage subImage = m_buffers.back()->asImage()->copy(QRectF::fromCGRect(subviewRect).toRect()); - m_buffers.back()->unlock(); - - qCInfo(lcQpaBackingStore) << "Flushing" << subImage - << "to" << flushedView.layer << "of subview" << flushedView; - QCFType cgImage = CGImageCreateCopyWithColorSpace( - QCFType(subImage.toCGImage()), colorSpace()); - flushedView.layer.contents = (__bridge id)static_cast(cgImage); - } + flushedView.layer.contents = backBufferSurface; // Since we may receive multiple flushes before a new frame is started, we do not // swap any buffers just yet. Instead we check in the next beginPaint if the layer's @@ -588,6 +574,53 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion ®ion, // the window server. } +void QCALayerBackingStore::flushSubWindow(QWindow *subWindow) +{ + qCInfo(lcQpaBackingStore) << "Flushing sub-window" << subWindow + << "via its own backingstore"; + + auto &subWindowBackingStore = m_subWindowBackingstores[subWindow]; + if (!subWindowBackingStore) { + subWindowBackingStore.reset(new QCALayerBackingStore(subWindow)); + QObject::connect(subWindow, &QObject::destroyed, this, &QCALayerBackingStore::windowDestroyed); + subWindowBackingStore->m_clearSurfaceOnPaint = false; + } + + auto subWindowSize = subWindow->size(); + static const auto kNoStaticContents = QRegion(); + subWindowBackingStore->resize(subWindowSize, kNoStaticContents); + + auto subWindowLocalRect = QRect(QPoint(), subWindowSize); + subWindowBackingStore->beginPaint(subWindowLocalRect); + + QPainter painter(subWindowBackingStore->m_buffers.back()->asImage()); + painter.setCompositionMode(QPainter::CompositionMode_Source); + + NSView *backingStoreView = static_cast(window()->handle())->view(); + NSView *flushedView = static_cast(subWindow->handle())->view(); + auto subviewRect = [flushedView convertRect:flushedView.bounds toView:backingStoreView]; + auto scale = flushedView.layer.contentsScale; + subviewRect = CGRectApplyAffineTransform(subviewRect, CGAffineTransformMakeScale(scale, scale)); + + m_buffers.back()->lock(QPlatformGraphicsBuffer::SWReadAccess); + const QImage *backingStoreImage = m_buffers.back()->asImage(); + painter.drawImage(subWindowLocalRect, *backingStoreImage, QRectF::fromCGRect(subviewRect)); + m_buffers.back()->unlock(); + + painter.end(); + subWindowBackingStore->endPaint(); + subWindowBackingStore->flush(subWindow, subWindowLocalRect, QPoint()); + + qCInfo(lcQpaBackingStore) << "Done flushing sub-window" << subWindow; +} + +void QCALayerBackingStore::windowDestroyed(QObject *object) +{ + auto *window = static_cast(object); + qCInfo(lcQpaBackingStore) << "Removing backingstore for sub-window" << window; + m_subWindowBackingstores.erase(window); +} + #ifndef QT_NO_OPENGL void QCALayerBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, bool translucentBackground) @@ -721,4 +754,6 @@ QImage *QCALayerBackingStore::GraphicsBuffer::asImage() return &m_image; } +#include "moc_qcocoabackingstore.cpp" + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index cbe86e7e489..1a718975d1a 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -45,7 +45,7 @@ // ------------- // // This file is not part of the Qt API. It provides helper functions -// for the Cocoa lighthouse plugin. This header file may +// for the Cocoa plugin. This header file may // change from version to version without notice, or even be removed. // // We mean it. diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm index d0baea5b362..000bcd708b7 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -74,8 +74,6 @@ QT_BEGIN_NAMESPACE Input method support in Cocoa uses NSTextInput protorol. Therefore almost all functionality is implemented in QNSView. - - \ingroup qt-lighthouse-cocoa */ diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp index 9689d6a89b8..95b30ec447b 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp @@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE \class QWindowsDirect2DBackingStore \brief Backing store for windows. \internal - \ingroup qt-lighthouse-win */ static inline QWindowsDirect2DPlatformPixmap *platformPixmap(QPixmap *p) diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp index a4cfaa85a83..2eb04a501b2 100644 --- a/src/plugins/platforms/wasm/qwasmcompositor.cpp +++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp @@ -327,11 +327,12 @@ QRect QWasmCompositor::titlebarRect(QWasmTitleBarOptions tb, QWasmCompositor::Su } break; case SC_TitleBarNormalButton: - if (isMinimized && (tb.flags & Qt::WindowMinimizeButtonHint)) + if (isMinimized && (tb.flags & Qt::WindowMinimizeButtonHint)) { offset += delta; - else if (isMaximized && (tb.flags & Qt::WindowMaximizeButtonHint)) + } else if (isMaximized && (tb.flags & Qt::WindowMaximizeButtonHint)) { ret.adjust(0, 0, -delta*2, 0); offset += (delta +delta); + } break; case SC_TitleBarSysMenu: if (tb.flags & Qt::WindowSystemMenuHint) { diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp index fbf700518ed..c122335a575 100644 --- a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp +++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp @@ -62,6 +62,16 @@ QWasmOpenGLContext::~QWasmOpenGLContext() } } +bool QWasmOpenGLContext::isOpenGLVersionSupported(QSurfaceFormat format) +{ + // Version check: support WebGL 1 and 2: + // (ES) 2.0 -> WebGL 1.0 + // (ES) 3.0 -> WebGL 2.0 + // [we don't expect that new WebGL versions will be created] + return ((format.majorVersion() == 2 && format.minorVersion() == 0) || + (format.majorVersion() == 3 && format.minorVersion() == 0)); +} + bool QWasmOpenGLContext::maybeCreateEmscriptenContext(QPlatformSurface *surface) { // Native emscripten/WebGL contexts are tied to a single screen/canvas. The first @@ -92,10 +102,8 @@ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(cons attributes.failIfMajorPerformanceCaveat = false; attributes.antialias = true; attributes.enableExtensionsByDefault = true; - - if (format.majorVersion() == 3) { - attributes.majorVersion = 2; - } + attributes.majorVersion = format.majorVersion() - 1; + attributes.minorVersion = format.minorVersion(); // WebGL doesn't allow separate attach buffers to STENCIL_ATTACHMENT and DEPTH_ATTACHMENT // we need both or none @@ -149,6 +157,9 @@ bool QWasmOpenGLContext::isSharing() const bool QWasmOpenGLContext::isValid() const { + if (!(isOpenGLVersionSupported(m_requestedFormat))) + return false; + // Note: we get isValid() calls before we see the surface and can // create a native context, so no context is also a valid state. return !m_context || !emscripten_is_webgl_context_lost(m_context); diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.h b/src/plugins/platforms/wasm/qwasmopenglcontext.h index d27007e8ea5..cf84379c367 100644 --- a/src/plugins/platforms/wasm/qwasmopenglcontext.h +++ b/src/plugins/platforms/wasm/qwasmopenglcontext.h @@ -51,6 +51,7 @@ public: QFunctionPointer getProcAddress(const char *procName) override; private: + static bool isOpenGLVersionSupported(QSurfaceFormat format); bool maybeCreateEmscriptenContext(QPlatformSurface *surface); static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const QString &canvasId, QSurfaceFormat format); diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp index 1929f800a47..94d8470ab14 100644 --- a/src/plugins/platforms/windows/main.cpp +++ b/src/plugins/platforms/windows/main.cpp @@ -46,10 +46,9 @@ QT_BEGIN_NAMESPACE /*! - \group qt-lighthouse-win - \title Qt Lighthouse plugin for Windows + \title Qt platform plugin for Windows - \brief Class documentation of the Qt Lighthouse plugin for Windows. + \brief Class documentation of the Qt platform plugin for Windows. \section1 Supported Parameters @@ -78,7 +77,6 @@ QT_BEGIN_NAMESPACE \class QWindowsIntegrationPlugin \brief Plugin. \internal - \ingroup qt-lighthouse-win */ /*! @@ -86,7 +84,6 @@ QT_BEGIN_NAMESPACE \brief Namespace for enumerations, etc. \internal - \ingroup qt-lighthouse-win */ /*! @@ -97,7 +94,6 @@ QT_BEGIN_NAMESPACE With flags that should help to structure the code. \internal - \ingroup qt-lighthouse-win */ class QWindowsIntegrationPlugin : public QPlatformIntegrationPlugin diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index bd7bdc55d17..e3939ca2d73 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE \class QWindowsBackingStore \brief Backing store for windows. \internal - \ingroup qt-lighthouse-win */ QWindowsBackingStore::QWindowsBackingStore(QWindow *window) : diff --git a/src/plugins/platforms/windows/qwindowsclipboard.cpp b/src/plugins/platforms/windows/qwindowsclipboard.cpp index efcb0b6e6ed..b23904e9780 100644 --- a/src/plugins/platforms/windows/qwindowsclipboard.cpp +++ b/src/plugins/platforms/windows/qwindowsclipboard.cpp @@ -71,7 +71,6 @@ QT_BEGIN_NAMESPACE \note The OLE-functions used in this class require OleInitialize(). \internal - \ingroup qt-lighthouse-win */ #ifndef QT_NO_DEBUG_STREAM @@ -110,7 +109,6 @@ static QDebug operator<<(QDebug d, const QMimeData *mimeData) \sa QWindowsInternalMimeDataBase, QWindowsClipboard \internal - \ingroup qt-lighthouse-win */ IDataObject *QWindowsClipboardRetrievalMimeData::retrieveDataObject() const diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index b8b54d9b860..c7b85187a39 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -186,7 +186,6 @@ static bool enableNonClientDpiScaling(HWND hwnd) \sa QWindowsShell32DLL \internal - \ingroup qt-lighthouse-win */ void QWindowsUser32DLL::init() @@ -252,7 +251,6 @@ QWindowsContext *QWindowsContext::m_instance = nullptr; Holds state information formerly stored in \c qapplication_win.cpp. \internal - \ingroup qt-lighthouse-win */ typedef QHash HandleBaseWindowHash; @@ -1007,6 +1005,13 @@ QByteArray QWindowsContext::comErrorString(HRESULT hr) return result; } +void QWindowsContext::forceNcCalcSize(HWND hwnd) +{ + // Force WM_NCCALCSIZE to adjust margin + SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); +} + bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out, unsigned dpi) { @@ -1667,7 +1672,6 @@ static inline bool isTopLevel(HWND hwnd) There is another one for timers, sockets, etc in QEventDispatcherWin32. - \ingroup qt-lighthouse-win */ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 1831ac6ec01..c89b8b91f4a 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -249,6 +249,8 @@ public: bool asyncExpose() const; void setAsyncExpose(bool value); + static void forceNcCalcSize(HWND hwnd); + static bool systemParametersInfo(unsigned action, unsigned param, void *out, unsigned dpi = 0); static bool systemParametersInfoForScreen(unsigned action, unsigned param, void *out, const QPlatformScreen *screen = nullptr); diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 19de3d59393..338bb9ff8fe 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -73,7 +73,6 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap); \brief Cache key for storing values in a QHash with a QCursor as key. \internal - \ingroup qt-lighthouse-win */ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) @@ -97,7 +96,6 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) as do the Window manager frames (resize/move handles). \internal - \ingroup qt-lighthouse-win \sa QWindowsWindowCursor */ @@ -816,7 +814,6 @@ HCURSOR QWindowsCursor::hCursor(const QCursor &c) const cursor handle resource. \internal - \ingroup qt-lighthouse-win \sa QWindowsCursor */ diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index ccc809413e8..dbd7d557db3 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -130,7 +130,6 @@ namespace QWindowsDialogs remove all those messages (usually 1) and post the last one with a reset button state. - \ingroup qt-lighthouse-win */ void eatMouseMove() @@ -173,7 +172,6 @@ void eatMouseMove() \sa QWindowsDialogHelperBase \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeDialogBase : public QObject @@ -213,7 +211,6 @@ private: \sa QWindowsDialogThread, QWindowsNativeDialogBase \internal - \ingroup qt-lighthouse-win */ template @@ -267,7 +264,6 @@ QWindowsNativeDialogBase *QWindowsDialogHelperBase::ensureNativeDialo \sa QWindowsDialogHelperBase \internal - \ingroup qt-lighthouse-win */ class QWindowsDialogThread : public QThread @@ -408,7 +404,6 @@ void QWindowsDialogHelperBase::exec() does not reliably work. Provides thread-safe setters (for the non-modal case). \internal - \ingroup qt-lighthouse-win \sa QFileDialogOptions */ @@ -502,7 +497,6 @@ inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer QWindowsNativeSaveFileDialog::selectedFiles() const Implements multi-selection methods. \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase @@ -1554,7 +1544,6 @@ QWindowsNativeFileDialogBase *QWindowsNativeFileDialogBase::create(QFileDialogOp but only on QQuickWindows, which do not have a fallback. \internal - \ingroup qt-lighthouse-win */ class QWindowsFileDialogHelper : public QWindowsDialogHelperBase @@ -1690,7 +1679,6 @@ QString QWindowsFileDialogHelper::selectedNameFilter() const \internal \sa QWindowsXpFileDialogHelper - \ingroup qt-lighthouse-win */ class QWindowsXpNativeFileDialog : public QWindowsNativeDialogBase @@ -1938,7 +1926,6 @@ QList QWindowsXpNativeFileDialog::execFileNames(HWND owner, int *selectedF \sa QWindowsXpNativeFileDialog \internal - \ingroup qt-lighthouse-win */ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase @@ -2015,7 +2002,6 @@ QString QWindowsXpFileDialogHelper::selectedNameFilter() const \sa QWindowsColorDialogHelper \sa #define USE_NATIVE_COLOR_DIALOG \internal - \ingroup qt-lighthouse-win */ using SharedPointerColor = QSharedPointer; @@ -2095,7 +2081,6 @@ void QWindowsNativeColorDialog::doExec(HWND owner) \sa #define USE_NATIVE_COLOR_DIALOG \sa QWindowsNativeColorDialog \internal - \ingroup qt-lighthouse-win */ class QWindowsColorDialogHelper : public QWindowsDialogHelperBase diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 3e4c93d47a4..bb1e1345dc3 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -75,7 +75,6 @@ QT_BEGIN_NAMESPACE \sa QWindowsOleDropSource \internal - \ingroup qt-lighthouse-win */ class QWindowsDragCursorWindow : public QRasterWindow @@ -135,7 +134,6 @@ void QWindowsDragCursorWindow::setPixmap(const QPixmap &p) \sa QWindowsDrag \internal - \ingroup qt-lighthouse-win */ IDataObject *QWindowsDropMimeData::retrieveDataObject() const @@ -217,7 +215,6 @@ static Qt::MouseButtons lastButtons = Qt::NoButton; \sa QWindowsDrag \internal - \ingroup qt-lighthouse-win */ class QWindowsOleDropSource : public QWindowsComBase @@ -485,7 +482,6 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect) \sa QWindowsDrag \internal - \ingroup qt-lighthouse-win */ QWindowsOleDropTarget::QWindowsOleDropTarget(QWindow *w) : m_window(w) @@ -659,7 +655,6 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState, \class QWindowsDrag \brief Windows drag implementation. \internal - \ingroup qt-lighthouse-win */ bool QWindowsDrag::m_canceled = false; diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp index c9dd1c7c177..a06a14a9802 100644 --- a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp +++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp @@ -54,7 +54,6 @@ QT_BEGIN_NAMESPACE (instead of creating local hyperlinks). \internal - \ingroup qt-lighthouse-win */ QWindowsDropDataObject::QWindowsDropDataObject(QMimeData *mimeData) : diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 76baa93d98c..4ae087dfaa6 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -63,7 +63,6 @@ QT_BEGIN_NAMESPACE there is no need to differentiate between dynamic or Angle-only builds in here. \internal - \ingroup qt-lighthouse-win */ QWindowsLibEGL QWindowsEGLStaticContext::libEGL; @@ -376,7 +375,6 @@ QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EG \endlist \internal - \ingroup qt-lighthouse-win */ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 7431f52e8ac..b2ac2e34769 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -858,7 +858,6 @@ static inline QOpenGLContextData createDummyWindowOpenGLContextData() context and to apply to a QSurfaceFormat. \internal - \ingroup qt-lighthouse-win */ QWindowsOpenGLContextFormat QWindowsOpenGLContextFormat::current() @@ -913,7 +912,6 @@ void QWindowsOpenGLContextFormat::apply(QSurfaceFormat *format) const is a current GL context. \internal - \ingroup qt-lighthouse-win */ class QOpenGLTemporaryContext @@ -946,7 +944,6 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext() /*! \class QWindowsOpenGLAdditionalFormat \brief Additional format information that is not in QSurfaceFormat - \ingroup qt-lighthouse-win */ /*! @@ -964,7 +961,6 @@ QOpenGLTemporaryContext::~QOpenGLTemporaryContext() \sa QWindowsGLContext \internal - \ingroup qt-lighthouse-win */ #define SAMPLE_BUFFER_EXTENSION "GL_ARB_multisample" @@ -1051,7 +1047,6 @@ QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering) QOpenGLContextData and are released in doneCurrent(). \internal - \ingroup qt-lighthouse-win */ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext, diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 7c4ddbd2a13..03be0b94510 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -160,7 +160,6 @@ Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); // from qlocale_win.cpp needs to be checked (mouse grab might interfere with candidate window). \internal - \ingroup qt-lighthouse-win */ diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 8963f2ad179..977b5903a5e 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -131,7 +131,6 @@ QT_BEGIN_NAMESPACE QWindowsUser32DLL and QWindowsShell32DLL. All function pointers should go to these structs to avoid lookups in several places. - \ingroup qt-lighthouse-win */ struct QWindowsIntegrationPrivate diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp index 44b7523fa69..ad3f02f83b2 100644 --- a/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp +++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.cpp @@ -60,7 +60,6 @@ \sa QInternalMimeData, QWindowsMime, QWindowsMimeConverter \internal - \ingroup qt-lighthouse-win */ bool QWindowsInternalMimeData::hasFormat_sys(const QString &mime) const diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index e3edf7e81e5..4f46c05f7af 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -88,7 +88,6 @@ QT_BEGIN_NAMESPACE \class QWindowsKeyMapper \brief Translates Windows keys to QWindowSystemInterface events. \internal - \ingroup qt-lighthouse-win In addition, handles some special keys to display system menus, etc. The code originates from \c qkeymapper_win.cpp. diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp index 7c3e87eec15..5f21bdfa33e 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.cpp +++ b/src/plugins/platforms/windows/qwindowsmenu.cpp @@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE Qt Widgets, either the containers or the items might be deleted first. \internal - \ingroup qt-lighthouse-win */ static uint nextId = 1; @@ -794,20 +793,13 @@ QWindowsMenuBar *QWindowsMenuBar::menuBarOf(const QWindow *notYetCreatedWindow) ? qobject_cast(menuBarV.value()) : nullptr; } -static inline void forceNcCalcSize(HWND hwnd) -{ - // Force WM_NCCALCSIZE to adjust margin: Does not appear to work? - SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, - SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER); -} - void QWindowsMenuBar::install(QWindowsWindow *window) { const HWND hwnd = window->handle(); const BOOL result = SetMenu(hwnd, m_hMenuBar); if (result) { window->setMenuBar(this); - forceNcCalcSize(hwnd); + QWindowsContext::forceNcCalcSize(hwnd); } } @@ -817,7 +809,7 @@ void QWindowsMenuBar::removeFromWindow() const HWND hwnd = window->handle(); SetMenu(hwnd, nullptr); window->setMenuBar(nullptr); - forceNcCalcSize(hwnd); + QWindowsContext::forceNcCalcSize(hwnd); } } diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 9bc79a10f9c..f8cc5e76ff7 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -450,7 +450,6 @@ QDebug operator<<(QDebug d, IDataObject *dataObj) \class QWindowsMime \brief The QWindowsMime class maps open-standard MIME to Window Clipboard formats. \internal - \ingroup qt-lighthouse-win Qt's drag-and-drop and clipboard facilities use the MIME standard. On X11, this maps trivially to the Xdnd protocol, but on Windows @@ -1498,7 +1497,6 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const \class QWindowsMimeConverter \brief Manages the list of QWindowsMime instances. \internal - \ingroup qt-lighthouse-win \sa QWindowsMime */ diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index b776efc942f..1b2d831268a 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -145,7 +145,6 @@ static inline QTouchDevice *createTouchDevice() Dispatches mouse and touch events. Separate for code cleanliness. \internal - \ingroup qt-lighthouse-win */ QWindowsMouseHandler::QWindowsMouseHandler() = default; diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index 90ba7a44c97..387f65ae8ff 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -58,7 +58,6 @@ QT_BEGIN_NAMESPACE \endlist \internal - \ingroup qt-lighthouse-win */ class QWindowsNativeInterface : public QPlatformNativeInterface diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp index f3450e28062..0a7fef6c30f 100644 --- a/src/plugins/platforms/windows/qwindowsole.cpp +++ b/src/plugins/platforms/windows/qwindowsole.cpp @@ -70,7 +70,6 @@ QT_BEGIN_NAMESPACE \endlist \internal - \ingroup qt-lighthouse-win */ QWindowsOleDataObject::QWindowsOleDataObject(QMimeData *mimeData) : @@ -228,7 +227,6 @@ QWindowsOleDataObject::EnumDAdvise(LPENUMSTATDATA FAR*) \class QWindowsOleEnumFmtEtc \brief Enumerates the FORMATETC structures supported by QWindowsOleDataObject. \internal - \ingroup qt-lighthouse-win */ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector &fmtetcs) diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index c7a0c2e62e9..9a4f8d152c3 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -171,7 +171,6 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) \brief Windows screen. \sa QWindowsScreenManager \internal - \ingroup qt-lighthouse-win */ QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) : @@ -432,7 +431,6 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy \sa QWindowsScreen \internal - \ingroup qt-lighthouse-win */ QWindowsScreenManager::QWindowsScreenManager() = default; diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index d6a5b29a710..def011e4bd4 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -184,7 +184,6 @@ static inline HWND createTrayIconMessageWindow() \brief Windows native system tray icon \internal - \ingroup qt-lighthouse-win */ QWindowsSystemTrayIcon::QWindowsSystemTrayIcon() diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index cd5a78abb6f..287ba931d9b 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -173,7 +173,6 @@ QWindowsWinTab32DLL QWindowsTabletSupport::m_winTab32DLL; \brief Functions from wintabl32.dll shipped with WACOM tablets used by QWindowsTabletSupport. \internal - \ingroup qt-lighthouse-win */ bool QWindowsWinTab32DLL::init() @@ -205,7 +204,6 @@ bool QWindowsWinTab32DLL::init() \internal \since 5.2 - \ingroup qt-lighthouse-win */ QWindowsTabletSupport::QWindowsTabletSupport(HWND window, HCTX context) diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h index ffe2e620695..a31e00c0ace 100644 --- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h +++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE to be done by using QWaitCondition/QMutex. \internal - \ingroup qt-lighthouse-win */ class QWindowsThreadPoolRunner { diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 3dfffa6de62..2b5f0b60752 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -489,7 +489,6 @@ static QMargins invisibleMargins(QPoint screenPoint) \sa QWindowCreationContext \internal - \ingroup qt-lighthouse-win */ struct WindowCreationData @@ -917,7 +916,6 @@ static QSize toNativeSizeConstrained(QSize dip, const QScreen *s) into account. \internal - \ingroup qt-lighthouse-win */ QMargins QWindowsGeometryHint::frameOnPrimaryScreen(DWORD style, DWORD exStyle) @@ -1087,7 +1085,6 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w) \since 5.6 \internal - \ingroup qt-lighthouse-win */ bool QWindowsBaseWindow::isRtlLayout(HWND hwnd) @@ -1176,7 +1173,6 @@ QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const \brief Window wrapping GetDesktopWindow not allowing any manipulation. \since 5.6 \internal - \ingroup qt-lighthouse-win */ /*! @@ -1189,7 +1185,6 @@ QPoint QWindowsBaseWindow::mapFromGlobal(const QPoint &pos) const \since 5.6 \internal - \ingroup qt-lighthouse-win */ QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd) @@ -1248,7 +1243,6 @@ void QWindowsForeignWindow::setVisible(bool visible) \sa WindowCreationData, QWindowsContext \internal - \ingroup qt-lighthouse-win */ QWindowCreationContext::QWindowCreationContext(const QWindow *w, const QScreen *s, @@ -1318,7 +1312,6 @@ void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const \endlist \internal - \ingroup qt-lighthouse-win */ const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle"; @@ -2442,7 +2435,17 @@ void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins) void QWindowsWindow::updateFullFrameMargins() { - // Normally obtained from WM_NCCALCSIZE + // QTBUG-82580: If a native menu is present, force a WM_NCCALCSIZE. + if (GetMenu(m_data.hwnd)) + QWindowsContext::forceNcCalcSize(m_data.hwnd); + else + calculateFullFrameMargins(); +} + +void QWindowsWindow::calculateFullFrameMargins() +{ + // Normally obtained from WM_NCCALCSIZE. This calculation only works + // when no native menu is present. const auto systemMargins = testFlag(DisableNonClientScaling) ? QWindowsGeometryHint::frameOnPrimaryScreen(m_data.hwnd) : frameMargins_sys(); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index e1f79086875..b35081d41da 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -373,6 +373,7 @@ private: void handleWindowStateChange(Qt::WindowStates state); inline void destroyIcon(); void fireExpose(const QRegion ®ion, bool force=false); + void calculateFullFrameMargins(); mutable QWindowsWindowData m_data; QPointer m_menuBar; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp index 32a57473ad0..fef5346eafe 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp @@ -105,6 +105,7 @@ static QString alertSound(const QObject *object) case Critical: return QStringLiteral("SystemHand"); } + return QString(); } return QStringLiteral("SystemAsterisk"); } diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 59360616a19..3962d2d27fa 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -305,11 +305,9 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow } break; case UIA_TogglePatternId: - // Checkbox controls. - if (accessible->role() == QAccessible::CheckBox - || (accessible->role() == QAccessible::MenuItem && accessible->state().checkable)) { + // Checkboxes and other checkable controls. + if (accessible->state().checkable) *pRetVal = new QWindowsUiaToggleProvider(id()); - } break; case UIA_SelectionPatternId: // Lists of items. diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp index b27c408f407..04d74178017 100644 --- a/src/plugins/platforms/winrt/qwinrtservices.cpp +++ b/src/plugins/platforms/winrt/qwinrtservices.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -94,13 +95,17 @@ bool QWinRTServices::openUrl(const QUrl &url) HRESULT hr = d->uriFactory->CreateUri(uriString.Get(), &uri); RETURN_FALSE_IF_FAILED("Failed to create URI from QUrl."); - ComPtr> op; - hr = d->launcher->LaunchUriAsync(uri.Get(), &op); - RETURN_FALSE_IF_FAILED("Failed to start URI launch."); - boolean result; - hr = QWinRTFunctions::await(op, &result); - RETURN_FALSE_IF_FAILED("Failed to launch URI."); + hr = QEventDispatcherWinRT::runOnXamlThread([this, d, uri, &result]() { + ComPtr> op; + HRESULT hr = d->launcher->LaunchUriAsync(uri.Get(), &op); + RETURN_HR_IF_FAILED("Failed to start URI launch."); + + hr = QWinRTFunctions::await(op, &result); + RETURN_HR_IF_FAILED("Failed to launch URI."); + return hr; + }); + RETURN_FALSE_IF_FAILED("Failed to launch URI from Xaml thread."); return result; } @@ -131,12 +136,16 @@ bool QWinRTServices::openDocument(const QUrl &url) boolean result; { - ComPtr> op; - hr = d->launcher->LaunchFileAsync(file.Get(), &op); - RETURN_FALSE_IF_FAILED("Failed to start file launch."); + hr = QEventDispatcherWinRT::runOnXamlThread([this, d, file, &result]() { + ComPtr> op; + HRESULT hr = d->launcher->LaunchFileAsync(file.Get(), &op); + RETURN_HR_IF_FAILED("Failed to start file launch."); - hr = QWinRTFunctions::await(op, &result); - RETURN_FALSE_IF_FAILED("Failed to launch file."); + hr = QWinRTFunctions::await(op, &result); + RETURN_HR_IF_FAILED("Failed to launch file."); + return hr; + }); + RETURN_FALSE_IF_FAILED("Failed to launch file from Xaml thread."); } return result; diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp index 7bf2b38d7d6..77d0caf6493 100644 --- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp +++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp @@ -37,6 +37,8 @@ ** ****************************************************************************/ +#include + #include #include #include @@ -504,7 +506,7 @@ static Picture getPatternFill(int screen, const QBrush &b) return X11->pattern_fills[i].picture; } // none found, replace one - int i = qrand() % 16; + int i = QRandomGenerator::global()->generate() % 16; if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) { XRenderFreePicture (QXcbX11Info::display(), X11->pattern_fills[i].picture); diff --git a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp index 57b1882e4b4..6a483fc7e56 100644 --- a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp +++ b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp @@ -37,6 +37,8 @@ ** ****************************************************************************/ +#include + #include "qxcbconnection.h" #include "qcolormap_x11_p.h" #include "qxcbnativepainting.h" @@ -279,7 +281,7 @@ Picture QXcbX11Data::getSolidFill(int screen, const QColor &c) return X11->solid_fills[i].picture; } // none found, replace one - int i = qrand() % 16; + int i = QRandomGenerator::global()->generate() % 16; if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) { XRenderFreePicture (X11->display, X11->solid_fills[i].picture); diff --git a/src/plugins/platforms/xcb/qxcbatom.cpp b/src/plugins/platforms/xcb/qxcbatom.cpp index ff5c50b7021..780816605ad 100644 --- a/src/plugins/platforms/xcb/qxcbatom.cpp +++ b/src/plugins/platforms/xcb/qxcbatom.cpp @@ -182,6 +182,7 @@ static const char *xcb_atomnames = { "XdndActionCopy\0" "XdndActionLink\0" "XdndActionMove\0" + "XdndActionAsk\0" "XdndActionPrivate\0" // Xkb diff --git a/src/plugins/platforms/xcb/qxcbatom.h b/src/plugins/platforms/xcb/qxcbatom.h index 80b5887395a..9cf93ec314a 100644 --- a/src/plugins/platforms/xcb/qxcbatom.h +++ b/src/plugins/platforms/xcb/qxcbatom.h @@ -183,6 +183,7 @@ public: XdndActionCopy, XdndActionLink, XdndActionMove, + XdndActionAsk, XdndActionPrivate, // Xkb diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 639e4f039cb..42c7a52bd45 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -289,10 +289,10 @@ QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c) if (pixmapCacheKey) { bitmapCacheKey = pixmapCacheKey; } else { - Q_ASSERT(c.bitmap()); - Q_ASSERT(c.mask()); - bitmapCacheKey = c.bitmap()->cacheKey(); - maskCacheKey = c.mask()->cacheKey(); + Q_ASSERT(!c.bitmap(Qt::ReturnByValue).isNull()); + Q_ASSERT(!c.mask(Qt::ReturnByValue).isNull()); + bitmapCacheKey = c.bitmap(Qt::ReturnByValue).cacheKey(); + maskCacheKey = c.mask(Qt::ReturnByValue).cacheKey(); } } } @@ -613,8 +613,8 @@ xcb_cursor_t QXcbCursor::createBitmapCursor(QCursor *cursor) qCWarning(lcQpaXcb, "xrender >= 0.5 required to create pixmap cursors"); } else { xcb_connection_t *conn = xcb_connection(); - xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap()->toImage()); - xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask()->toImage()); + xcb_pixmap_t cp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->bitmap(Qt::ReturnByValue).toImage()); + xcb_pixmap_t mp = qt_xcb_XPixmapFromBitmap(m_screen, cursor->mask(Qt::ReturnByValue).toImage()); c = xcb_generate_id(conn); xcb_create_cursor(conn, c, cp, mp, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, spot.x(), spot.y()); diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index e76fc8bd401..cc735f40a83 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -216,6 +216,22 @@ void QXcbDrag::endDrag() initiatorWindow.clear(); } +Qt::DropAction QXcbDrag::defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const +{ + if (currentDrag() || drop_actions.isEmpty()) + return QBasicDrag::defaultAction(possibleActions, modifiers); + + return toDropAction(drop_actions.first()); +} + +void QXcbDrag::handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) +{ + if (event->window != xdnd_dragsource || event->atom != atom(QXcbAtom::XdndActionList)) + return; + + readActionList(); +} + static bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType) { @@ -470,16 +486,20 @@ void QXcbDrag::move(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardMod move.data.data32[1] = 0; // flags move.data.data32[2] = (globalPos.x() << 16) + globalPos.y(); move.data.data32[3] = connection()->time(); - move.data.data32[4] = toXdndAction(defaultAction(currentDrag()->supportedActions(), mods)); + const auto supportedActions = currentDrag()->supportedActions(); + const auto requestedAction = defaultAction(supportedActions, mods); + move.data.data32[4] = toXdndAction(requestedAction); qCDebug(lcQpaXDnd) << "sending XdndPosition to target:" << target; source_time = connection()->time(); - if (w) + if (w) { handle_xdnd_position(w, &move, b, mods); - else + } else { + setActionList(requestedAction, supportedActions); xcb_send_event(xcb_connection(), false, proxy_target, XCB_EVENT_MASK_NO_EVENT, (const char *)&move); + } } static const bool isUnity = qgetenv("XDG_CURRENT_DESKTOP").toLower() == "unity"; @@ -560,6 +580,16 @@ Qt::DropAction QXcbDrag::toDropAction(xcb_atom_t a) const return Qt::CopyAction; } +Qt::DropActions QXcbDrag::toDropActions(const QVector &atoms) const +{ + Qt::DropActions actions; + for (const auto actionAtom : atoms) { + if (actionAtom != atom(QXcbAtom::XdndActionAsk)) + actions |= toDropAction(actionAtom); + } + return actions; +} + xcb_atom_t QXcbDrag::toXdndAction(Qt::DropAction a) const { switch (a) { @@ -577,6 +607,60 @@ xcb_atom_t QXcbDrag::toXdndAction(Qt::DropAction a) const } } +void QXcbDrag::readActionList() +{ + drop_actions.clear(); + auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, xdnd_dragsource, + atom(QXcbAtom::XdndActionList), XCB_ATOM_ATOM, + 0, 1024); + if (reply && reply->type != XCB_NONE && reply->format == 32) { + int length = xcb_get_property_value_length(reply.get()) / 4; + + xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get()); + for (int i = 0; i < length; ++i) + drop_actions.append(atoms[i]); + } +} + +void QXcbDrag::setActionList(Qt::DropAction requestedAction, Qt::DropActions supportedActions) +{ +#ifndef QT_NO_CLIPBOARD + QVector actions; + if (requestedAction != Qt::IgnoreAction) + actions.append(toXdndAction(requestedAction)); + + auto checkAppend = [this, requestedAction, supportedActions, &actions](Qt::DropAction action) { + if (requestedAction != action && supportedActions & action) + actions.append(toXdndAction(action)); + }; + + checkAppend(Qt::CopyAction); + checkAppend(Qt::MoveAction); + checkAppend(Qt::LinkAction); + + if (current_actions != actions) { + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, connection()->clipboard()->owner(), + atom(QXcbAtom::XdndActionList), + XCB_ATOM_ATOM, 32, actions.size(), actions.constData()); + current_actions = actions; + } +#endif +} + +void QXcbDrag::startListeningForActionListChanges() +{ + connection()->addWindowEventListener(xdnd_dragsource, this); + const uint32_t event_mask[] = { XCB_EVENT_MASK_PROPERTY_CHANGE }; + xcb_change_window_attributes(xcb_connection(), xdnd_dragsource, XCB_CW_EVENT_MASK, event_mask); +} + +void QXcbDrag::stopListeningForActionListChanges() +{ + const uint32_t event_mask[] = { XCB_EVENT_MASK_NO_EVENT }; + xcb_change_window_attributes(xcb_connection(), xdnd_dragsource, XCB_CW_EVENT_MASK, event_mask); + connection()->removeWindowEventListener(xdnd_dragsource); +} + int QXcbDrag::findTransactionByWindow(xcb_window_t window) { int at = -1; @@ -657,6 +741,9 @@ void QXcbDrag::handleEnter(QPlatformWindow *, const xcb_client_message_event_t * return; xdnd_dragsource = event->data.data32[0]; + startListeningForActionListChanges(); + readActionList(); + if (!proxy) proxy = xdndProxy(connection(), xdnd_dragsource); current_proxy_target = proxy ? proxy : xdnd_dragsource; @@ -723,7 +810,9 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message supported_actions = currentDrag()->supportedActions(); } else { dropData = m_dropData; - supported_actions = Qt::DropActions(toDropAction(e->data.data32[4])); + supported_actions = toDropActions(drop_actions); + if (e->data.data32[4] != atom(QXcbAtom::XdndActionAsk)) + supported_actions |= Qt::DropActions(toDropAction(e->data.data32[4])); } auto buttons = currentDrag() ? b : connection()->queryMouseButtons(); @@ -867,8 +956,10 @@ void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t // If the target receives XdndLeave, it frees any cached data and forgets the whole incident. qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndLeave"; - if (!currentWindow || w != currentWindow.data()->handle()) + if (!currentWindow || w != currentWindow.data()->handle()) { + stopListeningForActionListChanges(); return; // sanity + } // ### // if (checkEmbedded(current_embedding_widget, event)) { @@ -883,6 +974,8 @@ void QXcbDrag::handleLeave(QPlatformWindow *w, const xcb_client_message_event_t event->data.data32[0], xdnd_dragsource); } + stopListeningForActionListChanges(); + QWindowSystemInterface::handleDrag(w->window(), nullptr, QPoint(), Qt::IgnoreAction, { }, { }); } @@ -929,6 +1022,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e qCDebug(lcQpaXDnd) << "target:" << event->window << "received XdndDrop"; if (!currentWindow) { + stopListeningForActionListChanges(); xdnd_dragsource = 0; return; // sanity } @@ -951,7 +1045,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e supported_drop_actions = Qt::DropActions(l[4]); } else { dropData = m_dropData; - supported_drop_actions = accepted_drop_action; + supported_drop_actions = accepted_drop_action | toDropActions(drop_actions); } if (!dropData) @@ -986,6 +1080,8 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e xcb_send_event(xcb_connection(), false, current_proxy_target, XCB_EVENT_MASK_NO_EVENT, (char *)&finished); + stopListeningForActionListChanges(); + dropped = true; } diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 7bef7a818a7..0d16afc47e4 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -68,7 +68,7 @@ class QXcbScreen; class QDrag; class QShapedPixmapWindow; -class QXcbDrag : public QXcbObject, public QBasicDrag +class QXcbDrag : public QXcbObject, public QBasicDrag, public QXcbWindowEventListener { public: QXcbDrag(QXcbConnection *c); @@ -82,6 +82,10 @@ public: void drop(const QPoint &globalPos, Qt::MouseButtons b, Qt::KeyboardModifiers mods) override; void endDrag() override; + Qt::DropAction defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const override; + + void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) override; + void handleEnter(QPlatformWindow *window, const xcb_client_message_event_t *event, xcb_window_t proxy = 0); void handlePosition(QPlatformWindow *w, const xcb_client_message_event_t *event); void handleLeave(QPlatformWindow *w, const xcb_client_message_event_t *event); @@ -114,8 +118,14 @@ private: void send_leave(); Qt::DropAction toDropAction(xcb_atom_t atom) const; + Qt::DropActions toDropActions(const QVector &atoms) const; xcb_atom_t toXdndAction(Qt::DropAction a) const; + void readActionList(); + void setActionList(Qt::DropAction requestedAction, Qt::DropActions supportedActions); + void startListeningForActionListChanges(); + void stopListeningForActionListChanges(); + QPointer initiatorWindow; QPointer currentWindow; QPoint currentPosition; @@ -159,6 +169,9 @@ private: QVector drag_types; + QVector current_actions; + QVector drop_actions; + struct Transaction { xcb_timestamp_t timestamp; diff --git a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp index 3757ba2eff7..acfd31ee3aa 100644 --- a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp +++ b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp @@ -47,25 +47,38 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include +#include +#include +#include +#include +#include +void testProc() +{ //! [2] QSqlQuery q; q.exec("call qtestproc (@outval1, @outval2)"); q.exec("select @outval1, @outval2"); -q.next(); -qDebug() << q.value(0) << q.value(1); // outputs "42" and "43" +if (q.next()) + qDebug() << q.value(0) << q.value(1); // outputs "42" and "43" //! [2] +} - +void callStoredProc() +{ //! [10] // STORED_PROC uses the return statement or returns multiple result sets QSqlQuery query; query.setForwardOnly(true); query.exec("{call STORED_PROC}"); //! [10] +} - +void setHost() +{ //! [24] +QSqlDatabase db; db.setHostName("MyServer"); db.setDatabaseName("C:\\test.gdb"); //! [24] @@ -74,61 +87,57 @@ db.setDatabaseName("C:\\test.gdb"); //! [25] // connect to database using the Latin-1 character set db.setConnectOptions("ISC_DPB_LC_CTYPE=Latin1"); -db.open(); +if (db.open()) + qDebug("The database connection is open."); //! [25] +} - +void exProc() +{ //! [26] QSqlQuery q; q.exec("execute procedure my_procedure"); -q.next(); -qDebug() << q.value(0); // outputs the first RETURN/OUT value +if (q.next()) + qDebug() << q.value(0); // outputs the first RETURN/OUT value //! [26] - +qDebug( \ //! [31] -QSqlDatabase: QMYSQL driver not loaded -QSqlDatabase: available drivers: QMYSQL +"QSqlDatabase: QMYSQL driver not loaded \ +QSqlDatabase: available drivers: QMYSQL" \ //! [31] +); - +/* Commented because the following line is not compilable //! [34] column.contains(QRegularExpression("pattern")); //! [34] - - -//! [36] -QSqlQuery query(db); -query.setForwardOnly(true); -query.exec("SELECT * FROM table"); -while (query.next()) { - // Handle changes in every iteration of the loop - QVariant v = query.result()->handle(); - if (qstrcmp(v.typeName(), "PGresult*") == 0) { - PGresult *handle = *static_cast(v.data()); - if (handle) { - // Do something... - } - } +*/ } -//! [36] + +void updTable2() +{ +QSqlDatabase db; //! [37] int value; -QSqlQuery query1(db); +QSqlQuery query1; query1.setForwardOnly(true); query1.exec("select * FROM table1"); while (query1.next()) { value = query1.value(0).toInt(); if (value == 1) { - QSqlQuery query2(db); + QSqlQuery query2; query2.exec("update table2 set col=2"); // WRONG: This will discard all results of } // query1, and cause the loop to quit } //! [37] +} +void setConnString() +{ //! [39] QSqlDatabase db = QSqlDatabase::addDatabase("QODBC"); QString connectString = QStringLiteral( @@ -139,3 +148,4 @@ QString connectString = QStringLiteral( "SCROLLABLERESULT=true"); db.setDatabaseName(connectString); //! [39] +} diff --git a/src/sql/doc/snippets/code/doc_src_sql-driver_snippet.cpp b/src/sql/doc/snippets/code/doc_src_sql-driver_snippet.cpp new file mode 100644 index 00000000000..7cffe58ff1f --- /dev/null +++ b/src/sql/doc/snippets/code/doc_src_sql-driver_snippet.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +//! [36] +QSqlQuery query; +QVariant v; +query.setForwardOnly(true); +query.exec("SELECT * FROM table"); +while (query.next()) { + // Handle changes in every iteration of the loop + v = query.result()->handle(); + + if (qstrcmp(v.typeName(), "PGresult*") == 0) { + PGresult *handle = *static_cast(v.data()); + if (handle) { + // Do something... + } + } +} +//! [36] diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqldatabase.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqldatabase.cpp index f09315435ec..c7ceb847da1 100644 --- a/src/sql/doc/snippets/code/src_sql_kernel_qsqldatabase.cpp +++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqldatabase.cpp @@ -47,18 +47,25 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include +#include +#include +#include +void openDatabase() +{ //! [0] // WRONG QSqlDatabase db = QSqlDatabase::database("sales"); QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db); QSqlDatabase::removeDatabase("sales"); // will output a warning - // "db" is now a dangling invalid database connection, // "query" contains an invalid result set //! [0] +} - +void removeDatabase() +{ //! [1] { QSqlDatabase db = QSqlDatabase::database("sales"); @@ -67,72 +74,51 @@ QSqlDatabase::removeDatabase("sales"); // will output a warning // Both "db" and "query" are destroyed because they are out of scope QSqlDatabase::removeDatabase("sales"); // correct //! [1] +} - -//! [2] -QSqlDatabase::registerSqlDriver("MYDRIVER", - new QSqlDriverCreator); -QSqlDatabase db = QSqlDatabase::addDatabase("MYDRIVER"); -//! [2] - - +void setmyDatabase() +{ //! [3] -... -db = QSqlDatabase::addDatabase("QODBC"); +// ... +QSqlDatabase db = QSqlDatabase::addDatabase("QODBC"); db.setDatabaseName("DRIVER={Microsoft Access Driver (*.mdb, *.accdb)};FIL={MS Access};DBQ=myaccessfile.mdb"); if (db.open()) { // success! } -... +// ... //! [3] +} - -//! [4] -... +// ... // MySQL connection +void dbConnect() +{ +QSqlDatabase db; +//! [4] db.setConnectOptions("SSL_KEY=client-key.pem;SSL_CERT=client-cert.pem;SSL_CA=ca-cert.pem;CLIENT_IGNORE_SPACE=1"); // use an SSL connection to the server if (!db.open()) { db.setConnectOptions(); // clears the connect option string - ... + // ... } -... +// ... // PostgreSQL connection db.setConnectOptions("requiressl=1"); // enable PostgreSQL SSL connections if (!db.open()) { db.setConnectOptions(); // clear options - ... + // ... } -... +// ... // ODBC connection db.setConnectOptions("SQL_ATTR_ACCESS_MODE=SQL_MODE_READ_ONLY;SQL_ATTR_TRACE=SQL_OPT_TRACE_ON"); // set ODBC options if (!db.open()) { db.setConnectOptions(); // don't try to set this option - ... + // ... +} } //! [4] - -//! [5] -#include "qtdir/src/sql/drivers/psql/qsql_psql.cpp" -//! [5] - - -//! [6] -PGconn *con = PQconnectdb("host=server user=bart password=simpson dbname=springfield"); -QPSQLDriver *drv = new QPSQLDriver(con); -QSqlDatabase db = QSqlDatabase::addDatabase(drv); // becomes the new default connection -QSqlQuery query; -query.exec("SELECT NAME, ID FROM STAFF"); -... -//! [6] - - -//! [7] -unix:LIBS += -lpq -win32:LIBS += libpqdll.lib -//! [7] - - +void dbQdebug() +{ //! [8] QSqlDatabase db; qDebug() << db.isValid(); // Returns false @@ -143,3 +129,4 @@ qDebug() << db.isValid(); // Returns \c true if "sales" connection exists QSqlDatabase::removeDatabase("sales"); qDebug() << db.isValid(); // Returns false //! [8] +} diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqldatabase_snippet.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqldatabase_snippet.cpp new file mode 100644 index 00000000000..a53880fee11 --- /dev/null +++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqldatabase_snippet.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [2] +QSqlDatabase::registerSqlDriver("MYDRIVER", new QSqlDriverCreator); +QVERIFY(QSqlDatabase::drivers().contains("MYDRIVER")); +QSqlDatabase db = QSqlDatabase::addDatabase("MYDRIVER"); +QVERIFY(db.isValid()); +//! [2] +//! [6] +PGconn *con = PQconnectdb("host=server user=bart password=simpson dbname=springfield"); +QPSQLDriver *drv = new QPSQLDriver(con); +QSqlDatabase db = QSqlDatabase::addDatabase(drv); // becomes the new default connection +QSqlQuery query; +query.exec("SELECT NAME, ID FROM STAFF"); +//! [6] + +//! [7] +unix:LIBS += -lpq +win32:LIBS += libpqdll.lib +//! [7] + diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp index a13cf86d3f5..47e8701149f 100644 --- a/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp +++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqldriver.cpp @@ -47,28 +47,42 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include +#include +#include +#include +void checkHandle() +{ +//dummy definitions +typedef void sqlite3; +typedef void PGconn; +typedef void MYSQL; //! [0] -QSqlDatabase db = ...; +QSqlDatabase db = QSqlDatabase::database(); QVariant v = db.driver()->handle(); -if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0) { +if (v.isValid() && (qstrcmp(v.typeName(), "sqlite3*") == 0)) { // v.data() returns a pointer to the handle sqlite3 *handle = *static_cast(v.data()); if (handle) { - ... + // ... } } //! [0] - //! [1] if (qstrcmp(v.typeName(), "PGconn*") == 0) { PGconn *handle = *static_cast(v.data()); - if (handle) ... + if (handle) { + // ... + } } if (qstrcmp(v.typeName(), "MYSQL*") == 0) { MYSQL *handle = *static_cast(v.data()); - if (handle) ... + if (handle) { + // ... + } } //! [1] +} diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqlerror.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqlerror.cpp index 9f6c5da57c4..d442768fe20 100644 --- a/src/sql/doc/snippets/code/src_sql_kernel_qsqlerror.cpp +++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqlerror.cpp @@ -47,10 +47,18 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include +#include +#include +#include +#include +void checkSqlQueryModel() +{ //! [0] QSqlQueryModel model; model.setQuery("select * from myTable"); if (model.lastError().isValid()) qDebug() << model.lastError(); //! [0] +} diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqlquery.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqlquery.cpp index b99745c7491..496c9716219 100644 --- a/src/sql/doc/snippets/code/src_sql_kernel_qsqlquery.cpp +++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqlquery.cpp @@ -47,12 +47,13 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include +#include +#include +#include -//! [0] -SELECT forename, surname FROM people; -//! [0] - - +void selectEmployees() +{ //! [1] QSqlQuery q("select * from employees"); QSqlRecord rec = q.record(); @@ -63,8 +64,6 @@ int nameCol = rec.indexOf("name"); // index of the field "name" while (q.next()) qDebug() << q.value(nameCol).toString(); // output all names //! [1] - - //! [2] QSqlQuery q; q.prepare("insert into myTable values (?, ?)"); @@ -80,11 +79,4 @@ q.addBindValue(names); if (!q.execBatch()) qDebug() << q.lastError(); //! [2] - - -//! [3] -1 Harald -2 Boris -3 Trond -4 NULL -//! [3] +} diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqlquery_snippet.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqlquery_snippet.cpp new file mode 100644 index 00000000000..d7d2a14d564 --- /dev/null +++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqlquery_snippet.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +//! [0] +SELECT forename, surname FROM people; +//! [0] +//! [3] +1 Harald +2 Boris +3 Trond +4 NULL +//! [3] diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult.cpp index 8ab2baf2a14..606b6d19fa4 100644 --- a/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult.cpp +++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult.cpp @@ -47,7 +47,18 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include +#include +#include +#include +#include +#include +// dummy typedef +typedef void *sqlite3_stmt; + +void insertVariants() +{ //! [0] QSqlQuery q; q.prepare("insert into test (i1, i2, s) values (?, ?, ?)"); @@ -67,29 +78,21 @@ q.bindValue(2, col3); if (!q.execBatch()) qDebug() << q.lastError(); //! [0] +} - +void querySqlite() +{ //! [1] -QSqlQuery query = ... +QSqlDatabase db = QSqlDatabase::database("sales"); +QSqlQuery query("SELECT NAME, DOB FROM EMPLOYEES", db); + QVariant v = query.result()->handle(); if (v.isValid() && qstrcmp(v.typeName(), "sqlite3_stmt*") == 0) { // v.data() returns a pointer to the handle sqlite3_stmt *handle = *static_cast(v.data()); if (handle) { - ... + // ... } } //! [1] - - -//! [2] -if (qstrcmp(v.typeName(), "PGresult*") == 0) { - PGresult *handle = *static_cast(v.data()); - if (handle) ... } - -if (qstrcmp(v.typeName(), "MYSQL_STMT*") == 0) { - MYSQL_STMT *handle = *static_cast(v.data()); - if (handle) ... -} -//! [2] diff --git a/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult_snippet.cpp b/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult_snippet.cpp new file mode 100644 index 00000000000..2b1891f6c1a --- /dev/null +++ b/src/sql/doc/snippets/code/src_sql_kernel_qsqlresult_snippet.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [2] +if (qstrcmp(v.typeName(), "PGresult*") == 0) { + PGresult *handle = *static_cast(v.data()); + if (handle) { + // ... + } +} + +if (qstrcmp(v.typeName(), "MYSQL_STMT*") == 0) { + MYSQL_STMT *handle = *static_cast(v.data()); + if (handle) { + // ... + } + } +//! [2] diff --git a/src/sql/doc/snippets/code/src_sql_models_qsqlquerymodel.cpp b/src/sql/doc/snippets/code/src_sql_models_qsqlquerymodel.cpp index b3a43537a11..cb2bde6c7d2 100644 --- a/src/sql/doc/snippets/code/src_sql_models_qsqlquerymodel.cpp +++ b/src/sql/doc/snippets/code/src_sql_models_qsqlquerymodel.cpp @@ -47,16 +47,24 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include +#include +#include +#include +#include "../sqldatabase/sqldatabase.cpp" +void MyModel::fetchModel() +{ +MyModel *myModel = new MyModel; //! [0] while (myModel->canFetchMore()) myModel->fetchMore(); //! [0] - //! [1] QSqlQueryModel model; model.setQuery("select * from MyTable"); if (model.lastError().isValid()) qDebug() << model.lastError(); //! [1] +} diff --git a/src/sql/doc/snippets/snippets.pro b/src/sql/doc/snippets/snippets.pro new file mode 100644 index 00000000000..46eabbb0a17 --- /dev/null +++ b/src/sql/doc/snippets/snippets.pro @@ -0,0 +1,13 @@ +TEMPLATE = app +TARGET = sqldatabase_cppsnippet +QT = core sql sql-private + +SOURCES += sqldatabase/sqldatabase.cpp \ + code/doc_src_qtsql.cpp \ + code/doc_src_sql-driver.cpp \ + code/src_sql_kernel_qsqldatabase.cpp \ + code/src_sql_kernel_qsqlerror.cpp \ + code/src_sql_kernel_qsqlresult.cpp \ + code/src_sql_kernel_qsqldriver.cpp \ + code/src_sql_models_qsqlquerymodel.cpp + diff --git a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp index a45b5f409a0..0c09d761454 100644 --- a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp +++ b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp @@ -48,18 +48,13 @@ ** ****************************************************************************/ -#include +#include #include - +#include #include using namespace std; -QString tr(const char *text) -{ - return QApplication::translate(text, text); -} - void QSqlDatabase_snippets() { { @@ -209,11 +204,10 @@ void QSqlQuery_snippets() { // examine with named binding //! [14] - QMapIterator i(query.boundValues()); - while (i.hasNext()) { - i.next(); + QMap sqlIterator(query.boundValues()); + for (auto i = sqlIterator.begin(); i != sqlIterator.end(); ++i) { cout << i.key().toUtf8().data() << ": " - << i.value().toString().toUtf8().data() << Qt::endl; + << i.value().toString().toUtf8().data() << "\n"; } //! [14] } @@ -223,30 +217,13 @@ void QSqlQuery_snippets() //! [15] QList list = query.boundValues().values(); for (int i = 0; i < list.size(); ++i) - cout << i << ": " << list.at(i).toString().toUtf8().data() << Qt::endl; + cout << i << ": " << list.at(i).toString().toUtf8().data() << "\n"; //! [15] } } void QSqlQueryModel_snippets() { - { -//! [16] - QSqlQueryModel *model = new QSqlQueryModel; - model->setQuery("SELECT name, salary FROM employee"); - model->setHeaderData(0, Qt::Horizontal, tr("Name")); - model->setHeaderData(1, Qt::Horizontal, tr("Salary")); - -//! [17] - QTableView *view = new QTableView; -//! [17] //! [18] - view->setModel(model); -//! [18] //! [19] - view->show(); -//! [16] //! [19] //! [20] - view->setEditTriggers(QAbstractItemView::NoEditTriggers); -//! [20] - } //! [21] QSqlQueryModel model; @@ -273,6 +250,7 @@ class MyModel : public QSqlQueryModel { public: QVariant data(const QModelIndex &item, int role) const override; + void fetchModel(); int m_specialColumnNo; }; @@ -289,20 +267,6 @@ QVariant MyModel::data(const QModelIndex &item, int role) const void QSqlTableModel_snippets() { -//! [24] - QSqlTableModel *model = new QSqlTableModel(parentObject, database); - model->setTable("employee"); - model->setEditStrategy(QSqlTableModel::OnManualSubmit); - model->select(); - model->setHeaderData(0, Qt::Horizontal, tr("Name")); - model->setHeaderData(1, Qt::Horizontal, tr("Salary")); - - QTableView *view = new QTableView; - view->setModel(model); - view->hideColumn(0); // don't show the ID - view->show(); -//! [24] - { //! [25] QSqlTableModel model; @@ -310,6 +274,7 @@ void QSqlTableModel_snippets() model.select(); int salary = model.record(4).value("salary").toInt(); //! [25] + Q_UNUSED(salary); } } @@ -550,14 +515,14 @@ public: const QString & /* password */, const QString & /* host */, int /* port */, const QString & /* options */) override { return false; } - void close() {} + void close() override {} QSqlResult *createResult() const override { return new XyzResult(this); } }; //! [48] int main(int argc, char **argv) { - QApplication app(argc, argv); + QCoreApplication app(argc, argv); QSqlDatabase_snippets(); QSqlField_snippets(); diff --git a/src/sql/doc/snippets/sqldatabase/sqldatabase_snippet.cpp b/src/sql/doc/snippets/sqldatabase/sqldatabase_snippet.cpp new file mode 100644 index 00000000000..604eb97e58a --- /dev/null +++ b/src/sql/doc/snippets/sqldatabase/sqldatabase_snippet.cpp @@ -0,0 +1,387 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [16] + QSqlQueryModel *model = new QSqlQueryModel; + model->setQuery("SELECT name, salary FROM employee"); + model->setHeaderData(0, Qt::Horizontal, tr("Name")); + model->setHeaderData(1, Qt::Horizontal, tr("Salary")); +//! [17] + QTableView *view = new QTableView; +//! [17] //! [18] + view->setModel(model); +//! [18] //! [19] + view->show(); +//! [16] //! [19] //! [20] + view->setEditTriggers(QAbstractItemView::NoEditTriggers); +//! [20] + } + +//! [21] + QSqlQueryModel model; + model.setQuery("SELECT name, salary FROM employee"); + int salary = model.record(4).value("salary").toInt(); +//! [21] + Q_UNUSED(salary); + + { +//! [22] + int salary = model.data(model.index(4, 1)).toInt(); +//! [22] + Q_UNUSED(salary); + } + + for (int row = 0; row < model.rowCount(); ++row) { + for (int col = 0; col < model.columnCount(); ++col) { + qDebug() << model.data(model.index(row, col)); + } + } +} + +class MyModel : public QSqlQueryModel +{ +public: + QVariant data(const QModelIndex &item, int role) const override; + void fetchModel(); + + int m_specialColumnNo; +}; + +//! [23] +QVariant MyModel::data(const QModelIndex &item, int role) const +{ + if (item.column() == m_specialColumnNo) { + // handle column separately + } + return QSqlQueryModel::data(item, role); +} +//! [23] + +void QSqlTableModel_snippets() +{ +//! [24] + QSqlTableModel *model = new QSqlTableModel; + model->setTable("employee"); + model->setEditStrategy(QSqlTableModel::OnManualSubmit); + model->select(); + model->setHeaderData(0, Qt::Horizontal, tr("Name")); + model->setHeaderData(1, Qt::Horizontal, tr("Salary")); + + QTableView *view = new QTableView; + view->setModel(model); + view->hideColumn(0); // don't show the ID + view->show(); +//! [24] + + { +//! [25] + QSqlTableModel model; + model.setTable("employee"); + model.select(); + int salary = model.record(4).value("salary").toInt(); +//! [25] + } +} + +void sql_intro_snippets() +{ + { +//! [26] + QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); + db.setHostName("bigblue"); + db.setDatabaseName("flightdb"); + db.setUserName("acarlson"); + db.setPassword("1uTbSbAs"); + bool ok = db.open(); +//! [26] + Q_UNUSED(ok); + } + + { +//! [27] + QSqlDatabase firstDB = QSqlDatabase::addDatabase("QMYSQL", "first"); + QSqlDatabase secondDB = QSqlDatabase::addDatabase("QMYSQL", "second"); +//! [27] + } + + { +//! [28] + QSqlDatabase defaultDB = QSqlDatabase::database(); +//! [28] //! [29] + QSqlDatabase firstDB = QSqlDatabase::database("first"); +//! [29] //! [30] + QSqlDatabase secondDB = QSqlDatabase::database("second"); +//! [30] + } + + { + // SELECT1 +//! [31] + QSqlQuery query; + query.exec("SELECT name, salary FROM employee WHERE salary > 50000"); +//! [31] + +//! [32] + while (query.next()) { + QString name = query.value(0).toString(); + int salary = query.value(1).toInt(); + qDebug() << name << salary; + } +//! [32] + } + + { + // FEATURE +//! [33] + QSqlQuery query; + int numRows; + query.exec("SELECT name, salary FROM employee WHERE salary > 50000"); + + QSqlDatabase defaultDB = QSqlDatabase::database(); + if (defaultDB.driver()->hasFeature(QSqlDriver::QuerySize)) { + numRows = query.size(); + } else { + // this can be very slow + query.last(); + numRows = query.at() + 1; + } +//! [33] + } + + { + // INSERT1 +//! [34] + QSqlQuery query; + query.exec("INSERT INTO employee (id, name, salary) " + "VALUES (1001, 'Thad Beaumont', 65000)"); +//! [34] + } + + { + // NAMED BINDING +//! [35] + QSqlQuery query; + query.prepare("INSERT INTO employee (id, name, salary) " + "VALUES (:id, :name, :salary)"); + query.bindValue(":id", 1001); + query.bindValue(":name", "Thad Beaumont"); + query.bindValue(":salary", 65000); + query.exec(); +//! [35] + } + + { + // POSITIONAL BINDING +//! [36] + QSqlQuery query; + query.prepare("INSERT INTO employee (id, name, salary) " + "VALUES (?, ?, ?)"); + query.addBindValue(1001); + query.addBindValue("Thad Beaumont"); + query.addBindValue(65000); + query.exec(); +//! [36] + } + + { + // UPDATE1 +//! [37] + QSqlQuery query; + query.exec("UPDATE employee SET salary = 70000 WHERE id = 1003"); +//! [37] + } + + { + // DELETE1 +//! [38] + QSqlQuery query; + query.exec("DELETE FROM employee WHERE id = 1007"); +//! [38] + } + + { + // TRANSACTION +//! [39] + QSqlDatabase::database().transaction(); + QSqlQuery query; + query.exec("SELECT id FROM employee WHERE name = 'Torild Halvorsen'"); + if (query.next()) { + int employeeId = query.value(0).toInt(); + query.exec("INSERT INTO project (id, name, ownerid) " + "VALUES (201, 'Manhattan Project', " + + QString::number(employeeId) + ')'); + } + QSqlDatabase::database().commit(); +//! [39] + } + + { + // SQLQUERYMODEL1 +//! [40] + QSqlQueryModel model; + model.setQuery("SELECT * FROM employee"); + + for (int i = 0; i < model.rowCount(); ++i) { + int id = model.record(i).value("id").toInt(); + QString name = model.record(i).value("name").toString(); + qDebug() << id << name; + } +//! [40] + } + + { + // SQLTABLEMODEL1 +//! [41] + QSqlTableModel model; + model.setTable("employee"); + model.setFilter("salary > 50000"); + model.setSort(2, Qt::DescendingOrder); + model.select(); + + for (int i = 0; i < model.rowCount(); ++i) { + QString name = model.record(i).value("name").toString(); + int salary = model.record(i).value("salary").toInt(); + qDebug() << name << salary; + } +//! [41] + } + + { + // SQLTABLEMODEL2 + QSqlTableModel model; + model.setTable("employee"); + +//! [42] + for (int i = 0; i < model.rowCount(); ++i) { + QSqlRecord record = model.record(i); + double salary = record.value("salary").toInt(); + salary *= 1.1; + record.setValue("salary", salary); + model.setRecord(i, record); + } + model.submitAll(); +//! [42] + + // SQLTABLEMODEL3 + int row = 1; + int column = 2; +//! [43] + model.setData(model.index(row, column), 75000); + model.submitAll(); +//! [43] + + // SQLTABLEMODEL4 +//! [44] + model.insertRows(row, 1); + model.setData(model.index(row, 0), 1013); + model.setData(model.index(row, 1), "Peter Gordon"); + model.setData(model.index(row, 2), 68500); + model.submitAll(); +//! [44] + +//! [45] + model.removeRows(row, 5); +//! [45] //! [46] + model.submitAll(); +//! [46] + } +} + +//! [47] +class XyzResult : public QSqlResult +{ +public: + XyzResult(const QSqlDriver *driver) + : QSqlResult(driver) {} + ~XyzResult() {} + +protected: + QVariant data(int /* index */) override { return QVariant(); } + bool isNull(int /* index */) override { return false; } + bool reset(const QString & /* query */) override { return false; } + bool fetch(int /* index */) override { return false; } + bool fetchFirst() override { return false; } + bool fetchLast() override { return false; } + int size() override { return 0; } + int numRowsAffected() override { return 0; } + QSqlRecord record() const override { return QSqlRecord(); } +}; +//! [47] + +//! [48] +class XyzDriver : public QSqlDriver +{ +public: + XyzDriver() {} + ~XyzDriver() {} + + bool hasFeature(DriverFeature /* feature */) const override { return false; } + bool open(const QString & /* db */, const QString & /* user */, + const QString & /* password */, const QString & /* host */, + int /* port */, const QString & /* options */) override + { return false; } + void close() {} + QSqlResult *createResult() const override { return new XyzResult(this); } +}; +//! [48] + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + QSqlDatabase_snippets(); + QSqlField_snippets(); + QSqlQuery_snippets(); + QSqlQueryModel_snippets(); + QSqlTableModel_snippets(); + + XyzDriver driver; + XyzResult result(&driver); +} diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc index 28e17d23010..2747d934b25 100644 --- a/src/sql/doc/src/sql-driver.qdoc +++ b/src/sql/doc/src/sql-driver.qdoc @@ -457,7 +457,7 @@ SQL result must get a new handle after each call to any of QSqlResult fetch functions. Example: - \snippet code/doc_src_sql-driver.cpp 36 + \snippet code/doc_src_sql-driver_snippet.cpp 36 While reading the results of a forward-only query with PostgreSQL, the database connection cannot be used to execute other queries. diff --git a/src/sql/doc/src/sql-programming.qdoc b/src/sql/doc/src/sql-programming.qdoc index f20b1292fc2..56bb48b27ba 100644 --- a/src/sql/doc/src/sql-programming.qdoc +++ b/src/sql/doc/src/sql-programming.qdoc @@ -480,15 +480,15 @@ The following example creates a view based on an SQL data model: - \snippet sqldatabase/sqldatabase.cpp 17 - \snippet sqldatabase/sqldatabase.cpp 18 - \snippet sqldatabase/sqldatabase.cpp 19 + \snippet sqldatabase/sqldatabase_snippet.cpp 17 + \snippet sqldatabase/sqldatabase_snippet.cpp 18 + \snippet sqldatabase/sqldatabase_snippet.cpp 19 If the model is a read-write model (e.g., QSqlTableModel), the view lets the user edit the fields. You can disable this by calling - \snippet sqldatabase/sqldatabase.cpp 20 + \snippet sqldatabase/sqldatabase_snippet.cpp 20 You can use the same model as a data source for multiple views. If the user edits the model through one of the views, the other diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 094943ca315..7d74ba8ac54 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -561,7 +561,7 @@ QStringList QSqlDatabase::drivers() and don't want to compile it as a plugin. Example: - \snippet code/src_sql_kernel_qsqldatabase.cpp 2 + \snippet code/src_sql_kernel_qsqldatabase_snippet.cpp 2 QSqlDatabase takes ownership of the \a creator pointer, so you mustn't delete it yourself. @@ -1266,9 +1266,7 @@ bool QSqlDatabase::isDriverAvailable(const QString& name) application. For example, you can create a PostgreSQL connection with your own QPSQL driver like this: - \snippet code/src_sql_kernel_qsqldatabase.cpp 5 - \codeline - \snippet code/src_sql_kernel_qsqldatabase.cpp 6 + \snippet code/src_sql_kernel_qsqldatabase_snippet.cpp 6 The above code sets up a PostgreSQL connection and instantiates a QPSQLDriver object. Next, addDatabase() is called to add the @@ -1287,7 +1285,7 @@ bool QSqlDatabase::isDriverAvailable(const QString& name) client library. Make sure the client library is in your linker's search path, and add lines like these to your \c{.pro} file: - \snippet code/src_sql_kernel_qsqldatabase.cpp 7 + \snippet code/src_sql_kernel_qsqldatabase_snippet.cpp 7 The method described works for all the supplied drivers. The only difference will be in the driver constructor arguments. Here is a diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp index ce6c9979195..98e65b019cf 100644 --- a/src/sql/kernel/qsqlquery.cpp +++ b/src/sql/kernel/qsqlquery.cpp @@ -414,7 +414,7 @@ bool QSqlQuery::exec(const QString& query) The fields are numbered from left to right using the text of the \c SELECT statement, e.g. in - \snippet code/src_sql_kernel_qsqlquery.cpp 0 + \snippet code/src_sql_kernel_qsqlquery_snippet.cpp 0 field 0 is \c forename and field 1 is \c surname. Using \c{SELECT *} is not recommended because the order @@ -1044,7 +1044,7 @@ bool QSqlQuery::exec() The example above inserts four new rows into \c myTable: - \snippet code/src_sql_kernel_qsqlquery.cpp 3 + \snippet code/src_sql_kernel_qsqlquery_snippet.cpp 3 To bind NULL values, a null QVariant of the relevant type has to be added to the bound QVariantList; for example, \c diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp index a41b3d8424c..69c9dcbac91 100644 --- a/src/sql/kernel/qsqlresult.cpp +++ b/src/sql/kernel/qsqlresult.cpp @@ -1022,7 +1022,7 @@ bool QSqlResult::nextResult() This snippet returns the handle for PostgreSQL or MySQL: - \snippet code/src_sql_kernel_qsqlresult.cpp 2 + \snippet code/src_sql_kernel_qsqlresult_snippet.cpp 2 \sa QSqlDriver::handle() */ diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp index 31d0ec985dc..6d4e2c09c10 100644 --- a/src/sql/models/qsqlquerymodel.cpp +++ b/src/sql/models/qsqlquerymodel.cpp @@ -113,7 +113,7 @@ int QSqlQueryModelPrivate::columnInQuery(int modelColumn) const the lower-level QSqlQuery and can be used to provide data to view classes such as QTableView. For example: - \snippet sqldatabase/sqldatabase.cpp 16 + \snippet sqldatabase/sqldatabase_snippet.cpp 16 We set the model's query, then we set up the labels displayed in the view header. diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 941735767d4..12ea0f5666b 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -211,7 +211,7 @@ bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement, lower-level QSqlQuery and can be used to provide data to view classes such as QTableView. For example: - \snippet sqldatabase/sqldatabase.cpp 24 + \snippet sqldatabase/sqldatabase_snippet.cpp 24 We set the SQL table's name and the edit strategy, then we set up the labels displayed in the view header. The edit strategy diff --git a/src/src.pro b/src/src.pro index 3dc92e7811e..30034ae9521 100644 --- a/src/src.pro +++ b/src/src.pro @@ -176,6 +176,13 @@ qtConfig(network) { qtConfig(sql) { SUBDIRS += src_sql src_plugins.depends += src_sql + + contains(QT_CONFIG, private_tests) { + src_sql_doc_snippets.subdir = sql/doc/snippets + src_sql_doc_snippets.target = sub-sql-doc-snippets + src_sql_doc_snippets.depends = src_sql + SUBDIRS += src_sql_doc_snippets + } } qtConfig(xml): SUBDIRS += src_xml qtConfig(testlib): SUBDIRS += src_testlib diff --git a/src/testlib/doc/snippets/code/doc_src_qtestevent.cpp b/src/testlib/doc/snippets/code/doc_src_qtestevent.cpp index df9aa9b5581..8d125f60b7b 100644 --- a/src/testlib/doc/snippets/code/doc_src_qtestevent.cpp +++ b/src/testlib/doc/snippets/code/doc_src_qtestevent.cpp @@ -48,14 +48,28 @@ ** ****************************************************************************/ +#include +#include + +// dummy +class TestGui: public QObject +{ + Q_OBJECT +public: + void testGui_data(); +}; + +void TestGui::testGui_data() +{ +QWidget *myParent = nullptr; //! [0] QTestEventList events; events.addKeyClick('a'); events.addKeyClick(Qt::Key_Backspace); events.addDelay(200); - QLineEdit *lineEdit = new QLineEdit(myParent); -... +// ... events.simulate(lineEdit); events.simulate(lineEdit); //! [0] +} diff --git a/src/testlib/doc/snippets/code/doc_src_qtestlib.cpp b/src/testlib/doc/snippets/code/doc_src_qtestlib.cpp index de301b8df98..8938a159115 100644 --- a/src/testlib/doc/snippets/code/doc_src_qtestlib.cpp +++ b/src/testlib/doc/snippets/code/doc_src_qtestlib.cpp @@ -49,7 +49,7 @@ ****************************************************************************/ #include - +#include "src_qtestlib_qtestcase.cpp" //! [0] class MyFirstTest: public QObject { @@ -95,13 +95,15 @@ void TestQString::toUpper() } //! [8] - +void TestQString::Compare() +{ //! [11] QCOMPARE(QString("hello").toUpper(), QString("HELLO")); QCOMPARE(QString("Hello").toUpper(), QString("HELLO")); QCOMPARE(QString("HellO").toUpper(), QString("HELLO")); QCOMPARE(QString("HELLO").toUpper(), QString("HELLO")); //! [11] +} //! [12] class MyFirstBenchmark: public QObject diff --git a/src/testlib/doc/snippets/code/doc_src_qtqskip.cpp b/src/testlib/doc/snippets/code/doc_src_qtqskip.cpp index d261e87e4c3..550f85dd8a8 100644 --- a/src/testlib/doc/snippets/code/doc_src_qtqskip.cpp +++ b/src/testlib/doc/snippets/code/doc_src_qtqskip.cpp @@ -47,20 +47,22 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include -//! [0] +//dummy class +class tst_Skip +{ + public: + void test_data(); +}; -if ( tst_Databases::getMySqlVersion( db ).section( QChar('.'), 0, 0 ).toInt()<5 ) - QSKIP( "Test requires MySQL >= 5.0"); -//! [0] -//! [1] void tst_Skip::test_data() { +//! [1] QTest::addColumn("bool"); QTest::newRow("local 1") << false; QTest::newRow("local 2") << true; QSKIP("skipping all"); -} //! [1] -void tst_Skip::test_data() +} diff --git a/src/testlib/doc/snippets/code/doc_src_qtqskip_snippet.cpp b/src/testlib/doc/snippets/code/doc_src_qtqskip_snippet.cpp new file mode 100644 index 00000000000..98a209d4bbf --- /dev/null +++ b/src/testlib/doc/snippets/code/doc_src_qtqskip_snippet.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +//! [0] +if (tst_Databases::getMySqlVersion(db).section(QChar('.'), 0, 0).toInt() < 5) + QSKIP("Test requires MySQL >= 5.0"); +//! [0] diff --git a/src/testlib/doc/snippets/code/src_corelib_kernel_qtestsupport_core.cpp b/src/testlib/doc/snippets/code/src_corelib_kernel_qtestsupport_core.cpp index e793cb1f551..33b0e19be0a 100644 --- a/src/testlib/doc/snippets/code/src_corelib_kernel_qtestsupport_core.cpp +++ b/src/testlib/doc/snippets/code/src_corelib_kernel_qtestsupport_core.cpp @@ -47,17 +47,27 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include -//! [0] - MyObject obj; - obj.startup(); - QTest::qWaitFor([&]() { - return obj.isReady(); - }, 3000); -//! [0] +// dummy class +class MyObject +{ + public: + int isReady(); +}; +// dummy function +int myNetworkServerNotResponding() +{ + return 1; +} + +int MyObject::isReady() +{ //! [1] int i = 0; while (myNetworkServerNotResponding() && i++ < 50) QTest::qWait(250); //! [1] +return 1; +} diff --git a/src/testlib/doc/snippets/code/src_corelib_kernel_qtestsupport_core_snippet.cpp b/src/testlib/doc/snippets/code/src_corelib_kernel_qtestsupport_core_snippet.cpp new file mode 100644 index 00000000000..435ffa07549 --- /dev/null +++ b/src/testlib/doc/snippets/code/src_corelib_kernel_qtestsupport_core_snippet.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/! [0] + MyObject obj; + obj.startup(); + QTest::qWaitFor([&]() { + return obj.isReady(); + }, 3000); +//! [0] diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp index 2dc4fe49ef5..eda0f430a19 100644 --- a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp +++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase.cpp @@ -47,25 +47,50 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +#include +#include +// dummy +class TestBenchmark : public QObject +{ + Q_OBJECT +private slots: + void simple(); +}; + +// dummy +class MyTestClass : public QObject +{ + public: + void cleanup(); + void addSingleStringRows(); + void addMultStringRows(); + void addDataRow(); +}; +// dummy +void closeAllDatabases() +{ +}; + +class TestQString : public QObject +{ + public: + void toInt_data(); + void toInt(); + void toUpper(); + void Compare(); +}; void wrapInFunction() { - -//! [0] - QVERIFY(spy.isValid()) -//! [0] - - //! [1] QVERIFY2(qIsNaN(0.0 / 0.0), "Ill-defined division produced unambiguous result."); //! [1] - //! [2] QCOMPARE(QString("hello").toUpper(), QString("HELLO")); //! [2] - +} //! [3] void TestQString::toInt_data() @@ -79,7 +104,6 @@ void TestQString::toInt_data() } //! [3] - //! [4] void TestQString::toInt() { @@ -90,109 +114,69 @@ void TestQString::toInt() } //! [4] - +void testInt() +{ +// dummy +int i = 0, j = 0; //! [5] if (sizeof(int) != 4) QFAIL("This test has not been ported to this platform yet."); //! [5] - //! [6] QFETCH(QString, myString); QCOMPARE(QString("hello").toUpper(), myString); //! [6] - //! [7] QTEST(QString("hello").toUpper(), "myString"); //! [7] - //! [8] if (!QSqlDatabase::drivers().contains("SQLITE")) QSKIP("This test requires the SQLITE database driver"); //! [8] - //! [9] QEXPECT_FAIL("", "Will fix in the next release", Continue); QCOMPARE(i, 42); QCOMPARE(j, 43); //! [9] - //! [10] QEXPECT_FAIL("data27", "Oh my, this is soooo broken", Abort); QCOMPARE(i, 42); //! [10] - +} //! [11] -class TestQString: public QObject { ... }; QTEST_MAIN(TestQString) //! [11] - -//! [13] -QTest::keyClick(myWidget, 'a'); -//! [13] - - -//! [14] -QTest::keyClick(myWidget, Qt::Key_Escape); - -QTest::keyClick(myWidget, Qt::Key_Escape, Qt::ShiftModifier, 200); -//! [14] - - -//! [15] -QTest::keyClicks(myWidget, "hello world"); -//! [15] - - -//! [16] -namespace QTest { - template<> - char *toString(const MyPoint &point) - { - QByteArray ba = "MyPoint("; - ba += QByteArray::number(point.x()) + ", " + QByteArray::number(point.y()); - ba += ')'; - return qstrdup(ba.data()); - } -} -//! [16] - -//! [toString-overload] -namespace MyNamespace { - char *toString(const MyPoint &point) - { - // bring QTest::toString overloads into scope: - using QTest::toString; - // delegate char* handling to QTest::toString(QByteArray): - return toString("MyPoint(" + - QByteArray::number(point.x()) + ", " + - QByteArray::number(point.y()) + ')'); - } -} -//! [toString-overload] - +void testObject() +{ +class MyTestObject: public QObject +{ + public: + void toString(); +}; //! [18] MyTestObject test1; QTest::qExec(&test1); //! [18] +} - +void tstQDir() +{ //! [19] QDir dir; - QTest::ignoreMessage(QtWarningMsg, "QDir::mkdir: Empty or null file name(s)"); dir.mkdir(""); //! [19] - +} //! [20] -void myTestFunction_data() +void MyTestClass::addSingleStringRows() { QTest::addColumn("aString"); QTest::newRow("just hello") << QString("hello"); @@ -200,152 +184,65 @@ void myTestFunction_data() } //! [20] - -//! [addRow] -void myTestFunction_data() +void MyTestClass::addMultStringRows() { +//! [addRow] QTest::addColumn("input"); QTest::addColumn("output"); QTest::addRow("%d", 0) << 0 << QString("0"); QTest::addRow("%d", 1) << 1 << QString("1"); -} //! [addRow] +} - +void MyTestClass::addDataRow() +{ //! [21] -void myTestFunction_data() { QTest::addColumn("intval"); QTest::addColumn("str"); QTest::addColumn("dbl"); - QTest::newRow("row1") << 1 << "hello" << 1.5; -} //! [21] - +} //! [22] void MyTestClass::cleanup() { - if (qstrcmp(currentTestFunction(), "myDatabaseTest") == 0) { + if (qstrcmp(QTest::currentTestFunction(), "myDatabaseTest") == 0) { // clean up all database connections closeAllDatabases(); } } //! [22] - +void mySleep() +{ //! [23] QTest::qSleep(250); //! [23] - - -//! [25] -QTouchDevice *dev = QTest::createTouchDevice(); -QWidget widget; - -QTest::touchEvent(&widget, dev) - .press(0, QPoint(10, 10)); -QTest::touchEvent(&widget, dev) - .stationary(0) - .press(1, QPoint(40, 10)); -QTest::touchEvent(&widget, dev) - .move(0, QPoint(12, 12)) - .move(1, QPoint(45, 5)); -QTest::touchEvent(&widget, dev) - .release(0, QPoint(12, 12)) - .release(1, QPoint(45, 5)); -//! [25] - - -//! [26] -// Source: /home/user/sources/myxmlparser/tests/tst_myxmlparser/tst_myxmlparser.cpp -// Build: /home/user/build/myxmlparser/tests/tst_myxmlparser -// Qt: /usr/local/Qt-5.0.0 -void tst_MyXmlParser::parse() -{ - MyXmlParser parser; - QString input = QFINDTESTDATA("testxml/simple1.xml"); - QVERIFY(parser.parse(input)); } -//! [26] //! [27] void TestBenchmark::simple() { QString str1 = QLatin1String("This is a test string"); QString str2 = QLatin1String("This is a test string"); - QCOMPARE(str1.localeAwareCompare(str2), 0); - QBENCHMARK { str1.localeAwareCompare(str2); } } //! [27] -//! [28] -QTest::keyClick(myWindow, 'a'); -//! [28] - - -//! [29] -QTest::keyClick(myWindow, Qt::Key_Escape); - -QTest::keyClick(myWindow, Qt::Key_Escape, Qt::ShiftModifier, 200); -//! [29] - -} - -//! [30] -void TestQLocale::initTestCase_data() +void verifyString() { - QTest::addColumn("locale"); - QTest::newRow("C") << QLocale::c(); - QTest::newRow("UKish") << QLocale("en_GB"); - QTest::newRow("USAish") << QLocale(QLocale::English); -} - -void TestQLocale::roundTripInt_data() -{ - QTest::addColumn("number"); - QTest::newRow("one") << 1; - QTest::newRow("two") << 2; - QTest::newRow("ten") << 10; -} -//! [30] - -//! [31] -void TestQLocale::roundTripInt() -{ - QFETCH_GLOBAL(QLocale, locale); - QFETCH(int, number); - bool ok; - QCOMPARE(locale.toInt(locale.toString(number), &ok), number); - QVERIFY(ok); -} -//! [31] - - +QFile file; //! [32] bool opened = file.open(QIODevice::WriteOnly); QVERIFY(opened); //! [32] - - //! [33] QVERIFY2(file.open(QIODevice::WriteOnly), - qPrintable(QString("open %1: %2").arg(file.fileName()).arg(file.errorString())); + qPrintable(QString("open %1: %2") + .arg(file.fileName()).arg(file.errorString()))); //! [33] - -//! [34] -QT_BEGIN_NAMESPACE -namespace QTest { - template <> char *toString(const MyType &t) - { - char *repr = new char[t.reprSize()]; - t.writeRepr(repr); - return repr; - } } -QT_END_NAMESPACE -//! [34] diff --git a/src/testlib/doc/snippets/code/src_qtestlib_qtestcase_snippet.cpp b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase_snippet.cpp new file mode 100644 index 00000000000..f414ee42525 --- /dev/null +++ b/src/testlib/doc/snippets/code/src_qtestlib_qtestcase_snippet.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +//! [0] +QVERIFY(spy.isValid()); +//! [0] + +//! [13] +QTest::keyClick(myWidget, 'a'); +//! [13] + +//! [14] +QTest::keyClick(myWidget, Qt::Key_Escape); + +QTest::keyClick(myWidget, Qt::Key_Escape, Qt::ShiftModifier, 200); +//! [14] + +//! [15] +QTest::keyClicks(myWidget, "hello world"); +//! [15] + +//! [16] +namespace QTest { + template<> + char *toString(const MyPoint &point) + { + const QByteArray ba("MyPoint(" + + QByteArray::number(point.x()) + ", " + + QByteArray::number(point.y()) + ')'); + return qstrdup(ba.data()); + } +} +//! [16] + +//! [toString-overload] +namespace { + char *toString(const MyPoint &point) + { + return QTest::toString("MyPoint(" + + QByteArray::number(point.x()) + ", " + + QByteArray::number(point.y()) + ')'); + } +} +//! [toString-overload] + +void processTouchEvent() +{ +//! [25] +QTouchDevice *dev = QTest::createTouchDevice(); +QWidget widget; + +QTest::touchEvent(&widget, dev) + .press(0, QPoint(10, 10)); +QTest::touchEvent(&widget, dev) + .stationary(0) + .press(1, QPoint(40, 10)); +QTest::touchEvent(&widget, dev) + .move(0, QPoint(12, 12)) + .move(1, QPoint(45, 5)); +QTest::touchEvent(&widget, dev) + .release(0, QPoint(12, 12)) + .release(1, QPoint(45, 5)); +//! [25] +} + +//! [26] +bool tst_MyXmlParser::parse() +{ + MyXmlParser parser; + QString input = QFINDTESTDATA("testxml/simple1.xml"); + QVERIFY(parser.parse(input)); +} +//! [26] + +//! [28] +QWidget myWindow; +QTest::keyClick(&myWindow, Qt::Key_Tab); +//! [28] + +//! [29] +QTest::keyClick(&myWindow, Qt::Key_Escape); +QTest::keyClick(&myWindow, Qt::Key_Escape, Qt::ShiftModifier, 200); +//! [29] + +//! [30] +void TestQLocale::initTestCase_data() +{ + QTest::addColumn("locale"); + QTest::newRow("C") << QLocale::c(); + QTest::newRow("UKish") << QLocale("en_GB"); + QTest::newRow("USAish") << QLocale(QLocale::English, QLocale::UnitedStates); +} + +void TestQLocale::roundTripInt_data() +{ + QTest::addColumn("number"); + QTest::newRow("zero") << 0; + QTest::newRow("one") << 1; + QTest::newRow("two") << 2; + QTest::newRow("ten") << 10; +} +//! [30] + +//! [31] +void TestQLocale::roundTripInt() +{ + QFETCH_GLOBAL(QLocale, locale); + QFETCH(int, number); + bool ok; + QCOMPARE(locale.toInt(locale.toString(number), &ok), number); + QVERIFY(ok); +} +//! [31] + +//! [34] +char *toString(const MyType &t) +{ + char *repr = new char[t.reprSize()]; + t.writeRepr(repr); + return repr; +} +//! [34] diff --git a/src/testlib/doc/snippets/snippets.pro b/src/testlib/doc/snippets/snippets.pro new file mode 100644 index 00000000000..28b6682b72d --- /dev/null +++ b/src/testlib/doc/snippets/snippets.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +TARGET = testlib_cppsnippet +QT = core testlib sql widgets + +SOURCES += code/src_qtestlib_qtestcase.cpp \ + code/doc_src_qtestlib.cpp \ + code/doc_src_qtestevent.cpp \ + code/doc_src_qtqskip.cpp \ + code/doc_src_qttest.cpp \ + code/src_corelib_kernel_qtestsupport_core.cpp diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc index 56903d44bf7..5b8ef361ca8 100644 --- a/src/testlib/doc/src/qttestlib-manual.qdoc +++ b/src/testlib/doc/src/qttestlib-manual.qdoc @@ -475,7 +475,7 @@ For example, to test each number provided by \c {roundTripInt_data()} with each locale provided by \c {initTestCase_data()}: - \snippet code/src_qtestlib_qtestcase.cpp 31 + \snippet code/src_qtestlib_qtestcase_snippet.cpp 31 */ /*! @@ -902,7 +902,7 @@ Example of QSKIP in a test function: - \snippet code/doc_src_qtqskip.cpp 0 + \snippet code/doc_src_qtqskip_snippet.cpp 0 In a data-driven test, each call to QSKIP() skips only the current row of test data. If the data-driven test contains an unconditional diff --git a/src/testlib/qabstractitemmodeltester.cpp b/src/testlib/qabstractitemmodeltester.cpp index 2e050971226..a09d007a825 100644 --- a/src/testlib/qabstractitemmodeltester.cpp +++ b/src/testlib/qabstractitemmodeltester.cpp @@ -288,6 +288,12 @@ QAbstractItemModelTester::FailureReportingMode QAbstractItemModelTester::failure return d->failureReportingMode; } +bool QAbstractItemModelTester::verify(bool statement, const char *statementStr, const char *description, const char *file, int line) +{ + Q_D(QAbstractItemModelTester); + return d->verify(statement, statementStr, description, file, line); +} + QAbstractItemModelTesterPrivate::QAbstractItemModelTesterPrivate(QAbstractItemModel *model, QAbstractItemModelTester::FailureReportingMode failureReportingMode) : model(model), failureReportingMode(failureReportingMode), diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp index 91258e9ec45..4554d6017a4 100644 --- a/src/testlib/qtestblacklist.cpp +++ b/src/testlib/qtestblacklist.cpp @@ -102,7 +102,7 @@ static QSet keywords() #ifdef Q_OS_LINUX << "linux" #endif -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS << "osx" << "macos" #endif diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index fc6b22f0623..8b5df06d82a 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -231,7 +231,7 @@ static void stackTrace() if (system(cmd) == -1) fprintf(stderr, "calling gdb failed\n"); fprintf(stderr, "=== End of stack trace ===\n"); -#elif defined(Q_OS_OSX) +#elif defined(Q_OS_MACOS) char cmd[512]; qsnprintf(cmd, 512, "lldb -p %d 2>/dev/null <selectionModel()->currentIndex() == m_index) st.focused = true; - if (m_index.model()->data(m_index, Qt::CheckStateRole).toInt() == Qt::Checked) + + QVariant checkState = m_index.model()->data(m_index, Qt::CheckStateRole); + if (checkState.toInt() == Qt::Checked) st.checked = true; Qt::ItemFlags flags = m_index.flags(); + if ((flags & Qt::ItemIsUserCheckable) && checkState.isValid()) + st.checkable = true; if (flags & Qt::ItemIsSelectable) { st.selectable = true; st.focusable = true; diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 658d7b562b6..a319361ad84 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -1049,7 +1049,7 @@ static inline bool isCaseSensitiveFileSystem(const QString &path) // Return case insensitive unconditionally, even if someone has a case sensitive // file system mounted, wrongly capitalized drive letters will cause mismatches. return false; -#elif defined(Q_OS_OSX) +#elif defined(Q_OS_MACOS) return pathconf(QFile::encodeName(path).constData(), _PC_CASE_SENSITIVE); #else return true; diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp index 479e45ff56d..836d3bc1de8 100644 --- a/src/widgets/dialogs/qinputdialog.cpp +++ b/src/widgets/dialogs/qinputdialog.cpp @@ -1349,32 +1349,7 @@ int QInputDialog::getInt(QWidget *parent, const QString &title, const QString &l \sa getText(), getDouble(), getItem(), getMultiLineText() */ -#if QT_DEPRECATED_SINCE(5, 15) -/*! - Static convenience function to get a floating point number from the user. - - \a title is the text which is displayed in the title bar of the dialog. - \a label is the text which is shown to the user (it should say what should - be entered). - \a value is the default floating point number that the line edit will be - set to. - \a min and \a max are the minimum and maximum values the user may choose. - \a decimals is the maximum number of decimal places the number may have. - - If \a ok is nonnull, *\a ok will be set to true if the user pressed \uicontrol OK - and to false if the user pressed \uicontrol Cancel. The dialog's parent is - \a parent. The dialog will be modal and uses the widget \a flags. - - This function returns the floating point number which has been entered by - the user. - - Use this static function like this: - - \snippet dialogs/standarddialogs/dialog.cpp 1 - - \sa getText(), getInt(), getItem(), getMultiLineText() -*/ - +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) && !defined(Q_QDOC) double QInputDialog::getDouble(QWidget *parent, const QString &title, const QString &label, double value, double min, double max, int decimals, bool *ok, Qt::WindowFlags flags) @@ -1383,7 +1358,6 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr } #endif /*! - \overload Static convenience function to get a floating point number from the user. \a title is the text which is displayed in the title bar of the dialog. diff --git a/src/widgets/dialogs/qinputdialog.h b/src/widgets/dialogs/qinputdialog.h index 6e2d6eebf30..a8696cb5625 100644 --- a/src/widgets/dialogs/qinputdialog.h +++ b/src/widgets/dialogs/qinputdialog.h @@ -177,21 +177,19 @@ public: int minValue = -2147483647, int maxValue = 2147483647, int step = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()); -#if QT_DEPRECATED_SINCE(5, 15) - QT_DEPRECATED_X("This overload is deprecated. Use the overload that takes step as a final argument") - static double getDouble(QWidget *parent, const QString &title, const QString &label, double value = 0, - double minValue = -2147483647, double maxValue = 2147483647, - int decimals = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()); -#endif -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) || defined(Q_QDOC) static double getDouble(QWidget *parent, const QString &title, const QString &label, double value = 0, double minValue = -2147483647, double maxValue = 2147483647, int decimals = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags(), double step = 1); #else - static double getDouble(QWidget *parent, const QString &title, const QString &label, double value, - double minValue, double maxValue, int decimals, bool *ok, Qt::WindowFlags flags, - double step); + static double getDouble(QWidget *parent, const QString &title, const QString &label, + double value = 0, double minValue = -2147483647, + double maxValue = 2147483647, int decimals = 1, bool *ok = nullptr, + Qt::WindowFlags flags = Qt::WindowFlags()); + static double getDouble(QWidget *parent, const QString &title, const QString &label, + double value, double minValue, double maxValue, int decimals, bool *ok, + Qt::WindowFlags flags, double step); #endif #if QT_DEPRECATED_SINCE(5, 0) diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index b0f4312f401..17ea634efb7 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -2377,11 +2377,11 @@ bool QWizard::hasVisitedPage(int theid) const } /*! + \since 5.15 + Returns the list of IDs of visited pages, in the order in which the pages were visited. - Pressing \uicontrol Back marks the current page as "unvisited" again. - \sa hasVisitedPage() */ QList QWizard::visitedIds() const diff --git a/src/widgets/dialogs/qwizard.h b/src/widgets/dialogs/qwizard.h index dc29c80f513..13b584035c8 100644 --- a/src/widgets/dialogs/qwizard.h +++ b/src/widgets/dialogs/qwizard.h @@ -129,7 +129,7 @@ public: QWizardPage *page(int id) const; bool hasVisitedPage(int id) const; #if QT_DEPRECATED_SINCE(5, 15) - Q_DECL_DEPRECATED_X("Use visitedIds() instead") QList visitedPages() const; + QT_DEPRECATED_VERSION_X_5_15("Use visitedIds() instead") QList visitedPages() const; #endif QList visitedIds() const; QList pageIds() const; diff --git a/src/widgets/doc/snippets/graphicsview.cpp b/src/widgets/doc/snippets/graphicsview.cpp index 371cff24a4d..9578f91eec3 100644 --- a/src/widgets/doc/snippets/graphicsview.cpp +++ b/src/widgets/doc/snippets/graphicsview.cpp @@ -123,5 +123,9 @@ void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event) //! [6] QGraphicsView view(&scene); -view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); +QOpenGLWidget *gl = new QOpenGLWidget(); +QSurfaceFormat format; +format.setSamples(4); +gl->setFormat(format); +view.setViewport(gl); //! [6] diff --git a/src/widgets/doc/src/graphicsview.qdoc b/src/widgets/doc/src/graphicsview.qdoc index f1f848d6df8..0489203e409 100644 --- a/src/widgets/doc/src/graphicsview.qdoc +++ b/src/widgets/doc/src/graphicsview.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -438,8 +438,8 @@ To enable OpenGL rendering, you simply set a new QOpenGLWidget as the viewport of QGraphicsView by calling QGraphicsView::setViewport(). If - you want OpenGL with antialiasing, you need OpenGL sample buffer - support (see QSurfaceFormat::samples()). + you want OpenGL with antialiasing, you need to set a QSurfaceFormat + with the needed sample count (see QSurfaceFormat::setSamples()). Example: diff --git a/src/widgets/graphicsview/qgraphicsproxywidget.cpp b/src/widgets/graphicsview/qgraphicsproxywidget.cpp index fe3475e6bb1..45720802d3c 100644 --- a/src/widgets/graphicsview/qgraphicsproxywidget.cpp +++ b/src/widgets/graphicsview/qgraphicsproxywidget.cpp @@ -581,7 +581,7 @@ QGraphicsProxyWidget::~QGraphicsProxyWidget() Note that widgets with the Qt::WA_PaintOnScreen widget attribute set and widgets that wrap an external application or controller - cannot be embedded. Examples are QGLWidget and QAxWidget. + cannot be embedded. Examples are QOpenGLWidget and QAxWidget. \sa widget() */ diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp index b669b0fe610..38c68b8fa56 100644 --- a/src/widgets/graphicsview/qgraphicsscene.cpp +++ b/src/widgets/graphicsview/qgraphicsscene.cpp @@ -2904,7 +2904,7 @@ QGraphicsSimpleTextItem *QGraphicsScene::addSimpleText(const QString &text, cons Note that widgets with the Qt::WA_PaintOnScreen widget attribute set and widgets that wrap an external application or controller - are not supported. Examples are QGLWidget and QAxWidget. + are not supported. Examples are QOpenGLWidget and QAxWidget. \sa addEllipse(), addLine(), addPixmap(), addPixmap(), addRect(), addText(), addSimpleText(), addItem() diff --git a/src/widgets/graphicsview/qgraphicsview.cpp b/src/widgets/graphicsview/qgraphicsview.cpp index 1117f5e4739..5e345e010ab 100644 --- a/src/widgets/graphicsview/qgraphicsview.cpp +++ b/src/widgets/graphicsview/qgraphicsview.cpp @@ -89,8 +89,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < By default, QGraphicsView provides a regular QWidget for the viewport widget. You can access this widget by calling viewport(), or you can replace it by calling setViewport(). To render using OpenGL, simply call - setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport - widget. + setViewport(new QOpenGLWidget). QGraphicsView takes ownership of the + viewport widget. QGraphicsView supports affine transformations, using QTransform. You can either pass a matrix to setTransform(), or you can call one of the @@ -159,8 +159,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < fastest when QGraphicsView spends more time figuring out what to draw than it would spend drawing (e.g., when very many small items are repeatedly updated). This is the preferred update mode for viewports that do not - support partial updates, such as QGLWidget, and for viewports that need to - disable scroll optimization. + support partial updates, such as QOpenGLWidget, and for viewports that + need to disable scroll optimization. \value MinimalViewportUpdate QGraphicsView will determine the minimal viewport region that requires a redraw, minimizing the time spent drawing diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index b8c30321ffc..300795d3bf2 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -1844,10 +1844,16 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) || edit(index, NoEditTriggers, event)) return; - if (d->selectionMode != SingleSelection) - topLeft = d->pressedPosition - d->offset(); - else + if (d->selectionMode != SingleSelection) { + // Use the current selection start index if it is valid as this will be based on the + // start of the selection and not the last item being pressed which can be different + // when in extended selection + topLeft = d->currentSelectionStartIndex.isValid() + ? visualRect(d->currentSelectionStartIndex).center() + : d->pressedPosition - d->offset(); + } else { topLeft = bottomRight; + } d->checkMouseMove(index); @@ -2455,7 +2461,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) } #endif break; -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS case Qt::Key_Enter: case Qt::Key_Return: // Propagate the enter if you couldn't edit the item and there are no @@ -2487,7 +2493,7 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event) break; } #endif -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS if (event->key() == Qt::Key_O && event->modifiers() & Qt::ControlModifier && currentIndex().isValid()) { emit activated(currentIndex()); break; diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index f420857b088..6289974345f 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -2985,14 +2985,17 @@ void QTableView::timerEvent(QTimerEvent *event) Q_D(QTableView); if (event->timerId() == d->columnResizeTimerID) { - updateGeometries(); - killTimer(d->columnResizeTimerID); - d->columnResizeTimerID = 0; + const int oldScrollMax = horizontalScrollBar()->maximum(); + if (horizontalHeader()->d_func()->state != QHeaderViewPrivate::ResizeSection) { + updateGeometries(); + killTimer(d->columnResizeTimerID); + d->columnResizeTimerID = 0; + } QRect rect; int viewportHeight = d->viewport->height(); int viewportWidth = d->viewport->width(); - if (d->hasSpans()) { + if (d->hasSpans() || horizontalScrollBar()->value() == oldScrollMax) { rect = QRect(0, 0, viewportWidth, viewportHeight); } else { for (int i = d->columnsToUpdate.size()-1; i >= 0; --i) { @@ -3010,14 +3013,17 @@ void QTableView::timerEvent(QTimerEvent *event) } if (event->timerId() == d->rowResizeTimerID) { - updateGeometries(); - killTimer(d->rowResizeTimerID); - d->rowResizeTimerID = 0; + const int oldScrollMax = verticalScrollBar()->maximum(); + if (verticalHeader()->d_func()->state != QHeaderViewPrivate::ResizeSection) { + updateGeometries(); + killTimer(d->rowResizeTimerID); + d->rowResizeTimerID = 0; + } int viewportHeight = d->viewport->height(); int viewportWidth = d->viewport->width(); int top; - if (d->hasSpans()) { + if (d->hasSpans() || verticalScrollBar()->value() == oldScrollMax) { top = 0; } else { top = viewportHeight; diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index a3bebb8f3cd..da0e1188f2a 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -3773,7 +3773,8 @@ int QTreeViewPrivate::itemDecorationAt(const QPoint &pos) const bool spanned = false; if (!spanningIndexes.isEmpty()) { const QModelIndex index = q->indexAt(pos); - spanned = q->isFirstColumnSpanned(index.row(), index.parent()); + if (index.isValid()) + spanned = q->isFirstColumnSpanned(index.row(), index.parent()); } const int column = spanned ? 0 : header->logicalIndexAt(pos.x()); if (!isTreePosition(column)) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index de12347b890..6e5fe0d1cf2 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -4294,7 +4294,7 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, QWidget *targetWidget = static_cast(target.data()); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // Single-touch events are normally not sent unless WA_TouchPadAcceptSingleTouchEvents is set. // In Qt 4 this check was in OS X-only code. That behavior is preserved here by the #ifdef. if (touchPoints.count() == 1 diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 541519245e2..134cebca099 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -51,7 +51,7 @@ #include "qgesture.h" #include "qevent.h" -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include "qmacgesturerecognizer_p.h" #endif @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcGestureManager, "qt.widgets.gestures") -#if !defined(Q_OS_OSX) +#if !defined(Q_OS_MACOS) static inline int panTouchPoints() { // Override by environment variable for testing. @@ -89,7 +89,7 @@ QGestureManager::QGestureManager(QObject *parent) { qRegisterMetaType(); -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) registerGestureRecognizer(new QMacSwipeGestureRecognizer); registerGestureRecognizer(new QMacPinchGestureRecognizer); registerGestureRecognizer(new QMacPanGestureRecognizer); diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index 33dd3e59b67..661568dcadf 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -402,10 +402,10 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) #endif //QT_NO_STYLE_STYLESHEET QPoint p = pos; - int screenNumber = getTipScreen(pos, w); - QScreen *screen = QGuiApplication::screens().at(screenNumber); - if (screen) { - const QPlatformScreen *platformScreen = screen->handle(); + const QScreen *screen = QGuiApplication::screens().value(getTipScreen(pos, w), + QGuiApplication::primaryScreen()); + // a QScreen's handle *should* never be null, so this is a bit paranoid + if (const QPlatformScreen *platformScreen = screen ? screen->handle() : nullptr) { const QSize cursorSize = QHighDpi::fromNativePixels(platformScreen->cursor()->size(), platformScreen); QPoint offset(2, cursorSize.height()); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 79c8aba8cfc..7be83c18374 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1608,7 +1608,6 @@ void QWidgetPrivate::createTLExtra() x->opacity = 255; x->posIncludesFrame = 0; x->sizeAdjusted = false; - x->inTopLevelResize = false; x->embedded = 0; x->window = nullptr; x->initialScreenIndex = -1; @@ -10803,7 +10802,7 @@ void QWidgetPrivate::repaint(T r) return; QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) + if (tlwExtra && tlwExtra->backingStore) tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow); } @@ -10878,7 +10877,7 @@ void QWidgetPrivate::update(T r) } QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) + if (tlwExtra && tlwExtra->backingStore) tlwExtra->repaintManager->markDirty(clipped, q); } diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index a3eac8d9ec2..b71b72fe13d 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -155,7 +155,6 @@ struct QTLWExtra { uint opacity : 8; uint posIncludesFrame : 1; uint sizeAdjusted : 1; - uint inTopLevelResize : 1; uint embedded : 1; }; diff --git a/src/widgets/kernel/qwidgetrepaintmanager.cpp b/src/widgets/kernel/qwidgetrepaintmanager.cpp index 135a1527ac2..e7e85c39e71 100644 --- a/src/widgets/kernel/qwidgetrepaintmanager.cpp +++ b/src/widgets/kernel/qwidgetrepaintmanager.cpp @@ -166,7 +166,7 @@ void QWidgetPrivate::invalidateBackingStore(const T &r) return; QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore) + if (!tlwExtra || !tlwExtra->backingStore) return; T clipped(r); @@ -213,7 +213,6 @@ void QWidgetRepaintManager::markDirty(const T &r, QWidget *widget, UpdateTime up Q_ASSERT(tlw->d_func()->extra); Q_ASSERT(tlw->d_func()->extra->topextra); - Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize); Q_ASSERT(widget->isVisible() && widget->updatesEnabled()); Q_ASSERT(widget->window() == tlw); Q_ASSERT(!r.isEmpty()); @@ -446,8 +445,6 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) QWidget *tlw = q->window(); QTLWExtra* x = tlw->d_func()->topData(); - if (x->inTopLevelResize) - return; static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_MOVE") == 0; @@ -543,8 +540,6 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) Q_Q(QWidget); QWidget *tlw = q->window(); QTLWExtra* x = tlw->d_func()->topData(); - if (x->inTopLevelResize) - return; QWidgetRepaintManager *repaintManager = x->repaintManager.get(); if (!repaintManager) @@ -722,8 +717,7 @@ void QWidgetRepaintManager::sync(QWidget *exposedWidget, const QRegion &exposedR { qCInfo(lcWidgetPainting) << "Syncing" << exposedRegion << "of" << exposedWidget; - QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); - if (!tlw->isVisible() || !tlwExtra || tlwExtra->inTopLevelResize) + if (!tlw->isVisible()) return; if (!exposedWidget || !hasPlatformWindow(exposedWidget) @@ -815,13 +809,11 @@ void QWidgetRepaintManager::paintAndFlush() const bool updatesDisabled = !tlw->updatesEnabled(); bool repaintAllWidgets = false; - const bool inTopLevelResize = tlw->d_func()->maybeTopData()->inTopLevelResize; const QRect tlwRect = tlw->data->crect; - const QRect surfaceGeometry(tlwRect.topLeft(), store->size()); - if ((inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) { + if (!updatesDisabled && store->size() != tlwRect.size()) { if (hasStaticContents() && !store->size().isEmpty() ) { // Repaint existing dirty area and newly visible area. - const QRect clipRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); + const QRect clipRect(QPoint(0, 0), store->size()); const QRegion staticRegion(staticContents(nullptr, clipRect)); QRegion newVisible(0, 0, tlwRect.width(), tlwRect.height()); newVisible -= staticRegion; @@ -837,7 +829,7 @@ void QWidgetRepaintManager::paintAndFlush() } } - if (inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) + if (store->size() != tlwRect.size()) store->resize(tlwRect.size()); if (updatesDisabled) @@ -1248,11 +1240,10 @@ bool QWidgetRepaintManager::hasStaticContents() const QRegion QWidgetRepaintManager::staticContents(QWidget *parent, const QRect &withinClipRect) const { if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) { - const QSize surfaceGeometry(store->size()); - QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); + QRect backingstoreRect(QPoint(0, 0), store->size()); if (!withinClipRect.isEmpty()) - surfaceRect &= withinClipRect; - return QRegion(surfaceRect); + backingstoreRect &= withinClipRect; + return QRegion(backingstoreRect); } QRegion region; diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index e82ddbcd203..0fa3fb4c678 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -397,7 +397,7 @@ QPointer qt_last_mouse_receiver = nullptr; void QWidgetWindow::handleEnterLeaveEvent(QEvent *event) { -#if !defined(Q_OS_OSX) && !defined(Q_OS_IOS) // Cocoa tracks popups +#if !defined(Q_OS_MACOS) && !defined(Q_OS_IOS) // Cocoa tracks popups // Ignore all enter/leave events from QPA if we are not on the first-level context menu. // This prevents duplicated events on most platforms. Fake events will be delivered in // QWidgetWindow::handleMouseEvent(QMouseEvent *). Make an exception whether the widget @@ -505,7 +505,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::ContextMenuOnMouseRelease).toBool() ? QEvent::MouseButtonRelease : QEvent::MouseButtonPress; if (QApplicationPrivate::inPopupMode()) { - QWidget *activePopupWidget = QApplication::activePopupWidget(); + QPointer activePopupWidget = QApplication::activePopupWidget(); QPoint mapped = event->pos(); if (activePopupWidget != m_widget) mapped = activePopupWidget->mapFromGlobal(event->globalPos()); @@ -544,7 +544,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) if (receiver != activePopupWidget) widgetPos = receiver->mapFromGlobal(event->globalPos()); -#if !defined(Q_OS_OSX) && !defined(Q_OS_IOS) // Cocoa tracks popups +#if !defined(Q_OS_MACOS) && !defined(Q_OS_IOS) // Cocoa tracks popups const bool reallyUnderMouse = activePopupWidget->rect().contains(mapped); const bool underMouse = activePopupWidget->underMouse(); if (underMouse != reallyUnderMouse) { @@ -565,9 +565,11 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) #endif if ((event->type() != QEvent::MouseButtonPress) || !(event->flags().testFlag(Qt::MouseEventCreatedDoubleClick))) { - + // if the widget that was pressed is gone, then deliver move events without buttons + const auto buttons = event->type() == QEvent::MouseMove && qt_button_down == nullptr + ? Qt::NoButton : event->buttons(); QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(), - event->button(), event->buttons(), event->modifiers(), event->source()); + event->button(), buttons, event->modifiers(), event->source()); e.setTimestamp(event->timestamp()); QApplicationPrivate::sendMouseEvent(receiver, &e, receiver, receiver->window(), &qt_button_down, qt_last_mouse_receiver); qt_last_mouse_receiver = receiver; @@ -764,7 +766,7 @@ void QWidgetWindow::repaintWindow() return; QTLWExtra *tlwExtra = m_widget->window()->d_func()->maybeTopData(); - if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) + if (tlwExtra && tlwExtra->backingStore) tlwExtra->repaintManager->markDirty(m_widget->rect(), m_widget, QWidgetRepaintManager::UpdateNow, QWidgetRepaintManager::BufferInvalid); } @@ -813,16 +815,16 @@ void QWidgetWindow::handleMoveEvent(QMoveEvent *event) void QWidgetWindow::handleResizeEvent(QResizeEvent *event) { - QSize oldSize = m_widget->data->crect.size(); + auto oldRect = m_widget->rect(); if (updateSize()) { QGuiApplication::forwardEvent(m_widget, event); if (m_widget->d_func()->shouldPaintOnScreen()) { - QRegion updateRegion(geometry()); + QRegion dirtyRegion = m_widget->rect(); if (m_widget->testAttribute(Qt::WA_StaticContents)) - updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); - m_widget->d_func()->syncBackingStore(updateRegion); + dirtyRegion -= oldRect; + m_widget->d_func()->syncBackingStore(dirtyRegion); } else { m_widget->d_func()->syncBackingStore(); } diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp index 2a0d6d1b406..b9abedd6262 100644 --- a/src/widgets/styles/qfusionstyle.cpp +++ b/src/widgets/styles/qfusionstyle.cpp @@ -479,7 +479,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem, { QPixmap pixmap(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_groupbox.png")); int topMargin = 0; - auto control = dynamic_cast(widget); + auto control = qobject_cast(widget); if (control && !control->isCheckable() && control->title().isEmpty()) { // Shrinking the topMargin if Not checkable AND title is empty topMargin = groupBoxTopMargin; @@ -1532,7 +1532,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio //draw text QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText; uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; - if (!styleHint(SH_UnderlineShortcut, mbi, widget)) + if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget)) alignment |= Qt::TextHideMnemonic; proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole); } else { @@ -1702,7 +1702,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio p->save(); int t = s.indexOf(QLatin1Char('\t')); int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine; - if (!styleHint(SH_UnderlineShortcut, menuitem, widget)) + if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget)) text_flags |= Qt::TextHideMnemonic; text_flags |= Qt::AlignLeft; if (t >= 0) { diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp index 77ffda10b0f..6e42005e866 100644 --- a/src/widgets/widgets/qabstractbutton.cpp +++ b/src/widgets/widgets/qabstractbutton.cpp @@ -245,7 +245,7 @@ void QAbstractButtonPrivate::notifyChecked() void QAbstractButtonPrivate::moveFocus(int key) { - QList buttonList = queryButtonList();; + QList buttonList = queryButtonList(); #if QT_CONFIG(buttongroup) bool exclusive = group ? group->d_func()->exclusive : autoExclusive; #else @@ -265,7 +265,7 @@ void QAbstractButtonPrivate::moveFocus(int key) for (int i = 0; i < buttonList.count(); ++i) { QAbstractButton *button = buttonList.at(i); if (button != f && button->window() == f->window() && button->isEnabled() && !button->isHidden() && - (autoExclusive || (button->focusPolicy() & focus_flag) == focus_flag)) { + (exclusive || (button->focusPolicy() & focus_flag) == focus_flag)) { QRect buttonRect = button->rect().translated(button->mapToGlobal(QPoint(0,0))); QPoint p = buttonRect.center(); diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 257cffda62c..6bc88f129dd 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -308,7 +308,7 @@ void QAbstractScrollAreaPrivate::init() q->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); layoutChildren(); -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS # ifndef QT_NO_GESTURES viewport->grabGesture(Qt::PanGesture); # endif diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 47993b8f3b7..8f195381e4a 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -904,7 +904,8 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const This signal is sent when the user chooses an item in the combobox. The item's \a index is passed. Note that this signal is sent even when the choice is not changed. If you need to know when the - choice actually changes, use signal currentIndexChanged(). + choice actually changes, use signal currentIndexChanged() or + currentTextChanged(). */ /*! @@ -914,7 +915,8 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const This signal is sent when the user chooses an item in the combobox. The item's \a text is passed. Note that this signal is sent even when the choice is not changed. If you need to know when the - choice actually changes, use signal currentIndexChanged(). + choice actually changes, use signal currentIndexChanged() or + currentTextChanged(). */ /*! @@ -933,13 +935,13 @@ QStyleOptionComboBox QComboBoxPrivateContainer::comboStyleOption() const */ /*! - \fn void QComboBox::currentIndexChanged(int index, const QString &text) - \since 5.15 + \fn void QComboBox::currentIndexChanged(int index) + \since 4.1 This signal is sent whenever the currentIndex in the combobox changes either through user interaction or programmatically. The - item's \a index is passed or -1 if the combobox becomes empty or - the currentIndex was reset. The item's \a text is also passed. + item's \a index is passed or -1 if the combobox becomes empty or the + currentIndex was reset. */ /*! @@ -971,7 +973,6 @@ QComboBox::QComboBox(QComboBoxPrivate &dd, QWidget *parent) d->init(); } - /*! \class QComboBox \brief The QComboBox widget is a combined button and popup list. @@ -994,9 +995,10 @@ QComboBox::QComboBox(QComboBoxPrivate &dd, QWidget *parent) to clear the displayed string without changing the combobox's contents. - There are two signals emitted if the current item of a combobox - changes, currentIndexChanged() and activated(). - currentIndexChanged() is always emitted regardless if the change + There are three signals emitted if the current item of a combobox + changes, currentIndexChanged(), currentTextChanged() and activated(). + currentIndexChanged() and currentTextChanged() are always emitted + regardless if the change was done programmatically or by user interaction, while activated() is only emitted when the change is caused by user interaction. The highlighted() signal is emitted when the user @@ -1048,7 +1050,7 @@ QComboBox::QComboBox(QComboBoxPrivate &dd, QWidget *parent) void QComboBoxPrivate::init() { Q_Q(QComboBox); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // On OS X, only line edits and list views always get tab focus. It's only // when we enable full keyboard access that other controls can get tab focus. // When it's not editable, a combobox looks like a button, and it behaves as @@ -1205,7 +1207,7 @@ void QComboBoxPrivate::updateViewContainerPaletteAndOpacity() void QComboBoxPrivate::updateFocusPolicy() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS Q_Q(QComboBox); // See comment in QComboBoxPrivate::init() @@ -1412,7 +1414,7 @@ void QComboBoxPrivate::_q_emitCurrentIndexChanged(const QModelIndex &index) { Q_Q(QComboBox); const QString text = itemText(index); - emit q->currentIndexChanged(index.row(), text); + emit q->currentIndexChanged(index.row()); // signal lineEdit.textChanged already connected to signal currentTextChanged, so don't emit double here if (!lineEdit) emit q->currentTextChanged(text); @@ -2646,7 +2648,7 @@ bool QComboBoxPrivate::showNativePopup() const QRect targetRect = QRect(tlw->mapFromGlobal(q->mapToGlobal(offset)), QSize()); m_platformMenu->showPopup(tlw, QHighDpi::toNativePixels(targetRect, tlw), currentItem); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // The Cocoa popup will swallow any mouse release event. // We need to fake one here to un-press the button. QMouseEvent mouseReleased(QEvent::MouseButtonRelease, q->pos(), Qt::LeftButton, diff --git a/src/widgets/widgets/qcombobox.h b/src/widgets/widgets/qcombobox.h index 99816954fa8..1411d641433 100644 --- a/src/widgets/widgets/qcombobox.h +++ b/src/widgets/widgets/qcombobox.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -233,7 +233,7 @@ Q_SIGNALS: void textActivated(const QString &); void highlighted(int index); void textHighlighted(const QString &); - void currentIndexChanged(int index, const QString &text); + void currentIndexChanged(int index); void currentTextChanged(const QString &); protected: diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h index 0a4433846fc..ac9bd4401a0 100644 --- a/src/widgets/widgets/qdatetimeedit_p.h +++ b/src/widgets/widgets/qdatetimeedit_p.h @@ -94,8 +94,18 @@ public: // Override QDateTimeParser: QString displayText() const override { return edit->text(); } - QDateTime getMinimum() const override { return minimum.toDateTime(); } - QDateTime getMaximum() const override { return maximum.toDateTime(); } + QDateTime getMinimum() const override + { + if (keyboardTracking) + return minimum.toDateTime(); + return QDateTimeParser::getMinimum(); + } + QDateTime getMaximum() const override + { + if (keyboardTracking) + return maximum.toDateTime(); + return QDateTimeParser::getMaximum(); + } QLocale locale() const override { return q_func()->locale(); } int cursorPosition() const override { return edit ? edit->cursorPosition() : -1; } diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index d6db6dd5bc3..055412528f6 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -601,9 +601,17 @@ const QValidator * QLineEdit::validator() const } /*! - Sets this line edit to only accept input that the validator, \a v, - will accept. This allows you to place any arbitrary constraints on - the text which may be entered. + Sets the validator for values of line edit to \a v. + + The line edit's returnPressed() and editingFinished() signals will only + be emitted if \a v validates the line edit's content as \l{QValidator::}{Acceptable}. + The user may change the content to any \l{QValidator::}{Intermediate} + value during editing, but will be prevented from editing the text to a + value that \a v validates as \l{QValidator::}{Invalid}. + + This allows you to constrain the text that shall finally be entered when editing is + done, while leaving users with enough freedom to edit the text from one valid state + to another. If \a v == 0, setValidator() removes the current input validator. The initial setting is to have no input validator (i.e. any input @@ -703,7 +711,7 @@ QSize QLineEdit::sizeHint() const /*! Returns a minimum size for the line edit. - The width returned is enough for at least one character. + The width returned is usually enough for at least one character. */ QSize QLineEdit::minimumSizeHint() const @@ -715,7 +723,7 @@ QSize QLineEdit::minimumSizeHint() const int h = fm.height() + qMax(2 * QLineEditPrivate::verticalMargin, fm.leading()) + tm.top() + tm.bottom() + d->topmargin + d->bottommargin; - int w = fm.maxWidth() + int w = fm.maxWidth() + 2 * QLineEditPrivate::horizontalMargin + tm.left() + tm.right() + d->leftmargin + d->rightmargin; QStyleOptionFrame opt; @@ -1441,7 +1449,7 @@ void QLineEdit::copy() const Inserts the clipboard's text at the cursor position, deleting any selected text, providing the line edit is not \l{QLineEdit::readOnly}{read-only}. - If the end result would not be acceptable to the current + If the end result would be invalid to the current \l{setValidator()}{validator}, nothing happens. \sa copy(), cut() diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 4bd3e23479c..e3016371bab 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -67,7 +67,7 @@ #include "qtoolbar_p.h" #endif #include "qwidgetanimator_p.h" -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include #endif @@ -79,7 +79,7 @@ class QMainWindowPrivate : public QWidgetPrivate public: inline QMainWindowPrivate() : layout(nullptr), explicitIconSize(false), toolButtonStyle(Qt::ToolButtonIconOnly) -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS , useUnifiedToolBar(false) #endif { } @@ -87,7 +87,7 @@ public: QSize iconSize; bool explicitIconSize; Qt::ToolButtonStyle toolButtonStyle; -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS bool useUnifiedToolBar; #endif void init(); @@ -1357,7 +1357,7 @@ bool QMainWindow::event(QEvent *event) */ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS Q_D(QMainWindow); if (isWindow()) { d->useUnifiedToolBar = set; @@ -1382,7 +1382,7 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set) bool QMainWindow::unifiedTitleAndToolBarOnMac() const { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS return d_func()->useUnifiedToolBar; #endif return false; diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index e26f797501a..31a7ad8695d 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -49,7 +49,7 @@ #include "qlayout.h" #include "qpainter.h" #include -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include "qmacnativewidget_mac.h" #endif #include "qapplication.h" @@ -1496,7 +1496,7 @@ void QMenuPrivate::_q_platformMenuAboutToShow() emit q->aboutToShow(); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS if (platformMenu) { const auto actions = q->actions(); for (QAction *action : actions) { @@ -3556,7 +3556,7 @@ void QMenu::actionEvent(QActionEvent *e) d->currentAction = nullptr; if (QWidgetAction *wa = qobject_cast(e->action())) { if (QWidget *widget = d->widgetItems.value(wa)) { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QWidget *p = widget->parentWidget(); if (p != this && qobject_cast(p)) { // This widget was reparented into a native Mac view diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h index 6ae73cf9fe3..7a609075329 100644 --- a/src/widgets/widgets/qmenu.h +++ b/src/widgets/widgets/qmenu.h @@ -288,7 +288,7 @@ private: friend void qt_mac_menu_emit_hovered(QMenu *menu, QAction *action); }; -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // ### Qt 4 compatibility; remove in Qt 6 inline QT_DEPRECATED void qt_mac_set_dock_menu(QMenu *menu) { menu->setAsDockMenu(); } #endif diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index 02fe9f31a1d..3871d6763c9 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -335,7 +335,7 @@ public: void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem *item); QPlatformMenuItem *insertActionInPlatformMenu(const QAction *action, QPlatformMenuItem *beforeItem); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS void moveWidgetToPlatformItem(QWidget *w, QPlatformMenuItem* item); #endif diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index df480629dac..53be9179452 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -60,7 +60,7 @@ #ifndef QT_NO_ACCESSIBILITY #include "qaccessible.h" #endif -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include #endif @@ -115,7 +115,7 @@ inline static bool verticalTabs(QTabBar::Shape shape) void QTabBarPrivate::updateMacBorderMetrics() { -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) Q_Q(QTabBar); // Extend the unified title and toolbar area to cover the tab bar iff // 1) the tab bar is in document mode diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp index bb376e9613d..9c63f98a738 100644 --- a/src/widgets/widgets/qtoolbar.cpp +++ b/src/widgets/widgets/qtoolbar.cpp @@ -61,7 +61,7 @@ #include #include -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include #endif @@ -248,7 +248,7 @@ bool QToolBarPrivate::mousePressEvent(QMouseEvent *event) QStyleOptionToolBar opt; q->initStyleOption(&opt); if (q->style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, q).contains(event->pos()) == false) { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // When using the unified toolbar on OS X, the user can click and // drag between toolbar contents to move the window. Make this work by // implementing the standard mouse-dragging code and then call @@ -282,7 +282,7 @@ bool QToolBarPrivate::mouseReleaseEvent(QMouseEvent*) endDrag(); return true; } else { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS if (!macWindowDragging) return false; macWindowDragging = false; @@ -298,7 +298,7 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event) Q_Q(QToolBar); if (!state) { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS if (!macWindowDragging) return false; QWidget *w = q->window(); @@ -1084,7 +1084,7 @@ static bool waitForPopup(QToolBar *tb, QWidget *popup) return false; } -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS static void enableMacToolBar(QToolBar *toolbar, bool enable) { QPlatformNativeInterface *nativeInterface = QApplication::platformNativeInterface(); @@ -1123,7 +1123,7 @@ bool QToolBar::event(QEvent *event) Q_FALLTHROUGH(); case QEvent::Show: d->toggleViewAction->setChecked(event->type() == QEvent::Show); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS enableMacToolBar(this, event->type() == QEvent::Show); #endif emit visibilityChanged(event->type() == QEvent::Show); diff --git a/src/widgets/widgets/qtoolbar_p.h b/src/widgets/widgets/qtoolbar_p.h index e1b786cab73..07f1af3fe04 100644 --- a/src/widgets/widgets/qtoolbar_p.h +++ b/src/widgets/widgets/qtoolbar_p.h @@ -74,7 +74,7 @@ public: allowedAreas(Qt::AllToolBarAreas), orientation(Qt::Horizontal), toolButtonStyle(Qt::ToolButtonIconOnly), layout(nullptr), state(nullptr) -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS , macWindowDragging(false) #endif { } @@ -106,7 +106,7 @@ public: }; DragState *state; -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS bool macWindowDragging; QPoint macWindowDragPressPosition; #endif diff --git a/src/widgets/widgets/qtoolbarlayout.cpp b/src/widgets/widgets/qtoolbarlayout.cpp index 8ddf27c8785..e1c0df31d15 100644 --- a/src/widgets/widgets/qtoolbarlayout.cpp +++ b/src/widgets/widgets/qtoolbarlayout.cpp @@ -48,7 +48,7 @@ #include #include #include -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include #endif @@ -348,7 +348,7 @@ static bool defaultWidgetAction(QToolBarItem *item) void QToolBarLayout::updateMacBorderMetrics() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QToolBar *tb = qobject_cast(parentWidget()); if (!tb) return; diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp index 3b9ec618bbc..e22028aa498 100644 --- a/src/widgets/widgets/qwidgettextcontrol.cpp +++ b/src/widgets/widgets/qwidgettextcontrol.cpp @@ -2236,6 +2236,7 @@ void QWidgetTextControlPrivate::focusEvent(QFocusEvent *e) #endif } else { setCursorVisible(false); + cursorOn = false; if (cursorIsFocusIndicator && e->reason() != Qt::ActiveWindowFocusReason diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp index f997a40119f..c3407bcc529 100644 --- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp +++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp @@ -670,7 +670,7 @@ void tst_QRandomGenerator::qualityReal() RandomGenerator rng(control); enum { - SampleSize = 160, + SampleSize = 16000, // Expected value: sample size times proportion of the range: PerfectOctile = SampleSize / 8, @@ -678,8 +678,8 @@ void tst_QRandomGenerator::qualityReal() // Variance is (1 - proportion of range) * expected; sqrt() for standard deviations. // Should usually be within twice that and almost never outside four times: - RangeHalf = 25, // floor(4 * sqrt((1 - 0.5) * PerfectHalf)) - RangeOctile = 16 // floor(4 * sqrt((1 - 0.125) * PerfectOctile)) + RangeHalf = 252, // floor(4 * sqrt((1 - 0.5) * PerfectHalf)) + RangeOctile = 167 // floor(4 * sqrt((1 - 0.125) * PerfectOctile)) }; double data[SampleSize]; diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index f0fd3768a7d..bd2bba8a887 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2020 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -40,6 +40,12 @@ #include #include #include + +#include +#ifdef Q_OS_UNIX +# include +#endif + #include typedef void (QProcess::*QProcessErrorSignal)(QProcess::ProcessError); @@ -57,6 +63,7 @@ private slots: void getSetCheck(); void constructing(); void simpleStart(); + void setupChildProcess(); void startWithOpen(); void startWithOldOpen(); void execute(); @@ -274,6 +281,51 @@ void tst_QProcess::simpleStart() QCOMPARE(qvariant_cast(spy.at(2).at(0)), QProcess::NotRunning); } +void tst_QProcess::setupChildProcess() +{ + /* This test exists because in Qt 5.15, the Unix version of QProcess has + * some code that depends on whether it's an actual QProcess or a + * derived class */ + static const char setupChildMessage[] = "Called from setupChildProcess()"; + class DerivedProcessClass : public QProcess { + public: + int fd; + DerivedProcessClass(int fd) : fd(fd) + { + } + + protected: + void setupChildProcess() override + { + QT_WRITE(fd, setupChildMessage, sizeof(setupChildMessage) - 1); + QT_CLOSE(fd); + } + }; + + int pipes[2] = { -1 , -1 }; +#ifdef Q_OS_UNIX + QVERIFY(qt_safe_pipe(pipes) == 0); +#endif + + DerivedProcessClass process(pipes[1]); + process.start("testProcessNormal/testProcessNormal"); + if (process.state() != QProcess::Starting) + QCOMPARE(process.state(), QProcess::Running); + QVERIFY2(process.waitForStarted(5000), qPrintable(process.errorString())); + +#ifdef Q_OS_UNIX + char buf[sizeof setupChildMessage] = {}; + qt_safe_close(pipes[1]); + QCOMPARE(qt_safe_read(pipes[0], buf, sizeof(buf)), qint64(sizeof(setupChildMessage) - 1)); + QCOMPARE(buf, setupChildMessage); + qt_safe_close(pipes[0]); +#endif + + QVERIFY2(process.waitForFinished(5000), qPrintable(process.errorString())); + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QCOMPARE(process.exitCode(), 0); +} + void tst_QProcess::startWithOpen() { QProcess p; diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 1b3bc8a6273..86465d25fb0 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -4700,14 +4700,28 @@ void tst_QVariant::sequentialIterableEndianessSanityCheck() void tst_QVariant::sequentialIterableAppend() { - QVector container {1, 2}; - auto variant = QVariant::fromValue(container); - QVERIFY(variant.canConvert()); - auto asIterable = variant.value(); - const int i = 3, j = 4; - asIterable.append(&i); - asIterable.append(&j); - QCOMPARE(variant.value>(), QVector ({1, 2, 3, 4})); + { + QVector container {1, 2}; + auto variant = QVariant::fromValue(container); + QVERIFY(variant.canConvert()); + auto asIterable = variant.value(); + const int i = 3, j = 4; + asIterable.append(&i); + asIterable.append(&j); + QCOMPARE(variant.value>(), QVector ({1, 2, 3, 4})); + } + { + QSet container { QByteArray{"hello"}, QByteArray{"world"} }; + auto variant = QVariant::fromValue(std::move(container)); + QVERIFY(variant.canConvert()); + auto asIterable = variant.value(); + QByteArray qba1 {"goodbye"}; + QByteArray qba2 { "moon" }; + asIterable.append( &qba1 ); + asIterable.append( &qba2); + QSet reference { "hello", "world", "goodbye", "moon" }; + QCOMPARE(variant.value>(), reference); + } } void tst_QVariant::preferDirectConversionOverInterfaces() diff --git a/tests/auto/corelib/serialization/cborlargedatavalidation.cpp b/tests/auto/corelib/serialization/cborlargedatavalidation.cpp new file mode 100644 index 00000000000..9abfe0f575c --- /dev/null +++ b/tests/auto/corelib/serialization/cborlargedatavalidation.cpp @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** Copyright (C) 2020 Intel Corporation. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +namespace { +// A QIODevice that supplies a fixed header followed by a large sequence of +// null bytes up until a pre-determined size. +class LargeIODevice final : public QIODevice +{ +public: + qint64 realSize; + QByteArray start; + + LargeIODevice(const QByteArray &start, qint64 size, QObject *parent = nullptr) + : QIODevice(parent), realSize(size), start(start) + {} + + qint64 size() const override { return realSize; } + bool isSequential() const override { return false; } + +protected: + qint64 readData(char *data, qint64 maxlen) override; + qint64 writeData(const char *, qint64) override { return -1; } +}; +}; + +qint64 LargeIODevice::readData(char *data, qint64 maxlen) +{ + qint64 p = pos(); + if (maxlen > realSize - p) + maxlen = realSize - p; + memset(data, '\0', maxlen); + + qint64 fromstart = start.size() - p; + if (fromstart > maxlen) + fromstart = maxlen; + else if (fromstart < 0) + fromstart = 0; + if (fromstart) + memcpy(data, start.constData() + p, fromstart); + return maxlen; +} + +void addValidationLargeData(qsizetype minInvalid, qsizetype maxInvalid) +{ + char toolong[2 + sizeof(qsizetype)] = { char(0x81) }; + for (qsizetype v = maxInvalid; v >= minInvalid; --v) { + // 0x5a for 32-bit, 0x5b for 64-bit + toolong[1] = sizeof(v) > 4 ? 0x5b : 0x5a; + qToBigEndian(v, toolong + 2); + + QTest::addRow("bytearray-too-big-for-qbytearray-%llx", v) + << QByteArray(toolong, sizeof(toolong)) << 0 << CborErrorDataTooLarge; + toolong[1] |= 0x20; + + // QCborStreamReader::readString copies to a QByteArray first + QTest::addRow("string-too-big-for-qbytearray-%llx", v) + << QByteArray(toolong, sizeof(toolong)) << 0 << CborErrorDataTooLarge; + } +} + +void addValidationHugeDevice(qsizetype byteArrayInvalid, qsizetype stringInvalid) +{ + qRegisterMetaType>(); + QTest::addColumn>("device"); + QTest::addColumn("expectedError"); + + char buf[1 + sizeof(quint64)]; + auto device = [&buf](QCborStreamReader::Type t, quint64 size) { + buf[0] = quint8(t) | 0x1b; + qToBigEndian(size, buf + 1); + size += sizeof(buf); + QSharedPointer p = + QSharedPointer::create(QByteArray(buf, sizeof(buf)), size); + return p; + }; + + // do the exact limits + QTest::newRow("bytearray-just-too-big") + << device(QCborStreamReader::ByteArray, byteArrayInvalid) << CborErrorDataTooLarge; + QTest::newRow("string-just-too-big") + << device(QCborStreamReader::String, stringInvalid) << CborErrorDataTooLarge; + + auto addSize = [=](const char *sizename, qint64 size) { + if (byteArrayInvalid < size) + QTest::addRow("bytearray-%s", sizename) + << device(QCborStreamReader::ByteArray, size) << CborErrorDataTooLarge; + if (stringInvalid < size) + QTest::addRow("string-%s", sizename) + << device(QCborStreamReader::String, size) << CborErrorDataTooLarge; + }; + addSize("1GB", quint64(1) << 30); + addSize("2GB", quint64(1) << 31); + addSize("4GB", quint64(1) << 32); + addSize("max", std::numeric_limits::max() - sizeof(buf)); +} diff --git a/tests/auto/corelib/serialization/qcborstreamreader/CMakeLists.txt b/tests/auto/corelib/serialization/qcborstreamreader/CMakeLists.txt index 198cca8435c..d5f5aea5be8 100644 --- a/tests/auto/corelib/serialization/qcborstreamreader/CMakeLists.txt +++ b/tests/auto/corelib/serialization/qcborstreamreader/CMakeLists.txt @@ -12,4 +12,6 @@ add_qt_test(tst_qcborstreamreader INCLUDE_DIRECTORIES ../../../../../src/3rdparty/tinycbor/src ../../../../../src/3rdparty/tinycbor/tests/parser + PUBLIC_LIBRARIES + Qt::CorePrivate ) diff --git a/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro b/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro index 5df331314af..b758de1a9eb 100644 --- a/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro +++ b/tests/auto/corelib/serialization/qcborstreamreader/qcborstreamreader.pro @@ -1,4 +1,4 @@ -QT = core testlib +QT = core-private testlib TARGET = tst_qcborstreamreader CONFIG += testcase SOURCES += \ diff --git a/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp b/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp index 28d29168fb6..f969bb9074a 100644 --- a/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp +++ b/tests/auto/corelib/serialization/qcborstreamreader/tst_qcborstreamreader.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 Intel Corporation. +** Copyright (C) 2020 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -40,6 +40,8 @@ #include #include +#include + class tst_QCborStreamReader : public QObject { Q_OBJECT @@ -73,6 +75,8 @@ private Q_SLOTS: void next(); void validation_data(); void validation(); + void hugeDeviceValidation_data(); + void hugeDeviceValidation(); void recursionLimit_data(); void recursionLimit(); @@ -902,16 +906,26 @@ void tst_QCborStreamReader::next() QVERIFY(doit("\xbf\x9f\1\xff\x9f" + data + "\xff\xff")); } +#include "../cborlargedatavalidation.cpp" + void tst_QCborStreamReader::validation_data() { + // Add QCborStreamReader-specific limitations due to use of QByteArray and + // QString, which are allocated by QArrayData::allocate(). + const qsizetype MaxInvalid = std::numeric_limits::max(); + const qsizetype MinInvalid = MaxByteArraySize + 1; + addValidationColumns(); - addValidationData(); + addValidationData(MinInvalid); + addValidationLargeData(MinInvalid, MaxInvalid); } void tst_QCborStreamReader::validation() { QFETCH_GLOBAL(bool, useDevice); QFETCH(QByteArray, data); + QFETCH(CborError, expectedError); + QCborError error = { QCborError::Code(expectedError) }; QBuffer buffer(&data); QCborStreamReader reader(data); @@ -920,12 +934,39 @@ void tst_QCborStreamReader::validation() reader.setDevice(&buffer); } parse(reader, data); - QVERIFY(reader.lastError() != QCborError::NoError); + QCOMPARE(reader.lastError(), error); // next() should fail reader.reset(); QVERIFY(!reader.next()); - QVERIFY(reader.lastError() != QCborError::NoError); + QCOMPARE(reader.lastError(), error); +} + +void tst_QCborStreamReader::hugeDeviceValidation_data() +{ + addValidationHugeDevice(MaxByteArraySize + 1, MaxStringSize + 1); +} + +void tst_QCborStreamReader::hugeDeviceValidation() +{ + QFETCH_GLOBAL(bool, useDevice); + if (!useDevice) + return; + + QFETCH(QSharedPointer, device); + QFETCH(CborError, expectedError); + QCborError error = { QCborError::Code(expectedError) }; + + device->open(QIODevice::ReadOnly | QIODevice::Unbuffered); + QCborStreamReader reader(device.data()); + + QVERIFY(parseOne(reader).isEmpty()); + QCOMPARE(reader.lastError(), error); + + // next() should fail + reader.reset(); + QVERIFY(!reader.next()); + QCOMPARE(reader.lastError(), error); } static const int Recursions = 3; diff --git a/tests/auto/corelib/serialization/qcborvalue/CMakeLists.txt b/tests/auto/corelib/serialization/qcborvalue/CMakeLists.txt index 66cb80c56ad..0835ac9c50d 100644 --- a/tests/auto/corelib/serialization/qcborvalue/CMakeLists.txt +++ b/tests/auto/corelib/serialization/qcborvalue/CMakeLists.txt @@ -12,4 +12,6 @@ add_qt_test(tst_qcborvalue INCLUDE_DIRECTORIES ../../../../../src/3rdparty/tinycbor/src ../../../../../src/3rdparty/tinycbor/tests/parser + PUBLIC_LIBRARIES + Qt::CorePrivate ) diff --git a/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro b/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro index 9dd67da1f09..4d01b290f5d 100644 --- a/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro +++ b/tests/auto/corelib/serialization/qcborvalue/qcborvalue.pro @@ -1,4 +1,4 @@ -QT = core testlib +QT = core-private testlib TARGET = tst_qcborvalue CONFIG += testcase SOURCES += \ diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index d5a9012f9ff..6d8161c1f99 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 Intel Corporation. +** Copyright (C) 2020 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -40,6 +40,8 @@ #include #include +#include + Q_DECLARE_METATYPE(QCborKnownTags) Q_DECLARE_METATYPE(QCborValue) Q_DECLARE_METATYPE(QCborValue::EncodingOptions) @@ -102,6 +104,10 @@ private slots: void fromCborStreamReaderIODevice(); void validation_data(); void validation(); + void hugeDeviceValidation_data(); + void hugeDeviceValidation(); + void recursionLimit_data(); + void recursionLimit(); void toDiagnosticNotation_data(); void toDiagnosticNotation(); @@ -1687,39 +1693,127 @@ void tst_QCborValue::fromCborStreamReaderIODevice() fromCbor_common(doCheck); } +#include "../cborlargedatavalidation.cpp" + void tst_QCborValue::validation_data() { + // Add QCborStreamReader-specific limitations due to use of QByteArray and + // QString, which are allocated by QArrayData::allocate(). + const qsizetype MaxInvalid = std::numeric_limits::max(); + const qsizetype MinInvalid = MaxByteArraySize + 1; addValidationColumns(); - addValidationData(); + addValidationData(MinInvalid); + addValidationLargeData(MinInvalid, MaxInvalid); // These tests say we have arrays and maps with very large item counts. // They are meant to ensure we don't pre-allocate a lot of memory // unnecessarily and possibly crash the application. The actual number of // elements in the stream is only 2, so we should get an unexpected EOF - // error. QCborValue internally uses 16 bytes per element, so we get to - // 2 GB at 2^27 elements. - QTest::addRow("very-large-array-no-overflow") << raw("\x9a\x07\xff\xff\xff" "\0\0"); - QTest::addRow("very-large-array-overflow1") << raw("\x9a\x40\0\0\0" "\0\0"); + // error. QCborValue internally uses 16 bytes per element, so we get to 2 + // GB at 2^27 elements (32-bit) or, theoretically, 2^63 bytes at 2^59 + // elements (64-bit). + if (sizeof(QVector::size_type) == sizeof(int)) { + // 32-bit sizes (Qt 5 and 32-bit platforms) + QTest::addRow("very-large-array-no-overflow") << raw("\x9a\x07\xff\xff\xff" "\0\0") << 0 << CborErrorUnexpectedEOF; + QTest::addRow("very-large-array-overflow1") << raw("\x9a\x40\0\0\0" "\0\0") << 0 << CborErrorUnexpectedEOF; - // this makes sure we don't accidentally clip to 32-bit: sending 2^32+2 elements - QTest::addRow("very-large-array-overflow2") << raw("\x9b\0\0\0\1""\0\0\0\2" "\0\0"); + // this makes sure we don't accidentally clip to 32-bit: sending 2^32+2 elements + QTest::addRow("very-large-array-overflow2") << raw("\x9b\0\0\0\1""\0\0\0\2" "\0\0") << 0 << CborErrorDataTooLarge; + } else { + // 64-bit Qt 6 + QTest::addRow("very-large-array-no-overflow") << raw("\x9b\x07\xff\xff\xff" "\xff\xff\xff\xff" "\0\0"); + QTest::addRow("very-large-array-overflow") << raw("\x9b\x40\0\0\0" "\0\0\0\0" "\0\0"); + } } void tst_QCborValue::validation() { QFETCH(QByteArray, data); + QFETCH(CborError, expectedError); + QCborError error = { QCborError::Code(expectedError) }; - QCborParserError error; - QCborValue decoded = QCborValue::fromCbor(data, &error); - QVERIFY(error.error != QCborError{}); + QCborParserError parserError; + QCborValue decoded = QCborValue::fromCbor(data, &parserError); + QCOMPARE(parserError.error, error); if (data.startsWith('\x81')) { // decode without the array prefix - decoded = QCborValue::fromCbor(data.mid(1), &error); - QVERIFY(error.error != QCborError{}); + char *ptr = const_cast(data.constData()); + QByteArray mid = QByteArray::fromRawData(ptr + 1, data.size() - 1); + decoded = QCborValue::fromCbor(mid, &parserError); + QCOMPARE(parserError.error, error); } } +void tst_QCborValue::hugeDeviceValidation_data() +{ + addValidationHugeDevice(MaxByteArraySize + 1, MaxStringSize + 1); +} + +void tst_QCborValue::hugeDeviceValidation() +{ + QFETCH(QSharedPointer, device); + QFETCH(CborError, expectedError); + QCborError error = { QCborError::Code(expectedError) }; + + device->open(QIODevice::ReadOnly | QIODevice::Unbuffered); + QCborStreamReader reader(device.data()); + QCborValue decoded = QCborValue::fromCbor(reader); + QCOMPARE(reader.lastError(), error); +} + +void tst_QCborValue::recursionLimit_data() +{ + constexpr int RecursionAttempts = 4096; + QTest::addColumn("data"); + QByteArray arrays(RecursionAttempts, char(0x81)); + QByteArray _arrays(RecursionAttempts, char(0x9f)); + QByteArray maps(RecursionAttempts, char(0xa1)); + QByteArray _maps(RecursionAttempts, char(0xbf)); + QByteArray tags(RecursionAttempts, char(0xc0)); + + QTest::newRow("array-nesting-too-deep") << arrays; + QTest::newRow("_array-nesting-too-deep") << _arrays; + QTest::newRow("map-nesting-too-deep") << maps; + QTest::newRow("_map-nesting-too-deep") << _maps; + QTest::newRow("tag-nesting-too-deep") << tags; + + QByteArray mixed(5 * RecursionAttempts, Qt::Uninitialized); + char *ptr = mixed.data(); + for (int i = 0; i < RecursionAttempts; ++i) { + quint8 type = qBound(quint8(QCborStreamReader::Array), quint8(i & 0x80), quint8(QCborStreamReader::Tag)); + quint8 additional_info = i & 0x1f; + if (additional_info == 0x1f) + (void)additional_info; // leave it + else if (additional_info > 0x1a) + additional_info = 0x1a; + else if (additional_info < 1) + additional_info = 1; + + *ptr++ = type | additional_info; + if (additional_info == 0x18) { + *ptr++ = uchar(i); + } else if (additional_info == 0x19) { + qToBigEndian(ushort(i), ptr); + ptr += 2; + } else if (additional_info == 0x1a) { + qToBigEndian(uint(i), ptr); + ptr += 4; + } + } + + QTest::newRow("mixed-nesting-too-deep") << mixed; +} + +void tst_QCborValue::recursionLimit() +{ + QFETCH(QByteArray, data); + + QCborParserError error; + QCborValue decoded = QCborValue::fromCbor(data, &error); + QCOMPARE(error.error, QCborError::NestingTooDeep); +} + void tst_QCborValue::toDiagnosticNotation_data() { QTest::addColumn("v"); diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp index 6ed06ca237b..2b06e60c442 100644 --- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp @@ -514,7 +514,7 @@ static inline bool runSysApp(const QString &binary, errorMessage->clear(); QProcess process; process.setEnvironment(env); - process.start(binary); + process.start(binary, QStringList()); process.closeWriteChannel(); if (!process.waitForStarted()) { *errorMessage = QLatin1String("Cannot start '") + binary @@ -2589,12 +2589,12 @@ void tst_QLocale::currency() const QLocale en_US("en_US"); QCOMPARE(en_US.toCurrencyString(qulonglong(1234)), QString("$1,234")); - QCOMPARE(en_US.toCurrencyString(qlonglong(-1234)), QString("$-1,234")); + QCOMPARE(en_US.toCurrencyString(qlonglong(-1234)), QString("($1,234)")); QCOMPARE(en_US.toCurrencyString(double(1234.56)), QString("$1,234.56")); - QCOMPARE(en_US.toCurrencyString(double(-1234.56)), QString("$-1,234.56")); - QCOMPARE(en_US.toCurrencyString(double(-1234.5678)), QString("$-1,234.57")); - QCOMPARE(en_US.toCurrencyString(double(-1234.5678), NULL, 4), QString("$-1,234.5678")); - QCOMPARE(en_US.toCurrencyString(double(-1234.56), NULL, 4), QString("$-1,234.5600")); + QCOMPARE(en_US.toCurrencyString(double(-1234.56)), QString("($1,234.56)")); + QCOMPARE(en_US.toCurrencyString(double(-1234.5678)), QString("($1,234.57)")); + QCOMPARE(en_US.toCurrencyString(double(-1234.5678), NULL, 4), QString("($1,234.5678)")); + QCOMPARE(en_US.toCurrencyString(double(-1234.56), NULL, 4), QString("($1,234.5600)")); const QLocale ru_RU("ru_RU"); QCOMPARE(ru_RU.toCurrencyString(qulonglong(1234)), diff --git a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp index 2a9c1e1e415..898ac868743 100644 --- a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp +++ b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp @@ -428,9 +428,9 @@ void tst_QEasingCurve::setCustomType() QCOMPARE(curve.valueForProgress(0.15), 0.1); QCOMPARE(curve.valueForProgress(0.20), 0.2); QCOMPARE(curve.valueForProgress(0.25), 0.2); - // QTBUG-69947, MinGW 7.3 returns 0.2 + // QTBUG-69947, MinGW 7.3, 8.1 x86 returns 0.2 #if defined(Q_CC_MINGW) -#if !defined(__GNUC__) || __GNUC__ != 7 || __GNUC_MINOR__ < 3 +#if !defined(__GNUC__) || defined(__MINGW64__) QCOMPARE(curve.valueForProgress(0.30), 0.3); #endif #endif diff --git a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp index 4bb41138450..226af2f805c 100644 --- a/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp +++ b/tests/auto/corelib/tools/qscopeguard/tst_qscopeguard.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author SĂ©rgio Martins -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -101,8 +101,8 @@ void tst_QScopeGuard::construction() QScopeGuard fromNonVoidFunction(intFunc); QScopeGuard fromNoDiscardFunction(noDiscardFunc); #ifndef __apple_build_version__ - QScopeGuard fromStdFunction{std::function(func)}; - std::function stdFunction(func); + QScopeGuard fromStdFunction{std::function(func)}; + std::function stdFunction(func); QScopeGuard fromNamedStdFunction(stdFunction); #endif #else diff --git a/tests/auto/gui/kernel/CMakeLists.txt b/tests/auto/gui/kernel/CMakeLists.txt index ecac48d1c1a..1cb38a7c9eb 100644 --- a/tests/auto/gui/kernel/CMakeLists.txt +++ b/tests/auto/gui/kernel/CMakeLists.txt @@ -1,17 +1,18 @@ # Generated from kernel.pro. +if(QT_FEATURE_action) + add_subdirectory(qaction) + add_subdirectory(qactiongroup) +endif() add_subdirectory(qbackingstore) add_subdirectory(qcursor) add_subdirectory(qdrag) add_subdirectory(qevent) add_subdirectory(qfileopenevent) add_subdirectory(qguieventdispatcher) -add_subdirectory(qguimetatype) add_subdirectory(qguitimer) -add_subdirectory(qguivariant) add_subdirectory(qinputmethod) add_subdirectory(qkeyevent) -add_subdirectory(qkeysequence) add_subdirectory(qmouseevent) add_subdirectory(qpalette) add_subdirectory(qscreen) @@ -20,12 +21,22 @@ add_subdirectory(qwindow) add_subdirectory(qguiapplication) add_subdirectory(qpixelformat) add_subdirectory(qrasterwindow) +add_subdirectory(qaddpostroutine) if(NOT ANDROID AND NOT UIKIT) add_subdirectory(qclipboard) endif() if(TARGET Qt::Network) add_subdirectory(qguieventloop) endif() +if(QT_FEATURE_shortcut) + add_subdirectory(qguimetatype) + add_subdirectory(qguivariant) + add_subdirectory(qkeysequence) + add_subdirectory(qshortcut) +endif() +if(QT_FEATURE_highdpiscaling) + add_subdirectory(qhighdpiscaling) +endif() if(TARGET Qt::Widgets) add_subdirectory(qmouseevent_modal) add_subdirectory(qtouchevent) diff --git a/tests/auto/gui/kernel/kernel.pro b/tests/auto/gui/kernel/kernel.pro index 5a935699c50..85bebbddc94 100644 --- a/tests/auto/gui/kernel/kernel.pro +++ b/tests/auto/gui/kernel/kernel.pro @@ -28,7 +28,8 @@ SUBDIRS=\ qguiapplication \ qpixelformat \ qopenglwindow \ - qrasterwindow + qrasterwindow \ + qaddpostroutine win32:!winrt:qtHaveModule(network): SUBDIRS += noqteventloop diff --git a/tests/auto/gui/kernel/qaction/CMakeLists.txt b/tests/auto/gui/kernel/qaction/CMakeLists.txt index c14444c1236..bdd1a1d1654 100644 --- a/tests/auto/gui/kernel/qaction/CMakeLists.txt +++ b/tests/auto/gui/kernel/qaction/CMakeLists.txt @@ -1,10 +1,10 @@ # Generated from qaction.pro. ##################################################################### -## tst_qaction Test: +## tst_qaction_kernel Test: ##################################################################### -add_qt_test(tst_qaction +add_qt_test(tst_qaction_kernel SOURCES tst_qaction.cpp PUBLIC_LIBRARIES diff --git a/tests/auto/gui/kernel/qaction/qaction.pro b/tests/auto/gui/kernel/qaction/qaction.pro index fae8d826f42..83e8296e680 100644 --- a/tests/auto/gui/kernel/qaction/qaction.pro +++ b/tests/auto/gui/kernel/qaction/qaction.pro @@ -1,4 +1,4 @@ CONFIG += testcase -TARGET = tst_qaction +TARGET = tst_qaction_kernel QT += gui-private core-private testlib SOURCES += tst_qaction.cpp diff --git a/tests/auto/gui/kernel/qactiongroup/CMakeLists.txt b/tests/auto/gui/kernel/qactiongroup/CMakeLists.txt index 6ef659ebc1a..bcab5e05a2f 100644 --- a/tests/auto/gui/kernel/qactiongroup/CMakeLists.txt +++ b/tests/auto/gui/kernel/qactiongroup/CMakeLists.txt @@ -1,10 +1,10 @@ # Generated from qactiongroup.pro. ##################################################################### -## tst_qactiongroup Test: +## tst_qactiongroup_kernel Test: ##################################################################### -add_qt_test(tst_qactiongroup +add_qt_test(tst_qactiongroup_kernel SOURCES tst_qactiongroup.cpp PUBLIC_LIBRARIES diff --git a/tests/auto/gui/kernel/qactiongroup/qactiongroup.pro b/tests/auto/gui/kernel/qactiongroup/qactiongroup.pro index 81ceb104293..a60109c63ed 100644 --- a/tests/auto/gui/kernel/qactiongroup/qactiongroup.pro +++ b/tests/auto/gui/kernel/qactiongroup/qactiongroup.pro @@ -1,4 +1,4 @@ CONFIG += testcase -TARGET = tst_qactiongroup +TARGET = tst_qactiongroup_kernel QT += testlib SOURCES += tst_qactiongroup.cpp diff --git a/tests/auto/gui/kernel/qaddpostroutine/CMakeLists.txt b/tests/auto/gui/kernel/qaddpostroutine/CMakeLists.txt new file mode 100644 index 00000000000..4af9ebedd57 --- /dev/null +++ b/tests/auto/gui/kernel/qaddpostroutine/CMakeLists.txt @@ -0,0 +1,12 @@ +# Generated from qaddpostroutine.pro. + +##################################################################### +## tst_qaddpostroutine Test: +##################################################################### + +qt_add_test(tst_qaddpostroutine + SOURCES + tst_qaddpostroutine.cpp + PUBLIC_LIBRARIES + Qt::Gui +) diff --git a/tests/auto/gui/kernel/qaddpostroutine/qaddpostroutine.pro b/tests/auto/gui/kernel/qaddpostroutine/qaddpostroutine.pro new file mode 100644 index 00000000000..e67720b5d5c --- /dev/null +++ b/tests/auto/gui/kernel/qaddpostroutine/qaddpostroutine.pro @@ -0,0 +1,7 @@ +CONFIG += testcase +TARGET = tst_qaddpostroutine + +QT += testlib + +SOURCES += tst_qaddpostroutine.cpp + diff --git a/tests/auto/gui/kernel/qaddpostroutine/tst_qaddpostroutine.cpp b/tests/auto/gui/kernel/qaddpostroutine/tst_qaddpostroutine.cpp new file mode 100644 index 00000000000..500543d2e16 --- /dev/null +++ b/tests/auto/gui/kernel/qaddpostroutine/tst_qaddpostroutine.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include + +static bool done = false; + +static void cleanup() +{ + done = true; + QEventLoop loop; + QTimer::singleShot(100,&loop, &QEventLoop::quit); + loop.exec(); +} + +struct tst_qAddPostRoutine : public QObject +{ +public: + tst_qAddPostRoutine(); + ~tst_qAddPostRoutine(); +}; + +tst_qAddPostRoutine::tst_qAddPostRoutine() +{ + qAddPostRoutine(cleanup); +} + +tst_qAddPostRoutine::~tst_qAddPostRoutine() +{ + Q_ASSERT(done); +} +int main(int argc, char *argv[]) +{ + tst_qAddPostRoutine tc; + QGuiApplication app(argc, argv); + app.setAttribute(Qt::AA_Use96Dpi, true); + QTEST_SET_MAIN_SOURCE_PATH + return QTest::qExec(&tc, argc, argv); +} diff --git a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp index bff9f7d0e02..e099b4dfc7d 100644 --- a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp +++ b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp @@ -289,10 +289,10 @@ void tst_QClipboard::copyImage() image.fill(QColor(Qt::transparent)); image.setPixel(QPoint(1, 0), QColor(Qt::blue).rgba()); QGuiApplication::clipboard()->setImage(image); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // The Pasteboard needs a moment to breathe (at least on older Macs). QTest::qWait(100); -#endif // Q_OS_OSX +#endif // Q_OS_MACOS // paster will perform hard-coded checks on the copied image. QByteArray errorMessage; QVERIFY2(runHelper(QStringLiteral("paster/paster"), diff --git a/tests/auto/gui/kernel/qhighdpiscaling/CMakeLists.txt b/tests/auto/gui/kernel/qhighdpiscaling/CMakeLists.txt new file mode 100644 index 00000000000..69cff9229fa --- /dev/null +++ b/tests/auto/gui/kernel/qhighdpiscaling/CMakeLists.txt @@ -0,0 +1,14 @@ +# Generated from qhighdpiscaling.pro. + +##################################################################### +## tst_qhighdpiscaling Test: +##################################################################### + +qt_add_test(tst_qhighdpiscaling + SOURCES + tst_qhighdpiscaling.cpp + PUBLIC_LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate +) diff --git a/tests/auto/gui/kernel/qshortcut/CMakeLists.txt b/tests/auto/gui/kernel/qshortcut/CMakeLists.txt index 66ad66335ee..fab20dceed8 100644 --- a/tests/auto/gui/kernel/qshortcut/CMakeLists.txt +++ b/tests/auto/gui/kernel/qshortcut/CMakeLists.txt @@ -1,10 +1,10 @@ # Generated from qshortcut.pro. ##################################################################### -## tst_qshortcut Test: +## tst_qshortcut_kernel Test: ##################################################################### -add_qt_test(tst_qshortcut +add_qt_test(tst_qshortcut_kernel SOURCES tst_qshortcut.cpp PUBLIC_LIBRARIES diff --git a/tests/auto/gui/kernel/qshortcut/qshortcut.pro b/tests/auto/gui/kernel/qshortcut/qshortcut.pro index e7e37663e05..5dc016b099e 100644 --- a/tests/auto/gui/kernel/qshortcut/qshortcut.pro +++ b/tests/auto/gui/kernel/qshortcut/qshortcut.pro @@ -1,4 +1,4 @@ CONFIG += testcase -TARGET = tst_qshortcut +TARGET = tst_qshortcut_kernel QT += testlib SOURCES += tst_qshortcut.cpp diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp index 1ca60655a60..a92c948ade5 100644 --- a/tests/auto/network/access/http2/tst_http2.cpp +++ b/tests/auto/network/access/http2/tst_http2.cpp @@ -512,9 +512,7 @@ void tst_Http2::goaway() request.setAttribute(QNetworkRequest::Http2AllowedAttribute, QVariant(true)); replies[i] = manager->get(request); QCOMPARE(replies[i]->error(), QNetworkReply::NoError); - void (QNetworkReply::*errorSignal)(QNetworkReply::NetworkError) = - &QNetworkReply::errorOccurred; - connect(replies[i], errorSignal, this, &tst_Http2::replyFinishedWithError); + connect(replies[i], &QNetworkReply::errorOccurred, this, &tst_Http2::replyFinishedWithError); // Since we're using self-signed certificates, ignore SSL errors: replies[i]->ignoreSslErrors(); } diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index cc41260d598..4c4113d9d43 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -1090,12 +1090,21 @@ void tst_QUdpSocket::outOfProcessConnectedClientServerTest() QProcess serverProcess; serverProcess.start(QLatin1String("clientserver/clientserver server 1 1"), QIODevice::ReadWrite | QIODevice::Text); - QVERIFY2(serverProcess.waitForStarted(3000), - qPrintable("Failed to start subprocess: " + serverProcess.errorString())); + + const auto serverProcessCleaner = qScopeGuard([&serverProcess] { + serverProcess.kill(); + serverProcess.waitForFinished(); + }); + + if (!serverProcess.waitForStarted(3000)) + QSKIP("Failed to start server as a subprocess"); // Wait until the server has started and reports success. - while (!serverProcess.canReadLine()) - QVERIFY(serverProcess.waitForReadyRead(3000)); + while (!serverProcess.canReadLine()) { + if (!serverProcess.waitForReadyRead(3000)) + QSKIP("No output from the server process, bailing out"); + } + QByteArray serverGreeting = serverProcess.readLine(); QVERIFY(serverGreeting != QByteArray("XXX\n")); int serverPort = serverGreeting.trimmed().toInt(); @@ -1105,12 +1114,21 @@ void tst_QUdpSocket::outOfProcessConnectedClientServerTest() clientProcess.start(QString::fromLatin1("clientserver/clientserver connectedclient %1 %2") .arg(QLatin1String("127.0.0.1")).arg(serverPort), QIODevice::ReadWrite | QIODevice::Text); - QVERIFY2(clientProcess.waitForStarted(3000), - qPrintable("Failed to start subprocess: " + clientProcess.errorString())); - // Wait until the server has started and reports success. - while (!clientProcess.canReadLine()) - QVERIFY(clientProcess.waitForReadyRead(3000)); + const auto clientProcessCleaner = qScopeGuard([&clientProcess] { + clientProcess.kill(); + clientProcess.waitForFinished(); + }); + + if (!clientProcess.waitForStarted(3000)) + QSKIP("Client process did not start"); + + // Wait until the client has started and reports success. + while (!clientProcess.canReadLine()) { + if (!clientProcess.waitForReadyRead(3000)) + QSKIP("No output from the client process, bailing out"); + } + QByteArray clientGreeting = clientProcess.readLine(); QCOMPARE(clientGreeting, QByteArray("ok\n")); @@ -1135,11 +1153,6 @@ void tst_QUdpSocket::outOfProcessConnectedClientServerTest() QCOMPARE(serverData.at(i * 3 + 2).trimmed().mid(8).toInt(), sdata.mid(4).trimmed().toInt() * 2); } - - clientProcess.kill(); - QVERIFY(clientProcess.waitForFinished()); - serverProcess.kill(); - QVERIFY(serverProcess.waitForFinished()); #endif } @@ -1151,12 +1164,21 @@ void tst_QUdpSocket::outOfProcessUnconnectedClientServerTest() QProcess serverProcess; serverProcess.start(QLatin1String("clientserver/clientserver server 1 1"), QIODevice::ReadWrite | QIODevice::Text); - QVERIFY2(serverProcess.waitForStarted(3000), - qPrintable("Failed to start subprocess: " + serverProcess.errorString())); + + const auto serverProcessCleaner = qScopeGuard([&serverProcess] { + serverProcess.kill(); + serverProcess.waitForFinished(); + }); + + if (!serverProcess.waitForStarted(3000)) + QSKIP("Failed to start the server subprocess"); // Wait until the server has started and reports success. - while (!serverProcess.canReadLine()) - QVERIFY(serverProcess.waitForReadyRead(3000)); + while (!serverProcess.canReadLine()) { + if (!serverProcess.waitForReadyRead(3000)) + QSKIP("No output from the server, probably, it is not running"); + } + QByteArray serverGreeting = serverProcess.readLine(); QVERIFY(serverGreeting != QByteArray("XXX\n")); int serverPort = serverGreeting.trimmed().toInt(); @@ -1166,12 +1188,21 @@ void tst_QUdpSocket::outOfProcessUnconnectedClientServerTest() clientProcess.start(QString::fromLatin1("clientserver/clientserver unconnectedclient %1 %2") .arg(QLatin1String("127.0.0.1")).arg(serverPort), QIODevice::ReadWrite | QIODevice::Text); - QVERIFY2(clientProcess.waitForStarted(3000), - qPrintable("Failed to start subprocess: " + clientProcess.errorString())); - // Wait until the server has started and reports success. - while (!clientProcess.canReadLine()) - QVERIFY(clientProcess.waitForReadyRead(3000)); + const auto clientProcessCleaner = qScopeGuard([&clientProcess] { + clientProcess.kill(); + clientProcess.waitForFinished(); + }); + + if (!clientProcess.waitForStarted(3000)) + QSKIP("Failed to start the client's subprocess"); + + // Wait until the client has started and reports success. + while (!clientProcess.canReadLine()) { + if (!clientProcess.waitForReadyRead(3000)) + QSKIP("The client subprocess produced not output, exiting."); + } + QByteArray clientGreeting = clientProcess.readLine(); QCOMPARE(clientGreeting, QByteArray("ok\n")); @@ -1197,11 +1228,6 @@ void tst_QUdpSocket::outOfProcessUnconnectedClientServerTest() QCOMPARE(serverData.at(i * 3 + 2).trimmed().mid(8).toInt(), sdata.mid(4).trimmed().toInt() * 2); } - - clientProcess.kill(); - QVERIFY(clientProcess.waitForFinished()); - serverProcess.kill(); - QVERIFY(serverProcess.waitForFinished()); #endif } diff --git a/tests/auto/network/ssl/qocsp/tst_qocsp.cpp b/tests/auto/network/ssl/qocsp/tst_qocsp.cpp index 27476f451e4..519ae5c720c 100644 --- a/tests/auto/network/ssl/qocsp/tst_qocsp.cpp +++ b/tests/auto/network/ssl/qocsp/tst_qocsp.cpp @@ -409,7 +409,6 @@ private: static QString certDirPath; - void (QSslSocket::*socketErrorSignal)(QAbstractSocket::SocketError) = &QAbstractSocket::errorOccurred; void (QSslSocket::*tlsErrorsSignal)(const QList &) = &QSslSocket::sslErrors; void (QTestEventLoop::*exitLoopSlot)() = &QTestEventLoop::exitLoop; @@ -763,7 +762,7 @@ void tst_QOcsp::setupOcspClient(QSslSocket &clientSocket, const CertificateChain clientSocket.setSslConfiguration(clientConfig); clientSocket.setPeerVerifyName(name); - connect(&clientSocket, socketErrorSignal, &loop, exitLoopSlot); + connect(&clientSocket, &QAbstractSocket::errorOccurred, &loop, exitLoopSlot); connect(&clientSocket, tlsErrorsSignal, &loop, exitLoopSlot); connect(&clientSocket, &QSslSocket::encrypted, &loop, exitLoopSlot); } diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index c793a6a98b1..8b5b4156bb8 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -2535,8 +2535,7 @@ void tst_QSslSocket::closeWhileEmittingSocketError() clientSocket.setSslConfiguration(clientConfig); QSignalSpy socketErrorSpy(&clientSocket, SIGNAL(errorOccurred(QAbstractSocket::SocketError))); - void (QSslSocket::*errorSignal)(QAbstractSocket::SocketError) = &QSslSocket::errorOccurred; - connect(&clientSocket, errorSignal, &handshake, &BrokenPskHandshake::socketError); + connect(&clientSocket, &QSslSocket::errorOccurred, &handshake, &BrokenPskHandshake::socketError); clientSocket.connectToHostEncrypted(QStringLiteral("127.0.0.1"), handshake.serverPort()); // Make sure we have some data buffered so that close will try to flush: diff --git a/tests/auto/other/lancelot/scripts/linedashes.qps b/tests/auto/other/lancelot/scripts/linedashes.qps index ee7d18b1564..78c791e68b1 100644 --- a/tests/auto/other/lancelot/scripts/linedashes.qps +++ b/tests/auto/other/lancelot/scripts/linedashes.qps @@ -91,4 +91,42 @@ translate 100 0 repeat_block draw_lines setPen 0xffff0000 0 dashline squarecap translate 100 0 -repeat_block draw_lines \ No newline at end of file +repeat_block draw_lines + +path_moveTo mypath 10 10 +path_lineTo mypath 87 10 +path_moveTo mypath 10 30 +path_lineTo mypath 87 30 +path_moveTo mypath 10 50 +path_lineTo mypath 87 50 + +resetMatrix +translate 0 150 + +begin_block distinctLines + +setPen black 0 SolidLine SquareCap +pen_setDashPattern [ 3 3 ] +drawPath mypath + +translate 100 0 +setPen black 5 SolidLine SquareCap +pen_setDashPattern [ 3 3 ] +drawPath mypath + +translate 100 0 +setPen black 0 SolidLine RoundCap +pen_setDashPattern [ 3 3 ] +drawPath mypath + +translate 100 0 +setPen black 5 SolidLine RoundCap +pen_setDashPattern [ 3 3 ] +drawPath mypath + +end_block distinctLines + +resetMatrix +translate 0 220 +setRenderHint Antialiasing true +repeat_block distinctLines diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp index 1af3bade0e5..10a3746e362 100644 --- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp +++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp @@ -607,7 +607,7 @@ void tst_QDialog::snapToDefaultButton() + QPoint(100, 100), QSize(200, 200)); const QPoint startingPos = dialogGeometry.bottomRight() + QPoint(100, 100); QCursor::setPos(startingPos); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // On OS X we use CGEventPost to move the cursor, it needs at least // some time before the event handled and the position really set. QTest::qWait(100); diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp index 76314564f1d..543128915ea 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp +++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp @@ -51,7 +51,7 @@ private slots: void about(); void detailsText(); void detailsButtonText(); - void expandDetails_QTBUG_32473(); + void expandDetailsWithoutMoving(); #ifndef Q_OS_MAC void shortcut(); @@ -499,7 +499,7 @@ void tst_QMessageBox::detailsButtonText() } } -void tst_QMessageBox::expandDetails_QTBUG_32473() +void tst_QMessageBox::expandDetailsWithoutMoving() // QTBUG-32473 { tst_ResizingMessageBox box; box.setDetailedText("bla"); @@ -516,18 +516,14 @@ void tst_QMessageBox::expandDetails_QTBUG_32473() auto moreButton = *it; QVERIFY(QTest::qWaitForWindowExposed(&box)); + QTRY_VERIFY2(!box.geometry().topLeft().isNull(), "window manager is expected to decorate and position the dialog"); QRect geom = box.geometry(); box.resized = false; + // now click the "more" button, and verify that the dialog resizes but does not move moreButton->click(); QTRY_VERIFY(box.resized); - // After we receive the expose event for a second widget, it's likely - // that the window manager is also done manipulating the first QMessageBox. - QWidget fleece; - fleece.show(); - QVERIFY(QTest::qWaitForWindowExposed(&fleece)); - if (geom.topLeft() == box.geometry().topLeft()) - QTest::qWait(500); - QCOMPARE(geom.topLeft(), box.geometry().topLeft()); + QVERIFY(box.geometry().height() > geom.height()); + QCOMPARE(box.geometry().topLeft(), geom.topLeft()); } void tst_QMessageBox::incorrectDefaultButton() diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp index 44b728a0422..ba4c1473e81 100644 --- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp @@ -153,6 +153,7 @@ private slots: void currentFollowsIndexWidget(); void checkFocusAfterActivationChanges_data(); void checkFocusAfterActivationChanges(); + void dragSelectAfterNewPress(); private: static QAbstractItemView *viewFromString(const QByteArray &viewType, QWidget *parent = nullptr) { @@ -2553,5 +2554,62 @@ void tst_QAbstractItemView::checkFocusAfterActivationChanges() QVERIFY(view->hasFocus()); } +void tst_QAbstractItemView::dragSelectAfterNewPress() +{ + QStandardItemModel model; + for (int i = 0; i < 10; ++i) { + QStandardItem *item = new QStandardItem(QString::number(i)); + model.setItem(i, 0, item); + } + + QListView view; + view.setFixedSize(160, 650); // Minimum width for windows with frame on Windows 8 + view.setSelectionMode(QListView::ExtendedSelection); + view.setModel(&model); + centerOnScreen(&view); + moveCursorAway(&view); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QModelIndex index0 = model.index(0, 0); + QModelIndex index2 = model.index(2, 0); + + view.setCurrentIndex(index0); + QCOMPARE(view.currentIndex(), index0); + + // Select item 0 using a single click + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, + view.visualRect(index0).center()); + QCOMPARE(view.currentIndex(), index0); + + // Press to select item 2 + QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, + view.visualRect(index2).center()); + QCOMPARE(view.currentIndex(), index2); + + // Verify that the selection worked OK + QModelIndexList selected = view.selectionModel()->selectedIndexes(); + QCOMPARE(selected.count(), 3); + for (int i = 0; i < 2; ++i) + QVERIFY(selected.contains(model.index(i, 0))); + + QModelIndex index5 = model.index(5, 0); + const QPoint releasePos = view.visualRect(index5).center(); + // The mouse move event has to be created manually because the QTest framework does not + // contain a function for mouse moves with buttons pressed + QMouseEvent moveEvent2(QEvent::MouseMove, releasePos, Qt::NoButton, Qt::LeftButton, + Qt::ShiftModifier); + const bool moveEventReceived = qApp->notify(view.viewport(), &moveEvent2); + QVERIFY(moveEventReceived); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::ShiftModifier, releasePos); + QCOMPARE(view.currentIndex(), index5); + + // Verify that the selection worked OK + selected = view.selectionModel()->selectedIndexes(); + QCOMPARE(selected.count(), 6); + for (int i = 0; i < 5; ++i) + QVERIFY(selected.contains(model.index(i, 0))); +} + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 95501136cc7..760dcac6083 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -303,6 +303,12 @@ public: QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override { + if (onlyValidCalls) { + Q_ASSERT(row >= 0); + Q_ASSERT(column >= 0); + Q_ASSERT(row < rows); + Q_ASSERT(column < cols); + } if (row < 0 || column < 0 || (level(parent) > levels) || column >= cols || row >= rows) { return QModelIndex(); } @@ -411,6 +417,7 @@ public: mutable bool fetched = false; bool decorationsEnabled = false; bool statusTipsEnabled = false; + bool onlyValidCalls = false; }; // Testing get/set functions @@ -2459,6 +2466,7 @@ void tst_QTreeView::hiddenItems() void tst_QTreeView::spanningItems() { QtTestModel model(10, 10); + model.onlyValidCalls = true; QTreeView view; view.setModel(&model); view.show(); @@ -2498,6 +2506,8 @@ void tst_QTreeView::spanningItems() } } QCOMPARE(view.sizeHintForColumn(0), w); + + view.repaint(); // to check that this doesn't hit any assert } void tst_QTreeView::selectionOrderTest() diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index 8a5eff3facc..9ab7e4e3150 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -93,7 +93,11 @@ private slots: void quitOnLastWindowClosed(); void closeAllWindows(); void testDeleteLater(); - void testDeleteLaterProcessEvents(); + void testDeleteLaterProcessEvents1(); + void testDeleteLaterProcessEvents2(); + void testDeleteLaterProcessEvents3(); + void testDeleteLaterProcessEvents4(); + void testDeleteLaterProcessEvents5(); #if QT_CONFIG(library) void libraryPaths(); @@ -1225,6 +1229,11 @@ void DeleteLaterWidget::runTest() QCoreApplication::processEvents(); + // At this point, the event queue is empty. As we want a deferred + // deletion to occur before the timer event, we should provoke the + // event dispatcher for the next spin. + QCoreApplication::eventDispatcher()->interrupt(); + QVERIFY(!stillAlive); // verify at the end to make test terminate } @@ -1254,8 +1263,10 @@ void tst_QApplication::testDeleteLater() QObject *stillAlive = wgt->findChild("deleteLater"); QVERIFY(stillAlive); + wgt->show(); QCoreApplication::exec(); + QVERIFY(wgt->isHidden()); delete wgt; } @@ -1333,10 +1344,8 @@ public slots: } }; -void tst_QApplication::testDeleteLaterProcessEvents() +void tst_QApplication::testDeleteLaterProcessEvents1() { - int argc = 0; - // Calling processEvents() with no event dispatcher does nothing. QObject *object = new QObject; QPointer p(object); @@ -1344,75 +1353,85 @@ void tst_QApplication::testDeleteLaterProcessEvents() QApplication::processEvents(); QVERIFY(p); delete object; +} - { - QApplication app(argc, nullptr); - // If you call processEvents() with an event dispatcher present, but - // outside any event loops, deferred deletes are not processed unless - // sendPostedEvents(0, DeferredDelete) is called. - object = new QObject; - p = object; - object->deleteLater(); - QCoreApplication::processEvents(); - QVERIFY(p); - QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); - QVERIFY(!p); +void tst_QApplication::testDeleteLaterProcessEvents2() +{ + int argc = 0; + QApplication app(argc, nullptr); + // If you call processEvents() with an event dispatcher present, but + // outside any event loops, deferred deletes are not processed unless + // sendPostedEvents(0, DeferredDelete) is called. + auto object = new QObject; + QPointer p(object); + object->deleteLater(); + QCoreApplication::processEvents(); + QVERIFY(p); + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); + QVERIFY(!p); - // If you call deleteLater() on an object when there is no parent - // event loop, and then enter an event loop, the object will get - // deleted. - object = new QObject; - p = object; - object->deleteLater(); - QEventLoop loop; - QTimer::singleShot(1000, &loop, &QEventLoop::quit); - loop.exec(); - QVERIFY(!p); - } - { - // When an object is in an event loop, then calls deleteLater() and enters - // an event loop recursively, it should not die until the parent event - // loop continues. - QApplication app(argc, nullptr); - QEventLoop loop; - EventLoopNester *nester = new EventLoopNester; - p = nester; - QTimer::singleShot(3000, &loop, &QEventLoop::quit); - QTimer::singleShot(0, nester, &EventLoopNester::deleteLaterAndEnterLoop); + // If you call deleteLater() on an object when there is no parent + // event loop, and then enter an event loop, the object will get + // deleted. + QEventLoop loop; + object = new QObject; + connect(object, &QObject::destroyed, &loop, &QEventLoop::quit); + p = object; + object->deleteLater(); + QTimer::singleShot(1000, &loop, &QEventLoop::quit); + loop.exec(); + QVERIFY(!p); +} - loop.exec(); - QVERIFY(!p); - } +void tst_QApplication::testDeleteLaterProcessEvents3() +{ + int argc = 0; + // When an object is in an event loop, then calls deleteLater() and enters + // an event loop recursively, it should not die until the parent event + // loop continues. + QApplication app(argc, nullptr); + QEventLoop loop; + EventLoopNester *nester = new EventLoopNester; + QPointer p(nester); + QTimer::singleShot(3000, &loop, &QEventLoop::quit); + QTimer::singleShot(0, nester, &EventLoopNester::deleteLaterAndEnterLoop); - { - // When the event loop that calls deleteLater() is exited - // immediately, the object should die when returning to the - // parent event loop - QApplication app(argc, nullptr); - QEventLoop loop; - EventLoopNester *nester = new EventLoopNester; - p = nester; - QTimer::singleShot(3000, &loop, &QEventLoop::quit); - QTimer::singleShot(0, nester, &EventLoopNester::deleteLaterAndExitLoop); + loop.exec(); + QVERIFY(!p); +} - loop.exec(); - QVERIFY(!p); - } +void tst_QApplication::testDeleteLaterProcessEvents4() +{ + int argc = 0; + // When the event loop that calls deleteLater() is exited + // immediately, the object should die when returning to the + // parent event loop + QApplication app(argc, nullptr); + QEventLoop loop; + EventLoopNester *nester = new EventLoopNester; + QPointer p(nester); + QTimer::singleShot(3000, &loop, &QEventLoop::quit); + QTimer::singleShot(0, nester, &EventLoopNester::deleteLaterAndExitLoop); - { - // when the event loop that calls deleteLater() also calls - // processEvents() immediately afterwards, the object should - // not die until the parent loop continues - QApplication app(argc, nullptr); - QEventLoop loop; - EventLoopNester *nester = new EventLoopNester(); - p = nester; - QTimer::singleShot(3000, &loop, &QEventLoop::quit); - QTimer::singleShot(0, nester, &EventLoopNester::deleteLaterAndProcessEvents); + loop.exec(); + QVERIFY(!p); +} - loop.exec(); - QVERIFY(!p); - } +void tst_QApplication::testDeleteLaterProcessEvents5() +{ + // when the event loop that calls deleteLater() also calls + // processEvents() immediately afterwards, the object should + // not die until the parent loop continues + int argc = 0; + QApplication app(argc, nullptr); + QEventLoop loop; + EventLoopNester *nester = new EventLoopNester(); + QPointer p(nester); + QTimer::singleShot(3000, &loop, &QEventLoop::quit); + QTimer::singleShot(0, nester, &EventLoopNester::deleteLaterAndProcessEvents); + + loop.exec(); + QVERIFY(!p); } /* diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 2483d7b5bb5..5ffbbdd400c 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -75,7 +75,7 @@ #include #include -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) #include "tst_qwidget_mac_helpers.h" // Abstract the ObjC stuff out so not everyone must run an ObjC++ compile. #endif @@ -110,7 +110,7 @@ static HWND winHandleOf(const QWidget *w) # define Q_CHECK_PAINTEVENTS #endif -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS #include bool macHasAccessToWindowsServer() { @@ -216,7 +216,7 @@ private slots: void restoreVersion1Geometry(); void widgetAt(); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS void setMask(); #endif void optimizedResizeMove(); @@ -250,7 +250,7 @@ private slots: void update(); void isOpaque(); -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS void scroll(); void scrollNativeChildren(); #endif @@ -381,7 +381,7 @@ private slots: void taskQTBUG_7532_tabOrderWithFocusProxy(); void movedAndResizedAttributes(); void childAt(); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS void taskQTBUG_11373(); #endif void taskQTBUG_17333_ResizeInfiniteRecursion(); @@ -2301,7 +2301,7 @@ void tst_QWidget::activation() void tst_QWidget::windowState() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974"); #endif @@ -2514,7 +2514,7 @@ void tst_QWidget::showMaximized() void tst_QWidget::showFullScreen() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974"); #endif @@ -2834,14 +2834,14 @@ void tst_QWidget::showMinimizedKeepsFocus() window.showNormal(); QApplication::setActiveWindow(&window); QVERIFY(QTest::qWaitForWindowActive(&window)); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS if (!macHasAccessToWindowsServer()) QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue); #elif defined(Q_OS_WINRT) QEXPECT_FAIL("", "Winrt fails here - QTBUG-68297", Continue); #endif QTRY_COMPARE(window.focusWidget(), firstchild); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS if (!macHasAccessToWindowsServer()) QEXPECT_FAIL("", "When not having WindowServer access, we lose focus.", Continue); #elif defined(Q_OS_WINRT) @@ -2904,7 +2904,7 @@ void tst_QWidget::reparent() // Qt/Embedded does it differently. void tst_QWidget::icon() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974"); #endif @@ -2970,7 +2970,7 @@ void tst_QWidget::hideWhenFocusWidgetIsChild() void tst_QWidget::normalGeometry() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974"); #endif @@ -3230,7 +3230,7 @@ public: void tst_QWidget::lostUpdatesOnHide() { -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS UpdateWidget widget; widget.setAttribute(Qt::WA_DontShowOnScreen); widget.setWindowTitle(QLatin1String(QTest::currentTestFunction())); @@ -3271,7 +3271,7 @@ void tst_QWidget::raise() parentPtr->show(); QVERIFY(QTest::qWaitForWindowExposed(parentPtr.data())); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS if (child1->internalWinId()) { QSKIP("Cocoa has no Z-Order for views, we hack it, but it results in paint events."); } @@ -3412,7 +3412,7 @@ void tst_QWidget::lower() void tst_QWidget::stackUnder() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974: Cocoa has no Z-Order for views, we hack it, but it results in paint events."); #endif @@ -3445,7 +3445,7 @@ void tst_QWidget::stackUnder() for (UpdateWidget *child : qAsConst(allChildren)) { int expectedPaintEvents = child == child4 ? 1 : 0; -#if defined(Q_OS_WIN) || defined(Q_OS_OSX) +#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) if (expectedPaintEvents == 1 && child->numPaintEvents == 2) QEXPECT_FAIL(0, "Mac and Windows issues double repaints for Z-Order change", Continue); #endif @@ -3479,7 +3479,7 @@ void tst_QWidget::stackUnder() for (UpdateWidget *child : qAsConst(allChildren)) { int expectedZOrderChangeEvents = child == child1 ? 1 : 0; if (child == child3) { -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS QEXPECT_FAIL(0, "See QTBUG-493", Continue); #endif QCOMPARE(child->numPaintEvents, 0); @@ -3579,7 +3579,7 @@ void tst_QWidget::testContentsPropagation() void tst_QWidget::saveRestoreGeometry() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974"); #endif @@ -3817,7 +3817,7 @@ void tst_QWidget::restoreVersion1Geometry() void tst_QWidget::widgetAt() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974"); #endif @@ -4020,7 +4020,7 @@ void tst_QWidget::testDeletionInEventHandlers() delete w; } -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS class MaskedPainter : public QWidget { public: @@ -4887,7 +4887,7 @@ void tst_QWidget::update() QCOMPARE(sibling.numPaintEvents, 1); QCOMPARE(sibling.paintedRegion, sibling.visibleRegion()); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS if (child.internalWinId()) // child is native QEXPECT_FAIL(0, "Cocoa compositor paints child and sibling", Continue); #endif @@ -4904,7 +4904,7 @@ void tst_QWidget::update() } } -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS static inline bool isOpaque(QWidget *widget) { if (!widget) @@ -4915,7 +4915,7 @@ static inline bool isOpaque(QWidget *widget) void tst_QWidget::isOpaque() { -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS QWidget w; QVERIFY(::isOpaque(&w)); @@ -4987,7 +4987,7 @@ void tst_QWidget::isOpaque() #endif } -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS /* Test that scrolling of a widget invalidates the correct regions */ @@ -5431,7 +5431,7 @@ void tst_QWidget::windowMoveResize() widget.move(r.topLeft()); widget.resize(r.size()); QApplication::processEvents(); -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) if (r.width() == 0 && r.height() > 0) { widget.move(r.topLeft()); widget.resize(r.size()); @@ -5502,7 +5502,7 @@ void tst_QWidget::windowMoveResize() widget.move(r.topLeft()); widget.resize(r.size()); QApplication::processEvents(); -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) if (r.width() == 0 && r.height() > 0) { widget.move(r.topLeft()); widget.resize(r.size()); @@ -5689,7 +5689,7 @@ void tst_QWidget::moveChild() QTRY_COMPARE(pos, child.pos()); QTRY_COMPARE(parent.r, QRegion(oldGeometry) - child.geometry()); -#if !defined(Q_OS_OSX) +#if !defined(Q_OS_MACOS) // should be scrolled in backingstore QCOMPARE(child.r, QRegion()); #endif @@ -5739,7 +5739,7 @@ void tst_QWidget::showAndMoveChild() void tst_QWidget::subtractOpaqueSiblings() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974: Cocoa only has rect granularity."); #endif @@ -5816,7 +5816,7 @@ public slots: void tst_QWidget::multipleToplevelFocusCheck() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974"); #endif @@ -7584,7 +7584,7 @@ void tst_QWidget::render_systemClip() // rrrrrrrrrr // ... -#ifndef Q_OS_OSX +#ifndef Q_OS_MACOS for (int i = 0; i < image.height(); ++i) { for (int j = 0; j < image.width(); ++j) { if (i < 50 && j < i) @@ -8618,11 +8618,11 @@ void tst_QWidget::sendUpdateRequestImmediately() void tst_QWidget::doubleRepaint() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974"); #endif -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) if (!macHasAccessToWindowsServer()) QSKIP("Not having window server access causes the wrong number of repaints to be issues"); #endif @@ -9330,7 +9330,7 @@ void tst_QWidget::setClearAndResizeMask() child.setMask(childMask); QTRY_COMPARE(child.mask(), childMask); // and ensure that the child widget doesn't get any update. -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QCOMPARE(child.numPaintEvents, 1); @@ -9352,7 +9352,7 @@ void tst_QWidget::setClearAndResizeMask() // and ensure that that the child widget gets an update for the area outside the old mask. QTRY_COMPARE(child.numPaintEvents, 1); outsideOldMask = child.rect(); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (!child.internalWinId()) #endif @@ -9366,7 +9366,7 @@ void tst_QWidget::setClearAndResizeMask() // Mask child widget with a mask that is bigger than the rect child.setMask(QRegion(0, 0, 1000, 1000)); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QTRY_COMPARE(child.numPaintEvents, 1); @@ -9379,7 +9379,7 @@ void tst_QWidget::setClearAndResizeMask() // ...and the same applies when clearing the mask. child.clearMask(); QTest::qWait(100); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QTRY_VERIFY(child.numPaintEvents > 0); @@ -9409,7 +9409,7 @@ void tst_QWidget::setClearAndResizeMask() QTimer::singleShot(100, &resizeChild, SLOT(shrinkMask())); QTest::qWait(200); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask()); @@ -9421,7 +9421,7 @@ void tst_QWidget::setClearAndResizeMask() const QRegion oldMask = resizeChild.mask(); QTimer::singleShot(0, &resizeChild, SLOT(enlargeMask())); QTest::qWait(100); -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS // Mac always issues a full update when calling setMask, and we cannot force it to not do so. if (child.internalWinId()) QTRY_COMPARE(resizeChild.paintedRegion, resizeChild.mask()); @@ -10265,7 +10265,7 @@ void tst_QWidget::childAt() QCOMPARE(parent.childAt(120, 120), grandChild); } -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS void tst_QWidget::taskQTBUG_11373() { @@ -11121,7 +11121,7 @@ public: // when mousing over it. void tst_QWidget::taskQTBUG_27643_enterEvents() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QTBUG-52974: this test can crash!"); #endif // Move the mouse cursor to a safe location so it won't interfere diff --git a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp index 0ae2e6626fd..82527849b09 100644 --- a/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/widgets/styles/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -995,7 +995,7 @@ void tst_QStyleSheetStyle::focusColors() #ifndef QT_NO_CURSOR void tst_QStyleSheetStyle::hoverColors() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("This test is fragile on Mac, most likely due to QTBUG-33959."); #endif if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) diff --git a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp index 8bdd4b4783a..5e71c1888d8 100644 --- a/tests/auto/widgets/util/qscroller/tst_qscroller.cpp +++ b/tests/auto/widgets/util/qscroller/tst_qscroller.cpp @@ -82,8 +82,8 @@ public: currentPos = se->contentPos(); overshoot = se->overshootDistance(); - if (!qFuzzyCompare( overshoot.x() + 1.0, 1.0 ) || - !qFuzzyCompare( overshoot.y() + 1.0, 1.0 )) + if (!qFuzzyCompare(overshoot.x() + 1.0, 1.0) || + !qFuzzyCompare(overshoot.y() + 1.0, 1.0)) receivedOvershoot = true; return true; } @@ -116,8 +116,8 @@ public: ~tst_QScroller() { } private: - void kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd); - void kineticScrollNoTest( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd); + void kineticScroll(tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd); + void kineticScrollNoTest(tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd); private slots: void staticScrollers(); @@ -135,13 +135,13 @@ private: Generates touchBegin, touchUpdate and touchEnd events to trigger scrolling. Tests some in between states but does not wait until scrolling is finished. */ -void tst_QScroller::kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd) +void tst_QScroller::kineticScroll(tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd) { sw->scrollPosition = from; sw->currentPos= from; QScroller *s1 = QScroller::scroller(sw); - QCOMPARE( s1->state(), QScroller::Inactive ); + QCOMPARE(s1->state(), QScroller::Inactive); QScrollerProperties sp1 = QScroller::scroller(sw)->scrollerProperties(); @@ -161,7 +161,7 @@ void tst_QScroller::kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint (QList() << touchPoint)); QApplication::sendEvent(sw, &touchEvent1); - QCOMPARE( s1->state(), QScroller::Pressed ); + QCOMPARE(s1->state(), QScroller::Pressed); // send the touch update far enough to trigger a scroll QTest::qWait(200); // we need to wait a little or else the speed would be infinite. now we have around 500 pixel per second. @@ -175,13 +175,13 @@ void tst_QScroller::kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint (QList() << touchPoint)); QApplication::sendEvent(sw, &touchEvent2); - QCOMPARE( s1->state(), QScroller::Dragging ); - QCOMPARE( sw->receivedPrepare, true ); + QCOMPARE(s1->state(), QScroller::Dragging); + QCOMPARE(sw->receivedPrepare, true); - QTRY_COMPARE( sw->receivedFirst, true ); - QCOMPARE( sw->receivedScroll, true ); - QCOMPARE( sw->receivedOvershoot, false ); + QTRY_COMPARE(sw->receivedFirst, true); + QCOMPARE(sw->receivedScroll, true); + QCOMPARE(sw->receivedOvershoot, false); // note that the scrolling goes in a different direction than the mouse move QPoint calculatedPos = from.toPoint() - touchUpdate - touchStart; @@ -204,13 +204,13 @@ void tst_QScroller::kineticScroll( tst_QScrollerWidget *sw, QPointF from, QPoint Generates touchBegin, touchUpdate and touchEnd events to trigger scrolling. This function does not have any in between tests, it does not expect the scroller to actually scroll. */ -void tst_QScroller::kineticScrollNoTest( tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd) +void tst_QScroller::kineticScrollNoTest(tst_QScrollerWidget *sw, QPointF from, QPoint touchStart, QPoint touchUpdate, QPoint touchEnd) { sw->scrollPosition = from; sw->currentPos = from; QScroller *s1 = QScroller::scroller(sw); - QCOMPARE( s1->state(), QScroller::Inactive ); + QCOMPARE(s1->state(), QScroller::Inactive); QScrollerProperties sp1 = s1->scrollerProperties(); int fps = 60; @@ -348,52 +348,57 @@ void tst_QScroller::scrollerProperties() void tst_QScroller::scrollTo() { - { - tst_QScrollerWidget *sw = new tst_QScrollerWidget(); - sw->scrollArea = QRectF( 0, 0, 1000, 1000 ); - sw->scrollPosition = QPointF( 500, 500 ); + QScopedPointer sw(new tst_QScrollerWidget); + sw->show(); + QApplication::setActiveWindow(sw.data()); + if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data())) + QSKIP("Failed to show and activate window"); - QScroller *s1 = QScroller::scroller(sw); - QCOMPARE( s1->state(), QScroller::Inactive ); + sw->scrollArea = QRectF(0, 0, 1000, 1000); + sw->scrollPosition = QPointF(500, 500); - // a normal scroll - s1->scrollTo(QPointF(100,100), 100); - QTest::qWait(200); + QScroller *s1 = QScroller::scroller(sw.data()); + QCOMPARE(s1->state(), QScroller::Inactive); - QCOMPARE( sw->receivedPrepare, true ); - QCOMPARE( sw->receivedScroll, true ); - QCOMPARE( sw->receivedFirst, true ); - QCOMPARE( sw->receivedLast, true ); - QCOMPARE( sw->receivedOvershoot, false ); - QVERIFY(qFuzzyCompare( sw->currentPos.x(), 100 )); - QVERIFY(qFuzzyCompare( sw->currentPos.y(), 100 )); + // a normal scroll + s1->scrollTo(QPointF(100,100), 100); + QTest::qWait(200); - delete sw; - } + QTRY_COMPARE(sw->receivedPrepare, true); + QCOMPARE(sw->receivedScroll, true); + QCOMPARE(sw->receivedFirst, true); + QCOMPARE(sw->receivedLast, true); + QCOMPARE(sw->receivedOvershoot, false); + QTRY_VERIFY(qFuzzyCompare(sw->currentPos.x(), 100)); + QVERIFY(qFuzzyCompare(sw->currentPos.y(), 100)); } void tst_QScroller::scroll() { #if QT_CONFIG(gestures) && QT_CONFIG(scroller) // -- good case. normal scroll - tst_QScrollerWidget *sw = new tst_QScrollerWidget(); + QScopedPointer sw(new tst_QScrollerWidget()); sw->scrollArea = QRectF(0, 0, 1000, 1000); - QScroller::grabGesture(sw, QScroller::TouchGesture); + QScroller::grabGesture(sw.data(), QScroller::TouchGesture); sw->setGeometry(100, 100, 400, 300); + sw->show(); + QApplication::setActiveWindow(sw.data()); + if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data())) + QSKIP("Failed to show and activate window"); - QScroller *s1 = QScroller::scroller(sw); - kineticScroll(sw, QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200)); + QScroller *s1 = QScroller::scroller(sw.data()); + kineticScroll(sw.data(), QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200)); // now we should be scrolling - QTRY_COMPARE( s1->state(), QScroller::Scrolling ); + QTRY_COMPARE(s1->state(), QScroller::Scrolling); // wait until finished, check that no further first scroll is sent sw->receivedFirst = false; sw->receivedScroll = false; QTRY_VERIFY(s1->state() != QScroller::Scrolling); - QCOMPARE( sw->receivedFirst, false ); - QCOMPARE( sw->receivedScroll, true ); - QCOMPARE( sw->receivedLast, true ); + QCOMPARE(sw->receivedFirst, false); + QCOMPARE(sw->receivedScroll, true); + QCOMPARE(sw->receivedLast, true); QVERIFY(sw->currentPos.x() < 400); QVERIFY(sw->currentPos.y() < 400); @@ -401,26 +406,28 @@ void tst_QScroller::scroll() sw->reset(); sw->scrollArea = QRectF(0, 0, 0, 1000); - kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(100, 0), QPoint(200, 0)); + kineticScrollNoTest(sw.data(), QPointF(0, 500), QPoint(0, 0), QPoint(100, 0), QPoint(200, 0)); QTRY_COMPARE(s1->state(), QScroller::Inactive); QCOMPARE(sw->currentPos.x(), 0.0); QCOMPARE(sw->currentPos.y(), 500.0); - - delete sw; #endif } void tst_QScroller::overshoot() { #if QT_CONFIG(gestures) && QT_CONFIG(scroller) - tst_QScrollerWidget *sw = new tst_QScrollerWidget(); + QScopedPointer sw(new tst_QScrollerWidget); sw->scrollArea = QRectF(0, 0, 1000, 1000); - QScroller::grabGesture(sw, QScroller::TouchGesture); + QScroller::grabGesture(sw.data(), QScroller::TouchGesture); sw->setGeometry(100, 100, 400, 300); + sw->show(); + QApplication::setActiveWindow(sw.data()); + if (!QTest::qWaitForWindowExposed(sw.data()) || !QTest::qWaitForWindowActive(sw.data())) + QSKIP("Failed to show and activate window"); - QScroller *s1 = QScroller::scroller(sw); + QScroller *s1 = QScroller::scroller(sw.data()); QScrollerProperties sp1 = s1->scrollerProperties(); sp1.setScrollMetric(QScrollerProperties::OvershootDragResistanceFactor, 0.5); @@ -431,14 +438,14 @@ void tst_QScroller::overshoot() sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable)); s1->setScrollerProperties(sp1); - kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); + kineticScrollNoTest(sw.data(), QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); QTRY_COMPARE(s1->state(), QScroller::Inactive); //qDebug() << "Overshoot fuzzy: "<currentPos; - QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 )); - QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 )); - QCOMPARE( sw->receivedOvershoot, true ); + QVERIFY(qFuzzyCompare(sw->currentPos.x(), 0)); + QVERIFY(qFuzzyCompare(sw->currentPos.y(), 500)); + QCOMPARE(sw->receivedOvershoot, true); // -- try to scroll with overshoot (when scrollable bad case) sw->reset(); @@ -446,14 +453,14 @@ void tst_QScroller::overshoot() sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootWhenScrollable)); s1->setScrollerProperties(sp1); - kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); + kineticScrollNoTest(sw.data(), QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); QTRY_COMPARE(s1->state(), QScroller::Inactive); //qDebug() << "Overshoot fuzzy: "<currentPos; - QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 )); - QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 )); - QCOMPARE( sw->receivedOvershoot, false ); + QVERIFY(qFuzzyCompare(sw->currentPos.x(), 0)); + QVERIFY(qFuzzyCompare(sw->currentPos.y(), 500)); + QCOMPARE(sw->receivedOvershoot, false); // -- try to scroll with overshoot (always on) sw->reset(); @@ -461,15 +468,15 @@ void tst_QScroller::overshoot() sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn)); s1->setScrollerProperties(sp1); - kineticScrollNoTest(sw, QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); + kineticScrollNoTest(sw.data(), QPointF(0, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); QTRY_COMPARE(s1->state(), QScroller::Inactive); //qDebug() << "Overshoot fuzzy: "<currentPos; - QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 )); - QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 )); - QCOMPARE( sw->receivedOvershoot, true ); + QVERIFY(qFuzzyCompare(sw->currentPos.x(), 0)); + QVERIFY(qFuzzyCompare(sw->currentPos.y(), 500)); + QCOMPARE(sw->receivedOvershoot, true); // -- try to scroll with overshoot (always off) sw->reset(); @@ -477,13 +484,13 @@ void tst_QScroller::overshoot() sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOff)); s1->setScrollerProperties(sp1); - kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); + kineticScrollNoTest(sw.data(), QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); QTRY_COMPARE(s1->state(), QScroller::Inactive); - QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 )); - QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 )); - QCOMPARE( sw->receivedOvershoot, false ); + QVERIFY(qFuzzyCompare(sw->currentPos.x(), 0)); + QVERIFY(qFuzzyCompare(sw->currentPos.y(), 500)); + QCOMPARE(sw->receivedOvershoot, false); // -- try to scroll with overshoot (always on but max overshoot = 0) sp1.setScrollMetric(QScrollerProperties::OvershootDragDistanceFactor, 0.0); @@ -493,39 +500,39 @@ void tst_QScroller::overshoot() sp1.setScrollMetric(QScrollerProperties::HorizontalOvershootPolicy, QVariant::fromValue(QScrollerProperties::OvershootAlwaysOn)); s1->setScrollerProperties(sp1); - kineticScrollNoTest(sw, QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); + kineticScrollNoTest(sw.data(), QPointF(500, 500), QPoint(0, 0), QPoint(400, 0), QPoint(490, 0)); QTRY_COMPARE(s1->state(), QScroller::Inactive); - QVERIFY(qFuzzyCompare( sw->currentPos.x(), 0 )); - QVERIFY(qFuzzyCompare( sw->currentPos.y(), 500 )); - QCOMPARE( sw->receivedOvershoot, false ); - - delete sw; + QVERIFY(qFuzzyCompare(sw->currentPos.x(), 0)); + QVERIFY(qFuzzyCompare(sw->currentPos.y(), 500)); + QCOMPARE(sw->receivedOvershoot, false); #endif } void tst_QScroller::multipleWindows() { #if QT_CONFIG(gestures) && QT_CONFIG(scroller) - QScopedPointer sw1(new tst_QScrollerWidget()); + QScopedPointer sw1(new tst_QScrollerWidget); sw1->scrollArea = QRectF(0, 0, 1000, 1000); QScroller::grabGesture(sw1.data(), QScroller::TouchGesture); sw1->setGeometry(100, 100, 400, 300); + QScroller *s1 = QScroller::scroller(sw1.data()); kineticScroll(sw1.data(), QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200)); // now we should be scrolling - QTRY_COMPARE( s1->state(), QScroller::Scrolling ); + QTRY_COMPARE(s1->state(), QScroller::Scrolling); // That was fun! Do it again! QScopedPointer sw2(new tst_QScrollerWidget()); sw2->scrollArea = QRectF(0, 0, 1000, 1000); QScroller::grabGesture(sw2.data(), QScroller::TouchGesture); sw2->setGeometry(100, 100, 400, 300); + QScroller *s2 = QScroller::scroller(sw2.data()); kineticScroll(sw2.data(), QPointF(500, 500), QPoint(0, 0), QPoint(100, 100), QPoint(200, 200)); // now we should be scrolling - QTRY_COMPARE( s2->state(), QScroller::Scrolling ); + QTRY_COMPARE(s2->state(), QScroller::Scrolling); // wait for both to stop QTRY_VERIFY(s1->state() != QScroller::Scrolling); diff --git a/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp b/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp index 999cf4a9414..e4f927750ed 100644 --- a/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp +++ b/tests/auto/widgets/widgets/qbuttongroup/tst_qbuttongroup.cpp @@ -83,6 +83,7 @@ Q_OBJECT private slots: void arrowKeyNavigation(); + void keyNavigationPushButtons(); void exclusive(); void exclusiveWithActions(); void testSignals(); @@ -185,6 +186,73 @@ void tst_QButtonGroup::arrowKeyNavigation() QVERIFY(bt3.hasFocus()); } +/* + Test that tab and arrow key navigation through buttons + in an invisible button group works as expected. Tabbing + into the group should give focus to the checked button, + and arrow navigation should change the checked button and + move focus. +*/ +void tst_QButtonGroup::keyNavigationPushButtons() +{ + if (!qt_tab_all_widgets()) + QSKIP("This test requires full keyboard control to be enabled."); + + QDialog dlg(nullptr); + QLineEdit *le1 = new QLineEdit; + le1->setObjectName("le1"); + QPushButton *pb1 = new QPushButton("Exclusive 1"); + pb1->setObjectName("pb1"); + pb1->setCheckable(true); + pb1->setChecked(true); + QPushButton *pb2 = new QPushButton("Exclusive 2"); + pb2->setObjectName("pb2"); + pb2->setCheckable(true); + QPushButton *pb3 = new QPushButton("Exclusive 3"); + pb3->setObjectName("pb3"); + pb3->setCheckable(true); + QLineEdit *le2 = new QLineEdit; + le2->setObjectName("le2"); + + QVBoxLayout* layout = new QVBoxLayout(&dlg); + layout->addWidget(le1); + layout->addWidget(pb1); + layout->addWidget(pb2); + layout->addWidget(pb3); + layout->addWidget(le2); + + QButtonGroup *buttonGroup = new QButtonGroup; + buttonGroup->addButton(pb1); + buttonGroup->addButton(pb2); + buttonGroup->addButton(pb3); + + dlg.show(); + qApp->setActiveWindow(&dlg); + if (!QTest::qWaitForWindowActive(&dlg)) + QSKIP("Window activation failed, skipping test"); + + QVERIFY2(le1->hasFocus(), qPrintable(qApp->focusWidget()->objectName())); + QTest::keyClick(qApp->focusWidget(), Qt::Key_Tab); + QVERIFY2(pb1->hasFocus(), qPrintable(qApp->focusWidget()->objectName())); + QVERIFY2(pb1->isChecked(), qPrintable(buttonGroup->checkedButton()->objectName())); + QTest::keyClick(qApp->focusWidget(), Qt::Key_Down); + QVERIFY2(pb2->hasFocus(), qPrintable(qApp->focusWidget()->objectName())); + QVERIFY2(pb2->isChecked(), qPrintable(buttonGroup->checkedButton()->objectName())); + QTest::keyClick(qApp->focusWidget(), Qt::Key_Down); + QVERIFY2(pb3->hasFocus(), qPrintable(qApp->focusWidget()->objectName())); + QVERIFY2(pb3->isChecked(), qPrintable(buttonGroup->checkedButton()->objectName())); + QTest::keyClick(qApp->focusWidget(), Qt::Key_Up); + QVERIFY2(pb2->hasFocus(), qPrintable(qApp->focusWidget()->objectName())); + QVERIFY2(pb2->isChecked(), qPrintable(buttonGroup->checkedButton()->objectName())); + QTest::keyClick(qApp->focusWidget(), Qt::Key_Tab); + QVERIFY2(le2->hasFocus(), qPrintable(qApp->focusWidget()->objectName())); + QTest::keyClick(qApp->focusWidget(), Qt::Key_Backtab); + QVERIFY2(pb2->hasFocus(), qPrintable(qApp->focusWidget()->objectName())); + QVERIFY2(pb2->isChecked(), qPrintable(buttonGroup->checkedButton()->objectName())); + QTest::keyClick(qApp->focusWidget(), Qt::Key_Backtab); + QVERIFY2(le1->hasFocus(), qPrintable(qApp->focusWidget()->objectName())); +} + void tst_QButtonGroup::exclusiveWithActions() { QDialog dlg(0); diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index bd3c6d1f039..10430e1796c 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -1208,7 +1208,7 @@ void tst_QComboBox::currentIndex() QVERIFY(testWidget->currentText().isEmpty()); // spy on currentIndexChanged - QSignalSpy indexChangedSpy(testWidget, SIGNAL(currentIndexChanged(int, QString))); + QSignalSpy indexChangedInt(testWidget, SIGNAL(currentIndexChanged(int))); // stuff items into it foreach(QString text, initialItems) { @@ -1232,12 +1232,12 @@ void tst_QComboBox::currentIndex() QCOMPARE(testWidget->currentText(), expectedCurrentText); // check that signal count is correct - QCOMPARE(indexChangedSpy.count(), expectedSignalCount); + QCOMPARE(indexChangedInt.count(), expectedSignalCount); // compare with last sent signal values - if (indexChangedSpy.count()) - QCOMPARE(indexChangedSpy.at(indexChangedSpy.count() - 1).at(0).toInt(), - testWidget->currentIndex()); + if (indexChangedInt.count()) + QCOMPARE(indexChangedInt.at(indexChangedInt.count() - 1).at(0).toInt(), + testWidget->currentIndex()); if (edit) { testWidget->setCurrentIndex(-1); @@ -2336,8 +2336,7 @@ public: { QStringList list; list << "one" << "two"; - connect(this, SIGNAL(currentIndexChanged(int, QString)), - this, SLOT(onCurrentIndexChanged(int))); + connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(onCurrentIndexChanged(int))); addItems(list); } public slots: diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp index 9659d89833a..08c80c96ab3 100644 --- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp @@ -195,6 +195,8 @@ private slots: void specialValueText(); void setRange_data(); void setRange(); + void editingRanged_data(); + void editingRanged(); void selectAndScrollWithKeys(); void backspaceKey(); @@ -1312,6 +1314,120 @@ void tst_QDateTimeEdit::setRange() } } +/* + Test that a user can input a date into a ranged QDateTimeEdit or QDateEdit + where a part of date is larger than the respective part of the maximum, or + smaller than the respective part of the minimum of the range. + + This test is expected to fail unless keyboard tracking of the edit is set + to off. Otherwise the changed-signal would be emitted with values outside + of the allowed range as the user types. +*/ +void tst_QDateTimeEdit::editingRanged_data() +{ + QTest::addColumn("minDate"); + QTest::addColumn("minTime"); + QTest::addColumn("maxDate"); + QTest::addColumn("maxTime"); + QTest::addColumn("userInput"); + QTest::addColumn("expected"); + + QTest::addRow("trivial") + << QDate(2010, 1, 1) << QTime(9, 0) + << QDate(2011, 12, 31) << QTime(16, 0) + << QString::fromLatin1("311220101600") + << QDateTime(QDate(2010, 12, 31), QTime(16, 0)); + + QTest::addRow("data0") + << QDate(2010, 12, 30) << QTime(16, 0) + << QDate(2011, 1, 2) << QTime(9, 0) + << QString::fromLatin1("311220102359") + << QDateTime(QDate(2010, 12, 31), QTime(23, 59)); + + QTest::addRow("data1") + << QDate(2010, 12, 30) << QTime(16, 0) + << QDate(2011, 1, 2) << QTime(9, 0) + << QString::fromLatin1("010120111823") + << QDateTime(QDate(2011, 1, 1), QTime(18, 23)); + + QTest::addRow("Out of range") + << QDate(2010, 12, 30) << QTime(16, 0) + << QDate(2011, 1, 2) << QTime(9, 0) + << QString::fromLatin1("090920111823") + << QDateTime(QDate(2011, 1, 2), QTime(9, 0)); + + QTest::addRow("only date") + << QDate(2010, 12, 30) << QTime() + << QDate(2011, 1, 2) << QTime() + << QString::fromLatin1("01012011") + << QDateTime(QDate(2011, 1, 1), QTime()); +} + +void tst_QDateTimeEdit::editingRanged() +{ + QFETCH(QDate, minDate); + QFETCH(QTime, minTime); + QFETCH(QDate, maxDate); + QFETCH(QTime, maxTime); + QFETCH(QString, userInput); + QFETCH(QDateTime, expected); + + QDateTimeEdit *edit; + if (minTime.isValid()) { + edit = new QDateTimeEdit; + edit->setDisplayFormat("dd.MM.yyyy hh:mm"); + edit->setDateTimeRange(QDateTime(minDate, minTime), QDateTime(maxDate, maxTime)); + } else { + edit = new QDateEdit; + edit->setDisplayFormat("dd.MM.yyyy"); + edit->setDateRange(minDate, maxDate); + } + + int callCount = 0; + connect(edit, &QDateTimeEdit::dateTimeChanged, [&](const QDateTime &dateTime) { + ++callCount; + if (minTime.isValid()) { + QVERIFY(dateTime >= QDateTime(minDate, minTime)); + QVERIFY(dateTime <= QDateTime(maxDate, maxTime)); + } else { + QVERIFY(dateTime.date() >= minDate); + QVERIFY(dateTime.date() <= maxDate); + } + }); + + edit->show(); + QApplication::setActiveWindow(edit); + if (!QTest::qWaitForWindowActive(edit)) + QSKIP("Failed to make window active, aborting"); + edit->setFocus(); + + // with keyboard tracking, never get a signal with an out-of-range value + edit->setKeyboardTracking(true); + QTest::keyClicks(edit, userInput); + QTest::keyClick(edit, Qt::Key_Return); + QVERIFY(callCount > 0); + + // QDateTimeEdit blocks these dates from being entered - see QTBUG-65 + QEXPECT_FAIL("data0", "Can't enter this date", Continue); + QEXPECT_FAIL("data1", "Can't enter this date", Continue); + QEXPECT_FAIL("Out of range", "Can't enter this date", Continue); + QEXPECT_FAIL("only date", "Can't enter this date", Continue); + QCOMPARE(edit->dateTime(), expected); + + // reset + edit->clearFocus(); + edit->setFocus(); + callCount = 0; + + edit->setKeyboardTracking(false); + QTest::keyClicks(edit, userInput); + QTest::keyClick(edit, Qt::Key_Return); + QCOMPARE(edit->dateTime(), expected); + QCOMPARE(callCount, 1); + + delete edit; +} + void tst_QDateTimeEdit::wrappingTime_data() { QTest::addColumn("startWithMin"); diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index a89b3231ad3..c07961f8672 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -1267,7 +1267,7 @@ void tst_QMenu::QTBUG47515_widgetActionEnterLeave() if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) QSKIP("Window activation is not supported"); if (QGuiApplication::platformName() == QLatin1String("cocoa")) - QSKIP("See QTBUG-63031"); + QSKIP("This test is meaningless on macOS, for additional info see QTBUG-63031"); const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); QRect geometry(QPoint(), availableGeometry.size() / 3); diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp index 8cbe821a680..90e89ff1d5b 100644 --- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp @@ -1537,7 +1537,7 @@ void tst_QMenuBar::cornerWidgets() QFETCH(Qt::Corner, corner); -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) QSKIP("Test interferes with native menu bars on this platform"); #endif diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp index 73423d958b6..cb4fc201f69 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp +++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp @@ -579,7 +579,7 @@ bool verifyColor(const QWidget *widget, const QRect &clipArea, const QColor &col void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible() { -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QSKIP("QScreen::grabWindow() doesn't work properly on OSX HighDPI screen: QTBUG-46803"); return; #endif diff --git a/tests/benchmarks/corelib/codecs/qtextcodec/qtextcodec.pro b/tests/benchmarks/corelib/codecs/qtextcodec/qtextcodec.pro index 5ee577c2566..7d29c6bfdd5 100644 --- a/tests/benchmarks/corelib/codecs/qtextcodec/qtextcodec.pro +++ b/tests/benchmarks/corelib/codecs/qtextcodec/qtextcodec.pro @@ -1,6 +1,7 @@ -TARGET = tst_bench_qtextcodec +CONFIG += benchmark QT = core testlib + +TARGET = tst_bench_qtextcodec SOURCES += main.cpp TESTDATA = utf-8.txt - diff --git a/tests/benchmarks/corelib/io/qdir/10000/10000.pro b/tests/benchmarks/corelib/io/qdir/10000/10000.pro index 2e83dad071d..52325f314fb 100644 --- a/tests/benchmarks/corelib/io/qdir/10000/10000.pro +++ b/tests/benchmarks/corelib/io/qdir/10000/10000.pro @@ -1,6 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qdir_10000 - -SOURCES += bench_qdir_10000.cpp - +CONFIG += benchmark QT = core testlib + +TARGET = tst_bench_qdir_10000 +SOURCES += bench_qdir_10000.cpp diff --git a/tests/benchmarks/corelib/io/qdir/tree/tree.pro b/tests/benchmarks/corelib/io/qdir/tree/tree.pro index 2998a13b575..90ddd233451 100644 --- a/tests/benchmarks/corelib/io/qdir/tree/tree.pro +++ b/tests/benchmarks/corelib/io/qdir/tree/tree.pro @@ -1,7 +1,7 @@ TEMPLATE = app -TARGET = bench_qdir_tree +CONFIG += benchmark +QT = core testlib +TARGET = bench_qdir_tree SOURCES += bench_qdir_tree.cpp RESOURCES += bench_qdir_tree.qrc - -QT = core testlib diff --git a/tests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro b/tests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro index 609a578321c..0921b8424ef 100644 --- a/tests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro +++ b/tests/benchmarks/corelib/io/qdiriterator/qdiriterator.pro @@ -1,8 +1,6 @@ -TARGET = tst_bench_qdiriterator - +CONFIG += benchmark QT = core testlib -CONFIG += release # Enable c++17 support for std::filesystem qtConfig(cxx17_filesystem) { CONFIG += c++17 @@ -10,5 +8,6 @@ qtConfig(cxx17_filesystem) { QMAKE_LFLAGS += -lstdc++fs } +TARGET = tst_bench_qdiriterator SOURCES += main.cpp qfilesystemiterator.cpp HEADERS += qfilesystemiterator.h diff --git a/tests/benchmarks/corelib/io/qfile/qfile.pro b/tests/benchmarks/corelib/io/qfile/qfile.pro index 5f7b9af73fc..a882c4ea611 100644 --- a/tests/benchmarks/corelib/io/qfile/qfile.pro +++ b/tests/benchmarks/corelib/io/qfile/qfile.pro @@ -1,6 +1,7 @@ TEMPLATE = app -TARGET = tst_bench_qfile +CONFIG += benchmark QT = core core-private testlib win32: DEFINES+= _CRT_SECURE_NO_WARNINGS +TARGET = tst_bench_qfile SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro b/tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro index 42e8708b021..9c97bfc84af 100644 --- a/tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro +++ b/tests/benchmarks/corelib/io/qfileinfo/qfileinfo.pro @@ -1,9 +1,7 @@ TEMPLATE = app -TARGET = tst_bench_qfileinfo - +CONFIG += benchmark QT -= gui QT += core-private testlib -CONFIG += release - +TARGET = tst_bench_qfileinfo SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/io/qiodevice/qiodevice.pro b/tests/benchmarks/corelib/io/qiodevice/qiodevice.pro index 7937436e138..febe6e87f97 100644 --- a/tests/benchmarks/corelib/io/qiodevice/qiodevice.pro +++ b/tests/benchmarks/corelib/io/qiodevice/qiodevice.pro @@ -1,8 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qiodevice - +CONFIG += benchmark QT = core testlib -CONFIG += release - +TARGET = tst_bench_qiodevice SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/io/qprocess/test/test.pro b/tests/benchmarks/corelib/io/qprocess/test/test.pro index b665525b178..e7e8e01aef4 100644 --- a/tests/benchmarks/corelib/io/qprocess/test/test.pro +++ b/tests/benchmarks/corelib/io/qprocess/test/test.pro @@ -1,4 +1,5 @@ +CONFIG += benchmark +QT = core core-private testlib + TARGET = ../tst_bench_qprocess SOURCES += ../tst_bench_qprocess.cpp - -QT = core core-private testlib diff --git a/tests/benchmarks/corelib/io/qprocess/testProcessLoopback/testProcessLoopback.pro b/tests/benchmarks/corelib/io/qprocess/testProcessLoopback/testProcessLoopback.pro index a0230e1cb8e..1f56ad6ee69 100644 --- a/tests/benchmarks/corelib/io/qprocess/testProcessLoopback/testProcessLoopback.pro +++ b/tests/benchmarks/corelib/io/qprocess/testProcessLoopback/testProcessLoopback.pro @@ -1,5 +1,7 @@ -SOURCES = main.cpp +CONFIG += benchmark CONFIG -= qt CONFIG += cmdline winrt: QMAKE_LFLAGS += /ENTRY:mainCRTStartup + +SOURCES = main.cpp DESTDIR = ./ diff --git a/tests/benchmarks/corelib/io/qtemporaryfile/qtemporaryfile.pro b/tests/benchmarks/corelib/io/qtemporaryfile/qtemporaryfile.pro index 758930c139c..b6064e1f910 100644 --- a/tests/benchmarks/corelib/io/qtemporaryfile/qtemporaryfile.pro +++ b/tests/benchmarks/corelib/io/qtemporaryfile/qtemporaryfile.pro @@ -1,8 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qtemporaryfile - +CONFIG += benchmark QT = core testlib -CONFIG += release - +TARGET = tst_bench_qtemporaryfile SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/io/qtextstream/qtextstream.pro b/tests/benchmarks/corelib/io/qtextstream/qtextstream.pro index e8170319f27..fb45d05bc90 100644 --- a/tests/benchmarks/corelib/io/qtextstream/qtextstream.pro +++ b/tests/benchmarks/corelib/io/qtextstream/qtextstream.pro @@ -1,8 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qtextstream - +CONFIG += benchmark QT = core testlib -CONFIG += release - +TARGET = tst_bench_qtextstream SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/io/qurl/qurl.pro b/tests/benchmarks/corelib/io/qurl/qurl.pro index 52f7bdc8b63..0e10e32a222 100644 --- a/tests/benchmarks/corelib/io/qurl/qurl.pro +++ b/tests/benchmarks/corelib/io/qurl/qurl.pro @@ -1,6 +1,7 @@ TEMPLATE = app -TARGET = tst_qurl +CONFIG += benchmark QT = core testlib win32: DEFINES+= _CRT_SECURE_NO_WARNINGS +TARGET = tst_qurl SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/json/json.pro b/tests/benchmarks/corelib/json/json.pro index 004f4b123e3..8f9e515cb94 100644 --- a/tests/benchmarks/corelib/json/json.pro +++ b/tests/benchmarks/corelib/json/json.pro @@ -1,7 +1,8 @@ -TARGET = tst_bench_qtbinaryjson QT = core testlib +CONFIG += benchmark CONFIG -= app_bundle +TARGET = tst_bench_qtbinaryjson SOURCES += tst_bench_qtbinaryjson.cpp TESTDATA = numbers.json test.json diff --git a/tests/benchmarks/corelib/kernel/events/events.pro b/tests/benchmarks/corelib/kernel/events/events.pro index 798a880e5b8..1381bb001ee 100644 --- a/tests/benchmarks/corelib/kernel/events/events.pro +++ b/tests/benchmarks/corelib/kernel/events/events.pro @@ -1,6 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_events - +CONFIG += benchmark QT = core testlib +TARGET = tst_bench_events SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/kernel/qcoreapplication/qcoreapplication.pro b/tests/benchmarks/corelib/kernel/qcoreapplication/qcoreapplication.pro index 8bf8487a5fe..5572f06924b 100644 --- a/tests/benchmarks/corelib/kernel/qcoreapplication/qcoreapplication.pro +++ b/tests/benchmarks/corelib/kernel/qcoreapplication/qcoreapplication.pro @@ -1,6 +1,6 @@ +TEMPLATE = app +CONFIG += benchmark QT = core testlib -TEMPLATE = app TARGET = tst_bench_qcoreapplication - SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/kernel/qmetaobject/qmetaobject.pro b/tests/benchmarks/corelib/kernel/qmetaobject/qmetaobject.pro index 47d2acb9b1e..0d595ed4dae 100644 --- a/tests/benchmarks/corelib/kernel/qmetaobject/qmetaobject.pro +++ b/tests/benchmarks/corelib/kernel/qmetaobject/qmetaobject.pro @@ -1,5 +1,6 @@ TEMPLATE = app +CONFIG += benchmark QT += widgets testlib -TARGET = tst_bench_qmetaobject +TARGET = tst_bench_qmetaobject SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/kernel/qmetatype/qmetatype.pro b/tests/benchmarks/corelib/kernel/qmetatype/qmetatype.pro index 83d0708b60f..ffd36ad2026 100644 --- a/tests/benchmarks/corelib/kernel/qmetatype/qmetatype.pro +++ b/tests/benchmarks/corelib/kernel/qmetatype/qmetatype.pro @@ -1,6 +1,6 @@ -QT = core testlib TEMPLATE = app +CONFIG += benchmark +QT = core testlib + TARGET = tst_bench_qmetatype - SOURCES += tst_qmetatype.cpp - diff --git a/tests/benchmarks/corelib/kernel/qobject/qobject.pro b/tests/benchmarks/corelib/kernel/qobject/qobject.pro index e611eff0a2d..eb1d8a2daa7 100644 --- a/tests/benchmarks/corelib/kernel/qobject/qobject.pro +++ b/tests/benchmarks/corelib/kernel/qobject/qobject.pro @@ -1,7 +1,7 @@ +TEMPLATE = app +CONFIG += benchmark QT += widgets testlib -TEMPLATE = app TARGET = tst_bench_qobject - HEADERS += object.h SOURCES += main.cpp object.cpp diff --git a/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/qtimer_vs_qmetaobject.pro b/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/qtimer_vs_qmetaobject.pro index e127ba19343..3d4e48e76c6 100644 --- a/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/qtimer_vs_qmetaobject.pro +++ b/tests/benchmarks/corelib/kernel/qtimer_vs_qmetaobject/qtimer_vs_qmetaobject.pro @@ -1,10 +1,7 @@ TEMPLATE = app -TARGET = qtimer_vs_qmetaobject -INCLUDEPATH += . - -CONFIG += release -#CONFIG += debug - - -SOURCES += tst_qtimer_vs_qmetaobject.cpp +CONFIG += benchmark QT = core testlib + +INCLUDEPATH += . +TARGET = qtimer_vs_qmetaobject +SOURCES += tst_qtimer_vs_qmetaobject.cpp diff --git a/tests/benchmarks/corelib/kernel/qvariant/qvariant.pro b/tests/benchmarks/corelib/kernel/qvariant/qvariant.pro index 8a8e9f25d3f..2616ae78eae 100644 --- a/tests/benchmarks/corelib/kernel/qvariant/qvariant.pro +++ b/tests/benchmarks/corelib/kernel/qvariant/qvariant.pro @@ -1,9 +1,6 @@ -TARGET = tst_bench_qvariant +CONFIG += benchmark QT += testlib !qtHaveModule(gui): QT -= gui -CONFIG += release -#CONFIG += debug - - +TARGET = tst_bench_qvariant SOURCES += tst_qvariant.cpp diff --git a/tests/benchmarks/corelib/mimetypes/qmimedatabase/qmimedatabase.pro b/tests/benchmarks/corelib/mimetypes/qmimedatabase/qmimedatabase.pro index fe55b98e54d..3d218554d36 100644 --- a/tests/benchmarks/corelib/mimetypes/qmimedatabase/qmimedatabase.pro +++ b/tests/benchmarks/corelib/mimetypes/qmimedatabase/qmimedatabase.pro @@ -1,5 +1,5 @@ +CONFIG += benchmark QT = core testlib TARGET = tst_bench_qmimedatabase SOURCES = main.cpp - diff --git a/tests/benchmarks/corelib/plugin/quuid/quuid.pro b/tests/benchmarks/corelib/plugin/quuid/quuid.pro index 8f88bb85b41..5179c0cc406 100644 --- a/tests/benchmarks/corelib/plugin/quuid/quuid.pro +++ b/tests/benchmarks/corelib/plugin/quuid/quuid.pro @@ -1,5 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_quuid - -SOURCES += tst_quuid.cpp +CONFIG += benchmark QT = core testlib + +TARGET = tst_bench_quuid +SOURCES += tst_quuid.cpp diff --git a/tests/benchmarks/corelib/text/qbytearray/qbytearray.pro b/tests/benchmarks/corelib/text/qbytearray/qbytearray.pro index cf28b0247f1..25af9512d49 100644 --- a/tests/benchmarks/corelib/text/qbytearray/qbytearray.pro +++ b/tests/benchmarks/corelib/text/qbytearray/qbytearray.pro @@ -1,7 +1,7 @@ TEMPLATE = app -TARGET = tst_bench_qbytearray - +CONFIG += benchmark QT = core testlib -TESTDATA += main.cpp +TARGET = tst_bench_qbytearray SOURCES += main.cpp +TESTDATA += main.cpp diff --git a/tests/benchmarks/corelib/text/qchar/qchar.pro b/tests/benchmarks/corelib/text/qchar/qchar.pro index 80a9861f486..902acbb8316 100644 --- a/tests/benchmarks/corelib/text/qchar/qchar.pro +++ b/tests/benchmarks/corelib/text/qchar/qchar.pro @@ -1,3 +1,5 @@ -TARGET = tst_bench_qchar +CONFIG += benchmark QT = core testlib + +TARGET = tst_bench_qchar SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/text/qlocale/qlocale.pro b/tests/benchmarks/corelib/text/qlocale/qlocale.pro index e56bbe0341e..a39a20a6776 100644 --- a/tests/benchmarks/corelib/text/qlocale/qlocale.pro +++ b/tests/benchmarks/corelib/text/qlocale/qlocale.pro @@ -1,4 +1,5 @@ -TARGET = tst_bench_qlocale +CONFIG += benchmark QT = core testlib +TARGET = tst_bench_qlocale SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/text/qregexp/qregexp.pro b/tests/benchmarks/corelib/text/qregexp/qregexp.pro index f64ae781a2d..c04c13060be 100644 --- a/tests/benchmarks/corelib/text/qregexp/qregexp.pro +++ b/tests/benchmarks/corelib/text/qregexp/qregexp.pro @@ -1,8 +1,9 @@ TEMPLATE = app -TARGET = tst_bench_qregexp +CONFIG += benchmark +CONFIG += exceptions QT = core testlib -CONFIG += release exceptions +TARGET = tst_bench_qregexp SOURCES += main.cpp RESOURCES += qregexp.qrc @@ -17,4 +18,3 @@ qtHaveModule(script):!pcre { LIBS += -lboost_regex } } - diff --git a/tests/benchmarks/corelib/text/qstring/qstring.pro b/tests/benchmarks/corelib/text/qstring/qstring.pro index 9f5e34b9153..e25431b9838 100644 --- a/tests/benchmarks/corelib/text/qstring/qstring.pro +++ b/tests/benchmarks/corelib/text/qstring/qstring.pro @@ -1,5 +1,6 @@ -TARGET = tst_bench_qstring +CONFIG += benchmark QT -= gui QT += core testlib -SOURCES += main.cpp +TARGET = tst_bench_qstring +SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/text/qstringbuilder/qstringbuilder.pro b/tests/benchmarks/corelib/text/qstringbuilder/qstringbuilder.pro index fa4cbe3c13b..91421b3b2ca 100644 --- a/tests/benchmarks/corelib/text/qstringbuilder/qstringbuilder.pro +++ b/tests/benchmarks/corelib/text/qstringbuilder/qstringbuilder.pro @@ -1,11 +1,9 @@ TEMPLATE = app -TARGET = tst_bench_qstringbuilder +CONFIG += benchmark +QT = core testlib QMAKE_CXXFLAGS += -g QMAKE_CFLAGS += -g -QT = core testlib - -CONFIG += release - -SOURCES += main.cpp +TARGET = tst_bench_qstringbuilder +SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/text/qstringlist/qstringlist.pro b/tests/benchmarks/corelib/text/qstringlist/qstringlist.pro index 2e7ae058f7c..a27bf0a6ab2 100644 --- a/tests/benchmarks/corelib/text/qstringlist/qstringlist.pro +++ b/tests/benchmarks/corelib/text/qstringlist/qstringlist.pro @@ -1,6 +1,5 @@ -TARGET = tst_bench_qstringlist -CONFIG -= debug -CONFIG += release CONFIG += benchmark QT = core testlib + +TARGET = tst_bench_qstringlist SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/thread/qmutex/qmutex.pro b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro index ec87f60919f..a0b2ddeaa92 100644 --- a/tests/benchmarks/corelib/thread/qmutex/qmutex.pro +++ b/tests/benchmarks/corelib/thread/qmutex/qmutex.pro @@ -1,5 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qmutex +CONFIG += benchmark QT = core testlib -SOURCES += tst_qmutex.cpp +TARGET = tst_bench_qmutex +SOURCES += tst_qmutex.cpp diff --git a/tests/benchmarks/corelib/thread/qreadwritelock/qreadwritelock.pro b/tests/benchmarks/corelib/thread/qreadwritelock/qreadwritelock.pro index a1827d0276e..7c36067cb7d 100644 --- a/tests/benchmarks/corelib/thread/qreadwritelock/qreadwritelock.pro +++ b/tests/benchmarks/corelib/thread/qreadwritelock/qreadwritelock.pro @@ -1,7 +1,8 @@ TEMPLATE = app -TARGET = tst_bench_qreadwritelock -QT = core-private testlib -SOURCES += tst_qreadwritelock.cpp +CONFIG += benchmark CONFIG += c++14 # for std::shared_timed_mutex CONFIG += c++1z # for std::shared_mutex +QT = core-private testlib +TARGET = tst_bench_qreadwritelock +SOURCES += tst_qreadwritelock.cpp diff --git a/tests/benchmarks/corelib/thread/qthreadpool/qthreadpool.pro b/tests/benchmarks/corelib/thread/qthreadpool/qthreadpool.pro index 47e16e8b4dc..303b3cef69d 100644 --- a/tests/benchmarks/corelib/thread/qthreadpool/qthreadpool.pro +++ b/tests/benchmarks/corelib/thread/qthreadpool/qthreadpool.pro @@ -1,5 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qthreadpool - -SOURCES += tst_qthreadpool.cpp +CONFIG += benchmark QT = core testlib + +TARGET = tst_bench_qthreadpool +SOURCES += tst_qthreadpool.cpp diff --git a/tests/benchmarks/corelib/thread/qthreadstorage/qthreadstorage.pro b/tests/benchmarks/corelib/thread/qthreadstorage/qthreadstorage.pro index 95afc951bc5..3f62c4eb3cd 100644 --- a/tests/benchmarks/corelib/thread/qthreadstorage/qthreadstorage.pro +++ b/tests/benchmarks/corelib/thread/qthreadstorage/qthreadstorage.pro @@ -1,5 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qthreadstorage - -SOURCES += tst_qthreadstorage.cpp +CONFIG += benchmark QT = core testlib + +TARGET = tst_bench_qthreadstorage +SOURCES += tst_qthreadstorage.cpp diff --git a/tests/benchmarks/corelib/thread/qwaitcondition/qwaitcondition.pro b/tests/benchmarks/corelib/thread/qwaitcondition/qwaitcondition.pro index 43c7921a938..cc801bdc135 100644 --- a/tests/benchmarks/corelib/thread/qwaitcondition/qwaitcondition.pro +++ b/tests/benchmarks/corelib/thread/qwaitcondition/qwaitcondition.pro @@ -1,4 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qwaitcondition +CONFIG += benchmark QT = core testlib + +TARGET = tst_bench_qwaitcondition SOURCES += tst_qwaitcondition.cpp diff --git a/tests/benchmarks/corelib/time/qdate/qdate.pro b/tests/benchmarks/corelib/time/qdate/qdate.pro index a6559171355..ecb229dfdae 100644 --- a/tests/benchmarks/corelib/time/qdate/qdate.pro +++ b/tests/benchmarks/corelib/time/qdate/qdate.pro @@ -1,4 +1,5 @@ -TARGET = tst_bench_qdate +CONFIG += benchmark QT = core testlib +TARGET = tst_bench_qdate SOURCES += tst_bench_qdate.cpp diff --git a/tests/benchmarks/corelib/time/qdatetime/qdatetime.pro b/tests/benchmarks/corelib/time/qdatetime/qdatetime.pro index a85e7346c68..7133834ffcf 100644 --- a/tests/benchmarks/corelib/time/qdatetime/qdatetime.pro +++ b/tests/benchmarks/corelib/time/qdatetime/qdatetime.pro @@ -1,4 +1,5 @@ -TARGET = tst_bench_qdatetime +CONFIG += benchmark QT = core testlib +TARGET = tst_bench_qdatetime SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/time/qtimezone/main.cpp b/tests/benchmarks/corelib/time/qtimezone/main.cpp index 65455a72619..133e6451bca 100644 --- a/tests/benchmarks/corelib/time/qtimezone/main.cpp +++ b/tests/benchmarks/corelib/time/qtimezone/main.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 Crimson AS ** Copyright (C) 2018 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure ** Contact: https://www.qt.io/licensing/ ** @@ -30,14 +31,57 @@ #include #include +// Enable to test *every* zone, rather than a hand-picked few, in some _data() sets: +// #define EXHAUSTIVE + class tst_QTimeZone : public QObject { Q_OBJECT private Q_SLOTS: void isTimeZoneIdAvailable(); + void systemTimeZone(); + void zoneByName_data(); + void zoneByName(); + void transitionList_data(); + void transitionList(); + void transitionsForward_data() { transitionList_data(); } + void transitionsForward(); + void transitionsReverse_data() { transitionList_data(); } + void transitionsReverse(); }; +static QVector enoughZones() +{ +#ifdef EXHAUSTIVE + auto available = QTimeZone::availableTimeZoneIds(); + QVector result; + result.reserve(available.size() + 1); + for (conat auto &name : available) + result << name; +#else + QVector result{ + QByteArray("UTC"), + // Those named overtly in tst_QDateTime: + QByteArray("Europe/Oslo"), + QByteArray("America/Vancouver"), + QByteArray("Europe/Berlin"), + QByteArray("America/Sao_Paulo"), + QByteArray("Pacific/Auckland"), + QByteArray("Australia/Eucla"), + QByteArray("Asia/Kathmandu"), + QByteArray("Pacific/Kiritimati"), + QByteArray("Pacific/Apia"), + QByteArray("UTC+12:00"), + QByteArray("Australia/Sydney"), + QByteArray("Asia/Singapore"), + QByteArray("Australia/Brisbane") + }; +#endif + result << QByteArray("Vulcan/ShiKahr"); // invalid: also worth testing + return result; +} + void tst_QTimeZone::isTimeZoneIdAvailable() { const QList available = QTimeZone::availableTimeZoneIds(); @@ -47,6 +91,84 @@ void tst_QTimeZone::isTimeZoneIdAvailable() } } +void tst_QTimeZone::systemTimeZone() +{ + QBENCHMARK { + QTimeZone::systemTimeZone(); + } +} + +void tst_QTimeZone::zoneByName_data() +{ + QTest::addColumn("name"); + + const auto names = enoughZones(); + for (const auto &name : names) + QTest::newRow(name.constData()) << name; +} + +void tst_QTimeZone::zoneByName() +{ + QFETCH(QByteArray, name); + QTimeZone zone; + QBENCHMARK { + zone = QTimeZone(name); + } + Q_UNUSED(zone); +} + +void tst_QTimeZone::transitionList_data() +{ + QTest::addColumn("name"); + QTest::newRow("system") << QByteArray(); // Handled specially in the test. + + const auto names = enoughZones(); + for (const auto &name : names) { + QTimeZone zone(name); + if (zone.isValid() && zone.hasTransitions()) + QTest::newRow(name.constData()) << name; + } +} + +void tst_QTimeZone::transitionList() +{ + QFETCH(QByteArray, name); + const QTimeZone zone = name.isEmpty() ? QTimeZone::systemTimeZone() : QTimeZone(name); + const QDateTime early = QDate(1625, 6, 8).startOfDay(Qt::UTC); // Cassini's birth date + const QDateTime late // End of 32-bit signed time_t + = QDateTime::fromSecsSinceEpoch(std::numeric_limits::max(), Qt::UTC); + QTimeZone::OffsetDataList seq; + QBENCHMARK { + seq = zone.transitions(early, late); + } + Q_UNUSED(seq); +} + +void tst_QTimeZone::transitionsForward() +{ + QFETCH(QByteArray, name); + const QTimeZone zone = name.isEmpty() ? QTimeZone::systemTimeZone() : QTimeZone(name); + const QDateTime early = QDate(1625, 6, 8).startOfDay(Qt::UTC); // Cassini's birth date + QBENCHMARK { + QTimeZone::OffsetData tran = zone.nextTransition(early); + while (tran.atUtc.isValid()) + tran = zone.nextTransition(tran.atUtc); + } +} + +void tst_QTimeZone::transitionsReverse() +{ + QFETCH(QByteArray, name); + const QTimeZone zone = name.isEmpty() ? QTimeZone::systemTimeZone() : QTimeZone(name); + const QDateTime late // End of 32-bit signed time_t + = QDateTime::fromSecsSinceEpoch(std::numeric_limits::max(), Qt::UTC); + QBENCHMARK { + QTimeZone::OffsetData tran = zone.previousTransition(late); + while (tran.atUtc.isValid()) + tran = zone.previousTransition(tran.atUtc); + } +} + QTEST_MAIN(tst_QTimeZone) #include "main.moc" diff --git a/tests/benchmarks/corelib/time/qtimezone/qtimezone.pro b/tests/benchmarks/corelib/time/qtimezone/qtimezone.pro index d0531b568bf..6ebee0faf36 100644 --- a/tests/benchmarks/corelib/time/qtimezone/qtimezone.pro +++ b/tests/benchmarks/corelib/time/qtimezone/qtimezone.pro @@ -1,4 +1,5 @@ -TARGET = tst_bench_qtimezone +CONFIG += benchmark QT = core testlib +TARGET = tst_bench_qtimezone SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/tools/containers-associative/containers-associative.pro b/tests/benchmarks/corelib/tools/containers-associative/containers-associative.pro index 49edcbee706..89da01b02e8 100644 --- a/tests/benchmarks/corelib/tools/containers-associative/containers-associative.pro +++ b/tests/benchmarks/corelib/tools/containers-associative/containers-associative.pro @@ -1,6 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_containers-associative - +CONFIG += benchmark QT = core testlib +TARGET = tst_bench_containers-associative SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/tools/containers-sequential/containers-sequential.pro b/tests/benchmarks/corelib/tools/containers-sequential/containers-sequential.pro index 6f731cb6d8e..509da95d229 100644 --- a/tests/benchmarks/corelib/tools/containers-sequential/containers-sequential.pro +++ b/tests/benchmarks/corelib/tools/containers-sequential/containers-sequential.pro @@ -1,6 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_containers-sequential - +CONFIG += benchmark QT = core testlib +TARGET = tst_bench_containers-sequential SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/tools/qalgorithms/qalgorithms.pro b/tests/benchmarks/corelib/tools/qalgorithms/qalgorithms.pro index f54f8320d46..0bde3ac66a3 100644 --- a/tests/benchmarks/corelib/tools/qalgorithms/qalgorithms.pro +++ b/tests/benchmarks/corelib/tools/qalgorithms/qalgorithms.pro @@ -1,3 +1,5 @@ -TARGET = tst_bench_qalgorithms +CONFIG += benchmark QT = core testlib + +TARGET = tst_bench_qalgorithms SOURCES = tst_qalgorithms.cpp diff --git a/tests/benchmarks/corelib/tools/qcontiguouscache/qcontiguouscache.pro b/tests/benchmarks/corelib/tools/qcontiguouscache/qcontiguouscache.pro index fe74dafef4c..59adad6bbcb 100644 --- a/tests/benchmarks/corelib/tools/qcontiguouscache/qcontiguouscache.pro +++ b/tests/benchmarks/corelib/tools/qcontiguouscache/qcontiguouscache.pro @@ -1,7 +1,6 @@ -TARGET = tst_bench_qcontiguouscache - -SOURCES += main.cpp - +CONFIG += benchmark CONFIG += parallel_test - QT = core testlib + +TARGET = tst_bench_qcontiguouscache +SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/tools/qcryptographichash/qcryptographichash.pro b/tests/benchmarks/corelib/tools/qcryptographichash/qcryptographichash.pro index cf9d640f7e4..025c70c2d97 100644 --- a/tests/benchmarks/corelib/tools/qcryptographichash/qcryptographichash.pro +++ b/tests/benchmarks/corelib/tools/qcryptographichash/qcryptographichash.pro @@ -1,5 +1,6 @@ -TARGET = tst_bench_qcryptographichash -CONFIG -= debug -CONFIG += release cmdline +CONFIG += benchmark +CONFIG += cmdline QT = core testlib + +TARGET = tst_bench_qcryptographichash SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/tools/qhash/qhash.pro b/tests/benchmarks/corelib/tools/qhash/qhash.pro index 40f661c116b..f9a873d096c 100644 --- a/tests/benchmarks/corelib/tools/qhash/qhash.pro +++ b/tests/benchmarks/corelib/tools/qhash/qhash.pro @@ -1,5 +1,6 @@ -TARGET = tst_hash +CONFIG += benchmark QT = core testlib + INCLUDEPATH += . +TARGET = tst_hash SOURCES += main.cpp outofline.cpp -CONFIG += release diff --git a/tests/benchmarks/corelib/tools/qlist/qlist.pro b/tests/benchmarks/corelib/tools/qlist/qlist.pro index c83bc455d22..98767c32500 100644 --- a/tests/benchmarks/corelib/tools/qlist/qlist.pro +++ b/tests/benchmarks/corelib/tools/qlist/qlist.pro @@ -1,4 +1,5 @@ -TARGET = tst_bench_qlist +CONFIG += benchmark QT = core testlib +TARGET = tst_bench_qlist SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/tools/qmap/qmap.pro b/tests/benchmarks/corelib/tools/qmap/qmap.pro index 6c9bf5e8d63..0e06493c792 100644 --- a/tests/benchmarks/corelib/tools/qmap/qmap.pro +++ b/tests/benchmarks/corelib/tools/qmap/qmap.pro @@ -1,5 +1,6 @@ -TARGET = tst_bench_qmap +CONFIG += benchmark QT = core testlib + INCLUDEPATH += . +TARGET = tst_bench_qmap SOURCES += main.cpp -CONFIG += release diff --git a/tests/benchmarks/corelib/tools/qrect/qrect.pro b/tests/benchmarks/corelib/tools/qrect/qrect.pro index 42cfcd89244..211cdc5bcc9 100644 --- a/tests/benchmarks/corelib/tools/qrect/qrect.pro +++ b/tests/benchmarks/corelib/tools/qrect/qrect.pro @@ -1,7 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qrect - QT = core testlib -CONFIG += release +CONFIG += benchmark +TARGET = tst_bench_qrect SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/tools/qringbuffer/qringbuffer.pro b/tests/benchmarks/corelib/tools/qringbuffer/qringbuffer.pro index 21b50e10e58..69750865b56 100644 --- a/tests/benchmarks/corelib/tools/qringbuffer/qringbuffer.pro +++ b/tests/benchmarks/corelib/tools/qringbuffer/qringbuffer.pro @@ -1,7 +1,6 @@ TEMPLATE = app -TARGET = tst_bench_qringbuffer - +CONFIG += benchmark QT = core-private testlib -CONFIG += release +TARGET = tst_bench_qringbuffer SOURCES += main.cpp diff --git a/tests/benchmarks/corelib/tools/qset/qset.pro b/tests/benchmarks/corelib/tools/qset/qset.pro index 8fb8bcfa0b5..e448683e94d 100644 --- a/tests/benchmarks/corelib/tools/qset/qset.pro +++ b/tests/benchmarks/corelib/tools/qset/qset.pro @@ -1,4 +1,5 @@ -TARGET = tst_qset +CONFIG += benchmark QT = core testlib + +TARGET = tst_qset SOURCES += main.cpp -CONFIG += release diff --git a/tests/benchmarks/corelib/tools/qstack/qstack.pro b/tests/benchmarks/corelib/tools/qstack/qstack.pro index 7d8a8396102..17b7ebd4866 100644 --- a/tests/benchmarks/corelib/tools/qstack/qstack.pro +++ b/tests/benchmarks/corelib/tools/qstack/qstack.pro @@ -1,4 +1,5 @@ -TARGET = tst_bench_stack +CONFIG += benchmark QT = core testlib core-private + +TARGET = tst_bench_stack SOURCES += main.cpp -CONFIG += release diff --git a/tests/benchmarks/corelib/tools/qvector/qvector.pro b/tests/benchmarks/corelib/tools/qvector/qvector.pro index 24a65d8ee80..fce8a6cd788 100644 --- a/tests/benchmarks/corelib/tools/qvector/qvector.pro +++ b/tests/benchmarks/corelib/tools/qvector/qvector.pro @@ -1,5 +1,6 @@ -TARGET = tst_bench_vector +CONFIG += benchmark QT = core testlib core-private + INCLUDEPATH += . -SOURCES += main.cpp outofline.cpp -CONFIG += release +TARGET = tst_bench_vector +SOURCES += main.cpp outofline.cpp diff --git a/tests/libfuzzer/corelib/text/qregularexpression/optimize/CMakeLists.txt b/tests/libfuzzer/corelib/text/qregularexpression/optimize/CMakeLists.txt new file mode 100644 index 00000000000..a82e5fa3403 --- /dev/null +++ b/tests/libfuzzer/corelib/text/qregularexpression/optimize/CMakeLists.txt @@ -0,0 +1,27 @@ +# Generated from optimize.pro. + +##################################################################### +## optimize Binary: +##################################################################### + +qt_add_executable(optimize + GUI + SOURCES + main.cpp +) + +#### Keys ignored in scope 1:.:.:optimize.pro:: +# FUZZ_ENGINE = "$$(LIB_FUZZING_ENGINE)" + +## Scopes: +##################################################################### + +qt_extend_target(optimize CONDITION FUZZ_ENGINE_ISEMPTY + LINK_OPTIONS + "-fsanitize=fuzzer" +) + +qt_extend_target(optimize CONDITION NOT FUZZ_ENGINE_ISEMPTY + PUBLIC_LIBRARIES + $ENV{LIB_FUZZING_ENGINE} +) diff --git a/tests/libfuzzer/corelib/text/qregularexpression/optimize/main.cpp b/tests/libfuzzer/corelib/text/qregularexpression/optimize/main.cpp new file mode 100644 index 00000000000..30a714c2502 --- /dev/null +++ b/tests/libfuzzer/corelib/text/qregularexpression/optimize/main.cpp @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size) { + QRegularExpression qre(QByteArray::fromRawData(Data, Size)); + qre.optimize(); + return 0; +} diff --git a/tests/libfuzzer/corelib/text/qregularexpression/optimize/optimize.pro b/tests/libfuzzer/corelib/text/qregularexpression/optimize/optimize.pro new file mode 100644 index 00000000000..196aca42ebe --- /dev/null +++ b/tests/libfuzzer/corelib/text/qregularexpression/optimize/optimize.pro @@ -0,0 +1,8 @@ +QT -= gui +SOURCES += main.cpp +FUZZ_ENGINE = $$(LIB_FUZZING_ENGINE) +isEmpty(FUZZ_ENGINE) { + QMAKE_LFLAGS += -fsanitize=fuzzer +} else { + LIBS += $$FUZZ_ENGINE +} diff --git a/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/CMakeLists.txt b/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/CMakeLists.txt new file mode 100644 index 00000000000..ec52626e2dd --- /dev/null +++ b/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/CMakeLists.txt @@ -0,0 +1,30 @@ +# Generated from fromiccprofile.pro. + +##################################################################### +## fromiccprofile Binary: +##################################################################### + +qt_add_executable(fromiccprofile + GUI + SOURCES + main.cpp + PUBLIC_LIBRARIES + Qt::Gui +) + +#### Keys ignored in scope 1:.:.:fromiccprofile.pro:: +# FUZZ_ENGINE = "$$(LIB_FUZZING_ENGINE)" +# QTPLUGIN = "qminimal" + +## Scopes: +##################################################################### + +qt_extend_target(fromiccprofile CONDITION FUZZ_ENGINE_ISEMPTY + LINK_OPTIONS + "-fsanitize=fuzzer" +) + +qt_extend_target(fromiccprofile CONDITION NOT FUZZ_ENGINE_ISEMPTY + PUBLIC_LIBRARIES + $ENV{LIB_FUZZING_ENGINE} +) diff --git a/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/fromiccprofile.pro b/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/fromiccprofile.pro index 934ff810773..bed2198e0dc 100644 --- a/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/fromiccprofile.pro +++ b/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/fromiccprofile.pro @@ -1,4 +1,5 @@ QT += gui +QTPLUGIN *= qminimal SOURCES += main.cpp FUZZ_ENGINE = $$(LIB_FUZZING_ENGINE) isEmpty(FUZZ_ENGINE) { diff --git a/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/main.cpp b/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/main.cpp index 7681c1468e5..8a588c6e216 100644 --- a/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/main.cpp +++ b/tests/libfuzzer/gui/painting/qcolorspace/fromiccprofile/main.cpp @@ -26,16 +26,22 @@ ** ****************************************************************************/ +#include + #include #include -// Run this with -// QT_LOGGING_RULES="qt.gui.icc=false" -// to reduce noise and increase speed. - extern "C" int LLVMFuzzerTestOneInput(const char *data, size_t size) { - static int c = 0; - static QGuiApplication a(c, nullptr); + // to reduce noise and increase speed + static char quiet[] = "QT_LOGGING_RULES=qt.gui.icc=false"; + static int pe = putenv(quiet); + Q_UNUSED(pe) + static int argc = 3; + static char arg1[] = "fuzzer"; + static char arg2[] = "-platform"; + static char arg3[] = "minimal"; + static char *argv[] = {arg1, arg2, arg3, nullptr}; + static QGuiApplication qga(argc, argv); QColorSpace cs = QColorSpace::fromIccProfile(QByteArray::fromRawData(data, size)); return 0; } diff --git a/tests/libfuzzer/gui/text/qtextdocument/sethtml/CMakeLists.txt b/tests/libfuzzer/gui/text/qtextdocument/sethtml/CMakeLists.txt new file mode 100644 index 00000000000..982957bedf8 --- /dev/null +++ b/tests/libfuzzer/gui/text/qtextdocument/sethtml/CMakeLists.txt @@ -0,0 +1,30 @@ +# Generated from sethtml.pro. + +##################################################################### +## sethtml Binary: +##################################################################### + +qt_add_executable(sethtml + GUI + SOURCES + main.cpp + PUBLIC_LIBRARIES + Qt::Gui +) + +#### Keys ignored in scope 1:.:.:sethtml.pro:: +# FUZZ_ENGINE = "$$(LIB_FUZZING_ENGINE)" +# QTPLUGIN = "qminimal" + +## Scopes: +##################################################################### + +qt_extend_target(sethtml CONDITION FUZZ_ENGINE_ISEMPTY + LINK_OPTIONS + "-fsanitize=fuzzer" +) + +qt_extend_target(sethtml CONDITION NOT FUZZ_ENGINE_ISEMPTY + PUBLIC_LIBRARIES + $ENV{LIB_FUZZING_ENGINE} +) diff --git a/tests/libfuzzer/gui/text/qtextdocument/sethtml/main.cpp b/tests/libfuzzer/gui/text/qtextdocument/sethtml/main.cpp index 51fa3c9e0fb..ed2a5c4e373 100644 --- a/tests/libfuzzer/gui/text/qtextdocument/sethtml/main.cpp +++ b/tests/libfuzzer/gui/text/qtextdocument/sethtml/main.cpp @@ -26,12 +26,16 @@ ** ****************************************************************************/ -#include +#include #include extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size) { - static int c = 0; - static QApplication a(c, nullptr); + static int argc = 3; + static char arg1[] = "fuzzer"; + static char arg2[] = "-platform"; + static char arg3[] = "minimal"; + static char *argv[] = {arg1, arg2, arg3, nullptr}; + static QGuiApplication qga(argc, argv); QTextDocument().setHtml(QByteArray::fromRawData(Data, Size)); return 0; } diff --git a/tests/libfuzzer/gui/text/qtextdocument/sethtml/sethtml.pro b/tests/libfuzzer/gui/text/qtextdocument/sethtml/sethtml.pro index af5ef9e940e..bed2198e0dc 100644 --- a/tests/libfuzzer/gui/text/qtextdocument/sethtml/sethtml.pro +++ b/tests/libfuzzer/gui/text/qtextdocument/sethtml/sethtml.pro @@ -1,4 +1,5 @@ -QT += widgets +QT += gui +QTPLUGIN *= qminimal SOURCES += main.cpp FUZZ_ENGINE = $$(LIB_FUZZING_ENGINE) isEmpty(FUZZ_ENGINE) { diff --git a/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/CMakeLists.txt b/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/CMakeLists.txt new file mode 100644 index 00000000000..a10d4325568 --- /dev/null +++ b/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/CMakeLists.txt @@ -0,0 +1,30 @@ +# Generated from setmarkdown.pro. + +##################################################################### +## setmarkdown Binary: +##################################################################### + +qt_add_executable(setmarkdown + GUI + SOURCES + main.cpp + PUBLIC_LIBRARIES + Qt::Gui +) + +#### Keys ignored in scope 1:.:.:setmarkdown.pro:: +# FUZZ_ENGINE = "$$(LIB_FUZZING_ENGINE)" +# QTPLUGIN = "qminimal" + +## Scopes: +##################################################################### + +qt_extend_target(setmarkdown CONDITION FUZZ_ENGINE_ISEMPTY + LINK_OPTIONS + "-fsanitize=fuzzer" +) + +qt_extend_target(setmarkdown CONDITION NOT FUZZ_ENGINE_ISEMPTY + PUBLIC_LIBRARIES + $ENV{LIB_FUZZING_ENGINE} +) diff --git a/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/main.cpp b/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/main.cpp index 66ddf738f20..6093da9827d 100644 --- a/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/main.cpp +++ b/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/main.cpp @@ -26,9 +26,16 @@ ** ****************************************************************************/ +#include #include extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size) { + static int argc = 3; + static char arg1[] = "fuzzer"; + static char arg2[] = "-platform"; + static char arg3[] = "minimal"; + static char *argv[] = {arg1, arg2, arg3, nullptr}; + static QGuiApplication qga(argc, argv); QTextDocument().setMarkdown(QByteArray::fromRawData(Data, Size)); return 0; } diff --git a/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/setmarkdown.pro b/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/setmarkdown.pro index 758622e1af9..bed2198e0dc 100644 --- a/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/setmarkdown.pro +++ b/tests/libfuzzer/gui/text/qtextdocument/setmarkdown/setmarkdown.pro @@ -1,5 +1,5 @@ -CONFIG += console -CONFIG -= app_bundle +QT += gui +QTPLUGIN *= qminimal SOURCES += main.cpp FUZZ_ENGINE = $$(LIB_FUZZING_ENGINE) isEmpty(FUZZ_ENGINE) { diff --git a/tests/libfuzzer/gui/text/qtextlayout/beginlayout/CMakeLists.txt b/tests/libfuzzer/gui/text/qtextlayout/beginlayout/CMakeLists.txt new file mode 100644 index 00000000000..1810c5ed6f3 --- /dev/null +++ b/tests/libfuzzer/gui/text/qtextlayout/beginlayout/CMakeLists.txt @@ -0,0 +1,30 @@ +# Generated from beginlayout.pro. + +##################################################################### +## beginlayout Binary: +##################################################################### + +qt_add_executable(beginlayout + GUI + SOURCES + main.cpp + PUBLIC_LIBRARIES + Qt::Gui +) + +#### Keys ignored in scope 1:.:.:beginlayout.pro:: +# FUZZ_ENGINE = "$$(LIB_FUZZING_ENGINE)" +# QTPLUGIN = "qminimal" + +## Scopes: +##################################################################### + +qt_extend_target(beginlayout CONDITION FUZZ_ENGINE_ISEMPTY + LINK_OPTIONS + "-fsanitize=fuzzer" +) + +qt_extend_target(beginlayout CONDITION NOT FUZZ_ENGINE_ISEMPTY + PUBLIC_LIBRARIES + $ENV{LIB_FUZZING_ENGINE} +) diff --git a/tests/libfuzzer/gui/text/qtextlayout/beginlayout/beginlayout.pro b/tests/libfuzzer/gui/text/qtextlayout/beginlayout/beginlayout.pro index af5ef9e940e..bed2198e0dc 100644 --- a/tests/libfuzzer/gui/text/qtextlayout/beginlayout/beginlayout.pro +++ b/tests/libfuzzer/gui/text/qtextlayout/beginlayout/beginlayout.pro @@ -1,4 +1,5 @@ -QT += widgets +QT += gui +QTPLUGIN *= qminimal SOURCES += main.cpp FUZZ_ENGINE = $$(LIB_FUZZING_ENGINE) isEmpty(FUZZ_ENGINE) { diff --git a/tests/libfuzzer/gui/text/qtextlayout/beginlayout/main.cpp b/tests/libfuzzer/gui/text/qtextlayout/beginlayout/main.cpp index dfb95592410..27e0566c2cf 100644 --- a/tests/libfuzzer/gui/text/qtextlayout/beginlayout/main.cpp +++ b/tests/libfuzzer/gui/text/qtextlayout/beginlayout/main.cpp @@ -26,9 +26,16 @@ ** ****************************************************************************/ +#include #include extern "C" int LLVMFuzzerTestOneInput(const char *Data, size_t Size) { + static int argc = 3; + static char arg1[] = "fuzzer"; + static char arg2[] = "-platform"; + static char arg3[] = "minimal"; + static char *argv[] = {arg1, arg2, arg3, nullptr}; + static QGuiApplication qga(argc, argv); QTextLayout tl(QByteArray::fromRawData(Data, Size)); tl.beginLayout(); tl.endLayout(); diff --git a/tests/manual/diaglib/debugproxystyle.cpp b/tests/manual/diaglib/debugproxystyle.cpp index 809613cd1df..dc95241473b 100644 --- a/tests/manual/diaglib/debugproxystyle.cpp +++ b/tests/manual/diaglib/debugproxystyle.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. diff --git a/tests/manual/diaglib/nativewindowdump_win.cpp b/tests/manual/diaglib/nativewindowdump_win.cpp index 6334fcfedd1..d99a3a3d388 100644 --- a/tests/manual/diaglib/nativewindowdump_win.cpp +++ b/tests/manual/diaglib/nativewindowdump_win.cpp @@ -71,7 +71,7 @@ static QTextStream &operator<<(QTextStream &str, const QSize &s) static QTextStream &operator<<(QTextStream &str, const QRect &rect) { - str << rect.size() << forcesign << rect.x() << rect.y() << noforcesign; + str << rect.size() << Qt::forcesign << rect.x() << rect.y() << Qt::noforcesign; return str; } @@ -112,7 +112,7 @@ static bool isTopLevel(HWND hwnd) static void formatNativeWindow(HWND hwnd, QTextStream &str) { - str << hex << showbase << quintptr(hwnd) << noshowbase << dec; + str << Qt::hex << Qt::showbase << quintptr(hwnd) << Qt::noshowbase << Qt::dec; const bool topLevel = isTopLevel(hwnd); if (topLevel) @@ -138,7 +138,7 @@ static void formatNativeWindow(HWND hwnd, QTextStream &str) if (GetClassName(hwnd, buf, sizeof(buf)/sizeof(buf[0]))) str << '"' << QString::fromWCharArray(buf) << '"'; - str << hex << showbase; + str << Qt::hex << Qt::showbase; if (const LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE)) { str << " style=" << style; debugWinStyle(str, style, WS_OVERLAPPED) @@ -210,7 +210,7 @@ static void formatNativeWindow(HWND hwnd, QTextStream &str) if (const ULONG_PTR wndProc = GetClassLongPtr(hwnd, GCLP_WNDPROC)) str << " wndProc=" << wndProc; - str << noshowbase << dec; + str << Qt::noshowbase << Qt::dec; if (GetWindowModuleFileName(hwnd, buf, sizeof(buf)/sizeof(buf[0]))) str << " module=\"" << QString::fromWCharArray(buf) << '"'; @@ -260,7 +260,7 @@ static void dumpNativeWindows(const WIdVector& wins) DumpContext dc; QString s; dc.stream = QSharedPointer(new QTextStream(&s)); - foreach (WId win, wins) + for (WId win : wins) dumpNativeWindowRecursion(reinterpret_cast(win), &dc); #if QT_VERSION >= 0x050400 qDebug().noquote() << s; diff --git a/tests/manual/diaglib/qwidgetdump.cpp b/tests/manual/diaglib/qwidgetdump.cpp index 926d2aaf35f..371f3e23116 100644 --- a/tests/manual/diaglib/qwidgetdump.cpp +++ b/tests/manual/diaglib/qwidgetdump.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -137,7 +137,7 @@ static void dumpWidgetRecursion(QTextStream &str, const QWidget *w, str << '\n'; } #endif // Qt 5 - foreach (const QObject *co, w->children()) { + for (const QObject *co : w->children()) { if (co->isWidgetType()) dumpWidgetRecursion(str, static_cast(co), options, depth + 1); } @@ -153,11 +153,11 @@ void dumpAllWidgets(FormatWindowOptions options, const QWidget *root) topLevels.append(const_cast(root)); else topLevels = QApplication::topLevelWidgets(); - foreach (QWidget *tw, topLevels) + for (QWidget *tw : qAsConst(topLevels)) dumpWidgetRecursion(str, tw, options); #if QT_VERSION >= 0x050400 { - foreach (const QString &line, d.split(QLatin1Char('\n'))) + for (const QString &line : d.split(QLatin1Char('\n'))) qDebug().noquote() << line; } #else diff --git a/tests/manual/diaglib/qwindowdump.cpp b/tests/manual/diaglib/qwindowdump.cpp index 2be26ff1423..1e46f62b1dd 100644 --- a/tests/manual/diaglib/qwindowdump.cpp +++ b/tests/manual/diaglib/qwindowdump.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. @@ -61,8 +61,8 @@ void formatObject(QTextStream &str, const QObject *o) void formatRect(QTextStream &str, const QRect &geom) { - str << geom.width() << 'x' << geom.height() << Qt::forcesign << geom.x() << geom.y() - << Qt::noforcesign; + str << geom.width() << 'x' << geom.height() << Qt::forcesign + << geom.x() << geom.y() << Qt::noforcesign; } #define debugType(s, type, typeConstant) \ @@ -163,7 +163,7 @@ static void dumpWindowRecursion(QTextStream &str, const QWindow *w, { indentStream(str, 2 * depth); formatWindow(str, w, options); - foreach (const QObject *co, w->children()) { + for (const QObject *co : w->children()) { if (co->isWindowType()) dumpWindowRecursion(str, static_cast(co), options, depth + 1); } @@ -174,7 +174,7 @@ void dumpAllWindows(FormatWindowOptions options) QString d; QTextStream str(&d); str << "### QWindows:\n"; - foreach (QWindow *w, QGuiApplication::topLevelWindows()) + for (QWindow *w : QGuiApplication::topLevelWindows()) dumpWindowRecursion(str, w, options); #if QT_VERSION >= 0x050400 qDebug().noquote() << d; diff --git a/tests/manual/diaglib/textdump.cpp b/tests/manual/diaglib/textdump.cpp index 33455a2a567..54a251928a3 100644 --- a/tests/manual/diaglib/textdump.cpp +++ b/tests/manual/diaglib/textdump.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. diff --git a/tests/manual/qtabletevent/device_information/tabletwidget.cpp b/tests/manual/qtabletevent/device_information/tabletwidget.cpp index 14d059abc11..e1461751096 100644 --- a/tests/manual/qtabletevent/device_information/tabletwidget.cpp +++ b/tests/manual/qtabletevent/device_information/tabletwidget.cpp @@ -58,7 +58,7 @@ bool TabletWidget::eventFilter(QObject *, QEvent *ev) mPos = event->pos(); mGPos = event->globalPos(); mHiResGlobalPos = event->posF(); - mDev = event->device(); + mDev = event->deviceType(); mPointerType = event->pointerType(); mUnique = event->uniqueId(); mXT = event->xTilt(); diff --git a/tests/manual/qtabletevent/regular_widgets/main.cpp b/tests/manual/qtabletevent/regular_widgets/main.cpp index 4816e2f3b94..1d0af4559bf 100644 --- a/tests/manual/qtabletevent/regular_widgets/main.cpp +++ b/tests/manual/qtabletevent/regular_widgets/main.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include enum TabletPointType { diff --git a/tests/testserver/apache2/testdata/www/cgi-bin/multipart.cgi b/tests/testserver/apache2/testdata/www/cgi-bin/multipart.cgi index 6973875cc93..60c0c0e8ad5 100755 --- a/tests/testserver/apache2/testdata/www/cgi-bin/multipart.cgi +++ b/tests/testserver/apache2/testdata/www/cgi-bin/multipart.cgi @@ -11,7 +11,7 @@ print "content type: $contentType\n"; if ($contentType =~ /^multipart\/form-data/) { foreach my $key ($q->param) { - foreach my $value ($q->param($key)) { + foreach my $value (scalar $q->param($key)) { if ($key =~ /text/) { $retValue = $value; } else { diff --git a/util/locale_database/cldr.py b/util/locale_database/cldr.py new file mode 100644 index 00000000000..4b54f500807 --- /dev/null +++ b/util/locale_database/cldr.py @@ -0,0 +1,718 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# +"""Digesting the CLDR's data. + +Provides two classes: + CldrReader -- driver for reading CLDR data + CldrAccess -- used by the reader to access the tree of data files + +The former should normally be all you need to access. +See individual classes for further detail. +""" + +from xml.dom import minidom +from weakref import WeakValueDictionary as CacheDict +import os + +from ldml import Error, Node, XmlScanner, Supplement, LocaleScanner +from qlocalexml import Locale + +class CldrReader (object): + def __init__(self, root, grumble = lambda msg: None, whitter = lambda msg: None): + """Set up a reader object for reading CLDR data. + + Single parameter, root, is the file-system path to the root of + the unpacked CLDR archive; its common/ sub-directory should + contain dtd/, main/ and supplemental/ sub-directories. + + Optional second argument, grumble, is a callable that logs + warnings and complaints, e.g. sys.stderr.write would be a + suitable callable. The default is a no-op that ignores its + single argument. Optional third argument is similar, used for + less interesting output; pass sys.stderr.write for it for + verbose output.""" + self.root = CldrAccess(root) + self.whitter, self.grumble = whitter, grumble + + def likelySubTags(self): + """Generator for likely subtag information. + + Yields pairs (have, give) of 4-tuples; if what you have + matches the left member, giving the right member is probably + sensible. Each 4-tuple's entries are the full names of a + language, a script, a country (strictly territory) and a + variant (currently ignored).""" + skips = [] + for got, use in self.root.likelySubTags(): + try: + have = self.__parseTags(got) + give = self.__parseTags(use) + except Error as e: + if ((use.startswith(got) or got.startswith('und_')) + and e.message.startswith('Unknown ') and ' code ' in e.message): + skips.append(use) + else: + self.grumble('Skipping likelySubtag "{}" -> "{}" ({})\n'.format(got, use, e.message)) + continue + if all(code.startswith('Any') and code[3].isupper() for code in have[:-1]): + continue + + give = (give[0], + # Substitute according to http://www.unicode.org/reports/tr35/#Likely_Subtags + have[1] if give[1] == 'AnyScript' else give[1], + have[2] if give[2] == 'AnyCountry' else give[2], + give[3]) # AnyVariant similarly ? + + yield have, give + + if skips: + # TODO: look at LDML's reserved locale tag names; they + # show up a lot in this, and may be grounds for filtering + # more out. + pass # self.__wrapped(self.whitter, 'Skipping likelySubtags (for unknown codes): ', skips) + + def readLocales(self, calendars = ('gregorian',)): + locales = tuple(self.__allLocales(calendars)) + return dict(((k.language_id, k.script_id, k.country_id, k.variant_code), + k) for k in locales) + + def __allLocales(self, calendars): + def skip(locale, reason): + return 'Skipping defaultContent locale "{}" ({})\n'.format(locale, reason) + + for locale in self.root.defaultContentLocales: + try: + language, script, country, variant = self.__splitLocale(locale) + except ValueError: + self.whitter(skip(locale, 'only language tag')) + continue + + if not (script or country): + self.grumble(skip(locale, 'second tag is neither script nor territory')) + continue + + if not (language and country): + continue + + try: + yield self.__getLocaleData(self.root.locale(locale), calendars, + language, script, country, variant) + except Error as e: + self.grumble(skip(locale, e.message)) + + for locale in self.root.fileLocales: + try: + chain = self.root.locale(locale) + language, script, country, variant = chain.tagCodes() + assert language + # TODO: this skip should probably be based on likely + # sub-tags, instead of empty country: if locale has a + # likely-subtag expansion, that's what QLocale uses, + # and we'll be saving its data for the expanded locale + # anyway, so don't need to record it for itself. + # See also QLocaleXmlReader.loadLocaleMap's grumble. + if not country: + continue + yield self.__getLocaleData(chain, calendars, language, script, country, variant) + except Error as e: + self.grumble('Skipping file locale "{}" ({})\n'.format(locale, e.message)) + + import textwrap + @staticmethod + def __wrapped(writer, prefix, tokens, wrap = textwrap.wrap): + writer('\n'.join(wrap(prefix + ', '.join(tokens), + subsequent_indent=' ', width=80)) + '\n') + del textwrap + + def __parseTags(self, locale): + tags = self.__splitLocale(locale) + language = tags.next() + script = country = variant = '' + try: + script, country, variant = tags + except ValueError: + pass + return tuple(p[1] for p in self.root.codesToIdName(language, script, country, variant)) + + def __splitLocale(self, name): + """Generate (language, script, territory, variant) from a locale name + + Ignores any trailing fields (with a warning), leaves script (a + capitalised four-letter token), territory (either a number or + an all-uppercase token) or variant (upper case and digits) + empty if unspecified. Only generates one entry if name is a + single tag (i.e. contains no underscores). Always yields 1 or + 4 values, never 2 or 3.""" + tags = iter(name.split('_')) + yield tags.next() # Language + tag = tags.next() # may raise StopIteration + + # Script is always four letters, always capitalised: + if len(tag) == 4 and tag[0].isupper() and tag[1:].islower(): + yield tag + try: + tag = tags.next() + except StopIteration: + tag = '' + else: + yield '' + + # Territory is upper-case or numeric: + if tag and tag.isupper() or tag.isdigit(): + yield tag + try: + tag = tags.next() + except StopIteration: + tag = '' + else: + yield '' + + # Variant can be any mixture of upper-case and digits. + if tag and all(c.isupper() or c.isdigit() for c in tag): + yield tag + tag = '' + else: + yield '' + + # If nothing is left, StopIteration will avoid the warning: + if not tag: + tag = tags.next() + self.grumble('Ignoring unparsed cruft {} in {}\n'.format('_'.join(tag + tuple(tags)), name)) + + def __getLocaleData(self, scan, calendars, language, script, country, variant): + ids, names = zip(*self.root.codesToIdName(language, script, country, variant)) + assert ids[0] > 0 and ids[2] > 0, (language, script, country, variant) + locale = Locale( + language = names[0], language_code = language, language_id = ids[0], + script = names[1], script_code = script, script_id = ids[1], + country = names[2], country_code = country, country_id = ids[2], + variant_code = variant) + + firstDay, weStart, weEnd = self.root.weekData(country) + assert all(day in ('mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun') + for day in (firstDay, weStart, weEnd)) + + locale.update(firstDayOfWeek = firstDay, + weekendStart = weStart, + weekendEnd = weEnd) + + iso, digits, rounding = self.root.currencyData(country) + locale.update(currencyIsoCode = iso, + currencyDigits = int(digits), + currencyRounding = int(rounding)) + + locale.update(scan.currencyData(iso)) + locale.update(scan.numericData(self.root.numberSystem, self.whitter)) + locale.update(scan.textPatternData()) + locale.update(scan.endonyms(language, script, country, variant)) + locale.update(scan.unitData()) # byte, kB, MB, GB, ..., KiB, MiB, GiB, ... + locale.update(scan.calendarNames(calendars)) # Names of days and months + + return locale + +# Note: various caches assume this class is a singleton, so the +# "default" value for a parameter no caller should pass can serve as +# the cache. If a process were to instantiate this class with distinct +# roots, each cache would be filled by the first to need it ! +class CldrAccess (object): + def __init__(self, root): + """Set up a master object for accessing CLDR data. + + Single parameter, root, is the file-system path to the root of + the unpacked CLDR archive; its common/ sub-directory should + contain dtd/, main/ and supplemental/ sub-directories.""" + self.root = root + + def xml(self, *path): + """Load a single XML file and return its root element as an XmlScanner. + + The path is interpreted relative to self.root""" + return XmlScanner(Node(self.__xml(path))) + + def supplement(self, name): + """Loads supplemental data as a Supplement object. + + The name should be that of a file in common/supplemental/, without path. + """ + return Supplement(Node(self.__xml(('common', 'supplemental', name)))) + + def locale(self, name): + """Loads all data for a locale as a LocaleScanner object. + + The name should be a locale name; adding suffix '.xml' to it + should usually yield a file in common/main/. The returned + LocaleScanner object packages this file along with all those + from which it inherits; its methods know how to handle that + inheritance, where relevant.""" + return LocaleScanner(name, self.__localeRoots(name), self.__rootLocale) + + @property + def fileLocales(self, joinPath = os.path.join, listDirectory = os.listdir, + splitExtension = os.path.splitext): + """Generator for locale IDs seen in file-names. + + All *.xml other than root.xml in common/main/ are assumed to + identify locales.""" + for name in listDirectory(joinPath(self.root, 'common', 'main')): + stem, ext = splitExtension(name) + if ext == '.xml' and stem != 'root': + yield stem + + @property + def defaultContentLocales(self): + """Generator for the default content locales.""" + for name, attrs in self.supplement('supplementalMetadata.xml').find('metadata/defaultContent'): + try: + locales = attrs['locales'] + except KeyError: + pass + else: + for locale in locales.split(): + yield locale + + def likelySubTags(self): + for ignore, attrs in self.supplement('likelySubtags.xml').find('likelySubtags'): + yield attrs['from'], attrs['to'] + + def numberSystem(self, system): + """Get a description of a numbering system. + + Returns a mapping, with keys u'digits', u'type' and u'id'; the + value for this last is system. Raises KeyError for unknown + number system, ldml.Error on failure to load data.""" + try: + return self.__numberSystems[system] + except KeyError: + raise Error('Unsupported number system: {}'.format(system)) + + def weekData(self, country): + """Data on the weekly cycle. + + Returns a triple (W, S, E) of en's short names for week-days; + W is the first day of the week, S the start of the week-end + and E the end of the week-end. Where data for a country is + unavailable, the data for CLDR's territory 001 (The World) is + used.""" + try: + return self.__weekData[country] + except KeyError: + return self.__weekData['001'] + + def currencyData(self, country): + """Returns currency data for the given country code. + + Return value is a tuple (ISO4217 code, digit count, rounding + mode). If CLDR provides no data for this country, ('', 2, 1) + is the default result. + """ + try: + return self.__currencyData[country] + except KeyError: + return '', 2, 1 + + def codesToIdName(self, language, script, country, variant = ''): + """Maps each code to the appropriate ID and name. + + Returns a 4-tuple of (ID, name) pairs corresponding to the + language, script, country and variant given. Raises a + suitable error if any of them is unknown, indicating all that + are unknown plus suitable names for any that could sensibly be + added to enumdata.py to make them known. + + Until we implement variant support (QTBUG-81051), the fourth + member of the returned tuple is always 0 paired with a string + that should not be used.""" + enum = self.__enumMap + try: + return (enum('language')[language], + enum('script')[script], + enum('country')[country], + enum('variant')[variant]) + except KeyError: + pass + + parts, values = [], [language, script, country, variant] + for index, key in enumerate(('language', 'script', 'country', 'variant')): + naming, enums = self.__codeMap(key), enum(key) + value = values[index] + if value not in enums: + text = '{} code {}'.format(key, value) + name = naming.get(value) + if name and value != 'POSIX': + text += u' (could add {})'.format(name) + parts.append(text) + if len(parts) > 1: + parts[-1] = 'and ' + parts[-1] + assert parts + raise Error('Unknown ' + ', '.join(parts), + language, script, country, variant) + + def readWindowsTimeZones(self, lookup): # For use by cldr2qtimezone.py + """Digest CLDR's MS-Win time-zone name mapping. + + MS-Win have their own eccentric names for time-zones. CLDR + helpfully provides a translation to more orthodox names. + + Singe argument, lookup, is a mapping from known MS-Win names + for locales to a unique integer index (starting at 1). + + The XML structure we read has the form: + + + + + + + + + + + + +""" + zones = self.supplement('windowsZones.xml') + enum = self.__enumMap('country') + badZones, unLands, defaults, windows = set(), set(), {}, {} + + for name, attrs in zones.find('windowsZones/mapTimezones'): + if name != 'mapZone': + continue + + wid, code = attrs['other'], attrs['territory'] + data = dict(windowsId = wid, + countryCode = code, + ianaList = attrs['type']) + + try: + key = lookup[wid] + except KeyError: + badZones.add(wid) + key = 0 + data['windowsKey'] = key + + if code == u'001': + defaults[key] = data['ianaList'] + else: + try: + cid, name = enum[code] + except KeyError: + unLands.append(code) + continue + data.update(countryId = cid, country = name) + windows[key, cid] = data + + if unLands: + raise Error('Unknown country codes, please add to enumdata.py: ' + + ', '.join(sorted(unLands))) + + if badZones: + raise Error('Unknown Windows IDs, please add to cldr2qtimezone.py: ' + + ', '.join(sorted(badZones))) + + return self.cldrVersion, defaults, windows + + @property + def cldrVersion(self): + # Evaluate so as to ensure __cldrVersion is set: + self.__unDistinguishedAttributes + return self.__cldrVersion + + # Implementation details + def __xml(self, path, cache = CacheDict(), read = minidom.parse, joinPath = os.path.join): + try: + doc = cache[path] + except KeyError: + cache[path] = doc = read(joinPath(self.root, *path)).documentElement + return doc + + def __open(self, path, joinPath=os.path.join): + return open(joinPath(self.root, *path)) + + @property + def __rootLocale(self, cache = []): + if not cache: + cache.append(self.xml('common', 'main', 'root.xml')) + return cache[0] + + @property + def __supplementalData(self, cache = []): + if not cache: + cache.append(self.supplement('supplementalData.xml')) + return cache[0] + + @property + def __numberSystems(self, cache = {}, joinPath=os.path.join): + if not cache: + for ignore, attrs in self.supplement('numberingSystems.xml').find('numberingSystems'): + cache[attrs['id']] = attrs + assert cache + return cache + + @property + def __weekData(self, cache = {}): + if not cache: + firstDay, weStart, weEnd = self.__getWeekData() + # Massage those into an easily-consulted form: + # World defaults given for code '001': + mon, sat, sun = firstDay['001'], weStart['001'], weEnd['001'] + lands = set(firstDay) | set(weStart) | set(weEnd) + cache.update((land, + (firstDay.get(land, mon), weStart.get(land, sat), weEnd.get(land, sun))) + for land in lands) + assert cache + return cache + + def __getWeekData(self): + """Scan for data on the weekly cycle. + + Yields three mappings from locales to en's short names for + week-days; if a locale isn't a key of a given mapping, it + should use the '001' (world) locale's value. The first mapping + gives the day on which the week starts, the second gives the + day on which the week-end starts, the third gives the last day + of the week-end.""" + source = self.__supplementalData + for key in ('firstDay', 'weekendStart', 'weekendEnd'): + result = {} + for ignore, attrs in source.find('weekData/' + key): + assert ignore == key + day = attrs['day'] + assert day in ('mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'), day + if 'alt' in attrs: + continue + for loc in attrs.get('territories', '').split(): + result[loc] = day + yield result + + @property + def __currencyData(self, cache = {}): + if not cache: + source = self.__supplementalData + for elt in source.findNodes('currencyData/region'): + iso, digits, rounding = '', 2, 1 + try: + country = elt.dom.attributes['iso3166'].nodeValue + except KeyError: + continue + for child in elt.findAllChildren('currency'): + try: + if child.dom.attributes['tender'].nodeValue == 'false': + continue + except KeyError: + pass + try: + child.dom.attributes['to'] # Is set if this element has gone out of date. + except KeyError: + iso = child.dom.attributes['iso4217'].nodeValue + break + if iso: + for tag, data in source.find( + 'currencyData/fractions/info[iso4217={}]'.format(iso)): + digits = data['digits'] + rounding = data['rounding'] + cache[country] = iso, digits, rounding + assert cache + + return cache + + @property + def __unDistinguishedAttributes(self, cache = {}, joinPath = os.path.join): + """Mapping from tag names to lists of attributes. + + LDML defines some attributes as 'distinguishing': if a node + has distinguishing attributes that weren't specified in an + XPath, a search on that XPath should exclude the node's + children. + + This property is a mapping from tag names to tuples of + attribute names that *aren't* distinguishing for that tag. + Its value is cached (so its costly computation isonly done + once) and there's a side-effect of populating its cache: it + sets self.__cldrVersion to the value found in ldml.dtd, during + parsing.""" + if not cache: + cache.update(self.__scanLdmlDtd()) + assert cache + + return cache + + def __scanLdmlDtd(self, joinPath = os.path.join): + """Scan the LDML DTD, record CLDR version + + Yields (tag, attrs) pairs: on elements with a given tag, + attributes named in its attrs (a tuple) may be ignored in an + XPath search; other attributes are distinguished attributes, + in the terminology of LDML's locale-inheritance rules. + + Sets self.__cldrVersion as a side-effect, since this + information is found in the same file.""" + with self.__open(('common', 'dtd', 'ldml.dtd')) as dtd: + tag, ignored, last = None, None, None + + for line in dtd: + if line.startswith(' might be stuck on its end: + self.__cldrVersion = parts[5].split('"')[1] + continue + + # s can also be @METADATA, but not @VALUE: + if '' in line or (last and '' in line): + assert last is not None + assert ignored is not None + assert tag is not None + ignored.append(last) + last = None # No attribute is both value and metadata + + if tag and ignored: + yield tag, tuple(ignored) + + def __enumMap(self, key, cache = {}): + if not cache: + cache['variant'] = {'': (0, 'This should never be seen outside ldml.py')} + # They're not actually lists: mappings from numeric value + # to pairs of full name and short code. What we want, in + # each case, is a mapping from code to the other two. + from enumdata import language_list, script_list, country_list + for form, book, empty in (('language', language_list, 'AnyLanguage'), + ('script', script_list, 'AnyScript'), + ('country', country_list, 'AnyCountry')): + cache[form] = dict((pair[1], (num, pair[0])) + for num, pair in book.items() if pair[0] != 'C') + # (Have to filter out the C locale, as we give it the + # same (all space) code as AnyLanguage, whose code + # should probably be 'und' instead.) + + # Map empty to zero and the any value: + cache[form][''] = (0, empty) + # and map language code 'und' also to (0, any): + cache['language']['und'] = (0, 'AnyLanguage') + + return cache[key] + + def __codeMap(self, key, cache = {}, + # Maps our name for it to CLDR's name: + naming = {'language': 'languages', 'script': 'scripts', + 'country': 'territories', 'variant': 'variants'}): + if not cache: + root = self.xml('common', 'main', 'en.xml').root.findUniqueChild('localeDisplayNames') + for dst, src in naming.items(): + cache[dst] = dict(self.__codeMapScan(root.findUniqueChild(src))) + assert cache + + return cache[key] + + def __codeMapScan(self, node): + """Get mapping from codes to element values. + + Passed in node is a , , or + node, each child of which is a , + " -print " " - -print " " -for id in enumdata.country_list: - l = enumdata.country_list[id] - print " " - print " " + l[0] + "" - print " " + str(id) + "" - print " " + l[1] + "" - print " " -print " " - -def _parseLocale(l): - language = "AnyLanguage" - script = "AnyScript" - country = "AnyCountry" - - if l == "und": - raise xpathlite.Error("we are treating unknown locale like C") - - parsed = splitLocale(l) - language_code = parsed.next() - script_code = country_code = '' - try: - script_code, country_code = parsed - except ValueError: - pass - - if language_code != "und": - language_id = enumdata.languageCodeToId(language_code) - if language_id == -1: - raise xpathlite.Error('unknown language code "%s"' % language_code) - language = enumdata.language_list[language_id][0] - - if script_code: - script_id = enumdata.scriptCodeToId(script_code) - if script_id == -1: - raise xpathlite.Error('unknown script code "%s"' % script_code) - script = enumdata.script_list[script_id][0] - - if country_code: - country_id = enumdata.countryCodeToId(country_code) - if country_id == -1: - raise xpathlite.Error('unknown country code "%s"' % country_code) - country = enumdata.country_list[country_id][0] - - return (language, script, country) - -skips = [] -print " " -for ns in findTagsInFile(cldr_dir + "/../supplemental/likelySubtags.xml", "likelySubtags"): - tmp = {} - for data in ns[1:][0]: # ns looks like this: [u'likelySubtag', [(u'from', u'aa'), (u'to', u'aa_Latn_ET')]] - tmp[data[0]] = data[1] - - try: - from_language, from_script, from_country = _parseLocale(tmp[u"from"]) - to_language, to_script, to_country = _parseLocale(tmp[u"to"]) - except xpathlite.Error as e: - if tmp[u'to'].startswith(tmp[u'from']) and str(e) == 'unknown language code "%s"' % tmp[u'from']: - skips.append(tmp[u'to']) - else: - sys.stderr.write('skipping likelySubtag "%s" -> "%s" (%s)\n' % (tmp[u"from"], tmp[u"to"], str(e))) - continue - # substitute according to http://www.unicode.org/reports/tr35/#Likely_Subtags - if to_country == "AnyCountry" and from_country != to_country: - to_country = from_country - if to_script == "AnyScript" and from_script != to_script: - to_script = from_script - - print " " - print " " - print " " + from_language + "" - print " " - print " " + from_country + "" - print " " - print " " - print " " + to_language + "" - print " " - print " " + to_country + "" - print " " - print " " -print " " -if skips: - wrappedwarn('skipping likelySubtags (for unknown language codes): ', skips) -print " " - -Locale.C(calendars).toXml(calendars) -for key in locale_keys: - locale_database[key].toXml(calendars) - -print " " -print "" +if __name__ == '__main__': + sys.exit(main(sys.argv, sys.stdout, sys.stderr)) diff --git a/util/locale_database/cldr2qtimezone.py b/util/locale_database/cldr2qtimezone.py index 4c3609056d6..70b5d1e69e6 100755 --- a/util/locale_database/cldr2qtimezone.py +++ b/util/locale_database/cldr2qtimezone.py @@ -1,7 +1,7 @@ #!/usr/bin/env python2 ############################################################################# ## -## Copyright (C) 2019 The Qt Company Ltd. +## Copyright (C) 2020 The Qt Company Ltd. ## Contact: https://www.qt.io/licensing/ ## ## This file is part of the test suite of the Qt Toolkit. @@ -34,59 +34,20 @@ the CLDR data. Pass its common/ directory as first parameter to this script and the qtbase root directory as second parameter. It shall update qtbase's src/corelib/time/qtimezoneprivate_data_p.h ready for use. - -The XML structure is as follows: - - - - - - - - - - - - - - """ import os -import sys -import datetime -import tempfile -import enumdata -import xpathlite -from xpathlite import DraftResolution import re -import qlocalexml2cpp +import datetime +import textwrap -findAlias = xpathlite.findAlias -findEntry = xpathlite.findEntry -findEntryInFile = xpathlite._findEntryInFile -findTagsInFile = xpathlite.findTagsInFile -unicode2hex = qlocalexml2cpp.unicode2hex -wrap_list = qlocalexml2cpp.wrap_list +from localetools import unicode2hex, wrap_list, Error, SourceFileEditor +from cldr import CldrAccess -class ByteArrayData: - def __init__(self): - self.data = [] - self.hash = {} - def append(self, s): - s = s + '\0' - if s in self.hash: - return self.hash[s] +### Data that may need updates in response to new entries in the CLDR file ### - lst = unicode2hex(s) - index = len(self.data) - if index > 65535: - print "\n\n\n#error Data index is too big!" - sys.stderr.write ("\n\n\nERROR: index exceeds the uint16 range! index = %d\n" % index) - sys.exit(1) - self.hash[s] = index - self.data += lst - return index +# This script shall report the update you need, if this arises. +# However, you may need to research the relevant zone's standard offset. # List of currently known Windows IDs. # If this script reports missing IDs, please add them here. @@ -233,12 +194,6 @@ windowsIdList = ( (u'Yakutsk Standard Time', 32400), ) -def windowsIdToKey(windowsId): - for index, pair in enumerate(windowsIdList): - if pair[0] == windowsId: - return index + 1 - return 0 - # List of standard UTC IDs to use. Not public so may be safely changed. # Do not remove IDs, as each entry is part of the API/behavior guarantee. # ( UTC Id, Offset Seconds ) @@ -285,94 +240,43 @@ utcIdList = ( (u'UTC+14:00', 50400), ) -def usage(): - print "Usage: cldr2qtimezone.py " - sys.exit() +### End of data that may need updates in response to CLDR ### -if len(sys.argv) != 3: - usage() +class ByteArrayData: + def __init__(self): + self.data = [] + self.hash = {} -cldrPath = sys.argv[1] -qtPath = sys.argv[2] + def append(self, s): + s = s + '\0' + if s in self.hash: + return self.hash[s] -if not os.path.isdir(cldrPath) or not os.path.isdir(qtPath): - usage() + lst = unicode2hex(s) + index = len(self.data) + if index > 0xffff: + raise Error('Index ({}) outside the uint16 range !'.format(index)) + self.hash[s] = index + self.data += lst + return index -windowsZonesPath = cldrPath + "/supplemental/windowsZones.xml" -tempFileDir = qtPath -dataFilePath = qtPath + "/src/corelib/time/qtimezoneprivate_data_p.h" + def write(self, out, name): + out('\nstatic const char {}[] = {{\n'.format(name)) + out(wrap_list(self.data)) + out('\n};\n') -if not (os.path.isfile(windowsZonesPath) and os.path.isfile(dataFilePath)): - usage() +class ZoneIdWriter (SourceFileEditor): + def write(self, version, defaults, windowsIds): + self.__writeWarning(version) + windows, iana = self.__writeTables(self.writer.write, defaults, windowsIds) + windows.write(self.writer.write, 'windowsIdData') + iana.write(self.writer.write, 'ianaIdData') -cldr_version = 'unknown' -ldml = open(cldrPath + "/dtd/ldml.dtd", "r") -for line in ldml: - if 'version cldrVersion CDATA #FIXED' in line: - cldr_version = line.split('"')[1] - -# [[u'version', [(u'number', u'$Revision: 7825 $')]]] -versionNumber = findTagsInFile(windowsZonesPath, "version")[0][1][0][1] - -mapTimezones = findTagsInFile(windowsZonesPath, "windowsZones/mapTimezones") - -defaultDict = {} -windowsIdDict = {} - -if mapTimezones: - badZones = set() - for mapZone in mapTimezones: - # [u'mapZone', [(u'territory', u'MH'), (u'other', u'UTC+12'), (u'type', u'Pacific/Majuro Pacific/Kwajalein')]] - if mapZone[0] == u'mapZone': - data = {} - for attribute in mapZone[1]: - if attribute[0] == u'other': - data['windowsId'] = attribute[1] - if attribute[0] == u'territory': - data['countryCode'] = attribute[1] - if attribute[0] == u'type': - data['ianaList'] = attribute[1] - - data['windowsKey'] = windowsIdToKey(data['windowsId']) - if data['windowsKey'] <= 0: - badZones.add(data['windowsId']) - - countryId = 0 - if data['countryCode'] == u'001': - defaultDict[data['windowsKey']] = data['ianaList'] - else: - data['countryId'] = enumdata.countryCodeToId(data['countryCode']) - if data['countryId'] < 0: - raise xpathlite.Error("Unknown Country Code \"%s\"" % data['countryCode']) - data['country'] = enumdata.country_list[data['countryId']][0] - windowsIdDict[data['windowsKey'], data['countryId']] = data - if badZones: - sys.stderr.write('\n\t'.join(["\nUnknown Windows ID, please add:"] + sorted(badZones)) - + "\nto the windowIdList in cldr2qtimezone.py\n\n") - raise xpathlite.Error("Unknown Windows IDs") - -print "Input file parsed, now writing data" - -GENERATED_BLOCK_START = "// GENERATED PART STARTS HERE\n" -GENERATED_BLOCK_END = "// GENERATED PART ENDS HERE\n" - -# Create a temp file to write the new data into -(newTempFile, newTempFilePath) = tempfile.mkstemp("qtimezone_data_p", dir=tempFileDir) -newTempFile = os.fdopen(newTempFile, "w") - -# Open the old file and copy over the first non-generated section to the new file -oldDataFile = open(dataFilePath, "r") -s = oldDataFile.readline() -while s and s != GENERATED_BLOCK_START: - newTempFile.write(s) - s = oldDataFile.readline() - -# Write out generated block start tag and warning -newTempFile.write(GENERATED_BLOCK_START) -newTempFile.write(""" + def __writeWarning(self, version): + self.writer.write(""" /* - This part of the file was generated on %s from the - Common Locale Data Repository v%s supplemental/windowsZones.xml file %s + This part of the file was generated on {} from the + Common Locale Data Repository v{} file supplemental/windowsZones.xml http://www.unicode.org/cldr/ @@ -380,80 +284,111 @@ newTempFile.write(""" edited) CLDR data; see qtbase/util/locale_database/. */ -""" % (str(datetime.date.today()), cldr_version, versionNumber) ) +""".format(str(datetime.date.today()), version)) -windowsIdData = ByteArrayData() -ianaIdData = ByteArrayData() + @staticmethod + def __writeTables(out, defaults, windowsIds): + windowsIdData, ianaIdData = ByteArrayData(), ByteArrayData() -# Write Windows/IANA table -newTempFile.write("// Windows ID Key, Country Enum, IANA ID Index\n") -newTempFile.write("static const QZoneData zoneDataTable[] = {\n") -for index in sorted(windowsIdDict): - data = windowsIdDict[index] - newTempFile.write(" { %6d,%6d,%6d }, // %s / %s\n" - % (data['windowsKey'], - data['countryId'], - ianaIdData.append(data['ianaList']), - data['windowsId'], - data['country'])) -newTempFile.write(" { 0, 0, 0 } // Trailing zeroes\n") -newTempFile.write("};\n\n") + # Write Windows/IANA table + out('// Windows ID Key, Country Enum, IANA ID Index\n') + out('static const QZoneData zoneDataTable[] = {\n') + for index, data in sorted(windowsIds.items()): + out(' {{ {:6d},{:6d},{:6d} }}, // {} / {}\n'.format( + data['windowsKey'], data['countryId'], + ianaIdData.append(data['ianaList']), + data['windowsId'], data['country'])) + out(' { 0, 0, 0 } // Trailing zeroes\n') + out('};\n\n') -print "Done Zone Data" + # Write Windows ID key table + out('// Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset\n') + out('static const QWindowsData windowsDataTable[] = {\n') + for index, pair in enumerate(windowsIdList, 1): + out(' {{ {:6d},{:6d},{:6d},{:6d} }}, // {}\n'.format( + index, + windowsIdData.append(pair[0]), + ianaIdData.append(defaults[index]), + pair[1], pair[0])) + out(' { 0, 0, 0, 0 } // Trailing zeroes\n') + out('};\n\n') -# Write Windows ID key table -newTempFile.write("// Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset\n") -newTempFile.write("static const QWindowsData windowsDataTable[] = {\n") -for index, pair in enumerate(windowsIdList): - newTempFile.write(" { %6d,%6d,%6d,%6d }, // %s\n" - % (index + 1, windowsIdData.append(pair[0]), - ianaIdData.append(defaultDict[index + 1]), pair[1], pair[0])) -newTempFile.write(" { 0, 0, 0, 0 } // Trailing zeroes\n") -newTempFile.write("};\n\n") + # Write UTC ID key table + out('// IANA ID Index, UTC Offset\n') + out('static const QUtcData utcDataTable[] = {\n') + for pair in utcIdList: + out(' {{ {:6d},{:6d} }}, // {}\n'.format( + ianaIdData.append(pair[0]), pair[1], pair[0])) + out(' { 0, 0 } // Trailing zeroes\n') + out('};\n') -print "Done Windows Data Table" + return windowsIdData, ianaIdData -# Write UTC ID key table -newTempFile.write("// IANA ID Index, UTC Offset\n") -newTempFile.write("static const QUtcData utcDataTable[] = {\n") -for pair in utcIdList: - newTempFile.write(" { %6d,%6d }, // %s\n" - % (ianaIdData.append(pair[0]), pair[1], pair[0])) -newTempFile.write(" { 0, 0 } // Trailing zeroes\n") -newTempFile.write("};\n\n") +def usage(err, name, message=''): + err.write("""Usage: {} path/to/cldr/core/common path/to/qtbase +""".format(name)) # TODO: more interesting message + if message: + err.write('\n' + message + '\n') -print "Done UTC Data Table" +def main(args, out, err): + """Parses CLDR's data and updates Qt's representation of it. -# Write out Windows ID's data -newTempFile.write("static const char windowsIdData[] = {\n") -newTempFile.write(wrap_list(windowsIdData.data)) -newTempFile.write("\n};\n\n") + Takes sys.argv, sys.stdout, sys.stderr (or equivalents) as + arguments. Expects two command-line options: the root of the + unpacked CLDR data-file tree and the root of the qtbase module's + checkout. Updates QTimeZone's private data about Windows time-zone + IDs.""" + name = args.pop(0) + if len(args) != 2: + usage(err, name, "Expected two arguments") + return 1 -# Write out IANA ID's data -newTempFile.write("static const char ianaIdData[] = {\n") -newTempFile.write(wrap_list(ianaIdData.data)) -newTempFile.write("\n};\n") + cldrPath = args.pop(0) + qtPath = args.pop(0) -print "Done ID Data Table" + if not os.path.isdir(qtPath): + usage(err, name, "No such Qt directory: " + qtPath) + return 1 + if not os.path.isdir(cldrPath): + usage(err, name, "No such CLDR directory: " + cldrPath) + return 1 -# Write out the end of generated block tag -newTempFile.write(GENERATED_BLOCK_END) -s = oldDataFile.readline() + dataFilePath = os.path.join(qtPath, 'src', 'corelib', 'time', 'qtimezoneprivate_data_p.h') + if not os.path.isfile(dataFilePath): + usage(err, name, 'No such file: ' + dataFilePath) + return 1 -# Skip through the old generated data in the old file -while s and s != GENERATED_BLOCK_END: - s = oldDataFile.readline() + try: + version, defaults, winIds = CldrAccess(cldrPath).readWindowsTimeZones( + dict((name, ind) for ind, name in enumerate((x[0] for x in windowsIdList), 1))) + except IOError as e: + usage(err, name, + 'Failed to open common/supplemental/windowsZones.xml: ' + (e.message or e.args[1])) + return 1 + except Error as e: + err.write('\n'.join(textwrap.wrap( + 'Failed to read windowsZones.xml: ' + (e.message or e.args[1]), + subsequent_indent=' ', width=80)) + '\n') + return 1 -# Now copy the rest of the original file into the new file -s = oldDataFile.readline() -while s: - newTempFile.write(s) - s = oldDataFile.readline() + out.write('Input file parsed, now writing data\n') + try: + writer = ZoneIdWriter(dataFilePath, qtPath) + except IOError as e: + err.write('Failed to open files to transcribe: {}'.format(e.message or e.args[1])) + return 1 -# Now close the old and new file, delete the old file and copy the new file in its place -newTempFile.close() -oldDataFile.close() -os.remove(dataFilePath) -os.rename(newTempFilePath, dataFilePath) + try: + writer.write(version, defaults, winIds) + except Error as e: + writer.cleanup() + err.write('\nError in Windows ID data: ' + e.message + '\n') + return 1 -print "Data generation completed, please check the new file at " + dataFilePath + writer.close() + out.write('Data generation completed, please check the new file at ' + dataFilePath + '\n') + return 0 + +if __name__ == '__main__': + import sys + sys.exit(main(sys.argv, sys.stdout, sys.stderr)) diff --git a/util/locale_database/ldml.py b/util/locale_database/ldml.py new file mode 100644 index 00000000000..e3e3a2e4ba5 --- /dev/null +++ b/util/locale_database/ldml.py @@ -0,0 +1,589 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# +"""Parsing the Locale Data Markup Language + +It's an XML format, so the raw parsing of XML is, of course, delegated +to xml.dom.minidom; but it has its own specific schemata and some +funky rules for combining data from various files (inheritance between +locales). The use of it we're interested in is extraction of CLDR's +data, so some of the material here is specific to CLDR; see cldr.py +for how it is mainly used. + +Provides various classes to wrap xml.dom's objects, specifically those +returned by minidom.parse() and their child-nodes: + Node -- wraps any node in the DOM tree + XmlScanner -- wraps the root element of a stand-alone XML file + Supplement -- specializes XmlScanner for supplemental data files + LocaleScanner -- wraps a locale's inheritance-chain of file roots + +See individual classes for further detail. +""" +from localetools import Error +from dateconverter import convert_date + +class Node (object): + """Wrapper for an arbitrary DOM node. + + Provides various ways to select chldren of a node. Selected child + nodes are returned wrapped as Node objects. A Node exposes the + raw DOM node it wraps via its .dom attribute.""" + + def __init__(self, elt, dullAttrs = None, draft = 0): + """Wraps a DOM node for ease of access. + + First argument, elt, is the DOM node to wrap. + + Optional second argument, dullAttrs, should either be None or + map each LDML tag name to a list of the names of + non-distinguishing attributes for nodes with the given tag + name. If None is given, no distinguishing attribute checks are + performed. + + (Optional third argument, draft, should only be supplied by + this class's creation of child nodes; it is the maximum draft + score of any ancestor of the new node.)""" + self.dom, self.__dull = elt, dullAttrs + try: + attr = elt.attributes['draft'].nodeValue + except KeyError: + self.draft = draft + else: + self.draft = max(draft, self.draftScore(attr)) + + def findAllChildren(self, tag, wanted = None, allDull = False): + """All children that do have the given tag and attributes. + + First argument is the tag: children with any other tag are + ignored. + + Optional second argument, wanted, should either be None or map + attribute names to the values they must have. Only child nodes + with thes attributes set to the given values are yielded. + + By default, nodes that have distinguishing attributes, other + than those specified in wanted, are ignored. Pass the allDull + parameter a true value to suppress this check.""" + + if self.__dull is None: + allDull = True + dull = () if allDull else self.__dull[tag] + + for child in self.dom.childNodes: + if child.nodeType != child.ELEMENT_NODE: + continue + if child.nodeName != tag: + continue + + if wanted: + try: + if any(child.attributes[k].nodeValue != v + for k, v in wanted.items()): + continue + except KeyError: # Some wanted attribute is missing + continue + + if not (allDull or all(k in dull or k in wanted + for k in child.attributes.keys())): + continue + + elif not (allDull or all(k in dull + for k in child.attributes.keys())): + continue + + yield Node(child, self.__dull, self.draft) + + def findUniqueChild(self, tag): + """Returns the single child with the given nodeName. + + Raises Error if there is no such child or there is more than + one.""" + seq = self.findAllChildren(tag) + try: + node = seq.next() + except StopIteration: + raise Error('No child found where one was expected', tag) + for it in seq: + raise Error('Many children found where only one was expected', tag) + return node + + @classmethod + def draftScore(cls, level): + """Maps draft level names to numeric scores. + + Single parameter, level, is the least sure value of the draft + attribute on a node that you're willing to accept; returns a + numeric value (lower is less drafty). + + Tempting as it is to insist on low draft scores, there are + many locales in which pretty much every leaf is + unconfirmed. It may make sense to actually check each + XmlScanner object, or each node in each LocaleScanner's nodes + list, to see what its distribution of draft level looks like, + so as to set the acceptable draft score for its elements + accordingly. However, for the moment, we mostly just accept + all elements, regardless of draft values (the one exception is + am/pm indicators).""" + return cls.__draftScores.get(level, 5) if level else 0 + + # Implementation details: + __draftScores = dict(true = 4, unconfirmed = 3, provisional = 2, + contributed = 1, approved = 0, false = 0) + +def _parseXPath(selector): + # Split "tag[attr=val][...]" into tag-name and attribute mapping + attrs = selector.split('[') + name = attrs.pop(0) + if attrs: + attrs = [x.strip() for x in attrs] + assert all(x.endswith(']') for x in attrs) + attrs = [x[:-1].split('=') for x in attrs] + assert all(len(x) in (1, 2) for x in attrs) + attrs = (('type', x[0]) if len(x) == 1 else x for x in attrs) + return name, dict(attrs) + +def _iterateEach(iters): + # Flatten a two-layer iterator. + for it in iters: + for item in it: + yield item + +class XmlScanner (object): + """Wrap an XML file to enable XPath access to its nodes. + """ + def __init__(self, node): + self.root = node + + def findNodes(self, xpath): + """Return all nodes under self.root matching this xpath. + + Ignores any excess attributes.""" + elts = (self.root,) + for selector in xpath.split('/'): + tag, attrs = _parseXPath(selector) + elts = tuple(_iterateEach(e.findAllChildren(tag, attrs) for e in elts)) + if not elts: + break + return elts + +class Supplement (XmlScanner): + def find(self, xpath): + elts = self.findNodes(xpath) + for elt in _iterateEach(e.dom.childNodes if e.dom.childNodes else (e.dom,) + for e in elts): + if elt.attributes: + yield (elt.nodeName, + dict((k, v if isinstance(v, basestring) else v.nodeValue) + for k, v in elt.attributes.items())) + +class LocaleScanner (object): + def __init__(self, name, nodes, root): + self.name, self.nodes, self.base = name, nodes, root + + def find(self, xpath, default = None, draft = None): + """XPath search for the content of an element. + + Required argument, xpath, is the XPath to search for. Optional + second argument is a default value to use, if no such node is + found. Optional third argument is a draft score (see + Node.draftScore() for details); if given, leaf elements with + higher draft scores are ignored.""" + try: + for elt in self.__find(xpath): + try: + if draft is None or elt.draft <= draft: + return elt.dom.firstChild.nodeValue + except (AttributeError, KeyError): + pass + except Error as e: + if default is None: + raise + return default + + def tagCodes(self): + """Yields four tag codes + + The tag codes are language, script, country and variant; an + empty value for any of them indicates that no value was + provided. The values are obtained from the primary file's + top-level element. An Error is raised if any + top-level element of this file has a non-empty source + attribute; that attribute value is mentioned in the error's + message.""" + root = self.nodes[0] + for alias in root.findAllChildren('alias', allDull=True): + try: + source = alias.dom.attributes['source'].nodeValue + except (KeyError, AttributeError): + pass + else: + raise Error('Alias to {}'.format(source)) + + ids = root.findUniqueChild('identity') + for code in ('language', 'script', 'territory', 'variant'): + for node in ids.findAllChildren(code, allDull=True): + try: + yield node.dom.attributes['type'].nodeValue + except (KeyError, AttributeError): + pass + else: + break # only want one value for each code + else: # No value for this code, use empty + yield '' + + def currencyData(self, isoCode): + """Fetches currency data for this locale. + + Single argument, isoCode, is the ISO currency code for the + currency in use in the country. See also numericData, which + includes some currency formats. + """ + if isoCode: + stem = 'numbers/currencies/currency[{}]/'.format(isoCode) + symbol = self.find(stem + 'symbol', '') + displays = tuple(self.find(stem + 'displayName' + tail, '') + for tail in ('',) + tuple( + '[count={}]'.format(x) for x in ('zero', 'one', 'two', + 'few', 'many', 'other'))) + while displays and not displays[-1]: + displays = displays[:-1] + name = ';'.join(displays) + else: + symbol = name = '' + yield 'currencySymbol', symbol + yield 'currencyDisplayName', name + + def numericData(self, lookup, complain = lambda text: None): + """Generate assorted numeric data for the locale. + + First argument, lookup, is a callable that maps a numbering + system's name to certain data about the system, as a mapping; + we expect this to have u'digits' as a key. + """ + system = self.find('numbers/defaultNumberingSystem') + stem = 'numbers/symbols[numberSystem={}]/'.format(system) + decimal = self.find(stem + 'decimal') + group = self.find(stem + 'group') + assert decimal != group, (self.name, system, decimal) + yield 'decimal', decimal + yield 'group', group + yield 'percent', self.find(stem + 'percentSign') + yield 'list', self.find(stem + 'list') + yield 'exp', self.find(stem + 'exponential') + + digits = lookup(system)['digits'] + assert len(digits) == 10 + zero = digits[0] + # Qt's number-formatting code assumes digits are consecutive: + assert all(ord(c) == i for i, c in enumerate(digits, ord(zero))) + yield 'zero', zero + + plus = self.find(stem + 'plusSign') + minus = self.find(stem + 'minusSign') + yield 'plus', plus + yield 'minus', minus + + # Currency formatting: + xpath = 'numbers/currencyFormats/currencyFormatLength/currencyFormat[accounting]/pattern' + try: + money = self.find(xpath.replace('Formats/', + 'Formats[numberSystem={}]/'.format(system))) + except Error: + money = self.find(xpath) + money = self.__currencyFormats(money, plus, minus) + yield 'currencyFormat', money.next() + neg = '' + for it in money: + assert not neg, 'There should be at most one more pattern' + neg = it + yield 'currencyNegativeFormat', neg + + def textPatternData(self): + for key in ('quotationStart', 'alternateQuotationEnd', + 'quotationEnd', 'alternateQuotationStart'): + yield key, self.find('delimiters/' + key) + + for key in ('start', 'middle', 'end'): + yield ('listPatternPart' + key.capitalize(), + self.__fromLdmlListPattern(self.find( + 'listPatterns/listPattern/listPatternPart[{}]'.format(key)))) + yield ('listPatternPartTwo', + self.__fromLdmlListPattern(self.find( + 'listPatterns/listPattern/listPatternPart[2]'))) + + stem = 'dates/calendars/calendar[gregorian]/' + # TODO: is wide really the right width to use here ? + # abbreviated might be an option ... or try both ? + meridiem = stem + 'dayPeriods/dayPeriodContext[format]/dayPeriodWidth[wide]/' + for key in ('am', 'pm'): + yield key, self.find(meridiem + 'dayPeriod[{}]'.format(key), + draft = Node.draftScore('contributed')) + + for pair in (('long', 'full'), ('short', 'short')): + for key in ('time', 'date'): + yield (pair[0] + key.capitalize() + 'Format', + convert_date(self.find( + stem + '{}Formats/{}FormatLength[{}]/{}Format/pattern'.format( + key, key, pair[1], key)))) + + def endonyms(self, language, script, country, variant): + # TODO: take variant into account ? + for seq in ((language, script, country), + (language, script), (language, country), (language,)): + if not all(seq): + continue + try: + yield ('languageEndonym', + self.find('localeDisplayNames/languages/language[{}]' + .format('_'.join(seq)))) + except Error: + pass + else: + break + else: + # grumble(failed to find endonym for language) + yield 'languageEndonym', '' + + yield ('countryEndonym', + self.find('localeDisplayNames/territories/territory[{}]' + .format(country), '')) + + def unitData(self): + yield ('byte_unit', + self.find('units/unitLength[long]/unit[digital-byte]/displayName', + 'bytes')) + + unit = self.__findUnit('', 'B') + cache = [] # Populated by the SI call, to give hints to the IEC call + yield ('byte_si_quantified', + ';'.join(self.__unitCount('', unit, cache))) + # IEC 60027-2 + # http://physics.nist.gov/cuu/Units/binary.html + yield ('byte_iec_quantified', + ';'.join(self.__unitCount('bi', 'iB', cache))) + + def calendarNames(self, calendars): + namings = self.__nameForms + for cal in calendars: + stem = 'dates/calendars/calendar[' + cal + ']/months/' + for key, mode, size in namings: + prop = 'monthContext[' + mode + ']/monthWidth[' + size + ']/' + yield (key + 'Months_' + cal, + ';'.join(self.find(stem + prop + 'month[{}]'.format(i)) + for i in range(1, 13))) + + # Day data (for Gregorian, at least): + stem = 'dates/calendars/calendar[gregorian]/days/' + days = ('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat') + for (key, mode, size) in namings: + prop = 'dayContext[' + mode + ']/dayWidth[' + size + ']/day' + yield (key + 'Days', + ';'.join(self.find(stem + prop + '[' + day + ']') + for day in days)) + + # Implementation details + __nameForms = ( + ('standaloneLong', 'stand-alone', 'wide'), + ('standaloneShort', 'stand-alone', 'abbreviated'), + ('standaloneNarrow', 'stand-alone', 'narrow'), + ('long', 'format', 'wide'), + ('short', 'format', 'abbreviated'), + ('narrow', 'format', 'narrow'), + ) # Used for month and day names + + def __find(self, xpath): + retries = [ xpath.split('/') ] + while retries: + tags, elts, roots = retries.pop(), self.nodes, (self.base.root,) + for selector in tags: + tag, attrs = _parseXPath(selector) + elts = tuple(_iterateEach(e.findAllChildren(tag, attrs) for e in elts)) + if not elts: + break + + else: # Found matching elements + # Possibly filter elts to prefer the least drafty ? + for elt in elts: + yield elt + + # Process roots separately: otherwise the alias-processing + # is excessive. + for i, selector in enumerate(tags): + tag, attrs = _parseXPath(selector) + + for alias in tuple(_iterateEach(r.findAllChildren('alias', allDull=True) + for r in roots)): + if alias.dom.attributes['source'].nodeValue == 'locale': + replace = alias.dom.attributes['path'].nodeValue.split('/') + retries.append(self.__xpathJoin(tags[:i], replace, tags[i:])) + + roots = tuple(_iterateEach(r.findAllChildren(tag, attrs) for r in roots)) + if not roots: + if retries: # Let outer loop fall back on an alias path: + break + sought = '/'.join(tags) + if sought != xpath: + sought += ' (for {})'.format(xpath) + raise Error('All lack child {} for {} in {}'.format( + selector, sought, self.name)) + + else: # Found matching elements + for elt in roots: + yield elt + + sought = '/'.join(tags) + if sought != xpath: + sought += ' (for {})'.format(xpath) + raise Error('No {} in {}'.format(sought, self.name)) + + def __findUnit(self, keySuffix, quantify, fallback=''): + # The displayName for a quantified unit in en.xml is kByte + # (even for unitLength[narrow]) instead of kB (etc.), so + # prefer any unitPattern provided, but prune its placeholder: + for size in ('short', 'narrow'): # TODO: reverse order ? + stem = 'units/unitLength[{}]/unit[digital-{}byte]/'.format(size + keySuffix, quantify) + for count in ('many', 'few', 'two', 'other', 'zero', 'one'): + try: + ans = self.find(stem + 'unitPattern[count={}]'.format(count)) + except Error: + continue + + # TODO: do count-handling, instead of discarding placeholders + if False: # TODO: do it this way, instead ! + ans = ans.replace('{0}', '').strip() + elif ans.startswith('{0}'): + ans = ans[3:].lstrip() + if ans: + return ans + + try: + return self.find(stem + 'displayName') + except Error: + pass + + return fallback + + def __unitCount(self, keySuffix, suffix, cache, + # Stop at exa/exbi: 16 exbi = 2^{64} < zetta = + # 1000^7 < zebi = 2^{70}, the next quantifiers up: + siQuantifiers = ('kilo', 'mega', 'giga', 'tera', 'peta', 'exa')): + """Work out the unit quantifiers. + + Unfortunately, the CLDR data only go up to terabytes and we + want all the way to exabytes; but we can recognize the SI + quantifiers as prefixes, strip and identify the tail as the + localized translation for 'B' (e.g. French has 'octet' for + 'byte' and uses ko, Mo, Go, To from which we can extrapolate + Po, Eo). + + Should be called first for the SI quantifiers, with suffix = + 'B', then for the IEC ones, with suffix = 'iB'; the list cache + (initially empty before first call) is used to let the second + call know what the first learned about the localized unit. + """ + if suffix == 'iB': # second call, re-using first's cache + if cache: + byte = cache.pop() + if all(byte == k for k in cache): + suffix = 'i' + byte + for q in siQuantifiers: + # Those don't (yet, v36) exist in CLDR, so we always get the fall-back: + yield self.__findUnit(keySuffix, q[:2], q[0].upper() + suffix) + else: # first call + tail = suffix = suffix or 'B' + for q in siQuantifiers: + it = self.__findUnit(keySuffix, q) + # kB for kilobyte, in contrast with KiB for IEC: + q = q[0] if q == 'kilo' else q[0].upper() + if not it: + it = q + tail + elif it.startswith(q): + rest = it[1:] + tail = rest if all(rest == k for k in cache) else suffix + cache.append(rest) + yield it + + @staticmethod + def __currencyFormats(patterns, plus, minus): + for p in patterns.split(';'): + p = p.replace('0', '#').replace(',', '').replace('.', '') + try: + cut = p.find('#') + 1 + except ValueError: + pass + else: + p = p[:cut] + p[cut:].replace('#', '') + p = p.replace('#', "%1") + # According to http://www.unicode.org/reports/tr35/#Number_Format_Patterns + # there can be doubled or trippled currency sign, however none of the + # locales use that. + p = p.replace(u'\xa4', "%2") + # Single quote goes away, but double goes to single: + p = p.replace("''", '###').replace("'", '').replace('###', "'") + # Use number system's signs: + p = p.replace('+', plus).replace('-', minus) + yield p + + @staticmethod + def __fromLdmlListPattern(pattern): + # This is a very limited parsing of the format for list pattern part only. + return pattern.replace('{0}', '%1').replace('{1}', '%2').replace('{2}', '%3') + + @staticmethod + def __fromLdmlPath(seq): # tool function for __xpathJoin() + """Convert LDML's [@name='value'] to our [name=value] form.""" + for it in seq: + # First dismember it: + attrs = it.split('[') + tag = attrs.pop(0) + if not attrs: # Short-cut the easy case: + yield it + continue + + assert all(x.endswith(']') for x in attrs) + attrs = [x[:-1].split('=') for x in attrs] + # Then fix each attribute specification in it: + attrs = [(x[0][1:] if x[0].startswith('@') else x[0], + x[1][1:-1] if x[1].startswith("'") and x[1].endswith("'") else x[1]) + for x in attrs] + # Finally, put it all back together: + attrs = ['='.join(x) + ']' for x in attrs] + attrs.insert(0, tag) + yield '['.join(attrs) + + @classmethod + def __xpathJoin(cls, head, insert, tail): + """Join three lists of XPath selectors. + + Each of head, insert and tail is a sequence of selectors but + insert may start with some uses of '..', that we want to + resolve away, and may use LDML's attribute format, that we + want to convert to our format.""" + while insert and insert[0] == '..': + insert.pop(0) + head.pop() + return head + list(cls.__fromLdmlPath(insert)) + tail diff --git a/util/locale_database/localetools.py b/util/locale_database/localetools.py new file mode 100644 index 00000000000..29153366b33 --- /dev/null +++ b/util/locale_database/localetools.py @@ -0,0 +1,164 @@ +############################################################################# +## +## Copyright (C) 2020 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# +"""Utilities shared among the CLDR extraction tools. + +Functions: + unicode2hex() -- converts unicode text to UCS-2 in hex form. + wrap_list() -- map list to comma-separated string, 20 entries per line. + +Classes: + Error -- A shared error class. + Transcriber -- edit a file by writing a temporary file, then renaming. + SourceFileEditor -- adds standard prelude and tail handling to Transcriber. +""" + +import os +import tempfile + +class Error (StandardError): + __upinit = StandardError.__init__ + def __init__(self, msg, *args): + self.__upinit(msg, *args) + self.message = msg + def __str__(self): + return self.message + +def unicode2hex(s): + lst = [] + for x in s: + v = ord(x) + if v > 0xFFFF: + # make a surrogate pair + # copied from qchar.h + high = (v >> 10) + 0xd7c0 + low = (v % 0x400 + 0xdc00) + lst.append(hex(high)) + lst.append(hex(low)) + else: + lst.append(hex(v)) + return lst + +def wrap_list(lst): + def split(lst, size): + while lst: + head, lst = lst[:size], lst[size:] + yield head + return ",\n".join(", ".join(x) for x in split(lst, 20)) + +class Transcriber (object): + """Helper class to facilitate rewriting source files. + + This class takes care of the temporary file manipulation. Derived + classes need to implement transcribing of the content, with + whatever modifications they may want. Members reader and writer + are exposed; use writer.write() to output to the new file; use + reader.readline() or iterate reader to read the original. + + Callers should call close() on success or cleanup() on failure (to + clear away the temporary file). + """ + def __init__(self, path, temp): + # Open the old file + self.reader = open(path) + # Create a temp file to write the new data into + temp, tempPath = tempfile.mkstemp(os.path.split(path)[1], dir = temp) + self.__names = path, tempPath + self.writer = os.fdopen(temp, "w") + + def close(self): + self.reader.close() + self.writer.close() + self.reader = self.writer = None + source, temp = self.__names + os.remove(source) + os.rename(temp, source) + + def cleanup(self): + if self.__names: + self.reader.close() + self.writer.close() + # Remove temp-file: + os.remove(self.__names[1]) + self.__names = () + +class SourceFileEditor (Transcriber): + """Transcriber with transcription of code around a gnerated block. + + We have a common pattern of source files with a generated part + embedded in a context that's not touched by the regeneration + scripts. The generated part is, in each case, marked with a common + pair of start and end markers. We transcribe the old file to a new + temporary file; on success, we then remove the original and move + the new version to replace it. + + This class takes care of transcribing the parts before and after + the generated content; on creation, an instance will copy the + preamble up to the start marker; its close() will skip over the + original's generated content and resume transcribing with the end + marker. Derived classes need only implement the generation of the + content in between. + + Callers should call close() on success or cleanup() on failure (to + clear away the temporary file); see Transcriber. + """ + __upinit = Transcriber.__init__ + def __init__(self, path, temp): + """Set up the source file editor. + + Requires two arguments: the path to the source file to be read + and, on success, replaced with a new version; and the + directory in which to store the temporary file during the + rewrite.""" + self.__upinit(path, temp) + self.__copyPrelude() + + __upclose = Transcriber.close + def close(self): + self.__copyTail() + self.__upclose() + + # Implementation details: + GENERATED_BLOCK_START = '// GENERATED PART STARTS HERE' + GENERATED_BLOCK_END = '// GENERATED PART ENDS HERE' + + def __copyPrelude(self): + # Copy over the first non-generated section to the new file + for line in self.reader: + self.writer.write(line) + if line.strip() == self.GENERATED_BLOCK_START: + break + + def __copyTail(self): + # Skip through the old generated data in the old file + for line in self.reader: + if line.strip() == self.GENERATED_BLOCK_END: + self.writer.write(line) + break + # Transcribe the remainder: + for line in self.reader: + self.writer.write(line) diff --git a/util/locale_database/qlocalexml.py b/util/locale_database/qlocalexml.py index 0a4628e05ef..550021ba019 100644 --- a/util/locale_database/qlocalexml.py +++ b/util/locale_database/qlocalexml.py @@ -28,11 +28,18 @@ ############################################################################# """Shared serialization-scanning code for QLocaleXML format. -The Locale class is written by cldr2qlocalexml.py and read by qlocalexml2cpp.py +Provides classes: + Locale -- common data-type representing one locale as a namespace + QLocaleXmlWriter -- helper to write a QLocaleXML file + QLocaleXmlReader -- helper to read a QLocaleXML file back in + +Support: + Spacer -- provides control over indentation of the output. """ +from __future__ import print_function from xml.sax.saxutils import escape -import xpathlite +from localetools import Error # Tools used by Locale: def camel(seq): @@ -43,6 +50,10 @@ def camel(seq): def camelCase(words): return ''.join(camel(iter(words))) +def addEscapes(s): + return ''.join(c if n < 128 else '\\x{:02x}'.format(n) + for n, c in ((ord(c), c) for c in s)) + def startCount(c, text): # strspn """First index in text where it doesn't have a character in c""" assert text and text[0] in c @@ -58,6 +69,8 @@ def convertFormat(format): * https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table * QDateTimeParser::parseFormat() and QLocalePrivate::dateTimeToString() """ + # Compare and contrast dateconverter.py's convert_date(). + # Need to (check consistency and) reduce redundancy ! result = "" i = 0 while i < len(format): @@ -102,7 +115,314 @@ def convertFormat(format): return result -class Locale: +class QLocaleXmlReader (object): + def __init__(self, filename): + self.root = self.__parse(filename) + # Lists of (id, name, code) triples: + languages = tuple(self.__loadMap('language')) + scripts = tuple(self.__loadMap('script')) + countries = tuple(self.__loadMap('country')) + self.__likely = tuple(self.__likelySubtagsMap()) + # Mappings {ID: (name, code)} + self.languages = dict((v[0], v[1:]) for v in languages) + self.scripts = dict((v[0], v[1:]) for v in scripts) + self.countries = dict((v[0], v[1:]) for v in countries) + # Private mappings {name: (ID, code)} + self.__langByName = dict((v[1], (v[0], v[2])) for v in languages) + self.__textByName = dict((v[1], (v[0], v[2])) for v in scripts) + self.__landByName = dict((v[1], (v[0], v[2])) for v in countries) + # Other properties: + self.dupes = set(v[1] for v in languages) & set(v[1] for v in countries) + self.cldrVersion = self.__firstChildText(self.root, "version") + + def loadLocaleMap(self, calendars, grumble = lambda text: None): + kid = self.__firstChildText + likely = dict(self.__likely) + for elt in self.__eachEltInGroup(self.root, 'localeList', 'locale'): + locale = Locale.fromXmlData(lambda k: kid(elt, k), calendars) + language = self.__langByName[locale.language][0] + script = self.__textByName[locale.script][0] + country = self.__landByName[locale.country][0] + + if language != 1: # C + if country == 0: + grumble('loadLocaleMap: No country id for "{}"\n'.format(locale.language)) + + if script == 0: + # Find default script for the given language and country - see: + # http://www.unicode.org/reports/tr35/#Likely_Subtags + try: + try: + to = likely[(locale.language, 'AnyScript', locale.country)] + except KeyError: + to = likely[(locale.language, 'AnyScript', 'AnyCountry')] + except KeyError: + pass + else: + locale.script = to[1] + script = self.__textByName[locale.script][0] + + yield (language, script, country), locale + + def languageIndices(self, locales): + index = 0 + for key, value in self.languages.iteritems(): + i, count = 0, locales.count(key) + if count > 0: + i = index + index += count + yield i, value[0] + + def likelyMap(self): + def tag(t): + lang, script, land = t + yield lang[1] if lang[0] else 'und' + if script[0]: yield script[1] + if land[0]: yield land[1] + + def ids(t): + return tuple(x[0] for x in t) + + for i, pair in enumerate(self.__likely, 1): + have = self.__fromNames(pair[0]) + give = self.__fromNames(pair[1]) + yield ('_'.join(tag(have)), ids(have), + '_'.join(tag(give)), ids(give), + i == len(self.__likely)) + + def defaultMap(self): + """Map language and script to their default country by ID. + + Yields ((language, script), country) wherever the likely + sub-tags mapping says language's default locale uses the given + script and country.""" + for have, give in self.__likely: + if have[1:] == ('AnyScript', 'AnyCountry') and give[2] != 'AnyCountry': + assert have[0] == give[0], (have, give) + yield ((self.__langByName[give[0]][0], + self.__textByName[give[1]][0]), + self.__landByName[give[2]][0]) + + # Implementation details: + def __loadMap(self, category): + kid = self.__firstChildText + for element in self.__eachEltInGroup(self.root, category + 'List', category): + yield int(kid(element, 'id')), kid(element, 'name'), kid(element, 'code') + + def __likelySubtagsMap(self): + def triplet(element, keys=('language', 'script', 'country'), kid = self.__firstChildText): + return tuple(kid(element, key) for key in keys) + + kid = self.__firstChildElt + for elt in self.__eachEltInGroup(self.root, 'likelySubtags', 'likelySubtag'): + yield triplet(kid(elt, "from")), triplet(kid(elt, "to")) + + def __fromNames(self, names): + return self.__langByName[names[0]], self.__textByName[names[1]], self.__landByName[names[2]] + + # DOM access: + from xml.dom import minidom + @staticmethod + def __parse(filename, read = minidom.parse): + return read(filename).documentElement + + @staticmethod + def __isNodeNamed(elt, name, TYPE=minidom.Node.ELEMENT_NODE): + return elt.nodeType == TYPE and elt.nodeName == name + del minidom + + @staticmethod + def __eltWords(elt): + child = elt.firstChild + while child: + if child.nodeType == elt.TEXT_NODE: + yield child.nodeValue + child = child.nextSibling + + @classmethod + def __firstChildElt(cls, parent, name): + child = parent.firstChild + while child: + if cls.__isNodeNamed(child, name): + return child + child = child.nextSibling + + raise Error('No {} child found'.format(name)) + + @classmethod + def __firstChildText(cls, elt, key): + return ' '.join(cls.__eltWords(cls.__firstChildElt(elt, key))) + + @classmethod + def __eachEltInGroup(cls, parent, group, key): + try: + element = cls.__firstChildElt(parent, group).firstChild + except Error: + element = None + + while element: + if cls.__isNodeNamed(element, key): + yield element + element = element.nextSibling + + +class Spacer (object): + def __init__(self, indent = None, initial = ''): + """Prepare to manage indentation and line breaks. + + Arguments are both optional. + + First argument, indent, is either None (its default, for + 'minifying'), an ingeter (number of spaces) or the unit of + text that is to be used for each indentation level (e.g. '\t' + to use tabs). If indent is None, no indentation is added, nor + are line-breaks; otherwise, self(text), for non-empty text, + shall end with a newline and begin with indentation. + + Second argument, initial, is the initial indentation; it is + ignored if indent is None. Indentation increases after each + call to self(text) in which text starts with a tag and doesn't + include its end-tag; indentation decreases if text starts with + an end-tag. The text is not parsed any more carefully than + just described. + """ + if indent is None: + self.__call = lambda x: x + else: + self.__each = ' ' * indent if isinstance(indent, int) else indent + self.current = initial + self.__call = self.__wrap + + def __wrap(self, line): + if not line: + return '\n' + + indent = self.current + if line.startswith('') + tag = (line[1:] if cut < 0 else line[1 : cut]).strip().split()[0] + if ''.format(tag) not in line: + self.current += self.__each + return indent + line + '\n' + + def __call__(self, line): + return self.__call(line) + +class QLocaleXmlWriter (object): + def __init__(self, save = None, space = Spacer(4)): + """Set up to write digested CLDR data as QLocale XML. + + Arguments are both optional. + + First argument, save, is None (its default) or a callable that + will write content to where you intend to save it. If None, it + is replaced with a callable that prints the given content, + suppressing the newline (but see the following); this is + equivalent to passing sys.stdout.write. + + Second argument, space, is an object to call on each text + output to prepend indentation and append newlines, or not as + the case may be. The default is a Spacer(4), which grows + indent by four spaces after each unmatched new tag and shrinks + back on a close-tag (its parsing is naive, but adequate to how + this class uses it), while adding a newline to each line. + """ + self.__rawOutput = self.__printit if save is None else save + self.__wrap = space + self.__write('') + + # Output of various sections, in their usual order: + def enumData(self, languages, scripts, countries): + self.__enumTable('languageList', languages) + self.__enumTable('scriptList', scripts) + self.__enumTable('countryList', countries) + + def likelySubTags(self, entries): + self.__openTag('likelySubtags') + for have, give in entries: + self.__openTag('likelySubtag') + self.__likelySubTag('from', have) + self.__likelySubTag('to', give) + self.__closeTag('likelySubtag') + self.__closeTag('likelySubtags') + + def locales(self, locales, calendars): + self.__openTag('localeList') + self.__openTag('locale') + Locale.C(calendars).toXml(self.inTag, calendars) + self.__closeTag('locale') + keys = locales.keys() + keys.sort() + for key in keys: + self.__openTag('locale') + locales[key].toXml(self.inTag, calendars) + self.__closeTag('locale') + self.__closeTag('localeList') + + def version(self, cldrVersion): + self.inTag('version', cldrVersion) + + def inTag(self, tag, text): + self.__write('<{0}>{1}'.format(tag, text)) + + def close(self): + if self.__rawOutput != self.__complain: + self.__write('') + self.__rawOutput = self.__complain + + # Implementation details + @staticmethod + def __printit(text): + print(text, end='') + @staticmethod + def __complain(text): + raise Error('Attempted to write data after closing :-(') + + def __enumTable(self, tag, table): + self.__openTag(tag) + for key, value in table.iteritems(): + self.__openTag(tag[:-4]) + self.inTag('name', value[0]) + self.inTag('id', key) + self.inTag('code', value[1]) + self.__closeTag(tag[:-4]) + self.__closeTag(tag) + + def __likelySubTag(self, tag, likely): + self.__openTag(tag) + self.inTag('language', likely[0]) + self.inTag('script', likely[1]) + self.inTag('country', likely[2]) + # self.inTag('variant', likely[3]) + self.__closeTag(tag) + + def __openTag(self, tag): + self.__write('<{}>'.format(tag)) + def __closeTag(self, tag): + self.__write(''.format(tag)) + + def __write(self, line): + self.__rawOutput(self.__wrap(line)) + +class Locale (object): + """Holder for the assorted data representing one locale. + + Implemented as a namespace; its constructor and update() have the + same signatures as those of a dict, acting on the instance's + __dict__, so the results are accessed as attributes rather than + mapping keys.""" + def __init__(self, data=None, **kw): + self.update(data, **kw) + + def update(self, data=None, **kw): + if data: self.__dict__.update(data) + if kw: self.__dict__.update(kw) + + def __len__(self): # Used when testing as a boolean + return len(self.__dict__) + @staticmethod def propsMonthDay(scale, lengths=('long', 'short', 'narrow')): for L in lengths: @@ -158,16 +478,24 @@ class Locale: return cls(data) - def toXml(self, calendars=('gregorian',), indent=' ', tab=' '): - print indent + '' - inner = indent + tab + def toXml(self, write, calendars=('gregorian',)): + """Writes its data as QLocale XML. + + First argument, write, is a callable taking the name and + content of an XML element; it is expected to be the inTag + bound method of a QLocaleXmlWriter instance. + + Optional second argument is a list of calendar names, in the + form used by CLDR; its default is ('gregorian',). + """ get = lambda k: getattr(self, k) for key in ('language', 'script', 'country'): - print inner + "<%s>" % key + get(key) + "" % key - print inner + "<%scode>" % key + get(key + '_code') + "" % key + write(key, get(key)) + write('{}code'.format(key), get('{}_code'.format(key))) - for key in ('decimal', 'group', 'zero', 'list', 'percent', 'minus', 'plus', 'exp'): - print inner + "<%s>" % key + get(key) + "" % key + for key in ('decimal', 'group', 'zero', 'list', + 'percent', 'minus', 'plus', 'exp'): + write(key, get(key)) for key in ('languageEndonym', 'countryEndonym', 'quotationStart', 'quotationEnd', @@ -185,16 +513,10 @@ class Locale: '_'.join((k, cal)) for k in self.propsMonthDay('months') for cal in calendars): - print inner + "<%s>%s" % (key, escape(get(key)).encode('utf-8'), key) + write(key, escape(get(key)).encode('utf-8')) for key in ('currencyDigits', 'currencyRounding'): - print inner + "<%s>%d" % (key, get(key), key) - - print indent + "" - - def __init__(self, data=None, **kw): - if data: self.__dict__.update(data) - if kw: self.__dict__.update(kw) + write(key, get(key)) # Tools used by __monthNames: def fullName(i, name): return name @@ -213,6 +535,9 @@ class Locale: @staticmethod def __monthNames(calendars, known={ # Map calendar to (names, extractors...): + # TODO: do we even need these ? CLDR's root.xml seems to + # have them, complete with yeartype="leap" handling for + # Hebrew's extra. 'gregorian': (('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'), # Extractor pairs, (plain, standalone) @@ -240,8 +565,8 @@ class Locale: for cal in calendars: try: data = known[cal] - except KeyError: # Need to add an entry to known, above. - print 'Unsupported calendar:', cal + except KeyError as e: # Need to add an entry to known, above. + e.args += ('Unsupported calendar:', cal) raise names, get = data[0], data[1:] for n, size in enumerate(sizes): @@ -253,12 +578,11 @@ class Locale: @classmethod def C(cls, calendars=('gregorian',), - # Empty entry at end to ensure final separator when join()ed: days = ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'), quantifiers=('k', 'M', 'G', 'T', 'P', 'E')): """Returns an object representing the C locale.""" - return cls(dict(cls.__monthNames(calendars)), + return cls(cls.__monthNames(calendars), language='C', language_code='0', languageEndonym='', script='AnyScript', script_code='0', country='AnyCountry', country_code='0', countryEndonym='', diff --git a/util/locale_database/qlocalexml2cpp.py b/util/locale_database/qlocalexml2cpp.py index 3dde298f47c..db45ab27782 100755 --- a/util/locale_database/qlocalexml2cpp.py +++ b/util/locale_database/qlocalexml2cpp.py @@ -34,238 +34,53 @@ the root of the qtbase check-out as second parameter. """ import os -import sys -import tempfile import datetime -import xml.dom.minidom -from enumdata import language_aliases, country_aliases, script_aliases -from qlocalexml import Locale - -# TODO: Make calendars a command-line parameter -# map { CLDR name: Qt file name } -calendars = {'gregorian': 'roman', 'persian': 'jalali', 'islamic': 'hijri',} # 'hebrew': 'hebrew', - -generated_template = """ -/* - This part of the file was generated on %s from the - Common Locale Data Repository v%s - - http://www.unicode.org/cldr/ - - Do not edit this section: instead regenerate it using - cldr2qlocalexml.py and qlocalexml2cpp.py on updated (or - edited) CLDR data; see qtbase/util/locale_database/. -*/ - -""" - -class Error: - def __init__(self, msg): - self.msg = msg - def __str__(self): - return self.msg - -def wrap_list(lst): - def split(lst, size): - while lst: - head, lst = lst[:size], lst[size:] - yield head - return ",\n".join(", ".join(x) for x in split(lst, 20)) - -def isNodeNamed(elt, name, TYPE=xml.dom.minidom.Node.ELEMENT_NODE): - return elt.nodeType == TYPE and elt.nodeName == name - -def firstChildElt(parent, name): - child = parent.firstChild - while child: - if isNodeNamed(child, name): - return child - child = child.nextSibling - - raise Error('No %s child found' % name) - -def eachEltInGroup(parent, group, key): - try: - element = firstChildElt(parent, group).firstChild - except Error: - element = None - - while element: - if isNodeNamed(element, key): - yield element - element = element.nextSibling - -def eltWords(elt): - child = elt.firstChild - while child: - if child.nodeType == elt.TEXT_NODE: - yield child.nodeValue - child = child.nextSibling - -def firstChildText(elt, key): - return ' '.join(eltWords(firstChildElt(elt, key))) - -def loadMap(doc, category): - return dict((int(firstChildText(element, 'id')), - (firstChildText(element, 'name'), - firstChildText(element, 'code'))) - for element in eachEltInGroup(doc.documentElement, - category + 'List', category)) - -def loadLikelySubtagsMap(doc): - def triplet(element, keys=('language', 'script', 'country')): - return tuple(firstChildText(element, key) for key in keys) - - return dict((i, {'from': triplet(firstChildElt(elt, "from")), - 'to': triplet(firstChildElt(elt, "to"))}) - for i, elt in enumerate(eachEltInGroup(doc.documentElement, - 'likelySubtags', 'likelySubtag'))) - -def fixedScriptName(name, dupes): - # Don't .capitalize() as some names are already camel-case (see enumdata.py): - name = ''.join(word[0].upper() + word[1:] for word in name.split()) - if name[-6:] != "Script": - name = name + "Script" - if name in dupes: - sys.stderr.write("\n\n\nERROR: The script name '%s' is messy" % name) - sys.exit(1) - return name - -def fixedCountryName(name, dupes): - if name in dupes: - return name.replace(" ", "") + "Country" - return name.replace(" ", "") - -def fixedLanguageName(name, dupes): - if name in dupes: - return name.replace(" ", "") + "Language" - return name.replace(" ", "") - -def findDupes(country_map, language_map): - country_set = set(v[0] for a, v in country_map.iteritems()) - language_set = set(v[0] for a, v in language_map.iteritems()) - return country_set & language_set - -def languageNameToId(name, language_map): - for key in language_map.keys(): - if language_map[key][0] == name: - return key - return -1 - -def scriptNameToId(name, script_map): - for key in script_map.keys(): - if script_map[key][0] == name: - return key - return -1 - -def countryNameToId(name, country_map): - for key in country_map.keys(): - if country_map[key][0] == name: - return key - return -1 - -def loadLocaleMap(doc, language_map, script_map, country_map, likely_subtags_map): - result = {} - - for locale_elt in eachEltInGroup(doc.documentElement, "localeList", "locale"): - locale = Locale.fromXmlData(lambda k: firstChildText(locale_elt, k), calendars.keys()) - language_id = languageNameToId(locale.language, language_map) - if language_id == -1: - sys.stderr.write("Cannot find a language id for '%s'\n" % locale.language) - script_id = scriptNameToId(locale.script, script_map) - if script_id == -1: - sys.stderr.write("Cannot find a script id for '%s'\n" % locale.script) - country_id = countryNameToId(locale.country, country_map) - if country_id == -1: - sys.stderr.write("Cannot find a country id for '%s'\n" % locale.country) - - if language_id != 1: # C - if country_id == 0: - sys.stderr.write("loadLocaleMap: No country id for '%s'\n" % locale.language) - - if script_id == 0: - # find default script for a given language and country (see http://www.unicode.org/reports/tr35/#Likely_Subtags) - for key in likely_subtags_map.keys(): - tmp = likely_subtags_map[key] - if tmp["from"][0] == locale.language and tmp["from"][1] == "AnyScript" and tmp["from"][2] == locale.country: - locale.script = tmp["to"][1] - script_id = scriptNameToId(locale.script, script_map) - break - if script_id == 0 and country_id != 0: - # try with no country - for key in likely_subtags_map.keys(): - tmp = likely_subtags_map[key] - if tmp["from"][0] == locale.language and tmp["from"][1] == "AnyScript" and tmp["from"][2] == "AnyCountry": - locale.script = tmp["to"][1] - script_id = scriptNameToId(locale.script, script_map) - break - - result[(language_id, script_id, country_id)] = locale - - return result +from qlocalexml import QLocaleXmlReader +from xml.dom import minidom +from localetools import unicode2hex, wrap_list, Error, Transcriber, SourceFileEditor def compareLocaleKeys(key1, key2): if key1 == key2: return 0 - if key1[0] == key2[0]: - l1 = compareLocaleKeys.locale_map[key1] - l2 = compareLocaleKeys.locale_map[key2] - - if (l1.language, l1.script) in compareLocaleKeys.default_map.keys(): - default = compareLocaleKeys.default_map[(l1.language, l1.script)] - if l1.country == default: - return -1 - if l2.country == default: - return 1 - - if key1[1] != key2[1]: - if (l2.language, l2.script) in compareLocaleKeys.default_map.keys(): - default = compareLocaleKeys.default_map[(l2.language, l2.script)] - if l2.country == default: - return 1 - if l1.country == default: - return -1 - - if key1[1] != key2[1]: - return key1[1] - key2[1] - else: + if key1[0] != key2[0]: # First sort by language: return key1[0] - key2[0] - return key1[2] - key2[2] + defaults = compareLocaleKeys.default_map + # maps {(language, script): country} by ID + try: + country = defaults[key1[:2]] + except KeyError: + pass + else: + if key1[2] == country: + return -1 + if key2[2] == country: + return 1 + if key1[1] == key2[1]: + return key1[2] - key2[2] -def languageCount(language_id, locale_map): - result = 0 - for key in locale_map.keys(): - if key[0] == language_id: - result += 1 - return result + try: + country = defaults[key2[:2]] + except KeyError: + pass + else: + if key2[2] == country: + return 1 + if key1[2] == country: + return -1 + + return key1[1] - key2[1] -def unicode2hex(s): - lst = [] - for x in s: - v = ord(x) - if v > 0xFFFF: - # make a surrogate pair - # copied from qchar.h - high = (v >> 10) + 0xd7c0 - low = (v % 0x400 + 0xdc00) - lst.append(hex(high)) - lst.append(hex(low)) - else: - lst.append(hex(v)) - return lst class StringDataToken: def __init__(self, index, length, bits): if index > 0xffff: - print "\n\n\n#error Data index is too big!", index - raise ValueError("Start-index (%d) exceeds the uint16 range!" % index) + raise ValueError('Start-index ({}) exceeds the uint16 range!'.format(index)) if length >= (1 << bits): - print "\n\n\n#error Range length is too big!", length - raise ValueError("Data size (%d) exceeds the %d-bit range!" % (length, bits)) + raise ValueError('Data size ({}) exceeds the {}-bit range!'.format(length, bits)) self.index = index self.length = length @@ -277,7 +92,7 @@ class StringData: self.name = name self.text = '' # Used in quick-search for matches in data - def append(self, s, bits=8): + def append(self, s, bits = 8): try: token = self.hash[s] except KeyError: @@ -317,592 +132,481 @@ class StringData: def write(self, fd): if len(self.data) > 0xffff: - raise ValueError("Data is too big for quint16 index to its end!" % len(self.data), + raise ValueError('Data is too big ({}) for quint16 index to its end!' + .format(len(self.data)), self.name) - fd.write("\nstatic const char16_t %s[] = {\n" % self.name) + fd.write("\nstatic const char16_t {}[] = {{\n".format(self.name)) fd.write(wrap_list(self.data)) fd.write("\n};\n") -def escapedString(s): - result = "" - i = 0 - while i < len(s): - if s[i] == '"': - result += '\\"' - i += 1 - else: - result += s[i] - i += 1 - s = result - - line = "" - need_escape = False - result = "" - for c in s: - if ord(c) < 128 and not (need_escape and ord('a') <= ord(c.lower()) <= ord('f')): - line += c - need_escape = False - else: - line += "\\x%02x" % (ord(c)) - need_escape = True - if len(line) > 80: - result = result + "\n" + '"' + line + '"' - line = "" - line += "\\0" - result = result + "\n" + '"' + line + '"' - if result[0] == "\n": - result = result[1:] - return result - -def printEscapedString(s): - print escapedString(s) - def currencyIsoCodeData(s): if s: return '{' + ",".join(str(ord(x)) for x in s) + '}' return "{0,0,0}" -def usage(): - print "Usage: qlocalexml2cpp.py " - sys.exit(1) +class LocaleSourceEditor (SourceFileEditor): + __upinit = SourceFileEditor.__init__ + def __init__(self, path, temp, version): + self.__upinit(path, temp) + self.writer.write(""" +/* + This part of the file was generated on {} from the + Common Locale Data Repository v{} -GENERATED_BLOCK_START = "// GENERATED PART STARTS HERE\n" -GENERATED_BLOCK_END = "// GENERATED PART ENDS HERE\n" + http://www.unicode.org/cldr/ -def main(): - if len(sys.argv) != 3: - usage() + Do not edit this section: instead regenerate it using + cldr2qlocalexml.py and qlocalexml2cpp.py on updated (or + edited) CLDR data; see qtbase/util/locale_database/. +*/ - qlocalexml = sys.argv[1] - qtsrcdir = sys.argv[2] +""".format(datetime.date.today(), version)) - if not (os.path.isdir(qtsrcdir) - and all(os.path.isfile(os.path.join(qtsrcdir, 'src', 'corelib', 'text', leaf)) - for leaf in ('qlocale_data_p.h', 'qlocale.h', 'qlocale.qdoc'))): - usage() +class LocaleDataWriter (LocaleSourceEditor): + def likelySubtags(self, likely): + self.writer.write('static const QLocaleId likely_subtags[] = {\n') + for had, have, got, give, last in likely: + self.writer.write(' {{ {:3d}, {:3d}, {:3d} }}'.format(*have)) + self.writer.write(', {{ {:3d}, {:3d}, {:3d} }}'.format(*give)) + self.writer.write(' ' if last else ',') + self.writer.write(' // {} -> {}\n'.format(had, got)) + self.writer.write('};\n\n') - (data_temp_file, data_temp_file_path) = tempfile.mkstemp("qlocale_data_p.h", dir=qtsrcdir) - data_temp_file = os.fdopen(data_temp_file, "w") - qlocaledata_file = open(qtsrcdir + "/src/corelib/text/qlocale_data_p.h", "r") - s = qlocaledata_file.readline() - while s and s != GENERATED_BLOCK_START: - data_temp_file.write(s) - s = qlocaledata_file.readline() - data_temp_file.write(GENERATED_BLOCK_START) + def localeIndex(self, indices): + self.writer.write('static const quint16 locale_index[] = {\n') + for pair in indices: + self.writer.write('{:6d}, // {}\n'.format(*pair)) + self.writer.write(' 0 // trailing 0\n') + self.writer.write('};\n\n') - doc = xml.dom.minidom.parse(qlocalexml) - language_map = loadMap(doc, 'language') - script_map = loadMap(doc, 'script') - country_map = loadMap(doc, 'country') - likely_subtags_map = loadLikelySubtagsMap(doc) - default_map = {} - for key in likely_subtags_map.keys(): - tmp = likely_subtags_map[key] - if tmp["from"][1] == "AnyScript" and tmp["from"][2] == "AnyCountry" and tmp["to"][2] != "AnyCountry": - default_map[(tmp["to"][0], tmp["to"][1])] = tmp["to"][2] - locale_map = loadLocaleMap(doc, language_map, script_map, country_map, likely_subtags_map) - dupes = findDupes(language_map, country_map) + def localeData(self, locales, names): + list_pattern_part_data = StringData('list_pattern_part_data') + single_character_data = StringData('single_character_data') + date_format_data = StringData('date_format_data') + time_format_data = StringData('time_format_data') + days_data = StringData('days_data') + am_data = StringData('am_data') + pm_data = StringData('pm_data') + byte_unit_data = StringData('byte_unit_data') + currency_symbol_data = StringData('currency_symbol_data') + currency_display_name_data = StringData('currency_display_name_data') + currency_format_data = StringData('currency_format_data') + endonyms_data = StringData('endonyms_data') - cldr_version = firstChildText(doc.documentElement, "version") - data_temp_file.write(generated_template % (datetime.date.today(), cldr_version)) + # Locale data + self.writer.write('static const QLocaleData locale_data[] = {\n') + # Table headings: keep each label centred in its field, matching line_format: + self.writer.write(' // ' + # Width 6 + comma + ' lang ' # IDs + 'script ' + ' terr ' - # Likely subtags map - data_temp_file.write("static const QLocaleId likely_subtags[] = {\n") - index = 0 - for key in likely_subtags_map.keys(): - tmp = likely_subtags_map[key] - from_language = languageNameToId(tmp["from"][0], language_map) - from_script = scriptNameToId(tmp["from"][1], script_map) - from_country = countryNameToId(tmp["from"][2], country_map) - to_language = languageNameToId(tmp["to"][0], language_map) - to_script = scriptNameToId(tmp["to"][1], script_map) - to_country = countryNameToId(tmp["to"][2], country_map) + # Range entries (all start-indices, then all sizes) + # Width 5 + comma + 'lStrt ' # List pattern + 'lpMid ' + 'lpEnd ' + 'lPair ' + 'lDelm ' # List delimiter + # Representing numbers + ' dec ' + 'group ' + 'prcnt ' + ' zero ' + 'minus ' + 'plus ' + ' exp ' + # Quotation marks + 'qtOpn ' + 'qtEnd ' + 'altQO ' + 'altQE ' + 'lDFmt ' # Date format + 'sDFmt ' + 'lTFmt ' # Time format + 'sTFmt ' + 'slDay ' # Day names + 'lDays ' + 'ssDys ' + 'sDays ' + 'snDay ' + 'nDays ' + ' am ' # am/pm indicators + ' pm ' + ' byte ' + 'siQnt ' + 'iecQn ' + 'crSym ' # Currency formatting + 'crDsp ' + 'crFmt ' + 'crFNg ' + 'ntLng ' # Name of language in itself, and of territory + 'ntTer ' + # Width 3 + comma for each size; no header + + ' ' * 37 + - cmnt_from = "" - if from_language != 0: - cmnt_from = cmnt_from + language_map[from_language][1] - else: - cmnt_from = cmnt_from + "und" - if from_script != 0: - if cmnt_from: - cmnt_from = cmnt_from + "_" - cmnt_from = cmnt_from + script_map[from_script][1] - if from_country != 0: - if cmnt_from: - cmnt_from = cmnt_from + "_" - cmnt_from = cmnt_from + country_map[from_country][1] - cmnt_to = "" - if to_language != 0: - cmnt_to = cmnt_to + language_map[to_language][1] - else: - cmnt_to = cmnt_to + "und" - if to_script != 0: - if cmnt_to: - cmnt_to = cmnt_to + "_" - cmnt_to = cmnt_to + script_map[to_script][1] - if to_country != 0: - if cmnt_to: - cmnt_to = cmnt_to + "_" - cmnt_to = cmnt_to + country_map[to_country][1] + # Strays (char array, bit-fields): + # Width 10 + 2 spaces + comma + ' currISO ' + # Width 6 + comma + 'curDgt ' # Currency digits + 'curRnd ' # Currencty rounding (unused: QTBUG-81343) + 'dow1st ' # First day of week + ' wknd+ ' # Week-end start/end days + ' wknd-' + # No trailing space on last entry (be sure to + # pad before adding anything after it). + '\n') - data_temp_file.write(" ") - data_temp_file.write("{ %3d, %3d, %3d }, { %3d, %3d, %3d }" % - (from_language, from_script, from_country, to_language, to_script, to_country)) - index += 1 - if index != len(likely_subtags_map): - data_temp_file.write(",") - else: - data_temp_file.write(" ") - data_temp_file.write(" // %s -> %s\n" % (cmnt_from, cmnt_to)) - data_temp_file.write("};\n") + formatLine = ''.join(( + ' {{ ', + # Locale-identifier + '{:6d},' * 3, + # List patterns, date/time formats, day names, am/pm + # SI/IEC byte-unit abbreviations + # Currency and endonyms + # Range starts + '{:5d},' * 37, + # Range sizes + '{:3d},' * 37, - data_temp_file.write("\n") + # Currency ISO code + ' {:>10s}, ', + # Currency formatting + '{:6d},{:6d}', + # Day of week and week-end + ',{:6d}' * 3, + ' }}')).format + for key in names: + locale = locales[key] + # Sequence of StringDataToken: + ranges = (tuple(list_pattern_part_data.append(p) for p in # 5 entries: + (locale.listPatternPartStart, locale.listPatternPartMiddle, + locale.listPatternPartEnd, locale.listPatternPartTwo, + locale.listDelim)) + + tuple(single_character_data.append(p) for p in # 11 entries + (locale.decimal, locale.group, locale.percent, locale.zero, + locale.minus, locale.plus, locale.exp, + locale.quotationStart, locale.quotationEnd, + locale.alternateQuotationStart, locale.alternateQuotationEnd)) + + tuple (date_format_data.append(f) for f in # 2 entries: + (locale.longDateFormat, locale.shortDateFormat)) + + tuple(time_format_data.append(f) for f in # 2 entries: + (locale.longTimeFormat, locale.shortTimeFormat)) + + tuple(days_data.append(d) for d in # 6 entries: + (locale.standaloneLongDays, locale.longDays, + locale.standaloneShortDays, locale.shortDays, + locale.standaloneNarrowDays, locale.narrowDays)) + + (am_data.append(locale.am), pm_data.append(locale.pm)) + # 2 entries + tuple(byte_unit_data.append(b) for b in # 3 entries: + (locale.byte_unit, + locale.byte_si_quantified, + locale.byte_iec_quantified)) + + (currency_symbol_data.append(locale.currencySymbol), + currency_display_name_data.append(locale.currencyDisplayName), + currency_format_data.append(locale.currencyFormat), + currency_format_data.append(locale.currencyNegativeFormat), + endonyms_data.append(locale.languageEndonym), + endonyms_data.append(locale.countryEndonym)) # 6 entries + ) # Total: 37 entries + assert len(ranges) == 37 - # Locale index - data_temp_file.write("static const quint16 locale_index[] = {\n") - index = 0 - for key in language_map.keys(): - i = 0 - count = languageCount(key, locale_map) - if count > 0: - i = index - index += count - data_temp_file.write("%6d, // %s\n" % (i, language_map[key][0])) - data_temp_file.write(" 0 // trailing 0\n") - data_temp_file.write("};\n\n") + self.writer.write(formatLine(*( + key + + tuple(r.index for r in ranges) + + tuple(r.length for r in ranges) + + (currencyIsoCodeData(locale.currencyIsoCode), + locale.currencyDigits, + locale.currencyRounding, # unused (QTBUG-81343) + locale.firstDayOfWeek, + locale.weekendStart, + locale.weekendEnd) )) + + ', // {}/{}/{}\n'.format( + locale.language, locale.script, locale.country)) + self.writer.write(formatLine(*( # All zeros, matching the format: + (0,) * 3 + (0,) * 37 * 2 + + (currencyIsoCodeData(0),) + + (0,) * 2 + + (0,) * 3 )) + + ' // trailing zeros\n') + self.writer.write('};\n') - list_pattern_part_data = StringData('list_pattern_part_data') - single_character_data = StringData('single_character_data') - date_format_data = StringData('date_format_data') - time_format_data = StringData('time_format_data') - days_data = StringData('days_data') - am_data = StringData('am_data') - pm_data = StringData('pm_data') - byte_unit_data = StringData('byte_unit_data') - currency_symbol_data = StringData('currency_symbol_data') - currency_display_name_data = StringData('currency_display_name_data') - currency_format_data = StringData('currency_format_data') - endonyms_data = StringData('endonyms_data') + # StringData tables: + for data in (list_pattern_part_data, single_character_data, + date_format_data, time_format_data, days_data, + byte_unit_data, am_data, pm_data, currency_symbol_data, + currency_display_name_data, currency_format_data, + endonyms_data): + data.write(self.writer) - # Locale data - data_temp_file.write("static const QLocaleData locale_data[] = {\n") - # Table headings: keep each label centred in its field, matching line_format: - data_temp_file.write(' // ' - # Width 6 + comma: - + ' lang ' # IDs - + 'script ' - + ' terr ' + @staticmethod + def __writeNameData(out, book, form): + out('static const char {}_name_list[] =\n'.format(form)) + out('"Default\\0"\n') + for key, value in book.items(): + if key == 0: + continue + out('"' + value[0] + '\\0"\n') + out(';\n\n') - # Range entries (all start-indices, then all sizes): - # Width 5 + comma: - + 'lStrt ' # List pattern - + 'lpMid ' - + 'lpEnd ' - + 'lPair ' - + 'lDelm ' # List delimiter - # Representing numbers: - + ' dec ' - + 'group ' - + 'prcnt ' - + ' zero ' - + 'minus ' - + 'plus ' - + ' exp ' - # Quotation marks - + 'qtOpn ' - + 'qtEnd ' - + 'altQO ' - + 'altQE ' - + 'lDFmt ' # Date format - + 'sDFmt ' - + 'lTFmt ' # Time format - + 'sTFmt ' - + 'slDay ' # Day names - + 'lDays ' - + 'ssDys ' - + 'sDays ' - + 'snDay ' - + 'nDays ' - + ' am ' # am/pm indicators - + ' pm ' - + ' byte ' - + 'siQnt ' - + 'iecQn ' - + 'crSym ' # Currency formatting: - + 'crDsp ' - + 'crFmt ' - + 'crFNg ' - + 'ntLng ' # Name of language in itself, and of territory: - + 'ntTer ' - # Width 3 + comma for each size; no header - + ' ' * 37 + out('static const quint16 {}_name_index[] = {{\n'.format(form)) + out(' 0, // Any{}\n'.format(form.capitalize())) + index = 8 + for key, value in book.items(): + if key == 0: + continue + name = value[0] + out('{:6d}, // {}\n'.format(index, name)) + index += len(name) + 1 + out('};\n\n') - # Strays (char array, bit-fields): - # Width 8+4 + comma - + ' currISO ' - # Width 6 + comma: - + 'curDgt ' # Currency digits - + 'curRnd ' # Currencty rounding (unused: QTBUG-81343) - + 'dow1st ' # First day of week - + ' wknd+ ' # Week-end start/end days: - + ' wknd-' - # No trailing space on last entry (be sure to - # pad before adding anything after it). - + '\n') + @staticmethod + def __writeCodeList(out, book, form, width): + out('static const unsigned char {}_code_list[] =\n'.format(form)) + for key, value in book.items(): + code = value[1] + code += r'\0' * max(width - len(code), 0) + out('"{}" // {}\n'.format(code, value[0])) + out(';\n\n') - locale_keys = locale_map.keys() - compareLocaleKeys.default_map = default_map - compareLocaleKeys.locale_map = locale_map - locale_keys.sort(compareLocaleKeys) + def languageNames(self, languages): + self.__writeNameData(self.writer.write, languages, 'language') - line_format = (' { ' - # Locale-identifier: - + '%6d,' * 3 - # Offsets for starts of ranges: - + '%5d,' * 37 - # Sizes for the same: - + '%3d,' * 37 + def scriptNames(self, scripts): + self.__writeNameData(self.writer.write, scripts, 'script') - # Currency ISO code: - + ' %10s, ' - # Currency formatting: - + '%6d,%6d' - # Day of week and week-end: - + ',%6d' * 3 - + ' }') - for key in locale_keys: - l = locale_map[key] - # Sequence of StringDataToken: - ranges = (tuple(list_pattern_part_data.append(p) for p in # 5 entries: - (l.listPatternPartStart, l.listPatternPartMiddle, - l.listPatternPartEnd, l.listPatternPartTwo, l.listDelim)) + - tuple(single_character_data.append(p) for p in # 11 entries - (l.decimal, l.group, l.percent, l.zero, l.minus, l.plus, l.exp, - l.quotationStart, l.quotationEnd, - l.alternateQuotationStart, l.alternateQuotationEnd)) + - tuple (date_format_data.append(f) for f in # 2 entries: - (l.longDateFormat, l.shortDateFormat)) + - tuple(time_format_data.append(f) for f in # 2 entries: - (l.longTimeFormat, l.shortTimeFormat)) + - tuple(days_data.append(d) for d in # 6 entries: - (l.standaloneLongDays, l.longDays, - l.standaloneShortDays, l.shortDays, - l.standaloneNarrowDays, l.narrowDays)) + - (am_data.append(l.am), pm_data.append(l.pm)) + # 2 entries: - tuple(byte_unit_data.append(b) for b in # 3 entries: - (l.byte_unit, l.byte_si_quantified, l.byte_iec_quantified)) + - (currency_symbol_data.append(l.currencySymbol), - currency_display_name_data.append(l.currencyDisplayName), - currency_format_data.append(l.currencyFormat), - currency_format_data.append(l.currencyNegativeFormat), - endonyms_data.append(l.languageEndonym), - endonyms_data.append(l.countryEndonym)) # 6 entries - ) # Total: 37 entries - assert len(ranges) == 37 + def countryNames(self, countries): + self.__writeNameData(self.writer.write, countries, 'country') - data_temp_file.write(line_format - % ((key[0], key[1], key[2]) + - tuple(r.index for r in ranges) + - tuple(r.length for r in ranges) + - (currencyIsoCodeData(l.currencyIsoCode), - l.currencyDigits, - l.currencyRounding, # unused (QTBUG-81343) - l.firstDayOfWeek, - l.weekendStart, - l.weekendEnd)) - + ", // %s/%s/%s\n" % (l.language, l.script, l.country)) - data_temp_file.write(line_format # All zeros, matching the format: - % ( (0,) * 3 + (0,) * 37 * 2 - + (currencyIsoCodeData(0),) - + (0,) * 2 - + (0,) * 3) - + " // trailing zeros\n") - data_temp_file.write("};\n") + # TODO: unify these next three into the previous three; kept + # separate for now to verify we're not changing data. - # StringData tables: - for data in (list_pattern_part_data, single_character_data, - date_format_data, time_format_data, days_data, - byte_unit_data, am_data, pm_data, currency_symbol_data, - currency_display_name_data, currency_format_data, - endonyms_data): - data.write(data_temp_file) + def languageCodes(self, languages): + self.__writeCodeList(self.writer.write, languages, 'language', 3) - data_temp_file.write("\n") + def scriptCodes(self, scripts): + self.__writeCodeList(self.writer.write, scripts, 'script', 4) - # Language name list - data_temp_file.write("static const char language_name_list[] =\n") - data_temp_file.write('"Default\\0"\n') - for key in language_map.keys(): - if key == 0: - continue - data_temp_file.write('"' + language_map[key][0] + '\\0"\n') - data_temp_file.write(";\n") + def countryCodes(self, countries): # TODO: unify with countryNames() + self.__writeCodeList(self.writer.write, countries, 'country', 3) - data_temp_file.write("\n") - - # Language name index - data_temp_file.write("static const quint16 language_name_index[] = {\n") - data_temp_file.write(" 0, // AnyLanguage\n") - index = 8 - for key in language_map.keys(): - if key == 0: - continue - language = language_map[key][0] - data_temp_file.write("%6d, // %s\n" % (index, language)) - index += len(language) + 1 - data_temp_file.write("};\n") - - data_temp_file.write("\n") - - # Script name list - data_temp_file.write("static const char script_name_list[] =\n") - data_temp_file.write('"Default\\0"\n') - for key in script_map.keys(): - if key == 0: - continue - data_temp_file.write('"' + script_map[key][0] + '\\0"\n') - data_temp_file.write(";\n") - - data_temp_file.write("\n") - - # Script name index - data_temp_file.write("static const quint16 script_name_index[] = {\n") - data_temp_file.write(" 0, // AnyScript\n") - index = 8 - for key in script_map.keys(): - if key == 0: - continue - script = script_map[key][0] - data_temp_file.write("%6d, // %s\n" % (index, script)) - index += len(script) + 1 - data_temp_file.write("};\n") - - data_temp_file.write("\n") - - # Country name list - data_temp_file.write("static const char country_name_list[] =\n") - data_temp_file.write('"Default\\0"\n') - for key in country_map.keys(): - if key == 0: - continue - data_temp_file.write('"' + country_map[key][0] + '\\0"\n') - data_temp_file.write(";\n") - - data_temp_file.write("\n") - - # Country name index - data_temp_file.write("static const quint16 country_name_index[] = {\n") - data_temp_file.write(" 0, // AnyCountry\n") - index = 8 - for key in country_map.keys(): - if key == 0: - continue - country = country_map[key][0] - data_temp_file.write("%6d, // %s\n" % (index, country)) - index += len(country) + 1 - data_temp_file.write("};\n") - - data_temp_file.write("\n") - - # Language code list - data_temp_file.write("static const unsigned char language_code_list[] =\n") - for key in language_map.keys(): - code = language_map[key][1] - if len(code) == 2: - code += r"\0" - data_temp_file.write('"%2s" // %s\n' % (code, language_map[key][0])) - data_temp_file.write(";\n") - - data_temp_file.write("\n") - - # Script code list - data_temp_file.write("static const unsigned char script_code_list[] =\n") - for key in script_map.keys(): - code = script_map[key][1] - for i in range(4 - len(code)): - code += "\\0" - data_temp_file.write('"%2s" // %s\n' % (code, script_map[key][0])) - data_temp_file.write(";\n") - - # Country code list - data_temp_file.write("static const unsigned char country_code_list[] =\n") - for key in country_map.keys(): - code = country_map[key][1] - if len(code) == 2: - code += "\\0" - data_temp_file.write('"%2s" // %s\n' % (code, country_map[key][0])) - data_temp_file.write(";\n") - - data_temp_file.write("\n") - data_temp_file.write(GENERATED_BLOCK_END) - s = qlocaledata_file.readline() - # skip until end of the old block - while s and s != GENERATED_BLOCK_END: - s = qlocaledata_file.readline() - - s = qlocaledata_file.readline() - while s: - data_temp_file.write(s) - s = qlocaledata_file.readline() - data_temp_file.close() - qlocaledata_file.close() - - os.remove(qtsrcdir + "/src/corelib/text/qlocale_data_p.h") - os.rename(data_temp_file_path, qtsrcdir + "/src/corelib/text/qlocale_data_p.h") - - # Generate calendar data - calendar_format = ' {%6d,%6d,%6d' + ',%5d' * 6 + ',%3d' * 6 + ' },' - for calendar, stem in calendars.items(): +class CalendarDataWriter (LocaleSourceEditor): + formatCalendar = ( + ' {{' + + ','.join(('{:6d}',) * 3 + ('{:5d}',) * 6 + ('{:3d}',) * 6) + + ' }},').format + def write(self, calendar, locales, names): months_data = StringData('months_data') - calendar_data_file = "q%scalendar_data_p.h" % stem - calendar_template_file = open(os.path.join(qtsrcdir, 'src', 'corelib', 'time', - calendar_data_file), "r") - (calendar_temp_file, calendar_temp_file_path) = tempfile.mkstemp(calendar_data_file, dir=qtsrcdir) - calendar_temp_file = os.fdopen(calendar_temp_file, "w") - s = calendar_template_file.readline() - while s and s != GENERATED_BLOCK_START: - calendar_temp_file.write(s) - s = calendar_template_file.readline() - calendar_temp_file.write(GENERATED_BLOCK_START) - calendar_temp_file.write(generated_template % (datetime.date.today(), cldr_version)) - calendar_temp_file.write("static const QCalendarLocale locale_data[] = {\n") - calendar_temp_file.write(' // ' - # IDs, width 7 (6 + comma) - + ' lang ' - + ' script' - + ' terr ' - # Month-name start-indices, width 6 (5 + comma): - + 'sLng ' - + 'long ' - + 'sSrt ' - + 'shrt ' - + 'sNrw ' - + 'naro ' - # No individual headers for the sizes. - + 'Sizes...' - + '\n') - for key in locale_keys: - l = locale_map[key] + + self.writer.write('static const QCalendarLocale locale_data[] = {\n') + self.writer.write( + ' //' + # IDs, width 7 (6 + comma) + ' lang ' + ' script' + ' terr ' + # Month-name start-indices, width 6 (5 + comma) + 'sLong ' + ' long ' + 'sShrt ' + 'short ' + 'sNarw ' + 'narow ' + # No individual headers for the sizes. + 'Sizes...' + '\n') + for key in names: + locale = locales[key] # Sequence of StringDataToken: try: # Twelve long month names can add up to more than 256 (e.g. kde_TZ: 264) ranges = (tuple(months_data.append(m[calendar], 16) for m in - (l.standaloneLongMonths, l.longMonths)) + + (locale.standaloneLongMonths, locale.longMonths)) + tuple(months_data.append(m[calendar]) for m in - (l.standaloneShortMonths, l.shortMonths, - l.standaloneNarrowMonths, l.narrowMonths))) + (locale.standaloneShortMonths, locale.shortMonths, + locale.standaloneNarrowMonths, locale.narrowMonths))) except ValueError as e: - e.args += (l.language, l.script, l.country, stem) + e.args += (locale.language, locale.script, locale.country, stem) raise - calendar_temp_file.write( - calendar_format - % ((key[0], key[1], key[2]) + - tuple(r.index for r in ranges) + - tuple(r.length for r in ranges)) - + "// %s/%s/%s\n" % (l.language, l.script, l.country)) - calendar_temp_file.write(calendar_format % ( (0,) * (3 + 6 * 2) ) - + '// trailing zeros\n') - calendar_temp_file.write("};\n") - months_data.write(calendar_temp_file) - s = calendar_template_file.readline() - while s and s != GENERATED_BLOCK_END: - s = calendar_template_file.readline() - while s: - calendar_temp_file.write(s) - s = calendar_template_file.readline() - os.rename(calendar_temp_file_path, - os.path.join(qtsrcdir, 'src', 'corelib', 'time', calendar_data_file)) + self.writer.write( + self.formatCalendar(*( + key + + tuple(r.index for r in ranges) + + tuple(r.length for r in ranges) )) + + '// {}/{}/{}\n'.format(locale.language, locale.script, locale.country)) + self.writer.write(self.formatCalendar(*( (0,) * (3 + 6 * 2) )) + + '// trailing zeros\n') + self.writer.write('};\n') + months_data.write(self.writer) + +class LocaleHeaderWriter (SourceFileEditor): + __upinit = SourceFileEditor.__init__ + def __init__(self, path, temp, dupes): + self.__upinit(path, temp) + self.__dupes = dupes + + def languages(self, languages): + self.__enum('Language', languages, self.__language) + self.writer.write('\n') + + def countries(self, countries): + self.__enum('Country', countries, self.__country) + + def scripts(self, scripts): + self.__enum('Script', scripts, self.__script) + self.writer.write('\n') + + # Implementation details + from enumdata import (language_aliases as __language, + country_aliases as __country, + script_aliases as __script) + + def __enum(self, name, book, alias): + assert book + out, dupes = self.writer.write, self.__dupes + out(' enum {} {{\n'.format(name)) + for key, value in book.items(): + member = value[0] + if name == 'Script': + # Don't .capitalize() as some names are already camel-case (see enumdata.py): + member = ''.join(word[0].upper() + word[1:] for word in member.split()) + if not member.endswith('Script'): + member += 'Script' + if member in dupes: + raise Error('The script name "{}" is messy'.format(member)) + else: + member = ''.join(member.split()) + member = member + name if member in dupes else member + out(' {} = {},\n'.format(member, key)) + + out('\n ' + + ',\n '.join('{} = {}'.format(*pair) + for pair in sorted(alias.items())) + + ',\n\n Last{} = {}\n }};\n'.format(name, member)) + +def usage(name, err, message = ''): + err.write("""Usage: {} path/to/qlocale.xml root/of/qtbase +""".format(name)) # TODO: elaborate + if message: + err.write('\n' + message + '\n') + +def main(args, out, err): + # TODO: Make calendars a command-line parameter + # map { CLDR name: Qt file name } + calendars = {'gregorian': 'roman', 'persian': 'jalali', 'islamic': 'hijri',} # 'hebrew': 'hebrew', + + name = args.pop(0) + if len(args) != 2: + usage(name, err, 'I expect two arguments') + return 1 + + qlocalexml = args.pop(0) + qtsrcdir = args.pop(0) + + if not (os.path.isdir(qtsrcdir) + and all(os.path.isfile(os.path.join(qtsrcdir, 'src', 'corelib', 'text', leaf)) + for leaf in ('qlocale_data_p.h', 'qlocale.h', 'qlocale.qdoc'))): + usage(name, err, 'Missing expected files under qtbase source root ' + qtsrcdir) + return 1 + + reader = QLocaleXmlReader(qlocalexml) + locale_map = dict(reader.loadLocaleMap(calendars, err.write)) + + locale_keys = locale_map.keys() + compareLocaleKeys.default_map = dict(reader.defaultMap()) + locale_keys.sort(compareLocaleKeys) + + try: + writer = LocaleDataWriter(os.path.join(qtsrcdir, 'src', 'corelib', 'text', + 'qlocale_data_p.h'), + qtsrcdir, reader.cldrVersion) + except IOError as e: + err.write('Failed to open files to transcribe locale data: ' + (e.message or e.args[1])) + return 1 + + try: + writer.likelySubtags(reader.likelyMap()) + writer.localeIndex(reader.languageIndices(tuple(k[0] for k in locale_map))) + writer.localeData(locale_map, locale_keys) + writer.writer.write('\n') + writer.languageNames(reader.languages) + writer.scriptNames(reader.scripts) + writer.countryNames(reader.countries) + # TODO: merge the next three into the previous three + writer.languageCodes(reader.languages) + writer.scriptCodes(reader.scripts) + writer.countryCodes(reader.countries) + except Error as e: + writer.cleanup() + err.write('\nError updating locale data: ' + e.message + '\n') + return 1 + + writer.close() + + # Generate calendar data + for calendar, stem in calendars.items(): + try: + writer = CalendarDataWriter(os.path.join(qtsrcdir, 'src', 'corelib', 'time', + 'q{}calendar_data_p.h'.format(stem)), + qtsrcdir, reader.cldrVersion) + except IOError as e: + err.write('Failed to open files to transcribe ' + calendar + + ' data ' + (e.message or e.args[1])) + return 1 + + try: + writer.write(calendar, locale_map, locale_keys) + except Error as e: + writer.cleanup() + err.write('\nError updating ' + calendar + ' locale data: ' + e.message + '\n') + return 1 + + writer.close() # qlocale.h + try: + writer = LocaleHeaderWriter(os.path.join(qtsrcdir, 'src', 'corelib', 'text', 'qlocale.h'), + qtsrcdir, reader.dupes) + except IOError as e: + err.write('Failed to open files to transcribe qlocale.h: ' + (e.message or e.args[1])) + return 1 - (qlocaleh_temp_file, qlocaleh_temp_file_path) = tempfile.mkstemp("qlocale.h", dir=qtsrcdir) - qlocaleh_temp_file = os.fdopen(qlocaleh_temp_file, "w") - qlocaleh_file = open(qtsrcdir + "/src/corelib/text/qlocale.h", "r") - s = qlocaleh_file.readline() - while s and s != GENERATED_BLOCK_START: - qlocaleh_temp_file.write(s) - s = qlocaleh_file.readline() - qlocaleh_temp_file.write(GENERATED_BLOCK_START) - qlocaleh_temp_file.write("// see qlocale_data_p.h for more info on generated data\n") + try: + writer.languages(reader.languages) + writer.scripts(reader.scripts) + writer.countries(reader.countries) + except Error as e: + writer.cleanup() + err.write('\nError updating qlocale.h: ' + e.message + '\n') + return 1 - # Language enum - qlocaleh_temp_file.write(" enum Language {\n") - language = None - for key, value in language_map.items(): - language = fixedLanguageName(value[0], dupes) - qlocaleh_temp_file.write(" " + language + " = " + str(key) + ",\n") - - qlocaleh_temp_file.write("\n " + - ",\n ".join('%s = %s' % pair - for pair in sorted(language_aliases.items())) + - ",\n") - qlocaleh_temp_file.write("\n") - qlocaleh_temp_file.write(" LastLanguage = " + language + "\n") - qlocaleh_temp_file.write(" };\n\n") - - # Script enum - qlocaleh_temp_file.write(" enum Script {\n") - script = None - for key, value in script_map.items(): - script = fixedScriptName(value[0], dupes) - qlocaleh_temp_file.write(" " + script + " = " + str(key) + ",\n") - qlocaleh_temp_file.write("\n " + - ",\n ".join('%s = %s' % pair - for pair in sorted(script_aliases.items())) + - ",\n") - qlocaleh_temp_file.write("\n") - qlocaleh_temp_file.write(" LastScript = " + script + "\n") - qlocaleh_temp_file.write(" };\n\n") - - # Country enum - qlocaleh_temp_file.write(" enum Country {\n") - country = None - for key, value in country_map.items(): - country = fixedCountryName(value[0], dupes) - qlocaleh_temp_file.write(" " + country + " = " + str(key) + ",\n") - qlocaleh_temp_file.write("\n " + - ",\n ".join('%s = %s' % pair - for pair in sorted(country_aliases.items())) + - ",\n") - qlocaleh_temp_file.write("\n") - qlocaleh_temp_file.write(" LastCountry = " + country + "\n") - qlocaleh_temp_file.write(" };\n") - - qlocaleh_temp_file.write(GENERATED_BLOCK_END) - s = qlocaleh_file.readline() - # skip until end of the old block - while s and s != GENERATED_BLOCK_END: - s = qlocaleh_file.readline() - - s = qlocaleh_file.readline() - while s: - qlocaleh_temp_file.write(s) - s = qlocaleh_file.readline() - qlocaleh_temp_file.close() - qlocaleh_file.close() - - os.remove(qtsrcdir + "/src/corelib/text/qlocale.h") - os.rename(qlocaleh_temp_file_path, qtsrcdir + "/src/corelib/text/qlocale.h") + writer.close() # qlocale.qdoc + try: + writer = Transcriber(os.path.join(qtsrcdir, 'src', 'corelib', 'text', 'qlocale.qdoc'), + qtsrcdir) + except IOError as e: + err.write('Failed to open files to transcribe qlocale.qdoc: ' + (e.message or e.args[1])) + return 1 - (qlocaleqdoc_temp_file, qlocaleqdoc_temp_file_path) = tempfile.mkstemp("qlocale.qdoc", dir=qtsrcdir) - qlocaleqdoc_temp_file = os.fdopen(qlocaleqdoc_temp_file, "w") - qlocaleqdoc_file = open(qtsrcdir + "/src/corelib/text/qlocale.qdoc", "r") - s = qlocaleqdoc_file.readline() DOCSTRING = " QLocale's data is based on Common Locale Data Repository " - while s: - if DOCSTRING in s: - qlocaleqdoc_temp_file.write(DOCSTRING + "v" + cldr_version + ".\n") - else: - qlocaleqdoc_temp_file.write(s) - s = qlocaleqdoc_file.readline() - qlocaleqdoc_temp_file.close() - qlocaleqdoc_file.close() + try: + for line in writer.reader: + if DOCSTRING in line: + writer.writer.write(DOCSTRING + 'v' + reader.cldrVersion + '.\n') + else: + writer.writer.write(line) + except Error as e: + writer.cleanup() + err.write('\nError updating qlocale.qdoc: ' + e.message + '\n') + return 1 - os.remove(qtsrcdir + "/src/corelib/text/qlocale.qdoc") - os.rename(qlocaleqdoc_temp_file_path, qtsrcdir + "/src/corelib/text/qlocale.qdoc") + writer.close() + return 0 if __name__ == "__main__": - main() + import sys + sys.exit(main(sys.argv, sys.stdout, sys.stderr)) diff --git a/util/locale_database/xpathlite.py b/util/locale_database/xpathlite.py deleted file mode 100644 index 97efaaab41e..00000000000 --- a/util/locale_database/xpathlite.py +++ /dev/null @@ -1,288 +0,0 @@ -#!/usr/bin/env python -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of the Qt Toolkit. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import sys -import os -import xml.dom.minidom - -class DraftResolution: - # See http://www.unicode.org/cldr/process.html for description - unconfirmed = 'unconfirmed' - provisional = 'provisional' - contributed = 'contributed' - approved = 'approved' - _values = { unconfirmed : 1, provisional : 2, contributed : 3, approved : 4 } - def __init__(self, resolution): - self.resolution = resolution - def toInt(self): - return DraftResolution._values[self.resolution] - -class Error: - def __init__(self, msg): - self.msg = msg - def __str__(self): - return self.msg - -doc_cache = {} -def parseDoc(file): - if not doc_cache.has_key(file): - doc_cache[file] = xml.dom.minidom.parse(file) - return doc_cache[file] - -def findChild(parent, tag_name, arg_name=None, arg_value=None, draft=None): - for node in parent.childNodes: - if node.nodeType != node.ELEMENT_NODE: - continue - if node.nodeName != tag_name: - continue - if arg_value: - if not node.attributes.has_key(arg_name): - continue - if node.attributes[arg_name].nodeValue != arg_value: - continue - if draft: - if not node.attributes.has_key('draft'): - # if draft is not specified then it's approved - return node - value = node.attributes['draft'].nodeValue - value = DraftResolution(value).toInt() - exemplar = DraftResolution(draft).toInt() - if exemplar > value: - continue - return node - return False - -def codeMapsFromFile(file): - """Extract mappings of language, script and country codes to names. - - The file shall typically be common/main/en.xml, which contains a - localeDisplayNames element with children languages, scripts and - territories; each element in each of these has a code as its type - attribute and its name as element content. This returns a mapping - withe keys 'language', 'script' and 'country', each of which - has, as value, a mapping of the relevant codes to names. - """ - parent = findChild(findChild(parseDoc(file), 'ldml'), 'localeDisplayNames') - keys, result = {'languages': 'language', 'scripts': 'script', 'territories': 'country'}, {} - for src, dst in keys.items(): - child = findChild(parent, src) - data = result[dst] = {} - for elt in child.childNodes: - if elt.attributes and elt.attributes.has_key('type'): - key, value = elt.attributes['type'].value, elt.childNodes[0].wholeText - # Don't over-write previously-read data for an alt form: - if elt.attributes.has_key('alt') and data.has_key(key): - continue - data[key] = value - - return result - -def findTagsInFile(file, path): - doc = parseDoc(file) - - elt = doc.documentElement - tag_spec_list = path.split("/") - last_entry = None - for tag_spec in tag_spec_list: - tag_name = tag_spec - arg_name = 'type' - arg_value = '' - left_bracket = tag_spec.find('[') - if left_bracket != -1: - tag_name = tag_spec[:left_bracket] - arg_value = tag_spec[left_bracket+1:-1].split("=") - if len(arg_value) == 2: - arg_name = arg_value[0] - arg_value = arg_value[1] - else: - arg_value = arg_value[0] - elt = findChild(elt, tag_name, arg_name, arg_value) - if not elt: - return None - ret = [] - if elt.childNodes: - for node in elt.childNodes: - if node.attributes: - element = [node.nodeName, None] - element[1] = node.attributes.items() - ret.append(element) - else: - if elt.attributes: - element = [elt.nodeName, None] - element[1] = elt.attributes.items() - ret.append(element) - return ret - -def _findEntryInFile(file, path, draft=None, attribute=None): - doc = parseDoc(file) - - elt = doc.documentElement - tag_spec_list = path.split("/") - last_entry = None - for i in range(len(tag_spec_list)): - tag_spec = tag_spec_list[i] - tag_name = tag_spec - arg_name = 'type' - arg_value = '' - left_bracket = tag_spec.find('[') - if left_bracket != -1: - tag_name = tag_spec[:left_bracket] - arg_value = tag_spec[left_bracket+1:-1].split("=") - if len(arg_value) == 2: - arg_name = arg_value[0].replace("@", "").replace("'", "") - arg_value = arg_value[1] - else: - arg_value = arg_value[0] - alias = findChild(elt, 'alias') - if alias and alias.attributes['source'].nodeValue == 'locale': - path = alias.attributes['path'].nodeValue - aliaspath = tag_spec_list[:i] + path.split("/") - def resolve(x, y): - if y == '..': - return x[:-1] - return x + [y] - # resolve all dot-dot parts of the path - aliaspath = reduce(resolve, aliaspath, []) - # remove attribute specification that our xpathlite doesnt support - aliaspath = map(lambda x: x.replace("@type=", "").replace("'", ""), aliaspath) - # append the remaining path - aliaspath = aliaspath + tag_spec_list[i:] - aliaspath = "/".join(aliaspath) - # "locale" aliases are special - we need to start lookup from scratch - return (None, aliaspath) - elt = findChild(elt, tag_name, arg_name, arg_value, draft) - if not elt: - return ("", None) - if attribute is not None: - if elt.attributes.has_key(attribute): - return (elt.attributes[attribute].nodeValue, None) - return (None, None) - try: - return (elt.firstChild.nodeValue, None) - except: - pass - return (None, None) - -def findAlias(file): - doc = parseDoc(file) - - alias_elt = findChild(doc.documentElement, "alias") - if not alias_elt: - return False - if not alias_elt.attributes.has_key('source'): - return False - return alias_elt.attributes['source'].nodeValue - -lookup_chain_cache = {} -parent_locales = {} -def _fixedLookupChain(dirname, name): - if lookup_chain_cache.has_key(name): - return lookup_chain_cache[name] - - # see http://www.unicode.org/reports/tr35/#Parent_Locales - if not parent_locales: - for ns in findTagsInFile(dirname + "/../supplemental/supplementalData.xml", "parentLocales"): - tmp = {} - parent_locale = "" - for data in ns[1:][0]: # ns looks like this: [u'parentLocale', [(u'parent', u'root'), (u'locales', u'az_Cyrl bs_Cyrl en_Dsrt ..')]] - tmp[data[0]] = data[1] - if data[0] == u"parent": - parent_locale = data[1] - parent_locales[parent_locale] = tmp[u"locales"].split(" ") - - items = name.split("_") - # split locale name into items and iterate through them from back to front - # example: az_Latn_AZ => [az_Latn_AZ, az_Latn, az] - items = list(reversed(map(lambda x: "_".join(items[:x+1]), range(len(items))))) - - for i in range(len(items)): - item = items[i] - for parent_locale in parent_locales.keys(): - for locale in parent_locales[parent_locale]: - if item == locale: - if parent_locale == u"root": - items = items[:i+1] - else: - items = items[:i+1] + _fixedLookupChain(dirname, parent_locale) - lookup_chain_cache[name] = items - return items - - lookup_chain_cache[name] = items - return items - -def _findEntry(base, path, draft=None, attribute=None): - if base.endswith(".xml"): - base = base[:-4] - (dirname, filename) = os.path.split(base) - - items = _fixedLookupChain(dirname, filename) - for item in items: - file = dirname + "/" + item + ".xml" - if os.path.isfile(file): - alias = findAlias(file) - if alias: - # if alias is found we should follow it and stop processing current file - # see http://www.unicode.org/reports/tr35/#Common_Elements - aliasfile = os.path.dirname(file) + "/" + alias + ".xml" - if not os.path.isfile(aliasfile): - raise Error("findEntry: fatal error: found an alias '%s' to '%s', but the alias file couldn't be found" % (filename, alias)) - # found an alias, recurse into parsing it - result = _findEntry(aliasfile, path, draft, attribute) - return result - (result, aliaspath) = _findEntryInFile(file, path, draft, attribute) - if aliaspath: - # start lookup again because of the alias source="locale" - return _findEntry(base, aliaspath, draft, attribute) - if result: - return result - return None - -def findEntry(base, path, draft=None, attribute=None): - file = base - if base.endswith(".xml"): - file = base - base = base[:-4] - else: - file = base + ".xml" - (dirname, filename) = os.path.split(base) - - result = None - while path: - result = _findEntry(base, path, draft, attribute) - if result: - return result - (result, aliaspath) = _findEntryInFile(dirname + "/root.xml", path, draft, attribute) - if result: - return result - if not aliaspath: - raise Error("findEntry: fatal error: %s: cannot find key %s" % (filename, path)) - path = aliaspath - - return result -